From 0aec12f3fd801c5acc03a75818e06741957d51b9 Mon Sep 17 00:00:00 2001 From: Daniel Ankers Date: Mon, 21 Aug 2006 17:35:35 +0000 Subject: [PATCH] Threading changes in preparation for multiple core support git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10681 a1c6a512-1295-4272-9138-f99709370657 --- apps/debug_menu.c | 205 ++++++++++++++++++++------------------- firmware/export/config.h | 17 ++++ firmware/export/system.h | 14 +-- firmware/export/thread.h | 4 + firmware/system.c | 102 +++++++++++-------- firmware/thread.c | 174 +++++++++++++++++++++------------ 6 files changed, 309 insertions(+), 207 deletions(-) diff --git a/apps/debug_menu.c b/apps/debug_menu.c index c3a0d93dc6..69149767cc 100644 --- a/apps/debug_menu.c +++ b/apps/debug_menu.c @@ -78,8 +78,8 @@ /*---------------------------------------------------*/ extern char ata_device; extern int ata_io_address; -extern int num_threads; -extern const char *thread_name[]; +extern int num_threads[]; +extern const char *thread_name[][MAXTHREADS]; #ifdef HAVE_LCD_BITMAP /* Test code!!! */ @@ -88,6 +88,8 @@ bool dbg_os(void) char buf[32]; int i; int usage; + unsigned int core; + int line; lcd_setmargins(0, 0); lcd_setfont(FONT_SYSFIXED); @@ -95,12 +97,16 @@ bool dbg_os(void) while(1) { - lcd_puts(0, 0, "Stack usage:"); - for(i = 0; i < num_threads;i++) + lcd_puts(0, 0, "Core and stack usage:"); + line = 0; + for(core = 0; core < NUM_CORES; core++) { - usage = thread_stack_usage(i); - snprintf(buf, 32, "%s: %d%%", thread_name[i], usage); - lcd_puts(0, 1+i, buf); + for(i = 0; i < num_threads[core]; i++) + { + usage = thread_stack_usage_on_core(core, i); + snprintf(buf, 32, "(%d) %s: %d%%", core, thread_name[core][i], usage); + lcd_puts(0, ++line, buf); + } } lcd_update(); @@ -124,10 +130,11 @@ bool dbg_os(void) { lcd_puts(0, 0, "Stack usage"); + /* Only Archos Player uses this - so assume a single core */ usage = thread_stack_usage(currval); snprintf(buf, 32, "%d: %d%% ", currval, usage); lcd_puts(0, 1, buf); - + button = get_action(CONTEXT_SETTINGS,HZ/10); switch(button) @@ -162,14 +169,14 @@ bool dbg_audio_thread(void) lcd_setmargins(0, 0); lcd_setfont(FONT_SYSFIXED); - + while(1) { if (action_userabort(HZ/5)) return false; audio_get_debugdata(&d); - + lcd_clear_display(); snprintf(buf, sizeof(buf), "read: %x", d.audiobuf_read); @@ -186,17 +193,17 @@ bool dbg_audio_thread(void) lcd_puts(0, 5, buf); /* Playable space left */ - scrollbar(0, 6*8, 112, 4, d.audiobuflen, 0, + scrollbar(0, 6*8, 112, 4, d.audiobuflen, 0, d.playable_space, HORIZONTAL); /* Show the watermark limit */ - scrollbar(0, 6*8+4, 112, 4, d.audiobuflen, 0, + scrollbar(0, 6*8+4, 112, 4, d.audiobuflen, 0, d.low_watermark_level, HORIZONTAL); snprintf(buf, sizeof(buf), "wm: %x - %x", d.low_watermark_level, d.lowest_watermark_level); lcd_puts(0, 7, buf); - + lcd_update(); } return false; @@ -229,7 +236,7 @@ bool dbg_audio_thread(void) ticks = boost_ticks = 0; tick_add_task(dbg_audio_task); - + lcd_setmargins(0, 0); lcd_setfont(FONT_SYSFIXED); while(!done) @@ -249,7 +256,7 @@ bool dbg_audio_thread(void) } action_signalscreenchange(); line = 0; - + lcd_clear_display(); bufused = bufsize - pcmbuf_free(); @@ -283,12 +290,12 @@ bool dbg_audio_thread(void) snprintf(buf, sizeof(buf), "pcmbufdesc: %2d/%2d", pcmbuf_used_descs(), pcmbufdescs); lcd_puts(0, line++, buf); - + lcd_update(); } tick_remove_task(dbg_audio_task); - + return false; } #endif /* CONFIG_CODEC */ @@ -303,7 +310,7 @@ static void flash_write_word(unsigned addr, unsigned value) { flash_word_temp = value; long extAddr = (long)addr << 1; - ddma_transfer(1, 1, &flash_word_temp, extAddr, 2); + ddma_transfer(1, 1, &flash_word_temp, extAddr, 2); } static unsigned flash_read_word(unsigned addr) __attribute__ ((section(".icode"))); @@ -324,7 +331,7 @@ bool dbg_flash_id(unsigned* p_manufacturer, unsigned* p_device, __attribute__ ((section (".icode"))); bool dbg_flash_id(unsigned* p_manufacturer, unsigned* p_device, unsigned addr1, unsigned addr2) - + { #if (CONFIG_CPU == PP5002) || (CONFIG_CPU == PP5020) /* TODO: Implement for iPod */ @@ -382,9 +389,9 @@ bool dbg_flash_id(unsigned* p_manufacturer, unsigned* p_device, /* sleep(HZ/50); no sleeping possible while interrupts are disabled */ set_irq_level(old_level); /* enable interrupts again */ - + /* I assume success if the obtained values are different from - the normal flash content. This is not perfectly bulletproof, they + the normal flash content. This is not perfectly bulletproof, they could theoretically be the same by chance, causing us to fail. */ if (not_manu != manu || not_id != id) /* a value has changed */ { @@ -431,7 +438,7 @@ bool dbg_hw_info(void) got_id = dbg_flash_id(&manu, &id, 0x5555, 0x2AAA); /* try SST, Atmel, NexFlash */ if (!got_id) got_id = dbg_flash_id(&manu, &id, 0x555, 0x2AA); /* try AMD, Macronix */ - + /* check if the boot ROM area is a flash mirror */ has_bootrom = (memcmp((char*)0, (char*)0x02000000, 64*1024) != 0); if (has_bootrom) /* if ROM and Flash different */ @@ -450,16 +457,16 @@ bool dbg_hw_info(void) snprintf(buf, 32, "ROM: %d.%02d", rom_version/100, rom_version%100); lcd_puts(0, 1, buf); - + snprintf(buf, 32, "Mask: 0x%04x", bitmask); lcd_puts(0, 2, buf); - + snprintf(buf, 32, "USB: %s", usb_polarity?"positive":"negative"); lcd_puts(0, 3, buf); - + snprintf(buf, 32, "PR: %s", pr_polarity?"positive":"negative"); lcd_puts(0, 4, buf); - + if (got_id) snprintf(buf, 32, "Flash: M=%02x D=%02x", manu, id); else @@ -483,7 +490,7 @@ bool dbg_hw_info(void) snprintf(buf, 32, "ATA: 0x%x,%s", ata_io_address, ata_device ? "slave":"master"); lcd_puts(0, 7, buf); -#endif +#endif lcd_update(); while(1) @@ -503,7 +510,7 @@ bool dbg_hw_info(void) got_id = dbg_flash_id(&manu, &id, 0x5555, 0x2AAA); /* try SST, Atmel, NexFlash */ if (!got_id) got_id = dbg_flash_id(&manu, &id, 0x555, 0x2AA); /* try AMD, Macronix */ - + system_memory_guard(oldmode); /* re-enable memory guard */ lcd_setmargins(0, 0); @@ -533,7 +540,7 @@ bool dbg_hw_info(void) lcd_clear_display(); lcd_puts(0, 0, "[Hardware info]"); - + snprintf(buf, sizeof(buf), "HW rev: 0x%08x", ipod_hw_rev); lcd_puts(0, 1, buf); @@ -581,7 +588,7 @@ bool dbg_hw_info(void) /* calculate CRC16 checksum of boot ROM */ rom_crc = crc_32((unsigned char*)0x0000, 64*1024, 0xffffffff); } - + system_memory_guard(oldmode); /* re-enable memory guard */ lcd_clear_display(); @@ -617,7 +624,7 @@ bool dbg_hw_info(void) { if (rom_crc == 0x56DBA4EE) /* known Version 1 */ snprintf(buf, 32, "BootROM: V1"); - else if (rom_crc == 0x358099E8) + else if (rom_crc == 0x358099E8) snprintf(buf, 32, "BootROM: V2"); /* alternative boot ROM found in one single player so far */ else @@ -626,10 +633,10 @@ bool dbg_hw_info(void) else snprintf(buf, 32, "BootROM: no"); } - + lcd_puts(0, 1, buf); lcd_update(); - + button = get_action(CONTEXT_SETTINGS,TIMEOUT_BLOCK); switch(button) @@ -643,7 +650,7 @@ bool dbg_hw_info(void) if(currval < 0) currval = 5; break; - + case ACTION_SETTINGS_INC: currval++; if(currval > 5) @@ -677,7 +684,7 @@ bool dbg_partitions(void) snprintf(buf, sizeof buf, "T:%x %ld MB", p->type, p->size / 2048); lcd_puts(0, 1, buf); lcd_update(); - + button = get_action(CONTEXT_SETTINGS,TIMEOUT_BLOCK); switch(button) @@ -691,7 +698,7 @@ bool dbg_partitions(void) if (partition < 0) partition = 3; break; - + case ACTION_SETTINGS_INC: partition++; if (partition > 3) @@ -751,22 +758,22 @@ bool dbg_spdif(void) lcd_puts(0, line++, buf); line++; - + x = control >> 31; snprintf(buf, sizeof(buf), "PRO: %d (%s)", x, x?"Professional":"Consumer"); lcd_puts(0, line++, buf); - + x = (control >> 30) & 1; snprintf(buf, sizeof(buf), "Audio: %d (%s)", x, x?"Non-PCM":"PCM"); lcd_puts(0, line++, buf); - + x = (control >> 29) & 1; snprintf(buf, sizeof(buf), "Copy: %d (%s)", x, x?"Permitted":"Inhibited"); lcd_puts(0, line++, buf); - + x = (control >> 27) & 7; switch(x) { @@ -786,7 +793,7 @@ bool dbg_spdif(void) x = (control >> 24) & 3; snprintf(buf, sizeof(buf), "Mode: %d", x); lcd_puts(0, line++, buf); - + category = (control >> 17) & 127; switch(category) { @@ -801,7 +808,7 @@ bool dbg_spdif(void) } snprintf(buf, sizeof(buf), "Category: 0x%02x (%s)", category, s); lcd_puts(0, line++, buf); - + x = (control >> 16) & 1; generation = x; if(((category & 0x70) == 0x10) || @@ -813,11 +820,11 @@ bool dbg_spdif(void) snprintf(buf, sizeof(buf), "Generation: %d (%s)", x, generation?"Original":"No ind."); lcd_puts(0, line++, buf); - + x = (control >> 12) & 15; snprintf(buf, sizeof(buf), "Source: %d", x); lcd_puts(0, line++, buf); - + x = (control >> 8) & 15; switch(x) { @@ -836,7 +843,7 @@ bool dbg_spdif(void) } snprintf(buf, sizeof(buf), "Channel: %d (%s)", x, s); lcd_puts(0, line++, buf); - + x = (control >> 4) & 15; switch(x) { @@ -857,7 +864,7 @@ bool dbg_spdif(void) snprintf(buf, sizeof(buf), "Clock accuracy: %d", x); lcd_puts(0, line++, buf); line++; - + snprintf(buf, sizeof(buf), "Measured freq: %ldHz", (long)((long long)FREQMEAS*CPU_FREQ/((1 << 15)*3*(1 << 13))/128)); lcd_puts(0, line++, buf); @@ -914,7 +921,7 @@ bool dbg_ports(void) battery_voltage = (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) / 10000; batt_int = battery_voltage / 100; batt_frac = battery_voltage % 100; - + snprintf(buf, 32, "Batt: %d.%02dV %d%% ", batt_int, batt_frac, battery_level()); lcd_puts(0, 6, buf); @@ -960,7 +967,7 @@ bool dbg_ports(void) gpio1_function = GPIO1_FUNCTION; gpio_enable = GPIO_ENABLE; gpio1_enable = GPIO1_ENABLE; - + snprintf(buf, sizeof(buf), "GPIO_READ: %08x", gpio_read); lcd_puts(0, line++, buf); snprintf(buf, sizeof(buf), "GPIO_OUT: %08x", gpio_out); @@ -985,7 +992,7 @@ bool dbg_ports(void) #if defined(IRIVER_H100_SERIES) || defined(IRIVER_H300_SERIES) adc_remotedetect = adc_read(ADC_REMOTEDETECT); #endif - + snprintf(buf, sizeof(buf), "ADC_BUTTONS: %02x", adc_buttons); lcd_puts(0, line++, buf); snprintf(buf, sizeof(buf), "ADC_REMOTE: %02x", adc_remote); @@ -1000,16 +1007,16 @@ bool dbg_ports(void) battery_voltage = (adc_battery * BATTERY_SCALE_FACTOR) / 10000; batt_int = battery_voltage / 100; batt_frac = battery_voltage % 100; - + snprintf(buf, 32, "Batt: %d.%02dV %d%% ", batt_int, batt_frac, battery_level()); lcd_puts(0, line++, buf); - + #if defined(IRIVER_H100_SERIES) || defined(IRIVER_H300_SERIES) snprintf(buf, sizeof(buf), "remotetype:: %d", remote_type()); lcd_puts(0, line++, buf); #endif - + lcd_update(); if (action_userabort(HZ/10)) return false; @@ -1128,15 +1135,15 @@ bool dbg_ports(void) break; } lcd_puts(0, 0, buf); - - battery_voltage = (adc_read(ADC_UNREG_POWER) * + + battery_voltage = (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) / 10000; batt_int = battery_voltage / 100; batt_frac = battery_voltage % 100; - + snprintf(buf, 32, "Batt: %d.%02dV", batt_int, batt_frac); lcd_puts(0, 1, buf); - + button = get_action(CONTEXT_SETTINGS,HZ/5); switch(button) @@ -1179,7 +1186,7 @@ bool dbg_cpufreq(void) while(1) { line = 0; - + snprintf(buf, sizeof(buf), "Frequency: %ld", FREQ); lcd_puts(0, line++, buf); @@ -1212,7 +1219,7 @@ bool dbg_cpufreq(void) return false; } #endif /* HAVE_ADJUSTABLE_CPU_FREQ */ - + #ifdef HAVE_LCD_BITMAP /* * view_battery() shows a automatically scaled graph of the battery voltage @@ -1229,7 +1236,7 @@ bool view_battery(void) int i, x, y; unsigned short maxv, minv; char buf[32]; - + lcd_setmargins(0, 0); lcd_setfont(FONT_SYSFIXED); @@ -1248,20 +1255,20 @@ bool view_battery(void) minv = power_history[i]; } } - + if ((minv < 1) || (minv >= 65535)) minv = 1; if (maxv < 2) maxv = 2; - + lcd_clear_display(); snprintf(buf, 30, "Battery %d.%02d", power_history[0] / 100, power_history[0] % 100); lcd_puts(0, 0, buf); - snprintf(buf, 30, "scale %d.%02d-%d.%02d V", + snprintf(buf, 30, "scale %d.%02d-%d.%02d V", minv / 100, minv % 100, maxv / 100, maxv % 100); lcd_puts(0, 1, buf); - + x = 0; for (i = BAT_LAST_VAL - 1; i >= 0; i--) { y = (power_history[i] - minv) * BAT_YSPACE / (maxv - minv); @@ -1274,7 +1281,7 @@ bool view_battery(void) } break; - + case 1: /* status: */ lcd_clear_display(); lcd_puts(0, 0, "Power status:"); @@ -1289,7 +1296,7 @@ bool view_battery(void) #endif #ifdef CONFIG_CHARGING #if CONFIG_CHARGING == CHARGING_CONTROL - snprintf(buf, 30, "Chgr: %s %s", + snprintf(buf, 30, "Chgr: %s %s", charger_inserted() ? "present" : "absent", charger_enabled ? "on" : "off"); lcd_puts(0, 3, buf); @@ -1329,15 +1336,15 @@ bool view_battery(void) #endif /* CONFIG_CHARGING != CHARGING_CONTROL */ #endif /* CONFIG_CHARGING */ break; - + case 2: /* voltage deltas: */ lcd_clear_display(); lcd_puts(0, 0, "Voltage deltas:"); - + for (i = 0; i <= 6; i++) { y = power_history[i] - power_history[i+i]; snprintf(buf, 30, "-%d min: %s%d.%02d V", i, - (y < 0) ? "-" : "", ((y < 0) ? y * -1 : y) / 100, + (y < 0) ? "-" : "", ((y < 0) ? y * -1 : y) / 100, ((y < 0) ? y * -1 : y ) % 100); lcd_puts(0, i+1, buf); } @@ -1375,21 +1382,21 @@ bool view_battery(void) lcd_puts(0, 7, buf); break; } - + lcd_update(); - + switch(get_action(CONTEXT_SETTINGS,HZ/2)) { case ACTION_SETTINGS_DEC: if (view) view--; break; - + case ACTION_SETTINGS_INC: if (view < 3) view++; break; - + case ACTION_STD_CANCEL: action_signalscreenchange(); return false; @@ -1399,7 +1406,7 @@ bool view_battery(void) } #endif /* HAVE_LCD_BITMAP */ - + static bool view_runtime(void) { char s[32]; @@ -1441,7 +1448,7 @@ static bool view_runtime(void) t = global_settings.topruntime; lcd_puts(0, y++, "Top time"); } - + snprintf(s, sizeof(s), "%dh %dm %ds", t / 3600, (t % 3600) / 60, t % 60); lcd_puts(0, y++, s); @@ -1498,7 +1505,7 @@ bool dbg_mmc_info(void) static const unsigned char i_vmax[] = { 1, 5, 10, 25, 35, 45, 80, 200 }; static const unsigned char *kbit_units[] = { "kBit/s", "MBit/s", "GBit/s" }; static const unsigned char *nsec_units[] = { "ns", "µs", "ms" }; - + card_name[6] = '\0'; lcd_setmargins(0, 0); @@ -1574,7 +1581,7 @@ bool dbg_mmc_info(void) case ACTION_STD_CANCEL: done = true; break; - + case ACTION_SETTINGS_DEC: currval--; if (currval < 0) @@ -1606,7 +1613,7 @@ static bool dbg_disk_info(void) #ifdef HAVE_LCD_BITMAP lcd_setmargins(0, 0); #endif - + while(!done) { int y=0; @@ -1639,7 +1646,7 @@ static bool dbg_disk_info(void) case 2: snprintf(buf, sizeof buf, "%ld MB", - ((unsigned long)identify_info[61] << 16 | + ((unsigned long)identify_info[61] << 16 | (unsigned long)identify_info[60]) / 2048 ); lcd_puts(0, y++, "Size"); lcd_puts(0, y++, buf); @@ -1739,7 +1746,7 @@ static bool dbg_disk_info(void) if (--page < 0) page = max_page; break; - + case ACTION_SETTINGS_INC: if (++page > max_page) page = 0; @@ -1765,9 +1772,9 @@ static bool dbg_dircache_info(void) while (!done) { line = 0; - + lcd_clear_display(); - snprintf(buf, sizeof(buf), "Cache initialized: %s", + snprintf(buf, sizeof(buf), "Cache initialized: %s", dircache_is_enabled() ? "Yes" : "No"); lcd_puts(0, line++, buf); @@ -1819,25 +1826,25 @@ static bool dbg_tagcache_info(void) while (!done) { line = 0; - + lcd_clear_display(); stat = tagcache_get_stat(); - snprintf(buf, sizeof(buf), "Initialized: %s", stat->initialized ? "Yes" : "No"); + snprintf(buf, sizeof(buf), "Initialized: %s", stat->initialized ? "Yes" : "No"); lcd_puts(0, line++, buf); - snprintf(buf, sizeof(buf), "DB Ready: %s", stat->ready ? "Yes" : "No"); + snprintf(buf, sizeof(buf), "DB Ready: %s", stat->ready ? "Yes" : "No"); lcd_puts(0, line++, buf); - snprintf(buf, sizeof(buf), "RAM Cache: %s", stat->ramcache ? "Yes" : "No"); + snprintf(buf, sizeof(buf), "RAM Cache: %s", stat->ramcache ? "Yes" : "No"); lcd_puts(0, line++, buf); - snprintf(buf, sizeof(buf), "RAM: %d/%d B", - stat->ramcache_used, stat->ramcache_allocated); + snprintf(buf, sizeof(buf), "RAM: %d/%d B", + stat->ramcache_used, stat->ramcache_allocated); lcd_puts(0, line++, buf); - snprintf(buf, sizeof(buf), "Progress: %d%% (%d entries)", + snprintf(buf, sizeof(buf), "Progress: %d%% (%d entries)", stat->progress, stat->processed_entries); lcd_puts(0, line++, buf); - snprintf(buf, sizeof(buf), "Commit step: %d", stat->commit_step); + snprintf(buf, sizeof(buf), "Commit step: %d", stat->commit_step); lcd_puts(0, line++, buf); - snprintf(buf, sizeof(buf), "Commit delayed: %s", - stat->commit_delayed ? "Yes" : "No"); + snprintf(buf, sizeof(buf), "Commit delayed: %s", + stat->commit_delayed ? "Yes" : "No"); lcd_puts(0, line++, buf); lcd_update(); @@ -1892,7 +1899,7 @@ bool dbg_save_roms(void) close(fd); } system_memory_guard(oldmode); - + #ifdef HAVE_EEPROM fd = creat("/internal_eeprom.bin", O_WRONLY); if (fd >= 0) @@ -1916,7 +1923,7 @@ bool dbg_save_roms(void) close(fd); } #endif - + return false; } #endif /* CPU */ @@ -1938,10 +1945,10 @@ bool dbg_fm_radio(void) lcd_clear_display(); fm_detected = radio_hardware_present(); - + snprintf(buf, sizeof buf, "HW detected: %s", fm_detected?"yes":"no"); lcd_puts(0, row++, buf); - + #if (CONFIG_TUNER & S1A0903X01) regs = samsung_get(RADIO_ALL); snprintf(buf, sizeof buf, "Samsung regs: %08lx", regs); @@ -1954,7 +1961,7 @@ bool dbg_fm_radio(void) #endif lcd_update(); - + if (action_userabort(HZ)) return false; } @@ -1983,7 +1990,7 @@ bool dbg_set_memory_guard(void) { "Zero area (all)", -1 } }; int mode = system_memory_guard(MEMGUARD_KEEP); - + set_option( "Catch mem accesses", &mode, INT, names, MAXMEMGUARD, NULL); system_memory_guard(mode); @@ -1999,7 +2006,7 @@ bool dbg_write_eeprom(void) int old_irq_level; char buf[EEPROM_SIZE]; int err; - + fd = open("/internal_eeprom.bin", O_RDONLY); if (fd >= 0) @@ -2093,7 +2100,7 @@ bool debug_menu(void) NULL, NULL, NULL); result = menu_run(m); menu_exit(m); - + return result; } diff --git a/firmware/export/config.h b/firmware/export/config.h index 8f1a5e65cc..cd674b63f8 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h @@ -151,6 +151,10 @@ #define USBOTG_ISP1362 1362 #define USBOTG_M5636 5636 +/* Multiple cores */ +#define CPU 0 +#define COP 1 + /* now go and pick yours */ #if defined(ARCHOS_PLAYER) #include "config-player.h" @@ -219,6 +223,19 @@ /* 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 +#else +#define NUM_CORES 1 +#define CURRENT_CORE 0 #endif /* define for all cpus from ARM family */ diff --git a/firmware/export/system.h b/firmware/export/system.h index 1b326e1b8b..d13b27c529 100644 --- a/firmware/export/system.h +++ b/firmware/export/system.h @@ -43,6 +43,8 @@ static inline void udelay(unsigned usecs) unsigned start = USEC_TIMER; while ((USEC_TIMER - start) < usecs); } + +unsigned int current_core(void); #endif struct flash_header { @@ -88,7 +90,7 @@ void cpu_idle_mode(bool on_off); #define betoh32(x) swap32(x) #define htobe16(x) swap16(x) #define htobe32(x) swap32(x) -#else +#else #define letoh16(x) swap16(x) #define letoh32(x) swap32(x) #define htole16(x) swap16(x) @@ -178,7 +180,7 @@ static inline void coldfire_set_macsr(unsigned long flags) static inline unsigned long coldfire_get_macsr(void) { unsigned long m; - + asm volatile ("move.l %%macsr, %0" : "=r" (m)); return m; } @@ -301,7 +303,7 @@ static inline void invalidate_icache(void) "move.l #0x80000000,%d0\n" "movec.l %d0,%cacr"); } - + #define CPUFREQ_DEFAULT_MULT 1 #define CPUFREQ_DEFAULT (CPUFREQ_DEFAULT_MULT * CPU_FREQ) #define CPUFREQ_NORMAL_MULT 4 @@ -315,7 +317,7 @@ static inline void invalidate_icache(void) #define CPUFREQ_DEFAULT_MULT 8 #define CPUFREQ_DEFAULT 24000000 -#define CPUFREQ_NORMAL_MULT 10 +#define CPUFREQ_NORMAL_MULT 10 #define CPUFREQ_NORMAL 30000000 #define CPUFREQ_MAX_MULT 25 #define CPUFREQ_MAX 75000000 @@ -336,7 +338,7 @@ static inline unsigned long swap32(unsigned long value) result[15.. 8] = value[23..16]; result[ 7.. 0] = value[31..24]; */ -{ +{ unsigned int tmp; asm volatile ( @@ -418,7 +420,7 @@ static inline int set_irq_level(int level) __asm__ volatile ("clrsr ie"); else __asm__ volatile ("setsr ie"); - + return result; } diff --git a/firmware/export/thread.h b/firmware/export/thread.h index 762e315a4c..a5034aedab 100644 --- a/firmware/export/thread.h +++ b/firmware/export/thread.h @@ -31,12 +31,16 @@ int create_thread(void (*function)(void), void* stack, int stack_size, const char *name); +int create_thread_on_core(unsigned int core, void (*function)(void), void* stack, int stack_size, + const char *name); void remove_thread(int threadnum); +void remove_thread_on_core(unsigned int core, int threadnum); void switch_thread(void); void sleep_thread(void); void wake_up_thread(void); void init_threads(void); int thread_stack_usage(int threadnum); +int thread_stack_usage_on_core(unsigned int core, int threadnum); #ifdef RB_PROFILE void profile_thread(void); #endif diff --git a/firmware/system.c b/firmware/system.c index c97b5233ec..6aee823205 100644 --- a/firmware/system.c +++ b/firmware/system.c @@ -91,21 +91,21 @@ bool detect_flashed_rockbox(void) { struct flash_header hdr; uint8_t *src = (uint8_t *)FLASH_ENTRYPOINT; - + # ifndef BOOTLOADER int oldmode; oldmode = system_memory_guard(MEMGUARD_NONE); # endif - + memcpy(&hdr, src, sizeof(struct flash_header)); - + # ifndef BOOTLOADER system_memory_guard(oldmode); # endif - + if (hdr.magic != FLASH_MAGIC) return false; - + return true; } #else @@ -139,13 +139,13 @@ void ddma_transfer(int dir, int mem, void* intAddr, long extAddr, int num) { /* HW wants those two in word units. */ num /= 2; externalAddress /= 2; - + DDMACFG = (dir << 1) | (mem << 2); DDMAIADR = internalAddress; DDMAEADR = externalAddress; DDMANUM = num; DDMACOM |= 0x4; /* start */ - + ddma_wait_idle(); /* wait for completion */ set_irq_level(irq); } @@ -164,13 +164,13 @@ static void ddma_transfer_noicode(int dir, int mem, long intAddr, long extAddr, /* HW wants those two in word units. */ num /= 2; externalAddress /= 2; - + DDMACFG = (dir << 1) | (mem << 2); DDMAIADR = internalAddress; DDMAEADR = externalAddress; DDMANUM = num; DDMACOM |= 0x4; /* start */ - + ddma_wait_idle_noicode(); /* wait for completion */ set_irq_level(irq); } @@ -220,7 +220,7 @@ void smsc_delay() { Delay doesn't depend on CPU speed in Archos' firmware. */ for (i = 0; i < 100; i++) { - + } } @@ -228,9 +228,9 @@ static void extra_init(void) { /* Power on stuff */ P1 |= 0x07; P1CON |= 0x1f; - + /* P5 conf - * lines 0, 1 & 4 are digital, other analog. : + * lines 0, 1 & 4 are digital, other analog. : */ P5CON = 0xec; @@ -294,21 +294,21 @@ void system_init(void) /******** * CPU */ - - + + /* PLL0 (cpu osc. frequency) */ /* set_cpu_frequency(CPU_FREQ); */ /******************* - * configure S(D)RAM + * configure S(D)RAM */ /************************ * Copy .icode section to icram */ ddma_transfer_noicode(0, 0, 0x40, (long)&icodecopy, (int)&icodesize); - + /*************************** * Interrupts @@ -472,12 +472,12 @@ void UIE (void) /* Unexpected Interrupt or Exception */ unsigned int format_vector, pc; int vector; char str[32]; - + asm volatile ("move.l (52,%%sp),%0": "=r"(format_vector)); asm volatile ("move.l (56,%%sp),%0": "=r"(pc)); vector = (format_vector >> 18) & 0xff; - + /* clear screen */ lcd_clear_display (); #ifdef HAVE_LCD_BITMAP @@ -488,7 +488,7 @@ void UIE (void) /* Unexpected Interrupt or Exception */ snprintf(str,sizeof(str),"at %08x",pc); lcd_puts(0,1,str); lcd_update(); - + /* set cpu frequency to 11mhz (to prevent overheating) */ DCR = (DCR & ~0x01ff) | 1; PLLCR = 0x10800000; @@ -510,7 +510,7 @@ void UIE (void) /* Unexpected Interrupt or Exception */ } /* reset vectors are handled in crt0.S */ -void (* const vbr[]) (void) __attribute__ ((section (".vectors"))) = +void (* const vbr[]) (void) __attribute__ ((section (".vectors"))) = { UIE,UIE,UIE,UIE,UIE,UIE, UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE, @@ -520,7 +520,7 @@ void (* const vbr[]) (void) __attribute__ ((section (".vectors"))) = TRAP0,TRAP1,TRAP2,TRAP3,TRAP4,TRAP5,TRAP6,TRAP7, TRAP8,TRAP9,TRAP10,TRAP11,TRAP12,TRAP13,TRAP14,TRAP15, - + SWT,UIE,UIE,I2C,UART1,UART2,DMA0,DMA1, DMA2,DMA3,QSPI,UIE,UIE,UIE,UIE,UIE, PDIR1FULL,PDIR2FULL,EBUTXEMPTY,IIS2TXEMPTY, @@ -741,7 +741,7 @@ static const char* const irqname[] = { asm ( -/* Vector table. +/* Vector table. * Handled in asm because gcc 4.x doesn't allow weak aliases to symbols * defined in an asm block -- silly. * Reset vectors (0..3) are handled in crt0.S */ @@ -854,7 +854,7 @@ asm ( RESERVE_INTERRUPT ( 108) DEFAULT_INTERRUPT (ADITI, 109) -/* UIE# block. +/* UIE# block. * Must go into the same section as the UIE() handler */ "\t.text\n" @@ -979,7 +979,7 @@ void UIE (unsigned int pc) /* Unexpected Interrupt or Exception */ char str[32]; asm volatile ("sts\tpr,%0" : "=r"(n)); - + /* clear screen */ lcd_clear_display (); #ifdef HAVE_LCD_BITMAP @@ -1002,7 +1002,7 @@ void UIE (unsigned int pc) /* Unexpected Interrupt or Exception */ volatile int i; led (state); state = !state; - + for (i = 0; i < 240000; ++i); #endif @@ -1018,7 +1018,7 @@ void UIE (unsigned int pc) /* Unexpected Interrupt or Exception */ #elif CONFIG_KEYPAD == ONDIO_PAD if (!(PCDR & 0x0008)) #endif - { + { /* enable the watchguard timer, but don't service it */ RSTCSR_W = 0x5a40; /* Reset enabled, power-on reset */ TCSR_W = 0xa560; /* Watchdog timer mode, timer enabled, sysclk/2 */ @@ -1086,7 +1086,7 @@ int system_memory_guard(int newmode) int oldmode = MEMGUARD_NONE; int i; - + /* figure out the old mode from what is in the UBC regs. If the register values don't match any mode, assume MEMGUARD_NONE */ for (i = MEMGUARD_NONE; i < MAXMEMGUARD; i++) @@ -1098,7 +1098,7 @@ int system_memory_guard(int newmode) break; } } - + if (newmode == MEMGUARD_KEEP) newmode = oldmode; @@ -1109,7 +1109,7 @@ int system_memory_guard(int newmode) BAR = modes[newmode].addr; BAMR = modes[newmode].mask; BBR = modes[newmode].bbr; - + return oldmode; } #elif defined(CPU_ARM) @@ -1124,7 +1124,7 @@ static const char* const uiename[] = { void UIE(unsigned int pc, unsigned int num) { char str[32]; - + lcd_clear_display(); #ifdef HAVE_LCD_BITMAP lcd_setfont(FONT_SYSFIXED); @@ -1133,7 +1133,7 @@ void UIE(unsigned int pc, unsigned int num) snprintf(str, sizeof(str), "at %08x", pc); lcd_puts(0, 1, str); lcd_update(); - + while (1) { /* TODO: perhaps add button handling in here when we get a polling @@ -1160,7 +1160,7 @@ void irq(void) else if (CPU_INT_STAT & TIMER2_MASK) TIMER2(); else if (CPU_HI_INT_STAT & GPIO_MASK) - ipod_mini_button_int(); + ipod_mini_button_int(); } #elif (defined IRIVER_H10) || (defined IRIVER_H10_5GB) /* TODO: this should really be in the target tree, but moving it there caused @@ -1170,14 +1170,14 @@ void irq(void) if (CPU_INT_STAT & TIMER1_MASK) TIMER1(); else if (CPU_INT_STAT & TIMER2_MASK) - TIMER2(); + TIMER2(); } #else extern void ipod_4g_button_int(void); void irq(void) { - if (CPU_INT_STAT & TIMER1_MASK) + if (CPU_INT_STAT & TIMER1_MASK) TIMER1(); else if (CPU_INT_STAT & TIMER2_MASK) TIMER2(); @@ -1187,11 +1187,21 @@ void irq(void) #endif #endif /* BOOTLOADER */ +unsigned int current_core(void) +{ + if(((*(volatile unsigned long *)(0x60000000)) & 0xff) == 0x55) + { + return CPU; + } + return COP; +} + + /* TODO: The following two function have been lifted straight from IPL, and hence have a lot of numeric addresses used straight. I'd like to use #defines for these, but don't know what most of them are for or even what they should be named. Because of this I also have no way of knowing how - to extend the funtions to do alternate cache configurations and/or + to extend the funtions to do alternate cache configurations and/or some other CPU frequency scaling. */ #ifndef BOOTLOADER @@ -1251,7 +1261,7 @@ void set_cpu_frequency(long frequency) #if defined(IPOD_COLOR) || defined(IPOD_4G) || defined(IPOD_MINI) /* 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. + 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 "|=". @@ -1321,19 +1331,29 @@ extern void TIMER2(void); void irq(void) { - if (CPU_INT_STAT & TIMER1_MASK) + if (CPU_INT_STAT & TIMER1_MASK) TIMER1(); - else if (CPU_INT_STAT & TIMER2_MASK) + else if (CPU_INT_STAT & TIMER2_MASK) TIMER2(); } #endif +unsigned int current_core(void) +{ + if(((*(volatile unsigned long *)(0xc4000000)) & 0xff) == 0x55) + { + return CPU; + } + return COP; +} + + /* TODO: The following two function have been lifted straight from IPL, and hence have a lot of numeric addresses used straight. I'd like to use #defines for these, but don't know what most of them are for or even what they should be named. Because of this I also have no way of knowing how - to extend the funtions to do alternate cache configurations and/or + to extend the funtions to do alternate cache configurations and/or some other CPU frequency scaling. */ #ifndef BOOTLOADER @@ -1370,7 +1390,7 @@ void set_cpu_frequency(long frequency) else postmult = CPUFREQ_DEFAULT_MULT; cpu_frequency = frequency; - + outl(0x02, 0xcf005008); outl(0x55, 0xcf00500c); outl(0x6000, 0xcf005010); @@ -1501,7 +1521,7 @@ void system_init(void) IRQ_WRITE_WAIT(0, 0, v == 0); IRQ_WRITE_WAIT(4, 0, v == 0); */ - + for (i = 0; i < 0x1c; i++) { IRQ_WRITE_WAIT(0x404 + i * 4, 0x1e000001, (v & 0x3010f) == 1); diff --git a/firmware/thread.c b/firmware/thread.c index 0013d49519..c194b2694d 100644 --- a/firmware/thread.c +++ b/firmware/thread.c @@ -41,7 +41,7 @@ struct regs void *pr; /* Procedure register */ void *start; /* Thread start address, or NULL when started */ }; -#elif defined(CPU_ARM) +#elif defined(CPU_ARM) struct regs { unsigned int r[8]; /* Registers r4-r11 */ @@ -62,18 +62,31 @@ struct regs /* Cast to the the machine int type, whose size could be < 4. */ -int num_threads; -static volatile int num_sleepers; -static int current_thread; -static struct regs thread_contexts[MAXTHREADS] IBSS_ATTR; -const char *thread_name[MAXTHREADS]; -void *thread_stack[MAXTHREADS]; -int thread_stack_size[MAXTHREADS]; +int num_threads[NUM_CORES]; +static volatile int num_sleepers[NUM_CORES]; +static int current_thread[NUM_CORES]; +static struct regs thread_contexts[NUM_CORES][MAXTHREADS] IBSS_ATTR; +const char *thread_name[NUM_CORES][MAXTHREADS]; +void *thread_stack[NUM_CORES][MAXTHREADS]; +int thread_stack_size[NUM_CORES][MAXTHREADS]; static const char main_thread_name[] = "main"; extern int stackbegin[]; extern int stackend[]; +#ifdef CPU_PP +#ifndef BOOTLOADER +extern int cop_stackbegin[]; +extern int cop_stackend[]; +#else +/* The coprocessor stack is not set up in the bootloader code, but the + threading is. No threads are run on the coprocessor, so set up some dummy + stack */ +int *cop_stackbegin = stackbegin; +int *cop_stackend = stackend; +#endif +#endif + void switch_thread(void) ICODE_ATTR; static inline void store_context(void* addr) __attribute__ ((always_inline)); static inline void load_context(const void* addr) __attribute__ ((always_inline)); @@ -86,7 +99,7 @@ void profile_thread(void) { #endif #if defined(CPU_ARM) -/*--------------------------------------------------------------------------- +/*--------------------------------------------------------------------------- * Store non-volatile context. *--------------------------------------------------------------------------- */ @@ -116,7 +129,7 @@ static inline void load_context(const void* addr) } #elif defined(CPU_COLDFIRE) -/*--------------------------------------------------------------------------- +/*--------------------------------------------------------------------------- * Store non-volatile context. *--------------------------------------------------------------------------- */ @@ -199,7 +212,7 @@ static inline void load_context(const void* addr) } #elif CONFIG_CPU == TCC730 -/*--------------------------------------------------------------------------- +/*--------------------------------------------------------------------------- * Store non-volatile context. *--------------------------------------------------------------------------- */ @@ -215,7 +228,7 @@ static inline void load_context(const void* addr) "push a14\n\t" \ "ldw @[%0+0], a15\n\t" : : "a" (addr) ); -/*--------------------------------------------------------------------------- +/*--------------------------------------------------------------------------- * Load non-volatile context. *--------------------------------------------------------------------------- */ @@ -260,7 +273,7 @@ void switch_thread(void) #ifdef SIMULATOR /* Do nothing */ #else - while (num_sleepers == num_threads) + while (num_sleepers[CURRENT_CORE] == num_threads[CURRENT_CORE]) { /* Enter sleep mode, woken up on interrupt */ #ifdef CPU_COLDFIRE @@ -284,21 +297,21 @@ void switch_thread(void) #endif } #endif - current = current_thread; - store_context(&thread_contexts[current]); - + current = current_thread[CURRENT_CORE]; + store_context(&thread_contexts[CURRENT_CORE][current]); + #if CONFIG_CPU != TCC730 /* Check if the current thread stack is overflown */ - stackptr = thread_stack[current]; + stackptr = thread_stack[CURRENT_CORE][current]; if(stackptr[0] != DEADBEEF) - panicf("Stkov %s", thread_name[current]); + panicf("Stkov %s", thread_name[CURRENT_CORE][current]); #endif - if (++current >= num_threads) + if (++current >= num_threads[CURRENT_CORE]) current = 0; - current_thread = current; - load_context(&thread_contexts[current]); + current_thread[CURRENT_CORE] = current; + load_context(&thread_contexts[CURRENT_CORE][current]); #ifdef RB_PROFILE profile_thread_started(current_thread); #endif @@ -306,29 +319,42 @@ void switch_thread(void) void sleep_thread(void) { - ++num_sleepers; + ++num_sleepers[CURRENT_CORE]; switch_thread(); } void wake_up_thread(void) { - num_sleepers = 0; + num_sleepers[CURRENT_CORE] = 0; } -/*--------------------------------------------------------------------------- - * Create thread. + +/*--------------------------------------------------------------------------- + * Create thread on the current core. * Return ID if context area could be allocated, else -1. *--------------------------------------------------------------------------- */ int create_thread(void (*function)(void), void* stack, int stack_size, const char *name) +{ + return create_thread_on_core(CURRENT_CORE, function, stack, stack_size, + name); +} + +/*--------------------------------------------------------------------------- + * Create thread on a specific core. + * Return ID if context area could be allocated, else -1. + *--------------------------------------------------------------------------- + */ +int create_thread_on_core(unsigned int core, void (*function)(void), void* stack, int stack_size, + const char *name) { unsigned int i; unsigned int stacklen; unsigned int *stackptr; struct regs *regs; - if (num_threads >= MAXTHREADS) + if (num_threads[core] >= MAXTHREADS) return -1; /* Munge the stack to make it easy to spot stack overflows */ @@ -340,10 +366,10 @@ int create_thread(void (*function)(void), void* stack, int stack_size, } /* Store interesting information */ - thread_name[num_threads] = name; - thread_stack[num_threads] = stack; - thread_stack_size[num_threads] = stack_size; - regs = &thread_contexts[num_threads]; + thread_name[core][num_threads[core]] = name; + thread_stack[core][num_threads[core]] = stack; + thread_stack_size[core][num_threads[core]] = stack_size; + regs = &thread_contexts[core][num_threads[core]]; #if defined(CPU_COLDFIRE) || (CONFIG_CPU == SH7034) || defined(CPU_ARM) /* Align stack to an even 32 bit boundary */ regs->sp = (void*)(((unsigned int)stack + stack_size) & ~3); @@ -355,65 +381,91 @@ int create_thread(void (*function)(void), void* stack, int stack_size, regs->start = (void*)function; wake_up_thread(); - return num_threads++; /* return the current ID, e.g for remove_thread() */ + return num_threads[core]++; /* return the current ID, e.g for remove_thread() */ } -/*--------------------------------------------------------------------------- - * Remove a thread from the scheduler. +/*--------------------------------------------------------------------------- + * Remove a thread on the current core from the scheduler. * Parameter is the ID as returned from create_thread(). *--------------------------------------------------------------------------- */ void remove_thread(int threadnum) +{ + remove_thread_on_core(CURRENT_CORE, threadnum); +} + +/*--------------------------------------------------------------------------- + * Remove a thread on the specified core from the scheduler. + * Parameters are the core and the ID as returned from create_thread(). + *--------------------------------------------------------------------------- + */ +void remove_thread_on_core(unsigned int core, int threadnum) { int i; - if(threadnum >= num_threads) + if(threadnum >= num_threads[core]) return; - num_threads--; - for (i=threadnum; i threadnum) /* within the moved positions? */ - current_thread--; /* adjust it, point to same context again */ + if (current_thread[core] == threadnum) /* deleting the current one? */ + current_thread[core] = num_threads[core]; /* set beyond last, avoid store harm */ + else if (current_thread[core] > threadnum) /* within the moved positions? */ + current_thread[core]--; /* adjust it, point to same context again */ } void init_threads(void) { - num_threads = 1; /* We have 1 thread to begin with */ - current_thread = 0; /* The current thread is number 0 */ - thread_name[0] = main_thread_name; - thread_stack[0] = stackbegin; - thread_stack_size[0] = (int)stackend - (int)stackbegin; -#if CONFIG_CPU == TCC730 - thread_contexts[0].started = 1; -#else - thread_contexts[0].start = 0; /* thread 0 already running */ + unsigned int core = CURRENT_CORE; + + num_threads[core] = 1; /* We have 1 thread to begin with */ + current_thread[core] = 0; /* The current thread is number 0 */ + thread_name[core][0] = main_thread_name; +/* In multiple core setups, each core has a different stack. There is probably + a much better way to do this. */ + if(core == CPU) + { + thread_stack[CPU][0] = stackbegin; + thread_stack_size[CPU][0] = (int)stackend - (int)stackbegin; + } else { +#if NUM_CORES > 1 /* This code path will not be run on single core targets */ + thread_stack[COP][0] = cop_stackbegin; + thread_stack_size[COP][0] = (int)cop_stackend - (int)cop_stackbegin; #endif - num_sleepers = 0; + } +#if CONFIG_CPU == TCC730 + thread_contexts[core][0].started = 1; +#else + thread_contexts[core][0].start = 0; /* thread 0 already running */ +#endif + num_sleepers[core] = 0; } -int thread_stack_usage(int threadnum) +int thread_stack_usage(int threadnum){ + return thread_stack_usage_on_core(CURRENT_CORE, threadnum); +} + +int thread_stack_usage_on_core(unsigned int core, int threadnum) { unsigned int i; - unsigned int *stackptr = thread_stack[threadnum]; + unsigned int *stackptr = thread_stack[core][threadnum]; - if(threadnum >= num_threads) + if(threadnum >= num_threads[core]) return -1; - for(i = 0;i < thread_stack_size[threadnum]/sizeof(int);i++) + for(i = 0;i < thread_stack_size[core][threadnum]/sizeof(int);i++) { if(stackptr[i] != DEADBEEF) break; } - return ((thread_stack_size[threadnum] - i * sizeof(int)) * 100) / - thread_stack_size[threadnum]; -} + return ((thread_stack_size[core][threadnum] - i * sizeof(int)) * 100) / + thread_stack_size[core][threadnum]; +}