summaryrefslogtreecommitdiff
path: root/firmware/thread.c
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2008-03-07 23:44:46 +0000
committerJens Arnold <amiconn@rockbox.org>2008-03-07 23:44:46 +0000
commitcb57bf863a4bf0aca4d1807da648ff28e0d0daae (patch)
treeb58be97b40d7c2f7a756d6e358e3eae801c62af5 /firmware/thread.c
parent2ccdc48ee943f1506809e94df990873cb937bd1a (diff)
Fix the PP5002 crash bug affecting iPod 1st, 2nd and 3rd Gen. Yet another of those PP5002 quirks...
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16547 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/thread.c')
-rw-r--r--firmware/thread.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/firmware/thread.c b/firmware/thread.c
index b144e97403..d348f7439d 100644
--- a/firmware/thread.c
+++ b/firmware/thread.c
@@ -466,11 +466,19 @@ static inline void core_sleep(unsigned int core)
"strb r0, [%[sem], #2] \n"
"ldrb r0, [%[sem], #1] \n" /* && stay_awake == 0? */
"cmp r0, #0 \n"
- "moveq r0, #0xca \n" /* Then sleep */
- "streqb r0, [%[ctl], %[c], lsl #2] \n"
+ "bne 2f \n"
+ /* Sleep: PP5002 crashes if the instruction that puts it to sleep is
+ * located at 0xNNNNNNN0. 4/8/C works. This sequence makes sure
+ * that the correct alternative is executed. Don't change the order
+ * of the next 4 instructions! */
+ "tst pc, #0x0c \n"
+ "mov r0, #0xca \n"
+ "strne r0, [%[ctl], %[c], lsl #2] \n"
+ "streq r0, [%[ctl], %[c], lsl #2] \n"
"nop \n" /* nop's needed because of pipeline */
"nop \n"
"nop \n"
+ "2: \n"
"mov r0, #0 \n" /* Clear stay_awake and sleep intent */
"strb r0, [%[sem], #1] \n"
"strb r0, [%[sem], #2] \n"
@@ -593,7 +601,7 @@ void core_wake(unsigned int othercore)
"tst r1, r2, lsr %[oc] \n"
"ldrne r2, =0xcf004054 \n" /* If sleeping, wake it */
"movne r1, #0xce \n"
- "strneb r1, [r2, %[oc], lsl #2] \n"
+ "strne r1, [r2, %[oc], lsl #2] \n"
"mov r1, #0 \n" /* Done with wake procedure */
"strb r1, [%[sem], #0] \n"
"msr cpsr_c, r3 \n" /* Restore int status */