1
0
Fork 0
forked from len0rd/rockbox

TMS320DM320: Prevent lockup in udelay() when this function is called with interrupts disabled.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31392 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Tomasz Moń 2011-12-21 14:56:22 +00:00
parent 3aced71e54
commit 37f4dfc259

View file

@ -412,6 +412,9 @@ void set_cpu_frequency(long frequency)
} }
#endif #endif
/*
* Waits for specified amount of microseconds
*/
void udelay(int usec) { void udelay(int usec) {
unsigned short count = IO_TIMER1_TMCNT; unsigned short count = IO_TIMER1_TMCNT;
unsigned short stop; unsigned short stop;
@ -432,16 +435,28 @@ void udelay(int usec) {
stop -= tmp; stop -= tmp;
} }
/*
* Status in IO_INTC_IRQ0 is changed even when interrupts are
* masked. If IRQ_TIMER1 bit in IO_INTC_IRQ0 is set to 0, then
* there is pending current_tick update.
*
* Relaying solely on current_tick value when interrupts are disabled
* can lead to lockup.
* Interrupt status bit check below is used to prevent this lockup.
*/
if (stop < count) if (stop < count)
{ {
/* udelay will end after counter reset (tick) */ /* udelay will end after counter reset (tick) */
while ((IO_TIMER1_TMCNT < stop) || while ((IO_TIMER1_TMCNT < stop) ||
(current_tick == prev_tick)); /* ensure new tick */ ((current_tick == prev_tick) /* ensure new tick */ &&
(IO_INTC_IRQ0 & IRQ_TIMER1))); /* prevent lock */
} }
else else
{ {
/* udelay will end before counter reset (tick) */ /* udelay will end before counter reset (tick) */
while ((IO_TIMER1_TMCNT < stop) && (current_tick == prev_tick)); while ((IO_TIMER1_TMCNT < stop) &&
((current_tick == prev_tick) && (IO_INTC_IRQ0 & IRQ_TIMER1)));
} }
} }