summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/codecs.c2
-rw-r--r--apps/codecs.h5
-rw-r--r--apps/main.c14
-rw-r--r--apps/playback.c24
-rw-r--r--apps/playlist.c3
-rw-r--r--apps/plugin.c1
-rw-r--r--apps/plugin.h8
-rw-r--r--apps/plugins/alpine_cdc.c3
-rw-r--r--apps/plugins/battery_bench.c3
-rw-r--r--apps/plugins/mpegplayer/mpegplayer.c10
-rw-r--r--apps/tagcache.c3
-rw-r--r--docs/PLUGIN_API3
-rw-r--r--firmware/backlight.c3
-rw-r--r--firmware/common/dircache.c3
-rw-r--r--firmware/drivers/ata.c3
-rw-r--r--firmware/drivers/ata_mmc.c3
-rw-r--r--firmware/drivers/lcd-16bit.c3
-rw-r--r--firmware/drivers/lcd-1bit-vert.c3
-rw-r--r--firmware/drivers/lcd-2bit-horz.c3
-rw-r--r--firmware/drivers/lcd-2bit-vert.c3
-rw-r--r--firmware/drivers/lcd-player.c3
-rw-r--r--firmware/drivers/lcd-remote-1bit-v.c3
-rw-r--r--firmware/drivers/lcd-remote-2bit-vi.c3
-rw-r--r--firmware/export/config.h39
-rw-r--r--firmware/export/pp5002.h3
-rw-r--r--firmware/export/pp5020.h9
-rw-r--r--firmware/export/thread.h9
-rw-r--r--firmware/kernel.c67
-rw-r--r--firmware/mpeg.c3
-rw-r--r--firmware/pcm_record.c3
-rw-r--r--firmware/powermgmt.c3
-rw-r--r--firmware/system.c237
-rw-r--r--firmware/target/arm/crt0-pp.S17
-rw-r--r--firmware/target/arm/sandisk/sansa-e200/ata-e200.c3
-rw-r--r--firmware/thread.c78
-rw-r--r--firmware/usb.c3
-rw-r--r--uisimulator/common/stubs.c6
-rw-r--r--uisimulator/sdl/thread-sdl.c6
38 files changed, 383 insertions, 215 deletions
diff --git a/apps/codecs.c b/apps/codecs.c
index 0c6ddd0422..ccfa449d51 100644
--- a/apps/codecs.c
+++ b/apps/codecs.c
@@ -123,7 +123,7 @@ struct codec_api ci = {
&current_tick,
default_event_handler,
default_event_handler_ex,
- create_thread_on_core,
+ create_thread,
remove_thread,
reset_poweroff_timer,
#ifndef SIMULATOR
diff --git a/apps/codecs.h b/apps/codecs.h
index 6710afdc8e..3c2b754dac 100644
--- a/apps/codecs.h
+++ b/apps/codecs.h
@@ -199,9 +199,10 @@ struct codec_api {
long* current_tick;
long (*default_event_handler)(long event);
long (*default_event_handler_ex)(long event, void (*callback)(void *), void *parameter);
- struct thread_entry* (*create_thread)(unsigned int core, void (*function)(void),
+ struct thread_entry* (*create_thread)(void (*function)(void),
void* stack, int stack_size, const char *name
- IF_PRIO(, int priority));
+ IF_PRIO(, int priority)
+ IF_COP(, unsigned int core, bool fallback));
void (*remove_thread)(struct thread_entry *thread);
void (*reset_poweroff_timer)(void);
#ifndef SIMULATOR
diff --git a/apps/main.c b/apps/main.c
index 6286b68ed1..e4d90bce61 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -297,6 +297,9 @@ static void init(void)
/* 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();
@@ -549,19 +552,22 @@ void cop_main(void)
so it should not be assumed that the coprocessor be usable even on
platforms which support it.
- At present the COP sleeps unless it receives a message from the CPU telling
- it that we are loading a new kernel, so must reboot */
+ A kernel thread runs on the coprocessor which waits for other threads to be
+ added, and gracefully handles RoLo */
#if CONFIG_CPU == PP5002
-/* 3G doesn't have Rolo support yet */
+/* 3G doesn't have Rolo or dual core support yet */
while(1) {
COP_CTL = PROC_SLEEP;
}
#else
extern volatile unsigned char cpu_message;
+ system_init();
+ kernel_init();
+
while(cpu_message != COP_REBOOT) {
- COP_CTL = PROC_SLEEP;
+ sleep(HZ);
}
rolo_restart_cop();
#endif /* PP5002 */
diff --git a/apps/playback.c b/apps/playback.c
index fe7a9f6ab1..89caec92aa 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -194,9 +194,9 @@ static bool audio_is_initialized = false;
/* TBD: Split out "audio" and "playback" (ie. calling) threads */
/* Main state control */
-static volatile bool audio_codec_loaded; /* Is codec loaded? (C/A-) */
-static volatile bool playing; /* Is audio playing? (A) */
-static volatile bool paused; /* Is audio paused? (A/C-) */
+static volatile bool audio_codec_loaded NOCACHEBSS_ATTR;/* Codec loaded? (C/A-) */
+static volatile bool playing NOCACHEBSS_ATTR; /* Is audio playing? (A) */
+static volatile bool paused NOCACHEBSS_ATTR; /* Is audio paused? (A/C-) */
static volatile bool filling IDATA_ATTR; /* Is file buffer refilling? (A/C-) */
/* Ring buffer where compressed audio and codecs are loaded */
@@ -290,7 +290,7 @@ static void audio_reset_buffer(size_t pcmbufsize);
/* Codec thread */
extern struct codec_api ci;
-static struct event_queue codec_queue;
+static struct event_queue codec_queue NOCACHEBSS_ATTR;
static long codec_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
IBSS_ATTR;
static const char codec_thread_name[] = "codec";
@@ -304,7 +304,7 @@ static volatile int current_codec IDATA_ATTR; /* Current codec (normal/voice) */
extern struct codec_api ci_voice;
static struct thread_entry *voice_thread_p = NULL;
-static struct event_queue voice_queue;
+static struct event_queue voice_queue NOCACHEBSS_ATTR;
static long voice_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
IBSS_ATTR_VOICE_STACK;
static const char voice_thread_name[] = "voice codec";
@@ -324,12 +324,12 @@ static unsigned char *iram_buf[2] = { NULL, NULL };
/* Pointer to DRAM buffers for normal/voice codecs */
static unsigned char *dram_buf[2] = { NULL, NULL };
/* Mutex to control which codec (normal/voice) is running */
-static struct mutex mutex_codecthread;
+static struct mutex mutex_codecthread NOCACHEBSS_ATTR;
/* Voice state */
static volatile bool voice_thread_start; /* Triggers voice playback (A/V) */
-static volatile bool voice_is_playing; /* Is voice currently playing? (V) */
-static volatile bool voice_codec_loaded; /* Is voice codec loaded (V/A-) */
+static volatile bool voice_is_playing NOCACHEBSS_ATTR; /* Is voice currently playing? (V) */
+static volatile bool voice_codec_loaded NOCACHEBSS_ATTR; /* Is voice codec loaded (V/A-) */
static char *voicebuf;
static size_t voice_remaining;
@@ -863,7 +863,8 @@ void audio_preinit(void)
queue_init(&codec_queue, true);
create_thread(audio_thread, audio_stack, sizeof(audio_stack),
- audio_thread_name IF_PRIO(, PRIORITY_BUFFERING));
+ audio_thread_name IF_PRIO(, PRIORITY_BUFFERING)
+ IF_COP(, CPU, false));
}
void audio_init(void)
@@ -888,7 +889,7 @@ void voice_init(void)
queue_init(&voice_queue, true);
voice_thread_p = create_thread(voice_thread, voice_stack,
sizeof(voice_stack), voice_thread_name
- IF_PRIO(, PRIORITY_PLAYBACK));
+ IF_PRIO(, PRIORITY_PLAYBACK) IF_COP(, CPU, false));
while (!voice_codec_loaded)
yield();
@@ -3533,7 +3534,8 @@ static void audio_playback_init(void)
codec_thread_p = create_thread(
codec_thread, codec_stack, sizeof(codec_stack),
- codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK));
+ codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK)
+ IF_COP(, COP, true));
while (1)
{
diff --git a/apps/playlist.c b/apps/playlist.c
index 6997b12675..0358b6adc4 100644
--- a/apps/playlist.c
+++ b/apps/playlist.c
@@ -1873,7 +1873,8 @@ void playlist_init(void)
memset(playlist->filenames, 0,
playlist->max_playlist_size * sizeof(int));
create_thread(playlist_thread, playlist_stack, sizeof(playlist_stack),
- playlist_thread_name IF_PRIO(, PRIORITY_BACKGROUND));
+ playlist_thread_name IF_PRIO(, PRIORITY_BACKGROUND)
+ IF_COP(, CPU, false));
queue_init(&playlist_queue, true);
#endif
}
diff --git a/apps/plugin.c b/apps/plugin.c
index 5bbff96b04..230b62b819 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -481,7 +481,6 @@ static const struct plugin_api rockbox_api = {
sound_default,
pcm_record_more,
#endif
- create_thread_on_core,
#ifdef IRIVER_H100_SERIES
/* Routines for the iriver_flash -plugin. */
diff --git a/apps/plugin.h b/apps/plugin.h
index 48e9c40196..1d161783a1 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -327,7 +327,8 @@ struct plugin_api {
long (*default_event_handler_ex)(long event, void (*callback)(void *), void *parameter);
struct thread_entry* (*create_thread)(void (*function)(void), void* stack,
int stack_size, const char *name
- IF_PRIO(, int priority));
+ IF_PRIO(, int priority)
+ IF_COP(, unsigned int core, bool fallback));
void (*remove_thread)(struct thread_entry *thread);
void (*reset_poweroff_timer)(void);
#ifndef SIMULATOR
@@ -595,11 +596,6 @@ struct plugin_api {
void (*pcm_record_more)(void *start, size_t size);
#endif
- struct thread_entry*(*create_thread_on_core)(
- unsigned int core, void (*function)(void),
- void* stack, int stack_size,
- const char *name IF_PRIO(, int priority));
-
#ifdef IRIVER_H100_SERIES
/* Routines for the iriver_flash -plugin. */
bool (*detect_original_firmware)(void);
diff --git a/apps/plugins/alpine_cdc.c b/apps/plugins/alpine_cdc.c
index 9c1bc8bd0b..9cc1f9cde4 100644
--- a/apps/plugins/alpine_cdc.c
+++ b/apps/plugins/alpine_cdc.c
@@ -1171,7 +1171,8 @@ int main(void* parameter)
rb->memset(&gTread, 0, sizeof(gTread));
gTread.foreground = true;
rb->create_thread(thread, stack, stacksize, "CDC"
- IF_PRIO(, PRIORITY_BACKGROUND));
+ IF_PRIO(, PRIORITY_BACKGROUND)
+ IF_COP(, CPU, false));
#ifdef DEBUG
do
diff --git a/apps/plugins/battery_bench.c b/apps/plugins/battery_bench.c
index fff3c2fa57..6e3178237f 100644
--- a/apps/plugins/battery_bench.c
+++ b/apps/plugins/battery_bench.c
@@ -479,7 +479,8 @@ int main(void)
rb->queue_init(&thread_q, true); /* put the thread's queue in the bcast list */
if(rb->create_thread(thread, thread_stack,
sizeof(thread_stack), "Battery Benchmark"
- IF_PRIO(, PRIORITY_BACKGROUND)) == NULL)
+ IF_PRIO(, PRIORITY_BACKGROUND)
+ IF_COP(, CPU, false)) == NULL)
{
rb->splash(HZ,true,"Cannot create thread!");
return PLUGIN_ERROR;
diff --git a/apps/plugins/mpegplayer/mpegplayer.c b/apps/plugins/mpegplayer/mpegplayer.c
index 36f54dc224..684a491872 100644
--- a/apps/plugins/mpegplayer/mpegplayer.c
+++ b/apps/plugins/mpegplayer/mpegplayer.c
@@ -909,19 +909,17 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
videostatus = STREAM_PLAYING;
/* We put the video thread on the second processor for multi-core targets. */
-#if NUM_CORES > 1
- if ((videothread_id = rb->create_thread_on_core(COP,decode_mpeg2,
-#else
if ((videothread_id = rb->create_thread(decode_mpeg2,
-#endif
- (uint8_t*)video_stack,VIDEO_STACKSIZE,"mpgvideo" IF_PRIO(,PRIORITY_PLAYBACK))) == NULL)
+ (uint8_t*)video_stack,VIDEO_STACKSIZE,"mpgvideo" IF_PRIO(,PRIORITY_PLAYBACK)
+ IF_COP(, COP, true))) == NULL)
{
rb->splash(HZ,true,"Cannot create video thread!");
return PLUGIN_ERROR;
}
if ((audiothread_id = rb->create_thread(mad_decode,
- (uint8_t*)audio_stack,AUDIO_STACKSIZE,"mpgaudio" IF_PRIO(,PRIORITY_PLAYBACK))) == NULL)
+ (uint8_t*)audio_stack,AUDIO_STACKSIZE,"mpgaudio" IF_PRIO(,PRIORITY_PLAYBACK)
+ IF_COP(, CPU, false))) == NULL)
{
rb->splash(HZ,true,"Cannot create audio thread!");
rb->remove_thread(videothread_id);
diff --git a/apps/tagcache.c b/apps/tagcache.c
index a6a0168353..6b891f1011 100644
--- a/apps/tagcache.c
+++ b/apps/tagcache.c
@@ -3941,7 +3941,8 @@ void tagcache_init(void)
queue_init(&tagcache_queue, true);
create_thread(tagcache_thread, tagcache_stack,
sizeof(tagcache_stack), tagcache_thread_name
- IF_PRIO(, PRIORITY_BACKGROUND));
+ IF_PRIO(, PRIORITY_BACKGROUND)
+ IF_COP(, CPU, false));
#else
tc_stat.initialized = true;
allocate_tempbuf();
diff --git a/docs/PLUGIN_API b/docs/PLUGIN_API
index e24d70fece..feba0868fb 100644
--- a/docs/PLUGIN_API
+++ b/docs/PLUGIN_API
@@ -431,7 +431,8 @@ Kernel
SYS_USB_CONNECTED. Else do nothing and return 0.
int create_thread(void* function, void* stack, int stack_size,
- const char *name);
+ const char *name IF_PRIO(int priority)
+ IF_COP(, unsigned int core, bool fallback));
Create a thread.
??? (see firmware/thread.c:145)
diff --git a/firmware/backlight.c b/firmware/backlight.c
index a273b94a38..1e8dd46b2d 100644
--- a/firmware/backlight.c
+++ b/firmware/backlight.c
@@ -582,7 +582,8 @@ void backlight_init(void)
create_thread(backlight_thread, backlight_stack,
sizeof(backlight_stack), backlight_thread_name
- IF_PRIO(, PRIORITY_SYSTEM));
+ IF_PRIO(, PRIORITY_SYSTEM)
+ IF_COP(, CPU, false));
tick_add_task(backlight_tick);
}
diff --git a/firmware/common/dircache.c b/firmware/common/dircache.c
index fd9796c0d8..f78fa2d0cf 100644
--- a/firmware/common/dircache.c
+++ b/firmware/common/dircache.c
@@ -701,7 +701,8 @@ void dircache_init(void)
queue_init(&dircache_queue, true);
create_thread(dircache_thread, dircache_stack,
- sizeof(dircache_stack), dircache_thread_name IF_PRIO(, PRIORITY_BACKGROUND));
+ sizeof(dircache_stack), dircache_thread_name IF_PRIO(, PRIORITY_BACKGROUND)
+ IF_COP(, CPU, false));
}
/**
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c
index 21376ab9a7..76c0090a12 100644
--- a/firmware/drivers/ata.c
+++ b/firmware/drivers/ata.c
@@ -991,7 +991,8 @@ int ata_init(void)
last_disk_activity = current_tick;
create_thread(ata_thread, ata_stack,
sizeof(ata_stack), ata_thread_name
- IF_PRIO(, PRIORITY_SYSTEM));
+ IF_PRIO(, PRIORITY_SYSTEM)
+ IF_COP(, CPU, false));
initialized = true;
}
diff --git a/firmware/drivers/ata_mmc.c b/firmware/drivers/ata_mmc.c
index a549624b2c..377d2444bf 100644
--- a/firmware/drivers/ata_mmc.c
+++ b/firmware/drivers/ata_mmc.c
@@ -1173,7 +1173,8 @@ int ata_init(void)
queue_init(&mmc_queue, true);
create_thread(mmc_thread, mmc_stack,
- sizeof(mmc_stack), mmc_thread_name IF_PRIO(, PRIORITY_SYSTEM));
+ sizeof(mmc_stack), mmc_thread_name IF_PRIO(, PRIORITY_SYSTEM)
+ IF_COP(, CPU, false));
tick_add_task(mmc_tick);
initialized = true;
}
diff --git a/firmware/drivers/lcd-16bit.c b/firmware/drivers/lcd-16bit.c
index d545bf3fe4..7269e54dcd 100644
--- a/firmware/drivers/lcd-16bit.c
+++ b/firmware/drivers/lcd-16bit.c
@@ -89,7 +89,8 @@ void lcd_init(void)
create_thread(scroll_thread, scroll_stack,
sizeof(scroll_stack), scroll_name
- IF_PRIO(, PRIORITY_USER_INTERFACE));
+ IF_PRIO(, PRIORITY_USER_INTERFACE)
+ IF_COP(, CPU, false));
}
/*** parameter handling ***/
diff --git a/firmware/drivers/lcd-1bit-vert.c b/firmware/drivers/lcd-1bit-vert.c
index 62dfab0180..64c1ace292 100644
--- a/firmware/drivers/lcd-1bit-vert.c
+++ b/firmware/drivers/lcd-1bit-vert.c
@@ -68,7 +68,8 @@ void lcd_init(void)
/* Call device specific init */
lcd_init_device();
create_thread(scroll_thread, scroll_stack,
- sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_USER_INTERFACE));
+ sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_USER_INTERFACE)
+ IF_COP(, CPU, false));
}
/*** parameter handling ***/
diff --git a/firmware/drivers/lcd-2bit-horz.c b/firmware/drivers/lcd-2bit-horz.c
index 9ba52e1ba9..475e466c42 100644
--- a/firmware/drivers/lcd-2bit-horz.c
+++ b/firmware/drivers/lcd-2bit-horz.c
@@ -79,7 +79,8 @@ void lcd_init(void)
/* Call device specific init */
lcd_init_device();
create_thread(scroll_thread, scroll_stack,
- sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_USER_INTERFACE));
+ sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_USER_INTERFACE)
+ IF_COP(, CPU, false));
}
/*** parameter handling ***/
diff --git a/firmware/drivers/lcd-2bit-vert.c b/firmware/drivers/lcd-2bit-vert.c
index 7b3352b9d6..7a49f35312 100644
--- a/firmware/drivers/lcd-2bit-vert.c
+++ b/firmware/drivers/lcd-2bit-vert.c
@@ -82,7 +82,8 @@ void lcd_init(void)
/* Call device specific init */
lcd_init_device();
create_thread(scroll_thread, scroll_stack,
- sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_USER_INTERFACE));
+ sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_USER_INTERFACE)
+ IF_COP(, CPU, false));
}
/*** parameter handling ***/
diff --git a/firmware/drivers/lcd-player.c b/firmware/drivers/lcd-player.c
index 8ca81473fc..c863c9f188 100644
--- a/firmware/drivers/lcd-player.c
+++ b/firmware/drivers/lcd-player.c
@@ -610,7 +610,8 @@ void lcd_init (void)
lcd_set_contrast(lcd_default_contrast());
create_thread(scroll_thread, scroll_stack,
- sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_USER_INTERFACE));
+ sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_USER_INTERFACE)
+ IF_COP(, CPU, false));
}
void lcd_jump_scroll (int mode) /* 0=off, 1=once, ..., JUMP_SCROLL_ALWAYS */
diff --git a/firmware/drivers/lcd-remote-1bit-v.c b/firmware/drivers/lcd-remote-1bit-v.c
index c81ccc83c9..0aa3d890f7 100644
--- a/firmware/drivers/lcd-remote-1bit-v.c
+++ b/firmware/drivers/lcd-remote-1bit-v.c
@@ -903,5 +903,6 @@ void lcd_remote_init(void)
queue_init(&remote_scroll_queue, false);
#endif
create_thread(scroll_thread, scroll_stack,
- sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_USER_INTERFACE));
+ sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_USER_INTERFACE)
+ IF_COP(, CPU, false));
}
diff --git a/firmware/drivers/lcd-remote-2bit-vi.c b/firmware/drivers/lcd-remote-2bit-vi.c
index 281cbc2189..e0f6b35004 100644
--- a/firmware/drivers/lcd-remote-2bit-vi.c
+++ b/firmware/drivers/lcd-remote-2bit-vi.c
@@ -1241,5 +1241,6 @@ void lcd_remote_init(void)
queue_init(&remote_scroll_queue, false);
#endif
create_thread(scroll_thread, scroll_stack,
- sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_USER_INTERFACE));
+ sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_USER_INTERFACE)
+ IF_COP(, CPU, false));
}
diff --git a/firmware/export/config.h b/firmware/export/config.h
index d848d16155..13fb77661d 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -273,21 +273,6 @@
/* define for all cpus from PP family */
#if (CONFIG_CPU == PP5002) || (CONFIG_CPU == PP5020) || (CONFIG_CPU == PP5024)
#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
-
-#define COP_REBOOT 0x00000001
-#else
-#define NUM_CORES 1
-#define CURRENT_CORE 0
#endif
/* define for all cpus from ARM family */
@@ -348,4 +333,28 @@
#define IRAM_LCDFRAMEBUFFER
#endif
+/* Dual core support - not yet working on the 3G iPod */
+#if defined(CPU_PP) && CONFIG_CPU != PP5002
+#define NUM_CORES 2
+#define CURRENT_CORE current_core()
+/* Hopefully at some point we will learn how to mark areas of main memory as
+ * not to be cached. Until then, use IRAM for variables shared across cores */
+#define NOCACHEBSS_ATTR IBSS_ATTR
+#define NOCACHEDATA_ATTR IDATA_ATTR
+
+#define IF_COP(empty, x, y) , x, y
+
+/* Defines for inter-core messaging */
+#define COP_REBOOT 1
+
+#else
+#define NUM_CORES 1
+#define CURRENT_CORE CPU
+#define NOCACHEBSS_ATTR
+#define NOCACHEDATA_ATTR
+
+#define IF_COP(empty, x, y)
+
+#endif /* Processor specific */
+
#endif
diff --git a/firmware/export/pp5002.h b/firmware/export/pp5002.h
index ef131fe6d6..9636313390 100644
--- a/firmware/export/pp5002.h
+++ b/firmware/export/pp5002.h
@@ -73,6 +73,9 @@
#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 3d205a0ea1..a34f1251c9 100644
--- a/firmware/export/pp5020.h
+++ b/firmware/export/pp5020.h
@@ -30,6 +30,15 @@
#define PROC_ID_CPU 0x55
#define PROC_ID_COP 0xaa
+/* Mailboxes */
+/* Each processor has two mailboxes it can write to and two which
+ it can read from. We define the first to be for sending messages
+ and the second for replying to messages */
+#define CPU_MESSAGE (*(volatile unsigned long *)(0x60001000))
+#define COP_MESSAGE (*(volatile unsigned long *)(0x60001004))
+#define CPU_REPLY (*(volatile unsigned long *)(0x60001008))
+#define COP_REPLY (*(volatile unsigned long *)(0x6000100c))
+
/* Interrupts */
#define CPU_INT_STAT (*(volatile unsigned long*)(0x64004000))
#define COP_INT_STAT (*(volatile unsigned long*)(0x60004004))
diff --git a/firmware/export/thread.h b/firmware/export/thread.h
index bced98ea23..2ff4694159 100644
--- a/firmware/export/thread.h
+++ b/firmware/export/thread.h
@@ -124,13 +124,8 @@ struct core_entry {
struct thread_entry*
create_thread(void (*function)(void), void* stack, int stack_size,
- const char *name IF_PRIO(, int priority));
-
-struct thread_entry*
- create_thread_on_core(unsigned int core, void (*function)(void),
- void* stack, int stack_size,
- const char *name
- IF_PRIO(, int priority));
+ const char *name IF_PRIO(, int priority)
+ IF_COP(, unsigned int core, bool fallback));
#ifdef HAVE_SCHEDULER_BOOSTCTRL
void trigger_cpu_boost(void);
diff --git a/firmware/kernel.c b/firmware/kernel.c
index 75c6604682..313530ffba 100644
--- a/firmware/kernel.c
+++ b/firmware/kernel.c
@@ -26,7 +26,7 @@
#include "panic.h"
#if !defined(CPU_PP) || !defined(BOOTLOADER)
-long current_tick = 0;
+long current_tick NOCACHEDATA_ATTR = 0;
#endif
static void (*tick_funcs[MAX_NUM_TICK_TASKS])(void);
@@ -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);
}
@@ -496,28 +499,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;
@@ -645,6 +656,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);
+ }
+}
+
+#else
void mutex_lock(struct mutex *m)
{
if (m->locked)
@@ -656,6 +690,7 @@ void mutex_lock(struct mutex *m)
/* ...and lock it */
m->locked = true;
}
+#endif
void mutex_unlock(struct mutex *m)
{
diff --git a/firmware/mpeg.c b/firmware/mpeg.c
index 9afa8a20bd..909a21dcda 100644
--- a/firmware/mpeg.c
+++ b/firmware/mpeg.c
@@ -2905,7 +2905,8 @@ void audio_init(void)
queue_init(&mpeg_queue, true);
#endif /* !SIMULATOR */
create_thread(mpeg_thread, mpeg_stack,
- sizeof(mpeg_stack), mpeg_thread_name IF_PRIO(, PRIORITY_SYSTEM));
+ sizeof(mpeg_stack), mpeg_thread_name IF_PRIO(, PRIORITY_SYSTEM)
+ IF_COP(, CPU, false));
memset(trackdata, sizeof(trackdata), 0);
diff --git a/firmware/pcm_record.c b/firmware/pcm_record.c
index 270bb354d2..3f4abc7be3 100644
--- a/firmware/pcm_record.c
+++ b/firmware/pcm_record.c
@@ -418,7 +418,8 @@ void pcm_rec_init(void)
queue_enable_queue_send(&pcmrec_queue, &pcmrec_queue_send);
pcmrec_thread_p =
create_thread(pcmrec_thread, pcmrec_stack, sizeof(pcmrec_stack),
- pcmrec_thread_name IF_PRIO(, PRIORITY_RECORDING));
+ pcmrec_thread_name IF_PRIO(, PRIORITY_RECORDING)
+ IF_COP(, CPU, false));
} /* pcm_rec_init */
/** audio_* group **/
diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c
index c2f9ca0bca..1492c80bc4 100644
--- a/firmware/powermgmt.c
+++ b/firmware/powermgmt.c
@@ -1245,7 +1245,8 @@ void powermgmt_init(void)
/* init history to 0 */
memset(power_history, 0x00, sizeof(power_history));
create_thread(power_thread, power_stack, sizeof(power_stack),
- power_thread_name IF_PRIO(, PRIORITY_SYSTEM));
+ power_thread_name IF_PRIO(, PRIORITY_SYSTEM)
+ IF_COP(, CPU, false));
}
#endif /* SIMULATOR */
diff --git a/firmware/system.c b/firmware/system.c
index a86d945093..a9c9d9e350 100644
--- a/firmware/system.c
+++ b/firmware/system.c
@@ -612,12 +612,22 @@ 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) \
|| (defined SANSA_E200)
@@ -626,22 +636,40 @@ void irq(void)
/* TODO: Even if it isn't in the target tree, this should be the default case */
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 */
@@ -694,43 +722,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)
@@ -754,24 +786,33 @@ void ipod_set_cpu_frequency(void)
void system_init(void)
{
#ifndef BOOTLOADER
- /* Remap the flash ROM from 0x00000000 to 0x20000000. */
- MMAP3_LOGICAL = 0x20000000 | 0x3a00;
- MMAP3_PHYSICAL = 0x00000000 | 0x3f84;
-
- /* 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();
+ if (CURRENT_CORE == CPU)
+ {
+ /* Remap the flash ROM from 0x00000000 to 0x20000000. */
+ MMAP3_LOGICAL = 0x20000000 | 0x3a00;
+ MMAP3_PHYSICAL = 0x00000000 | 0x3f84;
+
+ /* 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 (!defined HAVE_ADJUSTABLE_CPU_FREQ) && (NUM_CORES == 1)
+ ipod_set_cpu_frequency();
+#endif
+ }
+#if (!defined HAVE_ADJUSTABLE_CPU_FREQ) && (NUM_CORES > 1)
+ else
+ {
+ ipod_set_cpu_frequency();
+ }
#endif
ipod_init_cache();
#endif
@@ -796,10 +837,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
@@ -848,29 +897,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)
@@ -901,17 +953,20 @@ static void ipod_set_cpu_speed(void)
void system_init(void)
{
#ifndef BOOTLOADER
- /* Remap the flash ROM from 0x00000000 to 0x20000000. */
- MMAP3_LOGICAL = 0x20000000 | 0x3a00;
- MMAP3_PHYSICAL = 0x00000000 | 0x3f84;
-
- ipod_hw_rev = (*((volatile unsigned long*)(0x01fffffc)));
- outl(-1, 0xcf00101c);
- outl(-1, 0xcf001028);
- outl(-1, 0xcf001038);
+ if (CURRENT_CORE == CPU)
+ {
+ /* Remap the flash ROM from 0x00000000 to 0x20000000. */
+ MMAP3_LOGICAL = 0x20000000 | 0x3a00;
+ MMAP3_PHYSICAL = 0x00000000 | 0x3f84;
+
+ 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 e0d1034f74..bbeace1b60 100644
--- a/firmware/target/arm/crt0-pp.S
+++ b/firmware/target/arm/crt0-pp.S
@@ -222,6 +222,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
/* Run cop_main() in apps/main.c */
@@ -307,6 +320,10 @@ UIE:
.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/target/arm/sandisk/sansa-e200/ata-e200.c b/firmware/target/arm/sandisk/sansa-e200/ata-e200.c
index cf05397a78..73a67d1ee6 100644
--- a/firmware/target/arm/sandisk/sansa-e200/ata-e200.c
+++ b/firmware/target/arm/sandisk/sansa-e200/ata-e200.c
@@ -687,7 +687,8 @@ int ata_init(void)
{
queue_init(&sd_queue, true);
create_thread(sd_thread, sd_stack,
- sizeof(sd_stack), sd_thread_name IF_PRIO(, PRIORITY_SYSTEM));
+ sizeof(sd_stack), sd_thread_name IF_PRIO(, PRIORITY_SYSTEM)
+ IF_COP(, CPU, false));
initialized = true;
}
diff --git a/firmware/thread.c b/firmware/thread.c
index 2281f43e53..281ab0fa54 100644
--- a/firmware/thread.c
+++ b/firmware/thread.c
@@ -64,6 +64,10 @@ int *cop_stackend = stackend;
#endif
#endif
+#if (NUM_CORES > 1)
+bool IDATA_ATTR kernel_running_on_cop = false;
+#endif
+
/* Conserve IRAM
static void add_to_list(struct thread_entry **list,
struct thread_entry *thread) ICODE_ATTR;
@@ -316,10 +320,13 @@ static inline void sleep_core(void)
#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 == S3C2440
CLKCON |= (1 << 2); /* set IDLE bit */
for(i=0; i<10; i++); /* wait for IDLE */
@@ -608,27 +615,16 @@ void wakeup_thread(struct thread_entry **list)
}
/*---------------------------------------------------------------------------
- * Create thread on the current core.
- * Return ID if context area could be allocated, else -1.
+ * Create a thread
+ * If using a dual core architecture, specify which core to start the thread
+ * on, and whether to fall back to the other core if it can't be created
+ * Return ID if context area could be allocated, else NULL.
*---------------------------------------------------------------------------
*/
struct thread_entry*
create_thread(void (*function)(void), void* stack, int stack_size,
- const char *name IF_PRIO(, int priority))
-{
- return create_thread_on_core(CURRENT_CORE, function, stack, stack_size,
- name IF_PRIO(, priority));
-}
-
-/*---------------------------------------------------------------------------
- * Create thread on a specific core.
- * Return ID if context area could be allocated, else -1.
- *---------------------------------------------------------------------------
- */
-struct thread_entry*
- create_thread_on_core(unsigned int core, void (*function)(void),
- void* stack, int stack_size,
- const char *name IF_PRIO(, int priority))
+ const char *name IF_PRIO(, int priority)
+ IF_COP(, unsigned int core, bool fallback))
{
unsigned int i;
unsigned int stacklen;
@@ -637,6 +633,29 @@ struct thread_entry*
struct regs *regs;
struct thread_entry *thread;
+/*****
+ * Ugly code alert!
+ * To prevent ifdef hell while keeping the binary size down, we define
+ * core here if it hasn't been passed as a parameter
+ *****/
+#if NUM_CORES == 1
+#define core CPU
+#endif
+
+#if NUM_CORES > 1
+/* If the kernel hasn't initialised on the COP (most likely due to an old
+ * bootloader) then refuse to start threads on the COP
+ */
+ if((core == COP) && !kernel_running_on_cop)
+ {
+ if (fallback)
+ return create_thread(function, stack, stack_size, name
+ IF_PRIO(, priority) IF_COP(, CPU, false));
+ else
+ return NULL;
+ }
+#endif
+
for (n = 0; n < MAXTHREADS; n++)
{
if (cores[core].threads[n].name == NULL)
@@ -644,8 +663,15 @@ struct thread_entry*
}
if (n == MAXTHREADS)
- return NULL;
-
+ {
+#if NUM_CORES > 1
+ if (fallback)
+ return create_thread(function, stack, stack_size, name
+ IF_PRIO(, priority) IF_COP(, 1 - core, fallback));
+ else
+#endif
+ return NULL;
+ }
/* Munge the stack to make it easy to spot stack overflows */
stacklen = stack_size / sizeof(int);
@@ -677,6 +703,9 @@ struct thread_entry*
THREAD_CPU_INIT(core, thread);
return thread;
+#if NUM_CORES == 1
+#undef core
+#endif
}
#ifdef HAVE_SCHEDULER_BOOSTCTRL
@@ -751,7 +780,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;
@@ -779,6 +809,10 @@ void init_threads(void)
#endif
}
cores[core].threads[0].context.start = 0; /* thread 0 already running */
+#if NUM_CORES > 1
+ if(core == COP)
+ kernel_running_on_cop = true; /* can we use context.start for this? */
+#endif
}
int thread_stack_usage(const struct thread_entry *thread)
diff --git a/firmware/usb.c b/firmware/usb.c
index ee08b04caa..cf4641950e 100644
--- a/firmware/usb.c
+++ b/firmware/usb.c
@@ -428,7 +428,8 @@ void usb_init(void)
#ifndef BOOTLOADER
queue_init(&usb_queue, true);
create_thread(usb_thread, usb_stack, sizeof(usb_stack),
- usb_thread_name IF_PRIO(, PRIORITY_SYSTEM));
+ usb_thread_name IF_PRIO(, PRIORITY_SYSTEM)
+ IF_COP(, CPU, false));
tick_add_task(usb_tick);
#endif
diff --git a/uisimulator/common/stubs.c b/uisimulator/common/stubs.c
index a993a9e0e8..8ea46824ce 100644
--- a/uisimulator/common/stubs.c
+++ b/uisimulator/common/stubs.c
@@ -258,12 +258,6 @@ void remove_thread(int threadnum)
(void)threadnum;
}
-void remove_thread_on_core(unsigned int core, int threadnum)
-{
- (void)core;
- (void)threadnum;
-}
-
/* assure an unused place to direct virtual pointers to */
#define VIRT_SIZE 0xFFFF /* more than enough for our string ID range */
unsigned char vp_dummy[VIRT_SIZE];
diff --git a/uisimulator/sdl/thread-sdl.c b/uisimulator/sdl/thread-sdl.c
index 041ca3153d..21697699a5 100644
--- a/uisimulator/sdl/thread-sdl.c
+++ b/uisimulator/sdl/thread-sdl.c
@@ -75,12 +75,6 @@ int create_thread(void (*fp)(void), void* sp, int stk_size)
return 0;
}
-int create_thread_on_core(void (*core)(void), void (*fp)(void), void* sp, int stk_size)
-{
- (void)core;
- return create_thread(fp, sp, stk_size);
-}
-
void init_threads(void)
{
m = SDL_CreateMutex();