mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-14 02:27:39 -04:00
Dual core support for PP502x players (iPod G4 and later, iriver h10, Sansa - iPod G3 will be coming soon.) This allows threads to be run on either core provided that all communications between the cores is done using uncached memory. There should be no significant change in battery life from doing this. Documentation (on the RockboxKernel wiki page) will follow shortly.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12601 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
74e572c9d6
commit
82f9056988
38 changed files with 379 additions and 211 deletions
|
@ -123,7 +123,7 @@ struct codec_api ci = {
|
||||||
¤t_tick,
|
¤t_tick,
|
||||||
default_event_handler,
|
default_event_handler,
|
||||||
default_event_handler_ex,
|
default_event_handler_ex,
|
||||||
create_thread_on_core,
|
create_thread,
|
||||||
remove_thread,
|
remove_thread,
|
||||||
reset_poweroff_timer,
|
reset_poweroff_timer,
|
||||||
#ifndef SIMULATOR
|
#ifndef SIMULATOR
|
||||||
|
|
|
@ -199,9 +199,10 @@ struct codec_api {
|
||||||
long* current_tick;
|
long* current_tick;
|
||||||
long (*default_event_handler)(long event);
|
long (*default_event_handler)(long event);
|
||||||
long (*default_event_handler_ex)(long event, void (*callback)(void *), void *parameter);
|
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
|
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 (*remove_thread)(struct thread_entry *thread);
|
||||||
void (*reset_poweroff_timer)(void);
|
void (*reset_poweroff_timer)(void);
|
||||||
#ifndef SIMULATOR
|
#ifndef SIMULATOR
|
||||||
|
|
14
apps/main.c
14
apps/main.c
|
@ -296,6 +296,9 @@ static void init(void)
|
||||||
#if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
|
#if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
|
||||||
/* if nobody initialized ATA before, I consider this a cold start */
|
/* if nobody initialized ATA before, I consider this a cold start */
|
||||||
bool coldstart = (PACR2 & 0x4000) != 0; /* starting from Flash */
|
bool coldstart = (PACR2 & 0x4000) != 0; /* starting from Flash */
|
||||||
|
#endif
|
||||||
|
#ifdef CPU_PP
|
||||||
|
COP_CTL = PROC_WAKE;
|
||||||
#endif
|
#endif
|
||||||
system_init();
|
system_init();
|
||||||
kernel_init();
|
kernel_init();
|
||||||
|
@ -549,19 +552,22 @@ void cop_main(void)
|
||||||
so it should not be assumed that the coprocessor be usable even on
|
so it should not be assumed that the coprocessor be usable even on
|
||||||
platforms which support it.
|
platforms which support it.
|
||||||
|
|
||||||
At present the COP sleeps unless it receives a message from the CPU telling
|
A kernel thread runs on the coprocessor which waits for other threads to be
|
||||||
it that we are loading a new kernel, so must reboot */
|
added, and gracefully handles RoLo */
|
||||||
|
|
||||||
#if CONFIG_CPU == PP5002
|
#if CONFIG_CPU == PP5002
|
||||||
/* 3G doesn't have Rolo support yet */
|
/* 3G doesn't have Rolo or dual core support yet */
|
||||||
while(1) {
|
while(1) {
|
||||||
COP_CTL = PROC_SLEEP;
|
COP_CTL = PROC_SLEEP;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
extern volatile unsigned char cpu_message;
|
extern volatile unsigned char cpu_message;
|
||||||
|
|
||||||
|
system_init();
|
||||||
|
kernel_init();
|
||||||
|
|
||||||
while(cpu_message != COP_REBOOT) {
|
while(cpu_message != COP_REBOOT) {
|
||||||
COP_CTL = PROC_SLEEP;
|
sleep(HZ);
|
||||||
}
|
}
|
||||||
rolo_restart_cop();
|
rolo_restart_cop();
|
||||||
#endif /* PP5002 */
|
#endif /* PP5002 */
|
||||||
|
|
|
@ -194,9 +194,9 @@ static bool audio_is_initialized = false;
|
||||||
/* TBD: Split out "audio" and "playback" (ie. calling) threads */
|
/* TBD: Split out "audio" and "playback" (ie. calling) threads */
|
||||||
|
|
||||||
/* Main state control */
|
/* Main state control */
|
||||||
static volatile bool audio_codec_loaded; /* Is codec loaded? (C/A-) */
|
static volatile bool audio_codec_loaded NOCACHEBSS_ATTR;/* Codec loaded? (C/A-) */
|
||||||
static volatile bool playing; /* Is audio playing? (A) */
|
static volatile bool playing NOCACHEBSS_ATTR; /* Is audio playing? (A) */
|
||||||
static volatile bool paused; /* Is audio paused? (A/C-) */
|
static volatile bool paused NOCACHEBSS_ATTR; /* Is audio paused? (A/C-) */
|
||||||
static volatile bool filling IDATA_ATTR; /* Is file buffer refilling? (A/C-) */
|
static volatile bool filling IDATA_ATTR; /* Is file buffer refilling? (A/C-) */
|
||||||
|
|
||||||
/* Ring buffer where compressed audio and codecs are loaded */
|
/* Ring buffer where compressed audio and codecs are loaded */
|
||||||
|
@ -290,7 +290,7 @@ static void audio_reset_buffer(size_t pcmbufsize);
|
||||||
|
|
||||||
/* Codec thread */
|
/* Codec thread */
|
||||||
extern struct codec_api ci;
|
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)]
|
static long codec_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
|
||||||
IBSS_ATTR;
|
IBSS_ATTR;
|
||||||
static const char codec_thread_name[] = "codec";
|
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;
|
extern struct codec_api ci_voice;
|
||||||
|
|
||||||
static struct thread_entry *voice_thread_p = NULL;
|
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)]
|
static long voice_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
|
||||||
IBSS_ATTR_VOICE_STACK;
|
IBSS_ATTR_VOICE_STACK;
|
||||||
static const char voice_thread_name[] = "voice codec";
|
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 */
|
/* Pointer to DRAM buffers for normal/voice codecs */
|
||||||
static unsigned char *dram_buf[2] = { NULL, NULL };
|
static unsigned char *dram_buf[2] = { NULL, NULL };
|
||||||
/* Mutex to control which codec (normal/voice) is running */
|
/* Mutex to control which codec (normal/voice) is running */
|
||||||
static struct mutex mutex_codecthread;
|
static struct mutex mutex_codecthread NOCACHEBSS_ATTR;
|
||||||
|
|
||||||
/* Voice state */
|
/* Voice state */
|
||||||
static volatile bool voice_thread_start; /* Triggers voice playback (A/V) */
|
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_is_playing NOCACHEBSS_ATTR; /* Is voice currently playing? (V) */
|
||||||
static volatile bool voice_codec_loaded; /* Is voice codec loaded (V/A-) */
|
static volatile bool voice_codec_loaded NOCACHEBSS_ATTR; /* Is voice codec loaded (V/A-) */
|
||||||
static char *voicebuf;
|
static char *voicebuf;
|
||||||
static size_t voice_remaining;
|
static size_t voice_remaining;
|
||||||
|
|
||||||
|
@ -863,7 +863,8 @@ void audio_preinit(void)
|
||||||
queue_init(&codec_queue, true);
|
queue_init(&codec_queue, true);
|
||||||
|
|
||||||
create_thread(audio_thread, audio_stack, sizeof(audio_stack),
|
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)
|
void audio_init(void)
|
||||||
|
@ -888,7 +889,7 @@ void voice_init(void)
|
||||||
queue_init(&voice_queue, true);
|
queue_init(&voice_queue, true);
|
||||||
voice_thread_p = create_thread(voice_thread, voice_stack,
|
voice_thread_p = create_thread(voice_thread, voice_stack,
|
||||||
sizeof(voice_stack), voice_thread_name
|
sizeof(voice_stack), voice_thread_name
|
||||||
IF_PRIO(, PRIORITY_PLAYBACK));
|
IF_PRIO(, PRIORITY_PLAYBACK) IF_COP(, CPU, false));
|
||||||
|
|
||||||
while (!voice_codec_loaded)
|
while (!voice_codec_loaded)
|
||||||
yield();
|
yield();
|
||||||
|
@ -3533,7 +3534,8 @@ static void audio_playback_init(void)
|
||||||
|
|
||||||
codec_thread_p = create_thread(
|
codec_thread_p = create_thread(
|
||||||
codec_thread, codec_stack, sizeof(codec_stack),
|
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)
|
while (1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1873,7 +1873,8 @@ void playlist_init(void)
|
||||||
memset(playlist->filenames, 0,
|
memset(playlist->filenames, 0,
|
||||||
playlist->max_playlist_size * sizeof(int));
|
playlist->max_playlist_size * sizeof(int));
|
||||||
create_thread(playlist_thread, playlist_stack, sizeof(playlist_stack),
|
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);
|
queue_init(&playlist_queue, true);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -481,7 +481,6 @@ static const struct plugin_api rockbox_api = {
|
||||||
sound_default,
|
sound_default,
|
||||||
pcm_record_more,
|
pcm_record_more,
|
||||||
#endif
|
#endif
|
||||||
create_thread_on_core,
|
|
||||||
|
|
||||||
#ifdef IRIVER_H100_SERIES
|
#ifdef IRIVER_H100_SERIES
|
||||||
/* Routines for the iriver_flash -plugin. */
|
/* Routines for the iriver_flash -plugin. */
|
||||||
|
|
|
@ -327,7 +327,8 @@ struct plugin_api {
|
||||||
long (*default_event_handler_ex)(long event, void (*callback)(void *), void *parameter);
|
long (*default_event_handler_ex)(long event, void (*callback)(void *), void *parameter);
|
||||||
struct thread_entry* (*create_thread)(void (*function)(void), void* stack,
|
struct thread_entry* (*create_thread)(void (*function)(void), void* stack,
|
||||||
int stack_size, const char *name
|
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 (*remove_thread)(struct thread_entry *thread);
|
||||||
void (*reset_poweroff_timer)(void);
|
void (*reset_poweroff_timer)(void);
|
||||||
#ifndef SIMULATOR
|
#ifndef SIMULATOR
|
||||||
|
@ -595,11 +596,6 @@ struct plugin_api {
|
||||||
void (*pcm_record_more)(void *start, size_t size);
|
void (*pcm_record_more)(void *start, size_t size);
|
||||||
#endif
|
#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
|
#ifdef IRIVER_H100_SERIES
|
||||||
/* Routines for the iriver_flash -plugin. */
|
/* Routines for the iriver_flash -plugin. */
|
||||||
bool (*detect_original_firmware)(void);
|
bool (*detect_original_firmware)(void);
|
||||||
|
|
|
@ -1171,7 +1171,8 @@ int main(void* parameter)
|
||||||
rb->memset(&gTread, 0, sizeof(gTread));
|
rb->memset(&gTread, 0, sizeof(gTread));
|
||||||
gTread.foreground = true;
|
gTread.foreground = true;
|
||||||
rb->create_thread(thread, stack, stacksize, "CDC"
|
rb->create_thread(thread, stack, stacksize, "CDC"
|
||||||
IF_PRIO(, PRIORITY_BACKGROUND));
|
IF_PRIO(, PRIORITY_BACKGROUND)
|
||||||
|
IF_COP(, CPU, false));
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
do
|
do
|
||||||
|
|
|
@ -479,7 +479,8 @@ int main(void)
|
||||||
rb->queue_init(&thread_q, true); /* put the thread's queue in the bcast list */
|
rb->queue_init(&thread_q, true); /* put the thread's queue in the bcast list */
|
||||||
if(rb->create_thread(thread, thread_stack,
|
if(rb->create_thread(thread, thread_stack,
|
||||||
sizeof(thread_stack), "Battery Benchmark"
|
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!");
|
rb->splash(HZ,true,"Cannot create thread!");
|
||||||
return PLUGIN_ERROR;
|
return PLUGIN_ERROR;
|
||||||
|
|
|
@ -909,19 +909,17 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
|
||||||
videostatus = STREAM_PLAYING;
|
videostatus = STREAM_PLAYING;
|
||||||
|
|
||||||
/* We put the video thread on the second processor for multi-core targets. */
|
/* 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,
|
if ((videothread_id = rb->create_thread(decode_mpeg2,
|
||||||
#endif
|
(uint8_t*)video_stack,VIDEO_STACKSIZE,"mpgvideo" IF_PRIO(,PRIORITY_PLAYBACK)
|
||||||
(uint8_t*)video_stack,VIDEO_STACKSIZE,"mpgvideo" IF_PRIO(,PRIORITY_PLAYBACK))) == NULL)
|
IF_COP(, COP, true))) == NULL)
|
||||||
{
|
{
|
||||||
rb->splash(HZ,true,"Cannot create video thread!");
|
rb->splash(HZ,true,"Cannot create video thread!");
|
||||||
return PLUGIN_ERROR;
|
return PLUGIN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((audiothread_id = rb->create_thread(mad_decode,
|
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->splash(HZ,true,"Cannot create audio thread!");
|
||||||
rb->remove_thread(videothread_id);
|
rb->remove_thread(videothread_id);
|
||||||
|
|
|
@ -3941,7 +3941,8 @@ void tagcache_init(void)
|
||||||
queue_init(&tagcache_queue, true);
|
queue_init(&tagcache_queue, true);
|
||||||
create_thread(tagcache_thread, tagcache_stack,
|
create_thread(tagcache_thread, tagcache_stack,
|
||||||
sizeof(tagcache_stack), tagcache_thread_name
|
sizeof(tagcache_stack), tagcache_thread_name
|
||||||
IF_PRIO(, PRIORITY_BACKGROUND));
|
IF_PRIO(, PRIORITY_BACKGROUND)
|
||||||
|
IF_COP(, CPU, false));
|
||||||
#else
|
#else
|
||||||
tc_stat.initialized = true;
|
tc_stat.initialized = true;
|
||||||
allocate_tempbuf();
|
allocate_tempbuf();
|
||||||
|
|
|
@ -431,7 +431,8 @@ Kernel
|
||||||
SYS_USB_CONNECTED. Else do nothing and return 0.
|
SYS_USB_CONNECTED. Else do nothing and return 0.
|
||||||
|
|
||||||
int create_thread(void* function, void* stack, int stack_size,
|
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.
|
Create a thread.
|
||||||
??? (see firmware/thread.c:145)
|
??? (see firmware/thread.c:145)
|
||||||
|
|
|
@ -582,7 +582,8 @@ void backlight_init(void)
|
||||||
|
|
||||||
create_thread(backlight_thread, backlight_stack,
|
create_thread(backlight_thread, backlight_stack,
|
||||||
sizeof(backlight_stack), backlight_thread_name
|
sizeof(backlight_stack), backlight_thread_name
|
||||||
IF_PRIO(, PRIORITY_SYSTEM));
|
IF_PRIO(, PRIORITY_SYSTEM)
|
||||||
|
IF_COP(, CPU, false));
|
||||||
tick_add_task(backlight_tick);
|
tick_add_task(backlight_tick);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -701,7 +701,8 @@ void dircache_init(void)
|
||||||
|
|
||||||
queue_init(&dircache_queue, true);
|
queue_init(&dircache_queue, true);
|
||||||
create_thread(dircache_thread, dircache_stack,
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -991,7 +991,8 @@ int ata_init(void)
|
||||||
last_disk_activity = current_tick;
|
last_disk_activity = current_tick;
|
||||||
create_thread(ata_thread, ata_stack,
|
create_thread(ata_thread, ata_stack,
|
||||||
sizeof(ata_stack), ata_thread_name
|
sizeof(ata_stack), ata_thread_name
|
||||||
IF_PRIO(, PRIORITY_SYSTEM));
|
IF_PRIO(, PRIORITY_SYSTEM)
|
||||||
|
IF_COP(, CPU, false));
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1173,7 +1173,8 @@ int ata_init(void)
|
||||||
|
|
||||||
queue_init(&mmc_queue, true);
|
queue_init(&mmc_queue, true);
|
||||||
create_thread(mmc_thread, mmc_stack,
|
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);
|
tick_add_task(mmc_tick);
|
||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,8 @@ void lcd_init(void)
|
||||||
|
|
||||||
create_thread(scroll_thread, scroll_stack,
|
create_thread(scroll_thread, scroll_stack,
|
||||||
sizeof(scroll_stack), scroll_name
|
sizeof(scroll_stack), scroll_name
|
||||||
IF_PRIO(, PRIORITY_USER_INTERFACE));
|
IF_PRIO(, PRIORITY_USER_INTERFACE)
|
||||||
|
IF_COP(, CPU, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*** parameter handling ***/
|
/*** parameter handling ***/
|
||||||
|
|
|
@ -68,7 +68,8 @@ void lcd_init(void)
|
||||||
/* Call device specific init */
|
/* Call device specific init */
|
||||||
lcd_init_device();
|
lcd_init_device();
|
||||||
create_thread(scroll_thread, scroll_stack,
|
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 ***/
|
/*** parameter handling ***/
|
||||||
|
|
|
@ -79,7 +79,8 @@ void lcd_init(void)
|
||||||
/* Call device specific init */
|
/* Call device specific init */
|
||||||
lcd_init_device();
|
lcd_init_device();
|
||||||
create_thread(scroll_thread, scroll_stack,
|
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 ***/
|
/*** parameter handling ***/
|
||||||
|
|
|
@ -82,7 +82,8 @@ void lcd_init(void)
|
||||||
/* Call device specific init */
|
/* Call device specific init */
|
||||||
lcd_init_device();
|
lcd_init_device();
|
||||||
create_thread(scroll_thread, scroll_stack,
|
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 ***/
|
/*** parameter handling ***/
|
||||||
|
|
|
@ -610,7 +610,8 @@ void lcd_init (void)
|
||||||
lcd_set_contrast(lcd_default_contrast());
|
lcd_set_contrast(lcd_default_contrast());
|
||||||
|
|
||||||
create_thread(scroll_thread, scroll_stack,
|
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 */
|
void lcd_jump_scroll (int mode) /* 0=off, 1=once, ..., JUMP_SCROLL_ALWAYS */
|
||||||
|
|
|
@ -903,5 +903,6 @@ void lcd_remote_init(void)
|
||||||
queue_init(&remote_scroll_queue, false);
|
queue_init(&remote_scroll_queue, false);
|
||||||
#endif
|
#endif
|
||||||
create_thread(scroll_thread, scroll_stack,
|
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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1241,5 +1241,6 @@ void lcd_remote_init(void)
|
||||||
queue_init(&remote_scroll_queue, false);
|
queue_init(&remote_scroll_queue, false);
|
||||||
#endif
|
#endif
|
||||||
create_thread(scroll_thread, scroll_stack,
|
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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -273,21 +273,6 @@
|
||||||
/* define for all cpus from PP family */
|
/* define for all cpus from PP family */
|
||||||
#if (CONFIG_CPU == PP5002) || (CONFIG_CPU == PP5020) || (CONFIG_CPU == PP5024)
|
#if (CONFIG_CPU == PP5002) || (CONFIG_CPU == PP5020) || (CONFIG_CPU == PP5024)
|
||||||
#define CPU_PP
|
#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
|
#endif
|
||||||
|
|
||||||
/* define for all cpus from ARM family */
|
/* define for all cpus from ARM family */
|
||||||
|
@ -348,4 +333,28 @@
|
||||||
#define IRAM_LCDFRAMEBUFFER
|
#define IRAM_LCDFRAMEBUFFER
|
||||||
#endif
|
#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
|
#endif
|
||||||
|
|
|
@ -73,6 +73,9 @@
|
||||||
#define CPU_INT_STAT (*(volatile unsigned long*)(0xcf001000))
|
#define CPU_INT_STAT (*(volatile unsigned long*)(0xcf001000))
|
||||||
#define CPU_INT_EN (*(volatile unsigned long*)(0xcf001024))
|
#define CPU_INT_EN (*(volatile unsigned long*)(0xcf001024))
|
||||||
#define CPU_INT_CLR (*(volatile unsigned long*)(0xcf001028))
|
#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 USB2D_IDENT (*(volatile unsigned long*)(0xc5000000))
|
||||||
#define USB_STATUS (*(volatile unsigned long*)(0xc50001a4))
|
#define USB_STATUS (*(volatile unsigned long*)(0xc50001a4))
|
||||||
|
|
|
@ -30,6 +30,15 @@
|
||||||
#define PROC_ID_CPU 0x55
|
#define PROC_ID_CPU 0x55
|
||||||
#define PROC_ID_COP 0xaa
|
#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 */
|
/* Interrupts */
|
||||||
#define CPU_INT_STAT (*(volatile unsigned long*)(0x64004000))
|
#define CPU_INT_STAT (*(volatile unsigned long*)(0x64004000))
|
||||||
#define COP_INT_STAT (*(volatile unsigned long*)(0x60004004))
|
#define COP_INT_STAT (*(volatile unsigned long*)(0x60004004))
|
||||||
|
|
|
@ -124,13 +124,8 @@ struct core_entry {
|
||||||
|
|
||||||
struct thread_entry*
|
struct thread_entry*
|
||||||
create_thread(void (*function)(void), void* stack, int stack_size,
|
create_thread(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));
|
||||||
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 HAVE_SCHEDULER_BOOSTCTRL
|
#ifdef HAVE_SCHEDULER_BOOSTCTRL
|
||||||
void trigger_cpu_boost(void);
|
void trigger_cpu_boost(void);
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#include "panic.h"
|
#include "panic.h"
|
||||||
|
|
||||||
#if !defined(CPU_PP) || !defined(BOOTLOADER)
|
#if !defined(CPU_PP) || !defined(BOOTLOADER)
|
||||||
long current_tick = 0;
|
long current_tick NOCACHEDATA_ATTR = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void (*tick_funcs[MAX_NUM_TICK_TASKS])(void);
|
static void (*tick_funcs[MAX_NUM_TICK_TASKS])(void);
|
||||||
|
@ -45,10 +45,13 @@ void kernel_init(void)
|
||||||
/* Init the threading API */
|
/* Init the threading API */
|
||||||
init_threads();
|
init_threads();
|
||||||
|
|
||||||
|
if(CURRENT_CORE == CPU)
|
||||||
|
{
|
||||||
memset(tick_funcs, 0, sizeof(tick_funcs));
|
memset(tick_funcs, 0, sizeof(tick_funcs));
|
||||||
|
|
||||||
num_queues = 0;
|
num_queues = 0;
|
||||||
memset(all_queues, 0, sizeof(all_queues));
|
memset(all_queues, 0, sizeof(all_queues));
|
||||||
|
}
|
||||||
|
|
||||||
tick_start(1000/HZ);
|
tick_start(1000/HZ);
|
||||||
}
|
}
|
||||||
|
@ -496,7 +499,9 @@ void TIMER1(void)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
TIMER1_VAL; /* Read value to ack IRQ */
|
TIMER1_VAL; /* Read value to ack IRQ */
|
||||||
/* Run through the list of tick tasks */
|
/* Run through the list of tick tasks (using main core) */
|
||||||
|
if (CURRENT_CORE == CPU)
|
||||||
|
{
|
||||||
for (i = 0;i < MAX_NUM_TICK_TASKS;i++)
|
for (i = 0;i < MAX_NUM_TICK_TASKS;i++)
|
||||||
{
|
{
|
||||||
if (tick_funcs[i])
|
if (tick_funcs[i])
|
||||||
|
@ -507,17 +512,23 @@ void TIMER1(void)
|
||||||
|
|
||||||
current_tick++;
|
current_tick++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void tick_start(unsigned int interval_in_ms)
|
void tick_start(unsigned int interval_in_ms)
|
||||||
{
|
{
|
||||||
#ifndef BOOTLOADER
|
#ifndef BOOTLOADER
|
||||||
|
if(CURRENT_CORE == CPU)
|
||||||
|
{
|
||||||
TIMER1_CFG = 0x0;
|
TIMER1_CFG = 0x0;
|
||||||
TIMER1_VAL;
|
TIMER1_VAL;
|
||||||
/* enable timer */
|
/* enable timer */
|
||||||
TIMER1_CFG = 0xc0000000 | (interval_in_ms*1000 - 1);
|
TIMER1_CFG = 0xc0000000 | (interval_in_ms*1000 - 1);
|
||||||
/* unmask interrupt source */
|
/* unmask interrupt source */
|
||||||
CPU_INT_EN = TIMER1_MASK;
|
CPU_INT_EN = TIMER1_MASK;
|
||||||
|
} else {
|
||||||
|
COP_INT_EN = TIMER1_MASK;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
/* We don't enable interrupts in the bootloader */
|
/* We don't enable interrupts in the bootloader */
|
||||||
(void)interval_in_ms;
|
(void)interval_in_ms;
|
||||||
|
@ -645,6 +656,29 @@ void mutex_init(struct mutex *m)
|
||||||
m->thread = NULL;
|
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)
|
void mutex_lock(struct mutex *m)
|
||||||
{
|
{
|
||||||
if (m->locked)
|
if (m->locked)
|
||||||
|
@ -656,6 +690,7 @@ void mutex_lock(struct mutex *m)
|
||||||
/* ...and lock it */
|
/* ...and lock it */
|
||||||
m->locked = true;
|
m->locked = true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void mutex_unlock(struct mutex *m)
|
void mutex_unlock(struct mutex *m)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2905,7 +2905,8 @@ void audio_init(void)
|
||||||
queue_init(&mpeg_queue, true);
|
queue_init(&mpeg_queue, true);
|
||||||
#endif /* !SIMULATOR */
|
#endif /* !SIMULATOR */
|
||||||
create_thread(mpeg_thread, mpeg_stack,
|
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);
|
memset(trackdata, sizeof(trackdata), 0);
|
||||||
|
|
||||||
|
|
|
@ -418,7 +418,8 @@ void pcm_rec_init(void)
|
||||||
queue_enable_queue_send(&pcmrec_queue, &pcmrec_queue_send);
|
queue_enable_queue_send(&pcmrec_queue, &pcmrec_queue_send);
|
||||||
pcmrec_thread_p =
|
pcmrec_thread_p =
|
||||||
create_thread(pcmrec_thread, pcmrec_stack, sizeof(pcmrec_stack),
|
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 */
|
} /* pcm_rec_init */
|
||||||
|
|
||||||
/** audio_* group **/
|
/** audio_* group **/
|
||||||
|
|
|
@ -1245,7 +1245,8 @@ void powermgmt_init(void)
|
||||||
/* init history to 0 */
|
/* init history to 0 */
|
||||||
memset(power_history, 0x00, sizeof(power_history));
|
memset(power_history, 0x00, sizeof(power_history));
|
||||||
create_thread(power_thread, power_stack, sizeof(power_stack),
|
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 */
|
#endif /* SIMULATOR */
|
||||||
|
|
|
@ -611,6 +611,8 @@ extern void TIMER2(void);
|
||||||
extern void ipod_mini_button_int(void);
|
extern void ipod_mini_button_int(void);
|
||||||
|
|
||||||
void irq(void)
|
void irq(void)
|
||||||
|
{
|
||||||
|
if(CURRENT_CORE == CPU)
|
||||||
{
|
{
|
||||||
if (CPU_INT_STAT & TIMER1_MASK)
|
if (CPU_INT_STAT & TIMER1_MASK)
|
||||||
TIMER1();
|
TIMER1();
|
||||||
|
@ -618,6 +620,14 @@ void irq(void)
|
||||||
TIMER2();
|
TIMER2();
|
||||||
else if (CPU_HI_INT_STAT & GPIO_MASK)
|
else if (CPU_HI_INT_STAT & GPIO_MASK)
|
||||||
ipod_mini_button_int();
|
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) \
|
#elif (defined IRIVER_H10) || (defined IRIVER_H10_5GB) || defined(ELIO_TPJ1022) \
|
||||||
|| (defined SANSA_E200)
|
|| (defined SANSA_E200)
|
||||||
|
@ -625,16 +635,26 @@ void irq(void)
|
||||||
crt0.S not to find it while linking */
|
crt0.S not to find it while linking */
|
||||||
/* TODO: Even if it isn't in the target tree, this should be the default case */
|
/* TODO: Even if it isn't in the target tree, this should be the default case */
|
||||||
void irq(void)
|
void irq(void)
|
||||||
|
{
|
||||||
|
if(CURRENT_CORE == CPU)
|
||||||
{
|
{
|
||||||
if (CPU_INT_STAT & TIMER1_MASK)
|
if (CPU_INT_STAT & TIMER1_MASK)
|
||||||
TIMER1();
|
TIMER1();
|
||||||
else if (CPU_INT_STAT & TIMER2_MASK)
|
else if (CPU_INT_STAT & TIMER2_MASK)
|
||||||
TIMER2();
|
TIMER2();
|
||||||
|
} else {
|
||||||
|
if (COP_INT_STAT & TIMER1_MASK)
|
||||||
|
TIMER1();
|
||||||
|
else if (COP_INT_STAT & TIMER2_MASK)
|
||||||
|
TIMER2();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
extern void ipod_4g_button_int(void);
|
extern void ipod_4g_button_int(void);
|
||||||
|
|
||||||
void irq(void)
|
void irq(void)
|
||||||
|
{
|
||||||
|
if(CURRENT_CORE == CPU)
|
||||||
{
|
{
|
||||||
if (CPU_INT_STAT & TIMER1_MASK)
|
if (CPU_INT_STAT & TIMER1_MASK)
|
||||||
TIMER1();
|
TIMER1();
|
||||||
|
@ -642,6 +662,14 @@ void irq(void)
|
||||||
TIMER2();
|
TIMER2();
|
||||||
else if (CPU_HI_INT_STAT & I2C_MASK)
|
else if (CPU_HI_INT_STAT & I2C_MASK)
|
||||||
ipod_4g_button_int();
|
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
|
||||||
#endif /* BOOTLOADER */
|
#endif /* BOOTLOADER */
|
||||||
|
@ -694,6 +722,8 @@ void set_cpu_frequency(long frequency)
|
||||||
{
|
{
|
||||||
unsigned long postmult;
|
unsigned long postmult;
|
||||||
|
|
||||||
|
if (CURRENT_CORE == CPU)
|
||||||
|
{
|
||||||
if (frequency == CPUFREQ_NORMAL)
|
if (frequency == CPUFREQ_NORMAL)
|
||||||
postmult = CPUFREQ_NORMAL_MULT;
|
postmult = CPUFREQ_NORMAL_MULT;
|
||||||
else if (frequency == CPUFREQ_MAX)
|
else if (frequency == CPUFREQ_MAX)
|
||||||
|
@ -730,8 +760,10 @@ void set_cpu_frequency(long frequency)
|
||||||
|
|
||||||
/* unmask interrupt source */
|
/* unmask interrupt source */
|
||||||
CPU_INT_EN |= TIMER1_MASK;
|
CPU_INT_EN |= TIMER1_MASK;
|
||||||
|
COP_INT_EN |= TIMER1_MASK;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#elif !defined(BOOTLOADER)
|
#elif !defined(BOOTLOADER)
|
||||||
void ipod_set_cpu_frequency(void)
|
void ipod_set_cpu_frequency(void)
|
||||||
{
|
{
|
||||||
|
@ -754,6 +786,8 @@ void ipod_set_cpu_frequency(void)
|
||||||
void system_init(void)
|
void system_init(void)
|
||||||
{
|
{
|
||||||
#ifndef BOOTLOADER
|
#ifndef BOOTLOADER
|
||||||
|
if (CURRENT_CORE == CPU)
|
||||||
|
{
|
||||||
/* Remap the flash ROM from 0x00000000 to 0x20000000. */
|
/* Remap the flash ROM from 0x00000000 to 0x20000000. */
|
||||||
MMAP3_LOGICAL = 0x20000000 | 0x3a00;
|
MMAP3_LOGICAL = 0x20000000 | 0x3a00;
|
||||||
MMAP3_PHYSICAL = 0x00000000 | 0x3f84;
|
MMAP3_PHYSICAL = 0x00000000 | 0x3f84;
|
||||||
|
@ -770,8 +804,15 @@ void system_init(void)
|
||||||
outl(-1, 0x60001038);
|
outl(-1, 0x60001038);
|
||||||
outl(-1, 0x60001028);
|
outl(-1, 0x60001028);
|
||||||
outl(-1, 0x6000101c);
|
outl(-1, 0x6000101c);
|
||||||
#ifndef HAVE_ADJUSTABLE_CPU_FREQ
|
#if (!defined HAVE_ADJUSTABLE_CPU_FREQ) && (NUM_CORES == 1)
|
||||||
ipod_set_cpu_frequency();
|
ipod_set_cpu_frequency();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#if (!defined HAVE_ADJUSTABLE_CPU_FREQ) && (NUM_CORES > 1)
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ipod_set_cpu_frequency();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
ipod_init_cache();
|
ipod_init_cache();
|
||||||
#endif
|
#endif
|
||||||
|
@ -795,11 +836,19 @@ extern void TIMER1(void);
|
||||||
extern void TIMER2(void);
|
extern void TIMER2(void);
|
||||||
|
|
||||||
void irq(void)
|
void irq(void)
|
||||||
|
{
|
||||||
|
if(CURRENT_CORE == CPU)
|
||||||
{
|
{
|
||||||
if (CPU_INT_STAT & TIMER1_MASK)
|
if (CPU_INT_STAT & TIMER1_MASK)
|
||||||
TIMER1();
|
TIMER1();
|
||||||
else if (CPU_INT_STAT & TIMER2_MASK)
|
else if (CPU_INT_STAT & TIMER2_MASK)
|
||||||
TIMER2();
|
TIMER2();
|
||||||
|
} else {
|
||||||
|
if (COP_INT_STAT & TIMER1_MASK)
|
||||||
|
TIMER1();
|
||||||
|
else if (COP_INT_STAT & TIMER2_MASK)
|
||||||
|
TIMER2();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -848,6 +897,8 @@ void set_cpu_frequency(long frequency)
|
||||||
{
|
{
|
||||||
unsigned long postmult;
|
unsigned long postmult;
|
||||||
|
|
||||||
|
if (CURRENT_CORE == CPU)
|
||||||
|
{
|
||||||
if (frequency == CPUFREQ_NORMAL)
|
if (frequency == CPUFREQ_NORMAL)
|
||||||
postmult = CPUFREQ_NORMAL_MULT;
|
postmult = CPUFREQ_NORMAL_MULT;
|
||||||
else if (frequency == CPUFREQ_MAX)
|
else if (frequency == CPUFREQ_MAX)
|
||||||
|
@ -872,6 +923,7 @@ void set_cpu_frequency(long frequency)
|
||||||
/* Select PLL as clock source? */
|
/* Select PLL as clock source? */
|
||||||
outl(0xa8, 0xcf00500c);
|
outl(0xa8, 0xcf00500c);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#elif !defined(BOOTLOADER)
|
#elif !defined(BOOTLOADER)
|
||||||
static void ipod_set_cpu_speed(void)
|
static void ipod_set_cpu_speed(void)
|
||||||
{
|
{
|
||||||
|
@ -901,6 +953,8 @@ static void ipod_set_cpu_speed(void)
|
||||||
void system_init(void)
|
void system_init(void)
|
||||||
{
|
{
|
||||||
#ifndef BOOTLOADER
|
#ifndef BOOTLOADER
|
||||||
|
if (CURRENT_CORE == CPU)
|
||||||
|
{
|
||||||
/* Remap the flash ROM from 0x00000000 to 0x20000000. */
|
/* Remap the flash ROM from 0x00000000 to 0x20000000. */
|
||||||
MMAP3_LOGICAL = 0x20000000 | 0x3a00;
|
MMAP3_LOGICAL = 0x20000000 | 0x3a00;
|
||||||
MMAP3_PHYSICAL = 0x00000000 | 0x3f84;
|
MMAP3_PHYSICAL = 0x00000000 | 0x3f84;
|
||||||
|
@ -912,6 +966,7 @@ void system_init(void)
|
||||||
#ifndef HAVE_ADJUSTABLE_CPU_FREQ
|
#ifndef HAVE_ADJUSTABLE_CPU_FREQ
|
||||||
ipod_set_cpu_speed();
|
ipod_set_cpu_speed();
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
ipod_init_cache();
|
ipod_init_cache();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,6 +222,19 @@ cop_init:
|
||||||
strhi r4, [r2], #4
|
strhi r4, [r2], #4
|
||||||
bhi 2b
|
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
|
ldr sp, =cop_stackend
|
||||||
|
|
||||||
/* Run cop_main() in apps/main.c */
|
/* Run cop_main() in apps/main.c */
|
||||||
|
@ -307,6 +320,10 @@ UIE:
|
||||||
.space 256*4
|
.space 256*4
|
||||||
irq_stack:
|
irq_stack:
|
||||||
|
|
||||||
|
/* 256 words of COP IRQ stack */
|
||||||
|
.space 256*4
|
||||||
|
cop_irq_stack:
|
||||||
|
|
||||||
/* 256 words of FIQ stack */
|
/* 256 words of FIQ stack */
|
||||||
.space 256*4
|
.space 256*4
|
||||||
fiq_stack:
|
fiq_stack:
|
||||||
|
|
|
@ -687,7 +687,8 @@ int ata_init(void)
|
||||||
{
|
{
|
||||||
queue_init(&sd_queue, true);
|
queue_init(&sd_queue, true);
|
||||||
create_thread(sd_thread, sd_stack,
|
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;
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,10 @@ int *cop_stackend = stackend;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (NUM_CORES > 1)
|
||||||
|
bool IDATA_ATTR kernel_running_on_cop = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Conserve IRAM
|
/* Conserve IRAM
|
||||||
static void add_to_list(struct thread_entry **list,
|
static void add_to_list(struct thread_entry **list,
|
||||||
struct thread_entry *thread) ICODE_ATTR;
|
struct thread_entry *thread) ICODE_ATTR;
|
||||||
|
@ -316,10 +320,13 @@ static inline void sleep_core(void)
|
||||||
#elif CONFIG_CPU == SH7034
|
#elif CONFIG_CPU == SH7034
|
||||||
and_b(0x7F, &SBYCR);
|
and_b(0x7F, &SBYCR);
|
||||||
asm volatile ("sleep");
|
asm volatile ("sleep");
|
||||||
#elif CONFIG_CPU == PP5020
|
#elif defined (CPU_PP)
|
||||||
/* This should sleep the CPU. It appears to wake by itself on
|
/* This should sleep the CPU. It appears to wake by itself on
|
||||||
interrupts */
|
interrupts */
|
||||||
CPU_CTL = 0x80000000;
|
if (CURRENT_CORE == CPU)
|
||||||
|
CPU_CTL = PROC_SLEEP;
|
||||||
|
else
|
||||||
|
COP_CTL = PROC_SLEEP;
|
||||||
#elif CONFIG_CPU == S3C2440
|
#elif CONFIG_CPU == S3C2440
|
||||||
CLKCON |= (1 << 2); /* set IDLE bit */
|
CLKCON |= (1 << 2); /* set IDLE bit */
|
||||||
for(i=0; i<10; i++); /* wait for IDLE */
|
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.
|
* Create a thread
|
||||||
* Return ID if context area could be allocated, else -1.
|
* 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*
|
struct thread_entry*
|
||||||
create_thread(void (*function)(void), void* stack, int stack_size,
|
create_thread(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))
|
||||||
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))
|
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
unsigned int stacklen;
|
unsigned int stacklen;
|
||||||
|
@ -637,6 +633,29 @@ struct thread_entry*
|
||||||
struct regs *regs;
|
struct regs *regs;
|
||||||
struct thread_entry *thread;
|
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++)
|
for (n = 0; n < MAXTHREADS; n++)
|
||||||
{
|
{
|
||||||
if (cores[core].threads[n].name == NULL)
|
if (cores[core].threads[n].name == NULL)
|
||||||
|
@ -644,8 +663,15 @@ struct thread_entry*
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n == MAXTHREADS)
|
if (n == MAXTHREADS)
|
||||||
|
{
|
||||||
|
#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;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Munge the stack to make it easy to spot stack overflows */
|
/* Munge the stack to make it easy to spot stack overflows */
|
||||||
stacklen = stack_size / sizeof(int);
|
stacklen = stack_size / sizeof(int);
|
||||||
|
@ -677,6 +703,9 @@ struct thread_entry*
|
||||||
THREAD_CPU_INIT(core, thread);
|
THREAD_CPU_INIT(core, thread);
|
||||||
|
|
||||||
return thread;
|
return thread;
|
||||||
|
#if NUM_CORES == 1
|
||||||
|
#undef core
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_SCHEDULER_BOOSTCTRL
|
#ifdef HAVE_SCHEDULER_BOOSTCTRL
|
||||||
|
@ -751,6 +780,7 @@ void init_threads(void)
|
||||||
{
|
{
|
||||||
unsigned int core = CURRENT_CORE;
|
unsigned int core = CURRENT_CORE;
|
||||||
|
|
||||||
|
if (core == CPU)
|
||||||
memset(cores, 0, sizeof cores);
|
memset(cores, 0, sizeof cores);
|
||||||
cores[core].sleeping = NULL;
|
cores[core].sleeping = NULL;
|
||||||
cores[core].running = NULL;
|
cores[core].running = NULL;
|
||||||
|
@ -779,6 +809,10 @@ void init_threads(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
cores[core].threads[0].context.start = 0; /* thread 0 already running */
|
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)
|
int thread_stack_usage(const struct thread_entry *thread)
|
||||||
|
|
|
@ -428,7 +428,8 @@ void usb_init(void)
|
||||||
#ifndef BOOTLOADER
|
#ifndef BOOTLOADER
|
||||||
queue_init(&usb_queue, true);
|
queue_init(&usb_queue, true);
|
||||||
create_thread(usb_thread, usb_stack, sizeof(usb_stack),
|
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);
|
tick_add_task(usb_tick);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -258,12 +258,6 @@ void remove_thread(int threadnum)
|
||||||
(void)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 */
|
/* assure an unused place to direct virtual pointers to */
|
||||||
#define VIRT_SIZE 0xFFFF /* more than enough for our string ID range */
|
#define VIRT_SIZE 0xFFFF /* more than enough for our string ID range */
|
||||||
unsigned char vp_dummy[VIRT_SIZE];
|
unsigned char vp_dummy[VIRT_SIZE];
|
||||||
|
|
|
@ -75,12 +75,6 @@ int create_thread(void (*fp)(void), void* sp, int stk_size)
|
||||||
return 0;
|
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)
|
void init_threads(void)
|
||||||
{
|
{
|
||||||
m = SDL_CreateMutex();
|
m = SDL_CreateMutex();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue