rendered paste bodydiff --git a/apps/main.c b/apps/main.c
index fdc5c0f..50c77f7 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -271,6 +271,9 @@ #if defined(CONFIG_CHARGING) && (CONFIG_
/* if nobody initialized ATA before, I consider this a cold start */
bool coldstart = (PACR2 & 0x4000) != 0; /* starting from Flash */
#endif
+#ifdef CPU_PP
+ COP_CTL = PROC_WAKE;
+#endif
system_init();
kernel_init();
@@ -511,9 +514,14 @@ void cop_main(void)
so it should not be assumed that the coprocessor be usable even on
platforms which support it.
- At present all we do is send the COP to sleep if anything wakes it. */
+ A kernel thread runs on the coprocessor, which just waits for other
+ threads to be added */
+
+ system_init();
+ kernel_init();
+
while(1) {
- COP_CTL = PROC_SLEEP;
+ sleep(HZ);
}
}
#endif
diff --git a/apps/playback.c b/apps/playback.c
index 370c7e4..c7200f6 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -173,12 +173,12 @@ #endif
-static struct mutex mutex_codecthread;
-static struct event_queue codec_callback_queue;
+static struct mutex mutex_codecthread IDATA_ATTR;
+static struct event_queue codec_callback_queue IDATA_ATTR;
-static volatile bool audio_codec_loaded;
-static volatile bool playing;
-static volatile bool paused;
+static volatile bool audio_codec_loaded IDATA_ATTR;
+static volatile bool playing IDATA_ATTR;
+static volatile bool paused IDATA_ATTR;
/* Is file buffer currently being refilled? */
static volatile bool filling IDATA_ATTR;
@@ -268,7 +268,7 @@ static void audio_reset_buffer(void);
/* Codec thread */
extern struct codec_api ci;
-static struct event_queue codec_queue;
+static struct event_queue codec_queue IDATA_ATTR;
static long codec_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
IBSS_ATTR;
static const char codec_thread_name[] = "codec";
@@ -280,14 +280,14 @@ #ifdef PLAYBACK_VOICE
extern struct codec_api ci_voice;
static volatile bool voice_thread_start;
-static volatile bool voice_is_playing;
-static volatile bool voice_codec_loaded;
+static volatile bool voice_is_playing IDATA_ATTR;
+static volatile bool voice_codec_loaded IDATA_ATTR;
static void (*voice_getmore)(unsigned char** start, int* size);
static char *voicebuf;
static size_t voice_remaining;
static struct thread_entry *voice_thread_p = NULL;
-static struct event_queue voice_queue;
+static struct event_queue voice_queue IDATA_ATTR;
static long voice_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
IBSS_ATTR;
static const char voice_thread_name[] = "voice codec";
diff --git a/firmware/export/config.h b/firmware/export/config.h
index 091de05..e5d681c 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -234,14 +234,8 @@ #if (CONFIG_CPU == PP5002) || (CONFIG_CP
#define CPU_PP
/* PP family has dual cores */
-#if 0
-/* Keep it as single core until dual core support is ready */
#define NUM_CORES 2
#define CURRENT_CORE current_core()
-#endif
-
-#define NUM_CORES 1
-#define CURRENT_CORE 0
#else
#define NUM_CORES 1
#define CURRENT_CORE 0
diff --git a/firmware/export/pp5002.h b/firmware/export/pp5002.h
index 59056e1..998ab73 100644
--- a/firmware/export/pp5002.h
+++ b/firmware/export/pp5002.h
@@ -62,6 +62,9 @@ #define DEV_EN (*(volatile unsigned long
#define CPU_INT_STAT (*(volatile unsigned long*)(0xcf001000))
#define CPU_INT_EN (*(volatile unsigned long*)(0xcf001024))
#define CPU_INT_CLR (*(volatile unsigned long*)(0xcf001028))
+#define COP_INT_STAT (*(volatile unsigned long*)(0xcf001010)) /* A guess */
+#define COP_INT_EN (*(volatile unsigned long*)(0xcf001034))
+#define COP_INT_CLR (*(volatile unsigned long*)(0xcf001038))
#define USB2D_IDENT (*(volatile unsigned long*)(0xc5000000))
#define USB_STATUS (*(volatile unsigned long*)(0xc50001a4))
diff --git a/firmware/export/pp5020.h b/firmware/export/pp5020.h
index be997e9..8bc9f3d 100644
--- a/firmware/export/pp5020.h
+++ b/firmware/export/pp5020.h
@@ -139,6 +139,12 @@ #define CPU_INT_EN (*(volatile uns
#define CPU_HI_INT_EN (*(volatile unsigned long*)(0x60004124))
#define CPU_INT_CLR (*(volatile unsigned long*)(0x60004028))
#define CPU_HI_INT_CLR (*(volatile unsigned long*)(0x60004128))
+#define COP_INT_STAT (*(volatile unsigned long*)(0x60004004)) /* Guessed */
+#define COP_HI_INT_STAT (*(volatile unsigned long*)(0x60004104)) /* From IPL*/
+#define COP_INT_EN (*(volatile unsigned long*)(0x60004034)) /* Guessed */
+#define COP_HI_INT_EN (*(volatile unsigned long*)(0x60004134)) /* From IPL*/
+#define COP_INT_CLR (*(volatile unsigned long*)(0x60004038)) /* Guessed */
+#define COP_HI_INT_CLR (*(volatile unsigned long*)(0x60004138)) /* From IPL*/
#define TIMER1_IRQ 0
#define TIMER2_IRQ 1
diff --git a/firmware/kernel.c b/firmware/kernel.c
index 6415f71..395339e 100644
--- a/firmware/kernel.c
+++ b/firmware/kernel.c
@@ -45,10 +45,13 @@ void kernel_init(void)
/* Init the threading API */
init_threads();
- memset(tick_funcs, 0, sizeof(tick_funcs));
+ if(CURRENT_CORE == CPU)
+ {
+ memset(tick_funcs, 0, sizeof(tick_funcs));
- num_queues = 0;
- memset(all_queues, 0, sizeof(all_queues));
+ num_queues = 0;
+ memset(all_queues, 0, sizeof(all_queues));
+ }
tick_start(1000/HZ);
}
@@ -366,28 +369,36 @@ void TIMER1(void)
int i;
TIMER1_VAL; /* Read value to ack IRQ */
- /* Run through the list of tick tasks */
- for (i = 0;i < MAX_NUM_TICK_TASKS;i++)
+ /* Run through the list of tick tasks (using main core) */
+ if (CURRENT_CORE == CPU)
{
- if (tick_funcs[i])
+ for (i = 0;i < MAX_NUM_TICK_TASKS;i++)
{
- tick_funcs[i]();
+ if (tick_funcs[i])
+ {
+ tick_funcs[i]();
+ }
}
- }
- current_tick++;
+ current_tick++;
+ }
}
#endif
void tick_start(unsigned int interval_in_ms)
{
#ifndef BOOTLOADER
- TIMER1_CFG = 0x0;
- TIMER1_VAL;
- /* enable timer */
- TIMER1_CFG = 0xc0000000 | (interval_in_ms*1000 - 1);
- /* unmask interrupt source */
- CPU_INT_EN = TIMER1_MASK;
+ if(CURRENT_CORE == CPU)
+ {
+ TIMER1_CFG = 0x0;
+ TIMER1_VAL;
+ /* enable timer */
+ TIMER1_CFG = 0xc0000000 | (interval_in_ms*1000 - 1);
+ /* unmask interrupt source */
+ CPU_INT_EN = TIMER1_MASK;
+ } else {
+ COP_INT_EN = TIMER1_MASK;
+ }
#else
/* We don't enable interrupts in the bootloader */
(void)interval_in_ms;
@@ -508,6 +519,29 @@ void mutex_init(struct mutex *m)
m->thread = NULL;
}
+#ifdef CPU_PP
+/* PortalPlayer chips have 2 cores, therefore need atomic mutexes */
+
+static inline bool test_and_set(bool *x, bool v)
+{
+ asm volatile (
+ "swpb %0, %0, [%1]\n"
+ : "+r"(v)
+ : "r"(x)
+ );
+ return v;
+}
+
+void mutex_lock(struct mutex *m)
+{
+ if (test_and_set(&m->locked,true))
+ {
+ /* Wait until the lock is open... */
+ block_thread(&m->thread, 0);
+ }
+}
+
+#else
void mutex_lock(struct mutex *m)
{
if (m->locked)
@@ -519,6 +553,7 @@ void mutex_lock(struct mutex *m)
/* ...and lock it */
m->locked = true;
}
+#endif
void mutex_unlock(struct mutex *m)
{
diff --git a/firmware/system.c b/firmware/system.c
index 6ba5dc6..0197a5e 100644
--- a/firmware/system.c
+++ b/firmware/system.c
@@ -1223,34 +1223,62 @@ extern void ipod_mini_button_int(void);
void irq(void)
{
- if (CPU_INT_STAT & TIMER1_MASK)
- TIMER1();
- else if (CPU_INT_STAT & TIMER2_MASK)
- TIMER2();
- else if (CPU_HI_INT_STAT & GPIO_MASK)
- ipod_mini_button_int();
+ if(CURRENT_CORE == CPU)
+ {
+ if (CPU_INT_STAT & TIMER1_MASK)
+ TIMER1();
+ else if (CPU_INT_STAT & TIMER2_MASK)
+ TIMER2();
+ else if (CPU_HI_INT_STAT & GPIO_MASK)
+ ipod_mini_button_int();
+ } else {
+ if (COP_INT_STAT & TIMER1_MASK)
+ TIMER1();
+ else if (COP_INT_STAT & TIMER2_MASK)
+ TIMER2();
+ else if (COP_HI_INT_STAT & GPIO_MASK)
+ ipod_mini_button_int();
+ }
}
#elif (defined IRIVER_H10) || (defined IRIVER_H10_5GB) || defined(ELIO_TPJ1022)
/* TODO: this should really be in the target tree, but moving it there caused
crt0.S not to find it while linking */
void irq(void)
{
- if (CPU_INT_STAT & TIMER1_MASK)
- TIMER1();
- else if (CPU_INT_STAT & TIMER2_MASK)
- TIMER2();
+ if(CURRENT_CORE == CPU)
+ {
+ if (CPU_INT_STAT & TIMER1_MASK)
+ TIMER1();
+ else if (CPU_INT_STAT & TIMER2_MASK)
+ TIMER2();
+ } else {
+ if (COP_INT_STAT & TIMER1_MASK)
+ TIMER1();
+ else if (COP_INT_STAT & TIMER2_MASK)
+ TIMER2();
+ }
}
#else
extern void ipod_4g_button_int(void);
void irq(void)
{
- if (CPU_INT_STAT & TIMER1_MASK)
- TIMER1();
- else if (CPU_INT_STAT & TIMER2_MASK)
- TIMER2();
- else if (CPU_HI_INT_STAT & I2C_MASK)
- ipod_4g_button_int();
+ if(CURRENT_CORE == CPU)
+ {
+ if (CPU_INT_STAT & TIMER1_MASK)
+ TIMER1();
+ else if (CPU_INT_STAT & TIMER2_MASK)
+ TIMER2();
+ else if (CPU_HI_INT_STAT & I2C_MASK)
+ ipod_4g_button_int();
+ } else {
+ if (COP_INT_STAT & TIMER1_MASK)
+ TIMER1();
+ else if (COP_INT_STAT & TIMER2_MASK)
+ TIMER2();
+ else if (COP_HI_INT_STAT & I2C_MASK)
+ ipod_4g_button_int();
+ }
}
#endif
#endif /* BOOTLOADER */
@@ -1303,43 +1331,47 @@ void set_cpu_frequency(long frequency)
{
unsigned long postmult;
- if (frequency == CPUFREQ_NORMAL)
- postmult = CPUFREQ_NORMAL_MULT;
- else if (frequency == CPUFREQ_MAX)
- postmult = CPUFREQ_MAX_MULT;
- else
- postmult = CPUFREQ_DEFAULT_MULT;
- cpu_frequency = frequency;
+ if (CURRENT_CORE == CPU)
+ {
+ if (frequency == CPUFREQ_NORMAL)
+ postmult = CPUFREQ_NORMAL_MULT;
+ else if (frequency == CPUFREQ_MAX)
+ postmult = CPUFREQ_MAX_MULT;
+ else
+ postmult = CPUFREQ_DEFAULT_MULT;
+ cpu_frequency = frequency;
- /* Enable PLL? */
- outl(inl(0x70000020) | (1<<30), 0x70000020);
+ /* Enable PLL? */
+ outl(inl(0x70000020) | (1<<30), 0x70000020);
- /* Select 24MHz crystal as clock source? */
- outl((inl(0x60006020) & 0x0fffff0f) | 0x20000020, 0x60006020);
+ /* Select 24MHz crystal as clock source? */
+ outl((inl(0x60006020) & 0x0fffff0f) | 0x20000020, 0x60006020);
- /* Clock frequency = (24/8)*postmult */
- outl(0xaa020000 | 8 | (postmult << 8), 0x60006034);
+ /* Clock frequency = (24/8)*postmult */
+ outl(0xaa020000 | 8 | (postmult << 8), 0x60006034);
- /* Wait for PLL relock? */
- udelay(2000);
+ /* Wait for PLL relock? */
+ udelay(2000);
- /* Select PLL as clock source? */
- outl((inl(0x60006020) & 0x0fffff0f) | 0x20000070, 0x60006020);
+ /* Select PLL as clock source? */
+ outl((inl(0x60006020) & 0x0fffff0f) | 0x20000070, 0x60006020);
#if defined(IPOD_COLOR) || defined(IPOD_4G) || defined(IPOD_MINI) || defined(IRIVER_H10) || defined(IRIVER_H10_5GB)
- /* We don't know why the timer interrupt gets disabled on the PP5020
- based ipods, but without the following line, the 4Gs will freeze
- when CPU frequency changing is enabled.
+ /* We don't know why the timer interrupt gets disabled on the PP5020
+ based ipods, but without the following line, the 4Gs will freeze
+ when CPU frequency changing is enabled.
- Note also that a simple "CPU_INT_EN = TIMER1_MASK;" (as used
- elsewhere to enable interrupts) doesn't work, we need "|=".
+ Note also that a simple "CPU_INT_EN = TIMER1_MASK;" (as used
+ elsewhere to enable interrupts) doesn't work, we need "|=".
- It's not needed on the PP5021 and PP5022 ipods.
- */
+ It's not needed on the PP5021 and PP5022 ipods.
+ */
- /* unmask interrupt source */
- CPU_INT_EN |= TIMER1_MASK;
+ /* unmask interrupt source */
+ CPU_INT_EN |= TIMER1_MASK;
+ COP_INT_EN |= TIMER1_MASK;
#endif
+ }
}
#elif !defined(BOOTLOADER)
void ipod_set_cpu_frequency(void)
@@ -1363,21 +1395,24 @@ #endif
void system_init(void)
{
#ifndef BOOTLOADER
- /* The hw revision is written to the last 4 bytes of SDRAM by the
- bootloader - we save it before Rockbox overwrites it. */
- ipod_hw_rev = (*((volatile unsigned long*)(0x01fffffc)));
-
- /* disable all irqs */
- outl(-1, 0x60001138);
- outl(-1, 0x60001128);
- outl(-1, 0x6000111c);
-
- outl(-1, 0x60001038);
- outl(-1, 0x60001028);
- outl(-1, 0x6000101c);
+ if (CURRENT_CORE == CPU)
+ {
+ /* The hw revision is written to the last 4 bytes of SDRAM by the
+ bootloader - we save it before Rockbox overwrites it. */
+ ipod_hw_rev = (*((volatile unsigned long*)(0x01fffffc)));
+
+ /* disable all irqs */
+ outl(-1, 0x60001138);
+ outl(-1, 0x60001128);
+ outl(-1, 0x6000111c);
+
+ outl(-1, 0x60001038);
+ outl(-1, 0x60001028);
+ outl(-1, 0x6000101c);
#ifndef HAVE_ADJUSTABLE_CPU_FREQ
- ipod_set_cpu_frequency();
+ ipod_set_cpu_frequency();
#endif
+ }
ipod_init_cache();
#endif
}
@@ -1401,10 +1436,18 @@ extern void TIMER2(void);
void irq(void)
{
- if (CPU_INT_STAT & TIMER1_MASK)
- TIMER1();
- else if (CPU_INT_STAT & TIMER2_MASK)
- TIMER2();
+ if(CURRENT_CORE == CPU)
+ {
+ if (CPU_INT_STAT & TIMER1_MASK)
+ TIMER1();
+ else if (CPU_INT_STAT & TIMER2_MASK)
+ TIMER2();
+ } else {
+ if (COP_INT_STAT & TIMER1_MASK)
+ TIMER1();
+ else if (COP_INT_STAT & TIMER2_MASK)
+ TIMER2();
+ }
}
#endif
@@ -1453,29 +1496,32 @@ void set_cpu_frequency(long frequency)
{
unsigned long postmult;
- if (frequency == CPUFREQ_NORMAL)
- postmult = CPUFREQ_NORMAL_MULT;
- else if (frequency == CPUFREQ_MAX)
- postmult = CPUFREQ_MAX_MULT;
- else
- postmult = CPUFREQ_DEFAULT_MULT;
- cpu_frequency = frequency;
+ if (CURRENT_CORE == CPU)
+ {
+ if (frequency == CPUFREQ_NORMAL)
+ postmult = CPUFREQ_NORMAL_MULT;
+ else if (frequency == CPUFREQ_MAX)
+ postmult = CPUFREQ_MAX_MULT;
+ else
+ postmult = CPUFREQ_DEFAULT_MULT;
+ cpu_frequency = frequency;
- outl(0x02, 0xcf005008);
- outl(0x55, 0xcf00500c);
- outl(0x6000, 0xcf005010);
+ outl(0x02, 0xcf005008);
+ outl(0x55, 0xcf00500c);
+ outl(0x6000, 0xcf005010);
- /* Clock frequency = (24/8)*postmult */
- outl(8, 0xcf005018);
- outl(postmult, 0xcf00501c);
+ /* Clock frequency = (24/8)*postmult */
+ outl(8, 0xcf005018);
+ outl(postmult, 0xcf00501c);
- outl(0xe000, 0xcf005010);
+ outl(0xe000, 0xcf005010);
- /* Wait for PLL relock? */
- udelay(2000);
+ /* Wait for PLL relock? */
+ udelay(2000);
- /* Select PLL as clock source? */
- outl(0xa8, 0xcf00500c);
+ /* Select PLL as clock source? */
+ outl(0xa8, 0xcf00500c);
+ }
}
#elif !defined(BOOTLOADER)
static void ipod_set_cpu_speed(void)
@@ -1506,13 +1552,16 @@ #endif
void system_init(void)
{
#ifndef BOOTLOADER
- ipod_hw_rev = (*((volatile unsigned long*)(0x01fffffc)));
- outl(-1, 0xcf00101c);
- outl(-1, 0xcf001028);
- outl(-1, 0xcf001038);
+ if (CURRENT_CORE == CPU)
+ {
+ ipod_hw_rev = (*((volatile unsigned long*)(0x01fffffc)));
+ outl(-1, 0xcf00101c);
+ outl(-1, 0xcf001028);
+ outl(-1, 0xcf001038);
#ifndef HAVE_ADJUSTABLE_CPU_FREQ
- ipod_set_cpu_speed();
+ ipod_set_cpu_speed();
#endif
+ }
ipod_init_cache();
#endif
}
diff --git a/firmware/target/arm/crt0-pp.S b/firmware/target/arm/crt0-pp.S
index 3bf2805..7badc69 100644
--- a/firmware/target/arm/crt0-pp.S
+++ b/firmware/target/arm/crt0-pp.S
@@ -285,6 +285,19 @@ cop_init:
strhi r4, [r2], #4
bhi 2b
+ /* Set up stack for IRQ mode */
+ msr cpsr_c, #0xd2
+ ldr sp, =cop_irq_stack
+ /* Set up stack for FIQ mode */
+ msr cpsr_c, #0xd1
+ ldr sp, =fiq_stack
+
+ /* Let abort and undefined modes use IRQ stack */
+ msr cpsr_c, #0xd7
+ ldr sp, =cop_irq_stack
+ msr cpsr_c, #0xdb
+ ldr sp, =cop_irq_stack
+
ldr sp, =cop_stackend
bl cop_main
@@ -368,6 +381,10 @@ #endif
.space 256*4
irq_stack:
+/* 256 words of COP IRQ stack */
+ .space 256*4
+cop_irq_stack:
+
/* 256 words of FIQ stack */
.space 256*4
fiq_stack:
diff --git a/firmware/thread.c b/firmware/thread.c
index 1662740..4eada84 100644
--- a/firmware/thread.c
+++ b/firmware/thread.c
@@ -338,10 +338,13 @@ #ifdef CPU_COLDFIRE
#elif CONFIG_CPU == SH7034
and_b(0x7F, &SBYCR);
asm volatile ("sleep");
-#elif CONFIG_CPU == PP5020
+#elif defined (CPU_PP)
/* This should sleep the CPU. It appears to wake by itself on
interrupts */
- CPU_CTL = 0x80000000;
+ if (CURRENT_CORE == CPU)
+ CPU_CTL = PROC_SLEEP;
+ else
+ COP_CTL = PROC_SLEEP;
#elif CONFIG_CPU == TCC730
/* Sleep mode is triggered by the SYS instr on CalmRisc16.
* Unfortunately, the manual doesn't specify which arg to use.
@@ -690,7 +693,8 @@ void init_threads(void)
{
unsigned int core = CURRENT_CORE;
- memset(cores, 0, sizeof cores);
+ if (core == CPU)
+ memset(cores, 0, sizeof cores);
cores[core].sleeping = NULL;
cores[core].running = NULL;
cores[core].threads[0].name = main_thread_name;