diff --git a/src/core/inth.S b/src/core/inth.S index 2cd6be2..2be849f 100644 --- a/src/core/inth.S +++ b/src/core/inth.S @@ -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. */ diff --git a/src/core/kernel.c b/src/core/kernel.c index 43b85bf..ad93f2b 100644 --- a/src/core/kernel.c +++ b/src/core/kernel.c @@ -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 }; diff --git a/src/rtc/inth.s b/src/rtc/inth.s index b21b5f7..5c067d8 100644 --- a/src/rtc/inth.s +++ b/src/rtc/inth.s @@ -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 */ diff --git a/src/rtc/rtc.c b/src/rtc/rtc.c index 47231aa..c118e29 100644 --- a/src/rtc/rtc.c +++ b/src/rtc/rtc.c @@ -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; } //---