From cea07eb2a4ddb72d084c7085192521613004a997 Mon Sep 17 00:00:00 2001 From: Jens Arnold Date: Sun, 20 Apr 2008 17:53:05 +0000 Subject: [PATCH] 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 --- apps/main.c | 2 +- firmware/panic.c | 5 +-- firmware/target/arm/system-target.h | 54 +++++++++++++++++++++++++++++ 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) /* This should never be reached */ #endif while(1) { - COP_CTL = PROC_SLEEP; + sleep_core(COP); } } #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, ...) /* try to restart firmware if ON is pressed */ #if defined (CPU_PP) /* For now, just sleep the core */ - if (CURRENT_CORE == CPU) - CPU_CTL = PROC_SLEEP; - else - COP_CTL = PROC_SLEEP; + sleep_core(CURRENT_CORE); #define system_reboot() nop #elif defined (TOSHIBA_GIGABEAT_F) 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) return id; } +#if CONFIG_CPU == PP5002 +static inline void sleep_core(int core) +{ + asm volatile ( + /* 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]] \n" + "streq r0, [%[ctl]] \n" + "nop \n" /* nop's needed because of pipeline */ + "nop \n" + "nop \n" + : + : [ctl]"r"(&PROC_CTL(core)) + : "r0" + ); +} +static inline void wake_core(int core) +{ + asm volatile ( + "mov r0, #0xce \n" + "str r0, [%[ctl]] \n" + : + : [ctl]"r"(&PROC_CTL(core)) + : "r0" + ); +} +#else /* PP502x */ +static inline void sleep_core(int core) +{ + asm volatile ( + "mov r0, #0x80000000 \n" + "str r0, [%[ctl]] \n" + "nop \n" + : + : [ctl]"r"(&PROC_CTL(core)) + : "r0" + ); +} +static inline void wake_core(int core) +{ + asm volatile ( + "mov r0, #0 \n" + "str r0, [%[ctl]] \n" + : + : [ctl]"r"(&PROC_CTL(core)) + : "r0" + ); +} +#endif + #ifdef BOOTLOADER /* All addresses within rockbox are in IRAM in the bootloader so 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) #if NUM_CORES == 1 static inline void core_sleep(void) { - PROC_CTL(CURRENT_CORE) = PROC_SLEEP; - nop; nop; nop; + sleep_core(CURRENT_CORE); enable_irq(); } #else @@ -429,7 +428,7 @@ static inline void core_sleep(unsigned int core) "tst r1, r0, lsr #2 \n" "bne 1b \n" : - : [ctl]"r"(&PROC_CTL(CPU)), [mbx]"r"(MBX_BASE), [c]"r"(core) + : [ctl]"r"(&CPU_CTL), [mbx]"r"(MBX_BASE), [c]"r"(core) : "r0", "r1"); #else /* C version for reference */ /* Signal intent to sleep */ @@ -438,8 +437,8 @@ static inline void core_sleep(unsigned int core) /* Something waking or other processor intends to wake us? */ if ((MBX_MSG_STAT & (0x10 << core)) == 0) { - PROC_CTL(core) = PROC_SLEEP; nop; /* Snooze */ - PROC_CTL(core) = 0; /* Clear control reg */ + sleep_core(core); + wake_core(core); } /* Signal wake - clear wake flag */ @@ -455,22 +454,7 @@ static inline void core_sleep(unsigned int core) #if NUM_CORES == 1 static inline void core_sleep(void) { - asm volatile ( - /* 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]] \n" - "streq r0, [%[ctl]] \n" - "nop \n" /* nop's needed because of pipeline */ - "nop \n" - "nop \n" - : - : [ctl]"r"(&PROC_CTL(CURRENT_CORE)) - : "r0" - ); + sleep_core(CURRENT_CORE); enable_irq(); } #else @@ -505,7 +489,7 @@ static inline void core_sleep(unsigned int core) "bne 1b \n" : : [sem]"r"(&core_semaphores[core]), [c]"r"(core), - [ctl]"r"(&PROC_CTL(CPU)) + [ctl]"r"(&CPU_CTL) : "r0" ); #else /* C version for reference */ @@ -515,8 +499,7 @@ static inline void core_sleep(unsigned int core) /* Something waking or other processor intends to wake us? */ if (core_semaphores[core].stay_awake == 0) { - PROC_CTL(core) = PROC_SLEEP; /* Snooze */ - nop; nop; nop; + sleep_core(core); } /* Signal wake - clear wake flag */ @@ -640,7 +623,7 @@ void core_wake(unsigned int othercore) /* If sleeping, wake it up */ if (PROC_STAT & PROC_SLEEPING(othercore)) - PROC_CTL(othercore) = PROC_WAKE; + wake_core(othercore); /* Done with wake procedure */ core_semaphores[othercore].intend_wake = 0; @@ -747,15 +730,14 @@ static void core_thread_init(unsigned int core) #ifdef CPU_PP502x MBX_MSG_CLR = 0x3f; #endif - COP_CTL = PROC_WAKE; + wake_core(COP); /* Sleep until COP has finished */ - CPU_CTL = PROC_SLEEP; - nop; nop; nop; + sleep_core(CPU); } else { /* Wake the CPU and return */ - CPU_CTL = PROC_WAKE; + wake_core(CPU); } } #endif /* NUM_CORES */