mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2024-12-28 20:43:36 +01:00
rtc: robust interrupt handling and SH3 compatibility
This commit changes the interrupt handler arrangement to support the PRI interrupt on SH3 (a gap is needed between 0xaa0 and its helper). It also introduces the use of the _gint_inth_callback function for the callback, which provides dynamic TLB during the interrupt, and revealed a bug about IMASK not being set automatically on SH3. Finally, it sets the interrupt settings of the RTC more conservatively, by wiping RCR1 and the carry, alarm and periodic interrupt flags during initialization and context restoration.
This commit is contained in:
parent
a06213ca11
commit
0622928f22
4 changed files with 30 additions and 17 deletions
|
@ -156,13 +156,13 @@ _gint_inth_7705:
|
|||
The VBR interrupt space on SH3 is laid out as follows:
|
||||
|
||||
VBR offset SH3 events Description
|
||||
----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
0x200 400 420 440 --- TMU0, TMU1, TMU2 and a helper
|
||||
0x280 f00 --- --- --- ETMU0, ETMU1, ETMU2 and a helper
|
||||
0x300 4a0 --- RTC Periodic Interrupt and a helper
|
||||
----------------------------------------------------------------
|
||||
0x300 4a0 [ ] --- RTC Periodic Interrupt, gap and helper
|
||||
-------------------------------------------------------------------
|
||||
0x600 --- --- Entry gate
|
||||
----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
|
||||
There is space for 16 gates at VBR + 0x200 so the VBR currently ends after
|
||||
the interrupt entry gate at VBR + 0x640. */
|
||||
|
|
|
@ -155,6 +155,7 @@ static const uint16_t sh3_vbr_map[] = {
|
|||
0xc40, /* ETMU2 underflow (used as helper on SH3) */
|
||||
0xc60, /* (gint custom: ETMU helper) */
|
||||
0xaa0, /* RTC Periodic Interrupt */
|
||||
1, /* (Filler to maintain the gap between 0xaa0 and 0xae0) */
|
||||
0xae0, /* (gint custom: RTC helper) */
|
||||
0
|
||||
};
|
||||
|
|
|
@ -14,17 +14,15 @@
|
|||
_inth_rtc_pri:
|
||||
/* Invoke the callback function with its argument */
|
||||
sts.l pr, @-r15
|
||||
mov.l 1f, r0
|
||||
mov.l 2f, r4
|
||||
mov.l .gint_inth_callback, r0
|
||||
mov.l 1f, r4
|
||||
mov.l 2f, r5
|
||||
jsr @r0
|
||||
nop
|
||||
|
||||
/* Save the return value */
|
||||
mov r0, r3
|
||||
|
||||
/* Prepare to clear the interrupt flag */
|
||||
mov.l 3f, r1
|
||||
|
||||
/* Jump to another gate to finish the work:
|
||||
- 0xc is the size of storage below
|
||||
- 0x20 is the size of the gap before next gate (alarm interrupt) */
|
||||
|
@ -34,12 +32,15 @@ _inth_rtc_pri:
|
|||
|
||||
1: .long 0 /* Callback function: edited dynamically */
|
||||
2: .long 0 /* Argument to callback function */
|
||||
3: .long 0xa413fede /* RCR2 address, edited at startup on SH3 */
|
||||
|
||||
.gint_inth_callback:
|
||||
.long _gint_inth_callback
|
||||
|
||||
_inth_rtc_pri_helper:
|
||||
|
||||
.clear:
|
||||
/* Clear the interrupt flag */
|
||||
mov.l .RCR2, r1
|
||||
mov.b @r1, r0
|
||||
tst #0x80, r0
|
||||
and #0x7f, r0
|
||||
|
@ -56,5 +57,6 @@ _inth_rtc_pri_helper:
|
|||
lds.l @r15+, pr
|
||||
rts
|
||||
nop
|
||||
nop
|
||||
|
||||
.zero 8
|
||||
.RCR2: .long 0xa413fede /* RCR2 address, edited at startup on SH3 */
|
||||
|
|
|
@ -25,7 +25,6 @@ static rtc_t *RTC = &SH7305_RTC;
|
|||
GBSS static struct {
|
||||
void *function;
|
||||
uint32_t arg;
|
||||
volatile uint8_t *RCR2;
|
||||
} GPACKED(4) *timer_params;
|
||||
|
||||
//---
|
||||
|
@ -144,6 +143,12 @@ static void driver_sh3(void)
|
|||
|
||||
static void init(void)
|
||||
{
|
||||
/* Disable the carry and alarm interrupts (they share their IPR bits
|
||||
with the periodic interrupt, which we want to enable) */
|
||||
RTC->RCR1.byte = 0;
|
||||
/* Clear the periodic interrupt flag */
|
||||
RTC->RCR2.PEF = 0;
|
||||
|
||||
/* Interrupt handlers provided by rtc/inth.s */
|
||||
extern void inth_rtc_pri(void);
|
||||
extern void inth_rtc_pri_helper(void);
|
||||
|
@ -154,11 +159,15 @@ static void init(void)
|
|||
h1 = gint_inthandler(0xae0, inth_rtc_pri_helper, 32);
|
||||
|
||||
timer_params = h0 + 20;
|
||||
timer_params->RCR2 = &RTC->RCR2.byte;
|
||||
|
||||
/* Disable the periodic interrupt for now, but give it priority 5 */
|
||||
volatile uint8_t **RCR2_pointer = h1 + 28;
|
||||
*RCR2_pointer = &RTC->RCR2.byte;
|
||||
|
||||
/* Disable the RTC interrupts for now. Give them priority 1; higher
|
||||
priorities cause freezes when going back to the system on SH3
|
||||
(TODO: Find out about the RTC interrupt problem on SH3) */
|
||||
RTC->RCR2.PES = RTC_NONE;
|
||||
intc_priority(INTC_RTC_PRI, 5);
|
||||
intc_priority(INTC_RTC_PRI, 1);
|
||||
}
|
||||
|
||||
//---
|
||||
|
@ -183,8 +192,9 @@ static void ctx_save(void *buf)
|
|||
static void ctx_restore(void *buf)
|
||||
{
|
||||
ctx_t *ctx = buf;
|
||||
RTC->RCR1.byte = ctx->RCR1;
|
||||
RTC->RCR2.byte = ctx->RCR2;
|
||||
|
||||
RTC->RCR1.byte = ctx->RCR1 & 0x18;
|
||||
RTC->RCR2.byte = ctx->RCR2 & 0x7f;
|
||||
}
|
||||
|
||||
//---
|
||||
|
|
Loading…
Reference in a new issue