summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomasz Moń <desowin@gmail.com>2011-12-21 14:56:22 +0000
committerTomasz Moń <desowin@gmail.com>2011-12-21 14:56:22 +0000
commit37f4dfc2597e98c7aa4922c1b32b2337c18a2ca6 (patch)
treede78aa8912cd8dcf90c9cb76bfa8db452c0f9270
parent3aced71e541d66b3f7051294ea58a93ec5a22d3f (diff)
downloadrockbox-37f4dfc2597e98c7aa4922c1b32b2337c18a2ca6.tar.gz
rockbox-37f4dfc2597e98c7aa4922c1b32b2337c18a2ca6.zip
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
-rw-r--r--firmware/target/arm/tms320dm320/system-dm320.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/firmware/target/arm/tms320dm320/system-dm320.c b/firmware/target/arm/tms320dm320/system-dm320.c
index 5d7872f2bc..741516a950 100644
--- a/firmware/target/arm/tms320dm320/system-dm320.c
+++ b/firmware/target/arm/tms320dm320/system-dm320.c
@@ -412,6 +412,9 @@ void set_cpu_frequency(long frequency)
412} 412}
413#endif 413#endif
414 414
415/*
416 * Waits for specified amount of microseconds
417 */
415void udelay(int usec) { 418void udelay(int usec) {
416 unsigned short count = IO_TIMER1_TMCNT; 419 unsigned short count = IO_TIMER1_TMCNT;
417 unsigned short stop; 420 unsigned short stop;
@@ -432,16 +435,28 @@ void udelay(int usec) {
432 stop -= tmp; 435 stop -= tmp;
433 } 436 }
434 437
438 /*
439 * Status in IO_INTC_IRQ0 is changed even when interrupts are
440 * masked. If IRQ_TIMER1 bit in IO_INTC_IRQ0 is set to 0, then
441 * there is pending current_tick update.
442 *
443 * Relaying solely on current_tick value when interrupts are disabled
444 * can lead to lockup.
445 * Interrupt status bit check below is used to prevent this lockup.
446 */
447
435 if (stop < count) 448 if (stop < count)
436 { 449 {
437 /* udelay will end after counter reset (tick) */ 450 /* udelay will end after counter reset (tick) */
438 while ((IO_TIMER1_TMCNT < stop) || 451 while ((IO_TIMER1_TMCNT < stop) ||
439 (current_tick == prev_tick)); /* ensure new tick */ 452 ((current_tick == prev_tick) /* ensure new tick */ &&
453 (IO_INTC_IRQ0 & IRQ_TIMER1))); /* prevent lock */
440 } 454 }
441 else 455 else
442 { 456 {
443 /* udelay will end before counter reset (tick) */ 457 /* udelay will end before counter reset (tick) */
444 while ((IO_TIMER1_TMCNT < stop) && (current_tick == prev_tick)); 458 while ((IO_TIMER1_TMCNT < stop) &&
459 ((current_tick == prev_tick) && (IO_INTC_IRQ0 & IRQ_TIMER1)));
445 } 460 }
446} 461}
447 462