diff options
author | Jens Arnold <amiconn@rockbox.org> | 2008-04-20 17:53:05 +0000 |
---|---|---|
committer | Jens Arnold <amiconn@rockbox.org> | 2008-04-20 17:53:05 +0000 |
commit | cea07eb2a4ddb72d084c7085192521613004a997 (patch) | |
tree | adbcaeac857c7fd10fa5f89f7acff0728f75f447 | |
parent | 02bfba6c616a4e4aedf0e36d742598c36334e228 (diff) | |
download | rockbox-cea07eb2a4ddb72d084c7085192521613004a997.tar.gz rockbox-cea07eb2a4ddb72d084c7085192521613004a997.zip |
Fix freezing of some builds on PP5002. The PP5002 needs the not-sleep-at 0xNNNNNNN0-addresses fix everywhere when caching is enabled, not only in core_sleep(). Introduced a pair of inline functions to sleep and wake cores on PP for consistency.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17192 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/main.c | 2 | ||||
-rw-r--r-- | firmware/panic.c | 5 | ||||
-rw-r--r-- | firmware/target/arm/system-target.h | 54 | ||||
-rw-r--r-- | firmware/thread.c | 40 |
4 files changed, 67 insertions, 34 deletions
diff --git a/apps/main.c b/apps/main.c index 47af3ab07a..8b1e2e4556 100644 --- a/apps/main.c +++ b/apps/main.c | |||
@@ -604,7 +604,7 @@ void cop_main(void) | |||
604 | /* This should never be reached */ | 604 | /* This should never be reached */ |
605 | #endif | 605 | #endif |
606 | while(1) { | 606 | while(1) { |
607 | COP_CTL = PROC_SLEEP; | 607 | sleep_core(COP); |
608 | } | 608 | } |
609 | } | 609 | } |
610 | #endif /* CPU_PP */ | 610 | #endif /* CPU_PP */ |
diff --git a/firmware/panic.c b/firmware/panic.c index 0ac458953b..c61476c423 100644 --- a/firmware/panic.c +++ b/firmware/panic.c | |||
@@ -101,10 +101,7 @@ void panicf( const char *fmt, ...) | |||
101 | /* try to restart firmware if ON is pressed */ | 101 | /* try to restart firmware if ON is pressed */ |
102 | #if defined (CPU_PP) | 102 | #if defined (CPU_PP) |
103 | /* For now, just sleep the core */ | 103 | /* For now, just sleep the core */ |
104 | if (CURRENT_CORE == CPU) | 104 | sleep_core(CURRENT_CORE); |
105 | CPU_CTL = PROC_SLEEP; | ||
106 | else | ||
107 | COP_CTL = PROC_SLEEP; | ||
108 | #define system_reboot() nop | 105 | #define system_reboot() nop |
109 | #elif defined (TOSHIBA_GIGABEAT_F) | 106 | #elif defined (TOSHIBA_GIGABEAT_F) |
110 | if ((GPGDAT & (1 << 0)) != 0) | 107 | if ((GPGDAT & (1 << 0)) != 0) |
diff --git a/firmware/target/arm/system-target.h b/firmware/target/arm/system-target.h index 2a72b524f7..ebfc162cf1 100644 --- a/firmware/target/arm/system-target.h +++ b/firmware/target/arm/system-target.h | |||
@@ -88,6 +88,60 @@ static inline unsigned int processor_id(void) | |||
88 | return id; | 88 | return id; |
89 | } | 89 | } |
90 | 90 | ||
91 | #if CONFIG_CPU == PP5002 | ||
92 | static inline void sleep_core(int core) | ||
93 | { | ||
94 | asm volatile ( | ||
95 | /* Sleep: PP5002 crashes if the instruction that puts it to sleep is | ||
96 | * located at 0xNNNNNNN0. 4/8/C works. This sequence makes sure | ||
97 | * that the correct alternative is executed. Don't change the order | ||
98 | * of the next 4 instructions! */ | ||
99 | "tst pc, #0x0c \n" | ||
100 | "mov r0, #0xca \n" | ||
101 | "strne r0, [%[ctl]] \n" | ||
102 | "streq r0, [%[ctl]] \n" | ||
103 | "nop \n" /* nop's needed because of pipeline */ | ||
104 | "nop \n" | ||
105 | "nop \n" | ||
106 | : | ||
107 | : [ctl]"r"(&PROC_CTL(core)) | ||
108 | : "r0" | ||
109 | ); | ||
110 | } | ||
111 | static inline void wake_core(int core) | ||
112 | { | ||
113 | asm volatile ( | ||
114 | "mov r0, #0xce \n" | ||
115 | "str r0, [%[ctl]] \n" | ||
116 | : | ||
117 | : [ctl]"r"(&PROC_CTL(core)) | ||
118 | : "r0" | ||
119 | ); | ||
120 | } | ||
121 | #else /* PP502x */ | ||
122 | static inline void sleep_core(int core) | ||
123 | { | ||
124 | asm volatile ( | ||
125 | "mov r0, #0x80000000 \n" | ||
126 | "str r0, [%[ctl]] \n" | ||
127 | "nop \n" | ||
128 | : | ||
129 | : [ctl]"r"(&PROC_CTL(core)) | ||
130 | : "r0" | ||
131 | ); | ||
132 | } | ||
133 | static inline void wake_core(int core) | ||
134 | { | ||
135 | asm volatile ( | ||
136 | "mov r0, #0 \n" | ||
137 | "str r0, [%[ctl]] \n" | ||
138 | : | ||
139 | : [ctl]"r"(&PROC_CTL(core)) | ||
140 | : "r0" | ||
141 | ); | ||
142 | } | ||
143 | #endif | ||
144 | |||
91 | #ifdef BOOTLOADER | 145 | #ifdef BOOTLOADER |
92 | /* All addresses within rockbox are in IRAM in the bootloader so | 146 | /* All addresses within rockbox are in IRAM in the bootloader so |
93 | are therefore uncached */ | 147 | are therefore uncached */ |
diff --git a/firmware/thread.c b/firmware/thread.c index a25a191b80..7ece27f4a6 100644 --- a/firmware/thread.c +++ b/firmware/thread.c | |||
@@ -404,8 +404,7 @@ void corelock_unlock(struct corelock *cl) | |||
404 | #if NUM_CORES == 1 | 404 | #if NUM_CORES == 1 |
405 | static inline void core_sleep(void) | 405 | static inline void core_sleep(void) |
406 | { | 406 | { |
407 | PROC_CTL(CURRENT_CORE) = PROC_SLEEP; | 407 | sleep_core(CURRENT_CORE); |
408 | nop; nop; nop; | ||
409 | enable_irq(); | 408 | enable_irq(); |
410 | } | 409 | } |
411 | #else | 410 | #else |
@@ -429,7 +428,7 @@ static inline void core_sleep(unsigned int core) | |||
429 | "tst r1, r0, lsr #2 \n" | 428 | "tst r1, r0, lsr #2 \n" |
430 | "bne 1b \n" | 429 | "bne 1b \n" |
431 | : | 430 | : |
432 | : [ctl]"r"(&PROC_CTL(CPU)), [mbx]"r"(MBX_BASE), [c]"r"(core) | 431 | : [ctl]"r"(&CPU_CTL), [mbx]"r"(MBX_BASE), [c]"r"(core) |
433 | : "r0", "r1"); | 432 | : "r0", "r1"); |
434 | #else /* C version for reference */ | 433 | #else /* C version for reference */ |
435 | /* Signal intent to sleep */ | 434 | /* Signal intent to sleep */ |
@@ -438,8 +437,8 @@ static inline void core_sleep(unsigned int core) | |||
438 | /* Something waking or other processor intends to wake us? */ | 437 | /* Something waking or other processor intends to wake us? */ |
439 | if ((MBX_MSG_STAT & (0x10 << core)) == 0) | 438 | if ((MBX_MSG_STAT & (0x10 << core)) == 0) |
440 | { | 439 | { |
441 | PROC_CTL(core) = PROC_SLEEP; nop; /* Snooze */ | 440 | sleep_core(core); |
442 | PROC_CTL(core) = 0; /* Clear control reg */ | 441 | wake_core(core); |
443 | } | 442 | } |
444 | 443 | ||
445 | /* Signal wake - clear wake flag */ | 444 | /* Signal wake - clear wake flag */ |
@@ -455,22 +454,7 @@ static inline void core_sleep(unsigned int core) | |||
455 | #if NUM_CORES == 1 | 454 | #if NUM_CORES == 1 |
456 | static inline void core_sleep(void) | 455 | static inline void core_sleep(void) |
457 | { | 456 | { |
458 | asm volatile ( | 457 | sleep_core(CURRENT_CORE); |
459 | /* Sleep: PP5002 crashes if the instruction that puts it to sleep is | ||
460 | * located at 0xNNNNNNN0. 4/8/C works. This sequence makes sure | ||
461 | * that the correct alternative is executed. Don't change the order | ||
462 | * of the next 4 instructions! */ | ||
463 | "tst pc, #0x0c \n" | ||
464 | "mov r0, #0xca \n" | ||
465 | "strne r0, [%[ctl]] \n" | ||
466 | "streq r0, [%[ctl]] \n" | ||
467 | "nop \n" /* nop's needed because of pipeline */ | ||
468 | "nop \n" | ||
469 | "nop \n" | ||
470 | : | ||
471 | : [ctl]"r"(&PROC_CTL(CURRENT_CORE)) | ||
472 | : "r0" | ||
473 | ); | ||
474 | enable_irq(); | 458 | enable_irq(); |
475 | } | 459 | } |
476 | #else | 460 | #else |
@@ -505,7 +489,7 @@ static inline void core_sleep(unsigned int core) | |||
505 | "bne 1b \n" | 489 | "bne 1b \n" |
506 | : | 490 | : |
507 | : [sem]"r"(&core_semaphores[core]), [c]"r"(core), | 491 | : [sem]"r"(&core_semaphores[core]), [c]"r"(core), |
508 | [ctl]"r"(&PROC_CTL(CPU)) | 492 | [ctl]"r"(&CPU_CTL) |
509 | : "r0" | 493 | : "r0" |
510 | ); | 494 | ); |
511 | #else /* C version for reference */ | 495 | #else /* C version for reference */ |
@@ -515,8 +499,7 @@ static inline void core_sleep(unsigned int core) | |||
515 | /* Something waking or other processor intends to wake us? */ | 499 | /* Something waking or other processor intends to wake us? */ |
516 | if (core_semaphores[core].stay_awake == 0) | 500 | if (core_semaphores[core].stay_awake == 0) |
517 | { | 501 | { |
518 | PROC_CTL(core) = PROC_SLEEP; /* Snooze */ | 502 | sleep_core(core); |
519 | nop; nop; nop; | ||
520 | } | 503 | } |
521 | 504 | ||
522 | /* Signal wake - clear wake flag */ | 505 | /* Signal wake - clear wake flag */ |
@@ -640,7 +623,7 @@ void core_wake(unsigned int othercore) | |||
640 | 623 | ||
641 | /* If sleeping, wake it up */ | 624 | /* If sleeping, wake it up */ |
642 | if (PROC_STAT & PROC_SLEEPING(othercore)) | 625 | if (PROC_STAT & PROC_SLEEPING(othercore)) |
643 | PROC_CTL(othercore) = PROC_WAKE; | 626 | wake_core(othercore); |
644 | 627 | ||
645 | /* Done with wake procedure */ | 628 | /* Done with wake procedure */ |
646 | core_semaphores[othercore].intend_wake = 0; | 629 | core_semaphores[othercore].intend_wake = 0; |
@@ -747,15 +730,14 @@ static void core_thread_init(unsigned int core) | |||
747 | #ifdef CPU_PP502x | 730 | #ifdef CPU_PP502x |
748 | MBX_MSG_CLR = 0x3f; | 731 | MBX_MSG_CLR = 0x3f; |
749 | #endif | 732 | #endif |
750 | COP_CTL = PROC_WAKE; | 733 | wake_core(COP); |
751 | /* Sleep until COP has finished */ | 734 | /* Sleep until COP has finished */ |
752 | CPU_CTL = PROC_SLEEP; | 735 | sleep_core(CPU); |
753 | nop; nop; nop; | ||
754 | } | 736 | } |
755 | else | 737 | else |
756 | { | 738 | { |
757 | /* Wake the CPU and return */ | 739 | /* Wake the CPU and return */ |
758 | CPU_CTL = PROC_WAKE; | 740 | wake_core(CPU); |
759 | } | 741 | } |
760 | } | 742 | } |
761 | #endif /* NUM_CORES */ | 743 | #endif /* NUM_CORES */ |