From 1697998a9c2b971866a4bb636406423ed84bc206 Mon Sep 17 00:00:00 2001 From: lephe Date: Thu, 18 Jul 2019 15:18:36 -0400 Subject: [PATCH] tmu: improve code style and clear masks Apparently there are some situations where the interrupt masks for TMU0 are set in the system. They should obviously be cleared. --- src/tmu/inth.s | 17 ++++---- src/tmu/sleep.c | 6 ++- src/tmu/tmu.c | 110 +++++++++++++++++++++++------------------------- 3 files changed, 64 insertions(+), 69 deletions(-) diff --git a/src/tmu/inth.s b/src/tmu/inth.s index 143c964..7eb0307 100644 --- a/src/tmu/inth.s +++ b/src/tmu/inth.s @@ -6,15 +6,12 @@ */ /* Gates for the standard Timer Unit (TMU) */ -.global _inth_tmu_0 -.global _inth_tmu_1 -.global _inth_tmu_2 -.global _inth_tmu_storage +.global _inth_tmu /* 128 bytes */ /* Gates for the extra timers (informally called ETMU) */ -.global _inth_etmu2 -.global _inth_etmu_help -.global _inth_etmux +.global _inth_etmu2 /* 32 bytes */ +.global _inth_etmu_help /* 32 bytes */ +.global _inth_etmux /* 32 bytes */ .section .gint.blocks, "ax" .align 4 @@ -36,6 +33,8 @@ crash because we will have broken the references. This is why we can only do it with handlers that are mapped to consecutive event codes. */ +_inth_tmu: + /* FIRST GATE - TMU0 entry, clear underflow flag and call back */ _inth_tmu_0: mova .storage0, r0 @@ -205,8 +204,8 @@ _inth_etmux: - 0x004 to skip its first instructions (the size is hardcoded) */ 1: .long 0xe64 +.id_etmux: + .long 0 /* Timer ID */ .storage_etmux: .long 0 /* Callback: Configured dynamically */ .long 0 /* Argument: Configured dynamically */ -.id_etmux: - .long 0 /* Timer ID */ diff --git a/src/tmu/sleep.c b/src/tmu/sleep.c index c7c18dd..fb30f19 100644 --- a/src/tmu/sleep.c +++ b/src/tmu/sleep.c @@ -9,9 +9,11 @@ void sleep_us(int tid, int us_delay) { volatile int flag = 0; + uint32_t delay = timer_delay(tid, us_delay); + + int free = timer_setup(tid, delay, 0, timer_timeout, &flag); + if(free < 0) return; - timer_setup(tid, timer_delay(tid, us_delay), 0, timer_timeout, &flag); timer_start(tid); - while(!flag) sleep(); } diff --git a/src/tmu/tmu.c b/src/tmu/tmu.c index 760eeab..7df533a 100644 --- a/src/tmu/tmu.c +++ b/src/tmu/tmu.c @@ -42,15 +42,15 @@ typedef struct /* This is the description of the structure on SH4. SH3-based fx9860g models, which are already very rare, will adapt the values in init functions */ GDATA static timer_t timers[9] = { - { .tmu = (void *)0xa4490008, .event = 0x400 }, - { .tmu = (void *)0xa4490014, .event = 0x420 }, - { .tmu = (void *)0xa4490020, .event = 0x440 }, - { .tmu = (void *)0xa44d0030, .event = 0x9e0 }, - { .tmu = (void *)0xa44d0050, .event = 0xc20 }, - { .tmu = (void *)0xa44d0070, .event = 0xc40 }, - { .tmu = (void *)0xa44d0090, .event = 0x900 }, - { .tmu = (void *)0xa44d00b0, .event = 0xd00 }, - { .tmu = (void *)0xa44d00d0, .event = 0xfa0 }, + { (void *)0xa4490008, NULL, 0x400 }, + { (void *)0xa4490014, NULL, 0x420 }, + { (void *)0xa4490020, NULL, 0x440 }, + { (void *)0xa44d0030, NULL, 0x9e0 }, + { (void *)0xa44d0050, NULL, 0xc20 }, + { (void *)0xa44d0070, NULL, 0xc40 }, + { (void *)0xa44d0090, NULL, 0x900 }, + { (void *)0xa44d00b0, NULL, 0xd00 }, + { (void *)0xa44d00d0, NULL, 0xfa0 }, }; /* TSTR register for standard timers */ @@ -61,33 +61,34 @@ GDATA static volatile uint8_t *TSTR = (void *)0xa4490004; //--- /* timer_setup() - set up a timer */ -int timer_setup(int tid, uint32_t delay, timer_input_t clock, +int timer_setup(int id, uint32_t delay, timer_input_t clock, int (*callback)(volatile void *arg), volatile void *arg) { /* We need to distinguish normal and extra timers */ - if(tid < 3) + if(id < 3) { /* Refuse to setup timers that are already in use */ - tmu_t *t = timers[tid].tmu; + tmu_t *t = timers[id].tmu; if(t->TCR.UNIE) return -1; /* Configure the registers of the target timer */ - t->TCOR = delay; - t->TCNT = delay; - t->TCR.TPSC = clock; + t->TCOR = delay; + t->TCNT = delay; + t->TCR.TPSC = clock; /* Clear the interrupt flag */ do t->TCR.UNF = 0; while(t->TCR.UNF); - t->TCR.UNIE = 1; /* Enable interrupt on underflow */ - t->TCR.CKEG = 0; /* Count on rising edge (SH7705) */ + /* Enable interrupt and count on rising edge (SH7705) */ + t->TCR.UNIE = 1; + t->TCR.CKEG = 0; } /* Extra timers have a simpler structure */ else { - etmu_t *t = timers[tid].tmu; + etmu_t *t = timers[id].tmu; if(t->TCR.UNIE) return -1; /* Clear the interrupt flag */ @@ -104,15 +105,15 @@ int timer_setup(int tid, uint32_t delay, timer_input_t clock, t->TCR.UNIE = 1; } - /* Register the callback and its argument (TMU-owned timers only) */ - if(timers[tid].data) + /* Register the callback and its argument */ + if(timers[id].data) { - timers[tid].data->cb = callback; - timers[tid].data->arg = arg; + timers[id].data->cb = callback; + timers[id].data->arg = arg; } /* Return the timer id, since configuration was successful */ - return tid; + return id; } /* timer_delay() - compute a delay constant from a duration in seconds */ @@ -134,44 +135,44 @@ uint32_t timer_delay(int tid, uint64_t delay_us) } /* timer_control() - start or stop a timer - @timer Timer ID to configure + @id Timer ID to configure @state 0 to start the timer, 1 to stop it (nothing else!) */ -static void timer_control(int tid, int state) +static void timer_control(int id, int state) { /* For standard timers, use the MPU's TSTR register */ - if(tid < 3) *TSTR = (*TSTR | (1 << tid)) ^ (state << tid); + if(id < 3) *TSTR = (*TSTR | (1 << id)) ^ (state << id); /* Extra timers all have their own TSTR register */ - else ((etmu_t *)timers[tid].tmu)->TSTR = state ^ 1; + else ((etmu_t *)timers[id].tmu)->TSTR = state ^ 1; } /* timer_start() - start a configured timer */ -void timer_start(int tid) +void timer_start(int id) { - timer_control(tid, 0); + timer_control(id, 0); } /* timer_reload() - change a timer's delay constant for next interrupts */ -void timer_reload(int tid, uint32_t delay) +void timer_reload(int id, uint32_t delay) { - if(tid < 3) ((tmu_t *)timers[tid].tmu)->TCOR = delay; - else ((etmu_t *)timers[tid].tmu)->TCOR = delay; + if(id < 3) ((tmu_t *)timers[id].tmu)->TCOR = delay; + else ((etmu_t *)timers[id].tmu)->TCOR = delay; } /* timer_pause() - stop a running timer */ -void timer_pause(int tid) +void timer_pause(int id) { - timer_control(tid, 1); + timer_control(id, 1); } /* timer_stp() - stop and free a timer */ -void timer_stop(int tid) +void timer_stop(int id) { /* Stop the timer and disable UNIE to indicate that it's free */ - timer_pause(tid); + timer_pause(id); - if(tid < 3) + if(id < 3) { - tmu_t *t = timers[tid].tmu; + tmu_t *t = timers[id].tmu; t->TCR.UNIE = 0; /* Clear TCOR and TCNT */ @@ -180,7 +181,7 @@ void timer_stop(int tid) } else { - etmu_t *t = timers[tid].tmu; + etmu_t *t = timers[id].tmu; t->TCR.UNIE = 0; /* Also clear TCOR and TCNT to avoid spurious interrupts */ @@ -236,13 +237,9 @@ void timer_clear(int timer, int stop) // Driver initialization //--- -/* Interrupt handlers provided by tmu/inth.s for standard timers */ -extern void inth_tmu_0(void); -extern void inth_tmu_1(void); -extern void inth_tmu_2(void); -extern void inth_tmu_storage(void); - -/* Interrupt handlers provided by tmu/inth.s for extra timers */ +/* Interrupt handlers for standard timers (4 gates) */ +extern void inth_tmu(void); +/* Interrupt handlers for extra timers */ extern void inth_etmu2(void); extern void inth_etmu_help(void); extern void inth_etmux(void); @@ -264,18 +261,12 @@ static void driver_sh3(void) static void init(void) { /* Install the standard's TMU interrupt handlers */ - void *h2, *hs; - gint_inthandler(0x400, inth_tmu_0, 32); - gint_inthandler(0x420, inth_tmu_1, 32); - h2 = gint_inthandler(0x440, inth_tmu_2, 32); - hs = gint_inthandler(0x460, inth_tmu_storage, 32); + void *h = gint_inthandler(0x400, inth_tmu, 128); /* User information in interrupt handlers */ - timers[0].data = h2 + 20; - timers[1].data = hs + 8; - timers[2].data = hs + 20; - /* SH3: Override the address of TSTR in the interrupt handler helper */ - if(isSH3()) *(volatile uint8_t **)(hs + 4) = TSTR; + timers[0].data = h + 84; + timers[1].data = h + 104; + timers[2].data = h + 116; /* Stop all timers */ *TSTR = 0; @@ -328,10 +319,10 @@ static void init(void) void *handler = (i == 5) ? inth_etmu2 : inth_etmux; void *h = gint_inthandler(timers[i].event, handler, 32); - timers[i].data = (i == 5) ? (h + 24) : (h + 20); + timers[i].data = h + 24; if(i == 5) continue; - uint32_t *data_id = (h + 28); + uint32_t *data_id = (h + 20); *data_id = i; } @@ -350,6 +341,9 @@ static void init(void) } else { + /* Unmask the standard timers' interrupts */ + SH7305_INTC.MSKCLR->IMR4 = 0x70; + gint_intlevel(36, 7); gint_intlevel(25, 7); gint_intlevel(26, 7);