tmu: fix freeze when using sleep_us_spin() with interrupts on

Because of timing the interrupt handler could run before the flag is
checked.
This commit is contained in:
Lephe 2021-11-15 06:42:11 +01:00
parent 1384c54b5f
commit caf585b0a1
No known key found for this signature in database
GPG key ID: 1BBA026E13FC0495
3 changed files with 14 additions and 6 deletions

View file

@ -162,10 +162,11 @@ void timer_stop(int timer);
it may have only paused. If the timer never stops, you're in trouble. */
void timer_wait(int timer);
/* timer_spinwait(): Actively wait for a timer to raise UNF
/* timer_spinwait(): Start a timer and actively wait for UNF
Waits until the timer raises UNF, without sleeping. This is useful for
delays in driver code that is run when interrupts are disabled. This relies
neither on the interrupt signal nor on the UNIE flag. */
delays in driver code that is run when interrupts are disabled. UNIE is
disabled before starting the timer and waiting, so the callback is never
called. */
void timer_spinwait(int timer);
//---

View file

@ -13,12 +13,14 @@ static void do_sleep(uint64_t delay_us, int spin)
GINT_CALL_SET_STOP(&flag));
if(timer < 0) return;
timer_start(timer);
if(spin) {
timer_spinwait(timer);
timer_stop(timer);
}
else timer_wait(timer);
else {
timer_start(timer);
timer_wait(timer);
}
}
/* sleep_us(): Sleep for a fixed duration in microseconds */

View file

@ -209,6 +209,7 @@ void timer_stop(int id)
if(id < 3)
{
TMU[id].TCR.UNIE = 0;
TMU[id].TCR.UNF = 0;
TMU[id].TCOR = 0xffffffff;
TMU[id].TCNT = 0xffffffff;
}
@ -240,17 +241,21 @@ void timer_wait(int id)
}
}
/* timer_spinwait(): Actively wait for a timer to raise UNF */
/* timer_spinwait(): Start a timer and actively wait for UNF */
void timer_spinwait(int id)
{
if(id < 3)
{
tmu_t *T = &TMU[id];
T->TCR.UNIE = 0;
timer_start(id);
while(!T->TCR.UNF) {}
}
else
{
etmu_t *T = &ETMU[id-3];
set(T->TCR.UNIE, 0);
timer_start(id);
while(!T->TCR.UNF) {}
}
}