summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2008-04-20 17:53:05 +0000
committerJens Arnold <amiconn@rockbox.org>2008-04-20 17:53:05 +0000
commitcea07eb2a4ddb72d084c7085192521613004a997 (patch)
treeadbcaeac857c7fd10fa5f89f7acff0728f75f447 /firmware
parent02bfba6c616a4e4aedf0e36d742598c36334e228 (diff)
downloadrockbox-cea07eb2a4ddb72d084c7085192521613004a997.tar.gz
rockbox-cea07eb2a4ddb72d084c7085192521613004a997.tar.bz2
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
Diffstat (limited to 'firmware')
-rw-r--r--firmware/panic.c5
-rw-r--r--firmware/target/arm/system-target.h54
-rw-r--r--firmware/thread.c40
3 files changed, 66 insertions, 33 deletions
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 */