summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/export/config.h17
-rw-r--r--firmware/export/system.h14
-rw-r--r--firmware/export/thread.h4
-rw-r--r--firmware/system.c102
-rw-r--r--firmware/thread.c170
5 files changed, 201 insertions, 106 deletions
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 @@
151#define USBOTG_ISP1362 1362 151#define USBOTG_ISP1362 1362
152#define USBOTG_M5636 5636 152#define USBOTG_M5636 5636
153 153
154/* Multiple cores */
155#define CPU 0
156#define COP 1
157
154/* now go and pick yours */ 158/* now go and pick yours */
155#if defined(ARCHOS_PLAYER) 159#if defined(ARCHOS_PLAYER)
156#include "config-player.h" 160#include "config-player.h"
@@ -219,6 +223,19 @@
219/* define for all cpus from PP family */ 223/* define for all cpus from PP family */
220#if (CONFIG_CPU == PP5002) || (CONFIG_CPU == PP5020) || (CONFIG_CPU == PP5024) 224#if (CONFIG_CPU == PP5002) || (CONFIG_CPU == PP5020) || (CONFIG_CPU == PP5024)
221#define CPU_PP 225#define CPU_PP
226
227/* PP family has dual cores */
228#if 0
229/* Keep it as single core until dual core support is ready */
230#define NUM_CORES 2
231#define CURRENT_CORE current_core()
232#endif
233
234#define NUM_CORES 1
235#define CURRENT_CORE 0
236#else
237#define NUM_CORES 1
238#define CURRENT_CORE 0
222#endif 239#endif
223 240
224/* define for all cpus from ARM family */ 241/* 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)
43 unsigned start = USEC_TIMER; 43 unsigned start = USEC_TIMER;
44 while ((USEC_TIMER - start) < usecs); 44 while ((USEC_TIMER - start) < usecs);
45} 45}
46
47unsigned int current_core(void);
46#endif 48#endif
47 49
48struct flash_header { 50struct flash_header {
@@ -88,7 +90,7 @@ void cpu_idle_mode(bool on_off);
88#define betoh32(x) swap32(x) 90#define betoh32(x) swap32(x)
89#define htobe16(x) swap16(x) 91#define htobe16(x) swap16(x)
90#define htobe32(x) swap32(x) 92#define htobe32(x) swap32(x)
91#else 93#else
92#define letoh16(x) swap16(x) 94#define letoh16(x) swap16(x)
93#define letoh32(x) swap32(x) 95#define letoh32(x) swap32(x)
94#define htole16(x) swap16(x) 96#define htole16(x) swap16(x)
@@ -178,7 +180,7 @@ static inline void coldfire_set_macsr(unsigned long flags)
178static inline unsigned long coldfire_get_macsr(void) 180static inline unsigned long coldfire_get_macsr(void)
179{ 181{
180 unsigned long m; 182 unsigned long m;
181 183
182 asm volatile ("move.l %%macsr, %0" : "=r" (m)); 184 asm volatile ("move.l %%macsr, %0" : "=r" (m));
183 return m; 185 return m;
184} 186}
@@ -301,7 +303,7 @@ static inline void invalidate_icache(void)
301 "move.l #0x80000000,%d0\n" 303 "move.l #0x80000000,%d0\n"
302 "movec.l %d0,%cacr"); 304 "movec.l %d0,%cacr");
303} 305}
304 306
305#define CPUFREQ_DEFAULT_MULT 1 307#define CPUFREQ_DEFAULT_MULT 1
306#define CPUFREQ_DEFAULT (CPUFREQ_DEFAULT_MULT * CPU_FREQ) 308#define CPUFREQ_DEFAULT (CPUFREQ_DEFAULT_MULT * CPU_FREQ)
307#define CPUFREQ_NORMAL_MULT 4 309#define CPUFREQ_NORMAL_MULT 4
@@ -315,7 +317,7 @@ static inline void invalidate_icache(void)
315 317
316#define CPUFREQ_DEFAULT_MULT 8 318#define CPUFREQ_DEFAULT_MULT 8
317#define CPUFREQ_DEFAULT 24000000 319#define CPUFREQ_DEFAULT 24000000
318#define CPUFREQ_NORMAL_MULT 10 320#define CPUFREQ_NORMAL_MULT 10
319#define CPUFREQ_NORMAL 30000000 321#define CPUFREQ_NORMAL 30000000
320#define CPUFREQ_MAX_MULT 25 322#define CPUFREQ_MAX_MULT 25
321#define CPUFREQ_MAX 75000000 323#define CPUFREQ_MAX 75000000
@@ -336,7 +338,7 @@ static inline unsigned long swap32(unsigned long value)
336 result[15.. 8] = value[23..16]; 338 result[15.. 8] = value[23..16];
337 result[ 7.. 0] = value[31..24]; 339 result[ 7.. 0] = value[31..24];
338 */ 340 */
339{ 341{
340 unsigned int tmp; 342 unsigned int tmp;
341 343
342 asm volatile ( 344 asm volatile (
@@ -418,7 +420,7 @@ static inline int set_irq_level(int level)
418 __asm__ volatile ("clrsr ie"); 420 __asm__ volatile ("clrsr ie");
419 else 421 else
420 __asm__ volatile ("setsr ie"); 422 __asm__ volatile ("setsr ie");
421 423
422 return result; 424 return result;
423} 425}
424 426
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 @@
31 31
32int create_thread(void (*function)(void), void* stack, int stack_size, 32int create_thread(void (*function)(void), void* stack, int stack_size,
33 const char *name); 33 const char *name);
34int create_thread_on_core(unsigned int core, void (*function)(void), void* stack, int stack_size,
35 const char *name);
34void remove_thread(int threadnum); 36void remove_thread(int threadnum);
37void remove_thread_on_core(unsigned int core, int threadnum);
35void switch_thread(void); 38void switch_thread(void);
36void sleep_thread(void); 39void sleep_thread(void);
37void wake_up_thread(void); 40void wake_up_thread(void);
38void init_threads(void); 41void init_threads(void);
39int thread_stack_usage(int threadnum); 42int thread_stack_usage(int threadnum);
43int thread_stack_usage_on_core(unsigned int core, int threadnum);
40#ifdef RB_PROFILE 44#ifdef RB_PROFILE
41void profile_thread(void); 45void profile_thread(void);
42#endif 46#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)
91{ 91{
92 struct flash_header hdr; 92 struct flash_header hdr;
93 uint8_t *src = (uint8_t *)FLASH_ENTRYPOINT; 93 uint8_t *src = (uint8_t *)FLASH_ENTRYPOINT;
94 94
95# ifndef BOOTLOADER 95# ifndef BOOTLOADER
96 int oldmode; 96 int oldmode;
97 oldmode = system_memory_guard(MEMGUARD_NONE); 97 oldmode = system_memory_guard(MEMGUARD_NONE);
98# endif 98# endif
99 99
100 memcpy(&hdr, src, sizeof(struct flash_header)); 100 memcpy(&hdr, src, sizeof(struct flash_header));
101 101
102# ifndef BOOTLOADER 102# ifndef BOOTLOADER
103 system_memory_guard(oldmode); 103 system_memory_guard(oldmode);
104# endif 104# endif
105 105
106 if (hdr.magic != FLASH_MAGIC) 106 if (hdr.magic != FLASH_MAGIC)
107 return false; 107 return false;
108 108
109 return true; 109 return true;
110} 110}
111#else 111#else
@@ -139,13 +139,13 @@ void ddma_transfer(int dir, int mem, void* intAddr, long extAddr, int num) {
139 /* HW wants those two in word units. */ 139 /* HW wants those two in word units. */
140 num /= 2; 140 num /= 2;
141 externalAddress /= 2; 141 externalAddress /= 2;
142 142
143 DDMACFG = (dir << 1) | (mem << 2); 143 DDMACFG = (dir << 1) | (mem << 2);
144 DDMAIADR = internalAddress; 144 DDMAIADR = internalAddress;
145 DDMAEADR = externalAddress; 145 DDMAEADR = externalAddress;
146 DDMANUM = num; 146 DDMANUM = num;
147 DDMACOM |= 0x4; /* start */ 147 DDMACOM |= 0x4; /* start */
148 148
149 ddma_wait_idle(); /* wait for completion */ 149 ddma_wait_idle(); /* wait for completion */
150 set_irq_level(irq); 150 set_irq_level(irq);
151} 151}
@@ -164,13 +164,13 @@ static void ddma_transfer_noicode(int dir, int mem, long intAddr, long extAddr,
164 /* HW wants those two in word units. */ 164 /* HW wants those two in word units. */
165 num /= 2; 165 num /= 2;
166 externalAddress /= 2; 166 externalAddress /= 2;
167 167
168 DDMACFG = (dir << 1) | (mem << 2); 168 DDMACFG = (dir << 1) | (mem << 2);
169 DDMAIADR = internalAddress; 169 DDMAIADR = internalAddress;
170 DDMAEADR = externalAddress; 170 DDMAEADR = externalAddress;
171 DDMANUM = num; 171 DDMANUM = num;
172 DDMACOM |= 0x4; /* start */ 172 DDMACOM |= 0x4; /* start */
173 173
174 ddma_wait_idle_noicode(); /* wait for completion */ 174 ddma_wait_idle_noicode(); /* wait for completion */
175 set_irq_level(irq); 175 set_irq_level(irq);
176} 176}
@@ -220,7 +220,7 @@ void smsc_delay() {
220 Delay doesn't depend on CPU speed in Archos' firmware. 220 Delay doesn't depend on CPU speed in Archos' firmware.
221 */ 221 */
222 for (i = 0; i < 100; i++) { 222 for (i = 0; i < 100; i++) {
223 223
224 } 224 }
225} 225}
226 226
@@ -228,9 +228,9 @@ static void extra_init(void) {
228 /* Power on stuff */ 228 /* Power on stuff */
229 P1 |= 0x07; 229 P1 |= 0x07;
230 P1CON |= 0x1f; 230 P1CON |= 0x1f;
231 231
232 /* P5 conf 232 /* P5 conf
233 * lines 0, 1 & 4 are digital, other analog. : 233 * lines 0, 1 & 4 are digital, other analog. :
234 */ 234 */
235 P5CON = 0xec; 235 P5CON = 0xec;
236 236
@@ -294,21 +294,21 @@ void system_init(void)
294 /******** 294 /********
295 * CPU 295 * CPU
296 */ 296 */
297 297
298 298
299 /* PLL0 (cpu osc. frequency) */ 299 /* PLL0 (cpu osc. frequency) */
300 /* set_cpu_frequency(CPU_FREQ); */ 300 /* set_cpu_frequency(CPU_FREQ); */
301 301
302 302
303 /******************* 303 /*******************
304 * configure S(D)RAM 304 * configure S(D)RAM
305 */ 305 */
306 306
307 /************************ 307 /************************
308 * Copy .icode section to icram 308 * Copy .icode section to icram
309 */ 309 */
310 ddma_transfer_noicode(0, 0, 0x40, (long)&icodecopy, (int)&icodesize); 310 ddma_transfer_noicode(0, 0, 0x40, (long)&icodecopy, (int)&icodesize);
311 311
312 312
313 /*************************** 313 /***************************
314 * Interrupts 314 * Interrupts
@@ -472,12 +472,12 @@ void UIE (void) /* Unexpected Interrupt or Exception */
472 unsigned int format_vector, pc; 472 unsigned int format_vector, pc;
473 int vector; 473 int vector;
474 char str[32]; 474 char str[32];
475 475
476 asm volatile ("move.l (52,%%sp),%0": "=r"(format_vector)); 476 asm volatile ("move.l (52,%%sp),%0": "=r"(format_vector));
477 asm volatile ("move.l (56,%%sp),%0": "=r"(pc)); 477 asm volatile ("move.l (56,%%sp),%0": "=r"(pc));
478 478
479 vector = (format_vector >> 18) & 0xff; 479 vector = (format_vector >> 18) & 0xff;
480 480
481 /* clear screen */ 481 /* clear screen */
482 lcd_clear_display (); 482 lcd_clear_display ();
483#ifdef HAVE_LCD_BITMAP 483#ifdef HAVE_LCD_BITMAP
@@ -488,7 +488,7 @@ void UIE (void) /* Unexpected Interrupt or Exception */
488 snprintf(str,sizeof(str),"at %08x",pc); 488 snprintf(str,sizeof(str),"at %08x",pc);
489 lcd_puts(0,1,str); 489 lcd_puts(0,1,str);
490 lcd_update(); 490 lcd_update();
491 491
492 /* set cpu frequency to 11mhz (to prevent overheating) */ 492 /* set cpu frequency to 11mhz (to prevent overheating) */
493 DCR = (DCR & ~0x01ff) | 1; 493 DCR = (DCR & ~0x01ff) | 1;
494 PLLCR = 0x10800000; 494 PLLCR = 0x10800000;
@@ -510,7 +510,7 @@ void UIE (void) /* Unexpected Interrupt or Exception */
510} 510}
511 511
512/* reset vectors are handled in crt0.S */ 512/* reset vectors are handled in crt0.S */
513void (* const vbr[]) (void) __attribute__ ((section (".vectors"))) = 513void (* const vbr[]) (void) __attribute__ ((section (".vectors"))) =
514{ 514{
515 UIE,UIE,UIE,UIE,UIE,UIE, 515 UIE,UIE,UIE,UIE,UIE,UIE,
516 UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE, 516 UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,
@@ -520,7 +520,7 @@ void (* const vbr[]) (void) __attribute__ ((section (".vectors"))) =
520 520
521 TRAP0,TRAP1,TRAP2,TRAP3,TRAP4,TRAP5,TRAP6,TRAP7, 521 TRAP0,TRAP1,TRAP2,TRAP3,TRAP4,TRAP5,TRAP6,TRAP7,
522 TRAP8,TRAP9,TRAP10,TRAP11,TRAP12,TRAP13,TRAP14,TRAP15, 522 TRAP8,TRAP9,TRAP10,TRAP11,TRAP12,TRAP13,TRAP14,TRAP15,
523 523
524 SWT,UIE,UIE,I2C,UART1,UART2,DMA0,DMA1, 524 SWT,UIE,UIE,I2C,UART1,UART2,DMA0,DMA1,
525 DMA2,DMA3,QSPI,UIE,UIE,UIE,UIE,UIE, 525 DMA2,DMA3,QSPI,UIE,UIE,UIE,UIE,UIE,
526 PDIR1FULL,PDIR2FULL,EBUTXEMPTY,IIS2TXEMPTY, 526 PDIR1FULL,PDIR2FULL,EBUTXEMPTY,IIS2TXEMPTY,
@@ -741,7 +741,7 @@ static const char* const irqname[] = {
741 741
742asm ( 742asm (
743 743
744/* Vector table. 744/* Vector table.
745 * Handled in asm because gcc 4.x doesn't allow weak aliases to symbols 745 * Handled in asm because gcc 4.x doesn't allow weak aliases to symbols
746 * defined in an asm block -- silly. 746 * defined in an asm block -- silly.
747 * Reset vectors (0..3) are handled in crt0.S */ 747 * Reset vectors (0..3) are handled in crt0.S */
@@ -854,7 +854,7 @@ asm (
854 RESERVE_INTERRUPT ( 108) 854 RESERVE_INTERRUPT ( 108)
855 DEFAULT_INTERRUPT (ADITI, 109) 855 DEFAULT_INTERRUPT (ADITI, 109)
856 856
857/* UIE# block. 857/* UIE# block.
858 * Must go into the same section as the UIE() handler */ 858 * Must go into the same section as the UIE() handler */
859 859
860 "\t.text\n" 860 "\t.text\n"
@@ -979,7 +979,7 @@ void UIE (unsigned int pc) /* Unexpected Interrupt or Exception */
979 char str[32]; 979 char str[32];
980 980
981 asm volatile ("sts\tpr,%0" : "=r"(n)); 981 asm volatile ("sts\tpr,%0" : "=r"(n));
982 982
983 /* clear screen */ 983 /* clear screen */
984 lcd_clear_display (); 984 lcd_clear_display ();
985#ifdef HAVE_LCD_BITMAP 985#ifdef HAVE_LCD_BITMAP
@@ -1002,7 +1002,7 @@ void UIE (unsigned int pc) /* Unexpected Interrupt or Exception */
1002 volatile int i; 1002 volatile int i;
1003 led (state); 1003 led (state);
1004 state = !state; 1004 state = !state;
1005 1005
1006 for (i = 0; i < 240000; ++i); 1006 for (i = 0; i < 240000; ++i);
1007#endif 1007#endif
1008 1008
@@ -1018,7 +1018,7 @@ void UIE (unsigned int pc) /* Unexpected Interrupt or Exception */
1018#elif CONFIG_KEYPAD == ONDIO_PAD 1018#elif CONFIG_KEYPAD == ONDIO_PAD
1019 if (!(PCDR & 0x0008)) 1019 if (!(PCDR & 0x0008))
1020#endif 1020#endif
1021 { 1021 {
1022 /* enable the watchguard timer, but don't service it */ 1022 /* enable the watchguard timer, but don't service it */
1023 RSTCSR_W = 0x5a40; /* Reset enabled, power-on reset */ 1023 RSTCSR_W = 0x5a40; /* Reset enabled, power-on reset */
1024 TCSR_W = 0xa560; /* Watchdog timer mode, timer enabled, sysclk/2 */ 1024 TCSR_W = 0xa560; /* Watchdog timer mode, timer enabled, sysclk/2 */
@@ -1086,7 +1086,7 @@ int system_memory_guard(int newmode)
1086 1086
1087 int oldmode = MEMGUARD_NONE; 1087 int oldmode = MEMGUARD_NONE;
1088 int i; 1088 int i;
1089 1089
1090 /* figure out the old mode from what is in the UBC regs. If the register 1090 /* figure out the old mode from what is in the UBC regs. If the register
1091 values don't match any mode, assume MEMGUARD_NONE */ 1091 values don't match any mode, assume MEMGUARD_NONE */
1092 for (i = MEMGUARD_NONE; i < MAXMEMGUARD; i++) 1092 for (i = MEMGUARD_NONE; i < MAXMEMGUARD; i++)
@@ -1098,7 +1098,7 @@ int system_memory_guard(int newmode)
1098 break; 1098 break;
1099 } 1099 }
1100 } 1100 }
1101 1101
1102 if (newmode == MEMGUARD_KEEP) 1102 if (newmode == MEMGUARD_KEEP)
1103 newmode = oldmode; 1103 newmode = oldmode;
1104 1104
@@ -1109,7 +1109,7 @@ int system_memory_guard(int newmode)
1109 BAR = modes[newmode].addr; 1109 BAR = modes[newmode].addr;
1110 BAMR = modes[newmode].mask; 1110 BAMR = modes[newmode].mask;
1111 BBR = modes[newmode].bbr; 1111 BBR = modes[newmode].bbr;
1112 1112
1113 return oldmode; 1113 return oldmode;
1114} 1114}
1115#elif defined(CPU_ARM) 1115#elif defined(CPU_ARM)
@@ -1124,7 +1124,7 @@ static const char* const uiename[] = {
1124void UIE(unsigned int pc, unsigned int num) 1124void UIE(unsigned int pc, unsigned int num)
1125{ 1125{
1126 char str[32]; 1126 char str[32];
1127 1127
1128 lcd_clear_display(); 1128 lcd_clear_display();
1129#ifdef HAVE_LCD_BITMAP 1129#ifdef HAVE_LCD_BITMAP
1130 lcd_setfont(FONT_SYSFIXED); 1130 lcd_setfont(FONT_SYSFIXED);
@@ -1133,7 +1133,7 @@ void UIE(unsigned int pc, unsigned int num)
1133 snprintf(str, sizeof(str), "at %08x", pc); 1133 snprintf(str, sizeof(str), "at %08x", pc);
1134 lcd_puts(0, 1, str); 1134 lcd_puts(0, 1, str);
1135 lcd_update(); 1135 lcd_update();
1136 1136
1137 while (1) 1137 while (1)
1138 { 1138 {
1139 /* TODO: perhaps add button handling in here when we get a polling 1139 /* TODO: perhaps add button handling in here when we get a polling
@@ -1160,7 +1160,7 @@ void irq(void)
1160 else if (CPU_INT_STAT & TIMER2_MASK) 1160 else if (CPU_INT_STAT & TIMER2_MASK)
1161 TIMER2(); 1161 TIMER2();
1162 else if (CPU_HI_INT_STAT & GPIO_MASK) 1162 else if (CPU_HI_INT_STAT & GPIO_MASK)
1163 ipod_mini_button_int(); 1163 ipod_mini_button_int();
1164} 1164}
1165#elif (defined IRIVER_H10) || (defined IRIVER_H10_5GB) 1165#elif (defined IRIVER_H10) || (defined IRIVER_H10_5GB)
1166/* TODO: this should really be in the target tree, but moving it there caused 1166/* TODO: this should really be in the target tree, but moving it there caused
@@ -1170,14 +1170,14 @@ void irq(void)
1170 if (CPU_INT_STAT & TIMER1_MASK) 1170 if (CPU_INT_STAT & TIMER1_MASK)
1171 TIMER1(); 1171 TIMER1();
1172 else if (CPU_INT_STAT & TIMER2_MASK) 1172 else if (CPU_INT_STAT & TIMER2_MASK)
1173 TIMER2(); 1173 TIMER2();
1174} 1174}
1175#else 1175#else
1176extern void ipod_4g_button_int(void); 1176extern void ipod_4g_button_int(void);
1177 1177
1178void irq(void) 1178void irq(void)
1179{ 1179{
1180 if (CPU_INT_STAT & TIMER1_MASK) 1180 if (CPU_INT_STAT & TIMER1_MASK)
1181 TIMER1(); 1181 TIMER1();
1182 else if (CPU_INT_STAT & TIMER2_MASK) 1182 else if (CPU_INT_STAT & TIMER2_MASK)
1183 TIMER2(); 1183 TIMER2();
@@ -1187,11 +1187,21 @@ void irq(void)
1187#endif 1187#endif
1188#endif /* BOOTLOADER */ 1188#endif /* BOOTLOADER */
1189 1189
1190unsigned int current_core(void)
1191{
1192 if(((*(volatile unsigned long *)(0x60000000)) & 0xff) == 0x55)
1193 {
1194 return CPU;
1195 }
1196 return COP;
1197}
1198
1199
1190/* TODO: The following two function have been lifted straight from IPL, and 1200/* TODO: The following two function have been lifted straight from IPL, and
1191 hence have a lot of numeric addresses used straight. I'd like to use 1201 hence have a lot of numeric addresses used straight. I'd like to use
1192 #defines for these, but don't know what most of them are for or even what 1202 #defines for these, but don't know what most of them are for or even what
1193 they should be named. Because of this I also have no way of knowing how 1203 they should be named. Because of this I also have no way of knowing how
1194 to extend the funtions to do alternate cache configurations and/or 1204 to extend the funtions to do alternate cache configurations and/or
1195 some other CPU frequency scaling. */ 1205 some other CPU frequency scaling. */
1196 1206
1197#ifndef BOOTLOADER 1207#ifndef BOOTLOADER
@@ -1251,7 +1261,7 @@ void set_cpu_frequency(long frequency)
1251#if defined(IPOD_COLOR) || defined(IPOD_4G) || defined(IPOD_MINI) 1261#if defined(IPOD_COLOR) || defined(IPOD_4G) || defined(IPOD_MINI)
1252 /* We don't know why the timer interrupt gets disabled on the PP5020 1262 /* We don't know why the timer interrupt gets disabled on the PP5020
1253 based ipods, but without the following line, the 4Gs will freeze 1263 based ipods, but without the following line, the 4Gs will freeze
1254 when CPU frequency changing is enabled. 1264 when CPU frequency changing is enabled.
1255 1265
1256 Note also that a simple "CPU_INT_EN = TIMER1_MASK;" (as used 1266 Note also that a simple "CPU_INT_EN = TIMER1_MASK;" (as used
1257 elsewhere to enable interrupts) doesn't work, we need "|=". 1267 elsewhere to enable interrupts) doesn't work, we need "|=".
@@ -1321,19 +1331,29 @@ extern void TIMER2(void);
1321 1331
1322void irq(void) 1332void irq(void)
1323{ 1333{
1324 if (CPU_INT_STAT & TIMER1_MASK) 1334 if (CPU_INT_STAT & TIMER1_MASK)
1325 TIMER1(); 1335 TIMER1();
1326 else if (CPU_INT_STAT & TIMER2_MASK) 1336 else if (CPU_INT_STAT & TIMER2_MASK)
1327 TIMER2(); 1337 TIMER2();
1328} 1338}
1329 1339
1330#endif 1340#endif
1331 1341
1342unsigned int current_core(void)
1343{
1344 if(((*(volatile unsigned long *)(0xc4000000)) & 0xff) == 0x55)
1345 {
1346 return CPU;
1347 }
1348 return COP;
1349}
1350
1351
1332/* TODO: The following two function have been lifted straight from IPL, and 1352/* TODO: The following two function have been lifted straight from IPL, and
1333 hence have a lot of numeric addresses used straight. I'd like to use 1353 hence have a lot of numeric addresses used straight. I'd like to use
1334 #defines for these, but don't know what most of them are for or even what 1354 #defines for these, but don't know what most of them are for or even what
1335 they should be named. Because of this I also have no way of knowing how 1355 they should be named. Because of this I also have no way of knowing how
1336 to extend the funtions to do alternate cache configurations and/or 1356 to extend the funtions to do alternate cache configurations and/or
1337 some other CPU frequency scaling. */ 1357 some other CPU frequency scaling. */
1338 1358
1339#ifndef BOOTLOADER 1359#ifndef BOOTLOADER
@@ -1370,7 +1390,7 @@ void set_cpu_frequency(long frequency)
1370 else 1390 else
1371 postmult = CPUFREQ_DEFAULT_MULT; 1391 postmult = CPUFREQ_DEFAULT_MULT;
1372 cpu_frequency = frequency; 1392 cpu_frequency = frequency;
1373 1393
1374 outl(0x02, 0xcf005008); 1394 outl(0x02, 0xcf005008);
1375 outl(0x55, 0xcf00500c); 1395 outl(0x55, 0xcf00500c);
1376 outl(0x6000, 0xcf005010); 1396 outl(0x6000, 0xcf005010);
@@ -1501,7 +1521,7 @@ void system_init(void)
1501 IRQ_WRITE_WAIT(0, 0, v == 0); 1521 IRQ_WRITE_WAIT(0, 0, v == 0);
1502 IRQ_WRITE_WAIT(4, 0, v == 0); 1522 IRQ_WRITE_WAIT(4, 0, v == 0);
1503 */ 1523 */
1504 1524
1505 for (i = 0; i < 0x1c; i++) 1525 for (i = 0; i < 0x1c; i++)
1506 { 1526 {
1507 IRQ_WRITE_WAIT(0x404 + i * 4, 0x1e000001, (v & 0x3010f) == 1); 1527 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
41 void *pr; /* Procedure register */ 41 void *pr; /* Procedure register */
42 void *start; /* Thread start address, or NULL when started */ 42 void *start; /* Thread start address, or NULL when started */
43}; 43};
44#elif defined(CPU_ARM) 44#elif defined(CPU_ARM)
45struct regs 45struct regs
46{ 46{
47 unsigned int r[8]; /* Registers r4-r11 */ 47 unsigned int r[8]; /* Registers r4-r11 */
@@ -62,18 +62,31 @@ struct regs
62/* Cast to the the machine int type, whose size could be < 4. */ 62/* Cast to the the machine int type, whose size could be < 4. */
63 63
64 64
65int num_threads; 65int num_threads[NUM_CORES];
66static volatile int num_sleepers; 66static volatile int num_sleepers[NUM_CORES];
67static int current_thread; 67static int current_thread[NUM_CORES];
68static struct regs thread_contexts[MAXTHREADS] IBSS_ATTR; 68static struct regs thread_contexts[NUM_CORES][MAXTHREADS] IBSS_ATTR;
69const char *thread_name[MAXTHREADS]; 69const char *thread_name[NUM_CORES][MAXTHREADS];
70void *thread_stack[MAXTHREADS]; 70void *thread_stack[NUM_CORES][MAXTHREADS];
71int thread_stack_size[MAXTHREADS]; 71int thread_stack_size[NUM_CORES][MAXTHREADS];
72static const char main_thread_name[] = "main"; 72static const char main_thread_name[] = "main";
73 73
74extern int stackbegin[]; 74extern int stackbegin[];
75extern int stackend[]; 75extern int stackend[];
76 76
77#ifdef CPU_PP
78#ifndef BOOTLOADER
79extern int cop_stackbegin[];
80extern int cop_stackend[];
81#else
82/* The coprocessor stack is not set up in the bootloader code, but the
83 threading is. No threads are run on the coprocessor, so set up some dummy
84 stack */
85int *cop_stackbegin = stackbegin;
86int *cop_stackend = stackend;
87#endif
88#endif
89
77void switch_thread(void) ICODE_ATTR; 90void switch_thread(void) ICODE_ATTR;
78static inline void store_context(void* addr) __attribute__ ((always_inline)); 91static inline void store_context(void* addr) __attribute__ ((always_inline));
79static inline void load_context(const void* addr) __attribute__ ((always_inline)); 92static inline void load_context(const void* addr) __attribute__ ((always_inline));
@@ -86,7 +99,7 @@ void profile_thread(void) {
86#endif 99#endif
87 100
88#if defined(CPU_ARM) 101#if defined(CPU_ARM)
89/*--------------------------------------------------------------------------- 102/*---------------------------------------------------------------------------
90 * Store non-volatile context. 103 * Store non-volatile context.
91 *--------------------------------------------------------------------------- 104 *---------------------------------------------------------------------------
92 */ 105 */
@@ -116,7 +129,7 @@ static inline void load_context(const void* addr)
116} 129}
117 130
118#elif defined(CPU_COLDFIRE) 131#elif defined(CPU_COLDFIRE)
119/*--------------------------------------------------------------------------- 132/*---------------------------------------------------------------------------
120 * Store non-volatile context. 133 * Store non-volatile context.
121 *--------------------------------------------------------------------------- 134 *---------------------------------------------------------------------------
122 */ 135 */
@@ -199,7 +212,7 @@ static inline void load_context(const void* addr)
199} 212}
200 213
201#elif CONFIG_CPU == TCC730 214#elif CONFIG_CPU == TCC730
202/*--------------------------------------------------------------------------- 215/*---------------------------------------------------------------------------
203 * Store non-volatile context. 216 * Store non-volatile context.
204 *--------------------------------------------------------------------------- 217 *---------------------------------------------------------------------------
205 */ 218 */
@@ -215,7 +228,7 @@ static inline void load_context(const void* addr)
215 "push a14\n\t" \ 228 "push a14\n\t" \
216 "ldw @[%0+0], a15\n\t" : : "a" (addr) ); 229 "ldw @[%0+0], a15\n\t" : : "a" (addr) );
217 230
218/*--------------------------------------------------------------------------- 231/*---------------------------------------------------------------------------
219 * Load non-volatile context. 232 * Load non-volatile context.
220 *--------------------------------------------------------------------------- 233 *---------------------------------------------------------------------------
221 */ 234 */
@@ -260,7 +273,7 @@ void switch_thread(void)
260#ifdef SIMULATOR 273#ifdef SIMULATOR
261 /* Do nothing */ 274 /* Do nothing */
262#else 275#else
263 while (num_sleepers == num_threads) 276 while (num_sleepers[CURRENT_CORE] == num_threads[CURRENT_CORE])
264 { 277 {
265 /* Enter sleep mode, woken up on interrupt */ 278 /* Enter sleep mode, woken up on interrupt */
266#ifdef CPU_COLDFIRE 279#ifdef CPU_COLDFIRE
@@ -284,21 +297,21 @@ void switch_thread(void)
284#endif 297#endif
285 } 298 }
286#endif 299#endif
287 current = current_thread; 300 current = current_thread[CURRENT_CORE];
288 store_context(&thread_contexts[current]); 301 store_context(&thread_contexts[CURRENT_CORE][current]);
289 302
290#if CONFIG_CPU != TCC730 303#if CONFIG_CPU != TCC730
291 /* Check if the current thread stack is overflown */ 304 /* Check if the current thread stack is overflown */
292 stackptr = thread_stack[current]; 305 stackptr = thread_stack[CURRENT_CORE][current];
293 if(stackptr[0] != DEADBEEF) 306 if(stackptr[0] != DEADBEEF)
294 panicf("Stkov %s", thread_name[current]); 307 panicf("Stkov %s", thread_name[CURRENT_CORE][current]);
295#endif 308#endif
296 309
297 if (++current >= num_threads) 310 if (++current >= num_threads[CURRENT_CORE])
298 current = 0; 311 current = 0;
299 312
300 current_thread = current; 313 current_thread[CURRENT_CORE] = current;
301 load_context(&thread_contexts[current]); 314 load_context(&thread_contexts[CURRENT_CORE][current]);
302#ifdef RB_PROFILE 315#ifdef RB_PROFILE
303 profile_thread_started(current_thread); 316 profile_thread_started(current_thread);
304#endif 317#endif
@@ -306,29 +319,42 @@ void switch_thread(void)
306 319
307void sleep_thread(void) 320void sleep_thread(void)
308{ 321{
309 ++num_sleepers; 322 ++num_sleepers[CURRENT_CORE];
310 switch_thread(); 323 switch_thread();
311} 324}
312 325
313void wake_up_thread(void) 326void wake_up_thread(void)
314{ 327{
315 num_sleepers = 0; 328 num_sleepers[CURRENT_CORE] = 0;
316} 329}
317 330
318/*--------------------------------------------------------------------------- 331
319 * Create thread. 332/*---------------------------------------------------------------------------
333 * Create thread on the current core.
320 * Return ID if context area could be allocated, else -1. 334 * Return ID if context area could be allocated, else -1.
321 *--------------------------------------------------------------------------- 335 *---------------------------------------------------------------------------
322 */ 336 */
323int create_thread(void (*function)(void), void* stack, int stack_size, 337int create_thread(void (*function)(void), void* stack, int stack_size,
324 const char *name) 338 const char *name)
325{ 339{
340 return create_thread_on_core(CURRENT_CORE, function, stack, stack_size,
341 name);
342}
343
344/*---------------------------------------------------------------------------
345 * Create thread on a specific core.
346 * Return ID if context area could be allocated, else -1.
347 *---------------------------------------------------------------------------
348 */
349int create_thread_on_core(unsigned int core, void (*function)(void), void* stack, int stack_size,
350 const char *name)
351{
326 unsigned int i; 352 unsigned int i;
327 unsigned int stacklen; 353 unsigned int stacklen;
328 unsigned int *stackptr; 354 unsigned int *stackptr;
329 struct regs *regs; 355 struct regs *regs;
330 356
331 if (num_threads >= MAXTHREADS) 357 if (num_threads[core] >= MAXTHREADS)
332 return -1; 358 return -1;
333 359
334 /* Munge the stack to make it easy to spot stack overflows */ 360 /* 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,
340 } 366 }
341 367
342 /* Store interesting information */ 368 /* Store interesting information */
343 thread_name[num_threads] = name; 369 thread_name[core][num_threads[core]] = name;
344 thread_stack[num_threads] = stack; 370 thread_stack[core][num_threads[core]] = stack;
345 thread_stack_size[num_threads] = stack_size; 371 thread_stack_size[core][num_threads[core]] = stack_size;
346 regs = &thread_contexts[num_threads]; 372 regs = &thread_contexts[core][num_threads[core]];
347#if defined(CPU_COLDFIRE) || (CONFIG_CPU == SH7034) || defined(CPU_ARM) 373#if defined(CPU_COLDFIRE) || (CONFIG_CPU == SH7034) || defined(CPU_ARM)
348 /* Align stack to an even 32 bit boundary */ 374 /* Align stack to an even 32 bit boundary */
349 regs->sp = (void*)(((unsigned int)stack + stack_size) & ~3); 375 regs->sp = (void*)(((unsigned int)stack + stack_size) & ~3);
@@ -355,65 +381,91 @@ int create_thread(void (*function)(void), void* stack, int stack_size,
355 regs->start = (void*)function; 381 regs->start = (void*)function;
356 382
357 wake_up_thread(); 383 wake_up_thread();
358 return num_threads++; /* return the current ID, e.g for remove_thread() */ 384 return num_threads[core]++; /* return the current ID, e.g for remove_thread() */
359} 385}
360 386
361/*--------------------------------------------------------------------------- 387/*---------------------------------------------------------------------------
362 * Remove a thread from the scheduler. 388 * Remove a thread on the current core from the scheduler.
363 * Parameter is the ID as returned from create_thread(). 389 * Parameter is the ID as returned from create_thread().
364 *--------------------------------------------------------------------------- 390 *---------------------------------------------------------------------------
365 */ 391 */
366void remove_thread(int threadnum) 392void remove_thread(int threadnum)
367{ 393{
394 remove_thread_on_core(CURRENT_CORE, threadnum);
395}
396
397/*---------------------------------------------------------------------------
398 * Remove a thread on the specified core from the scheduler.
399 * Parameters are the core and the ID as returned from create_thread().
400 *---------------------------------------------------------------------------
401 */
402void remove_thread_on_core(unsigned int core, int threadnum)
403{
368 int i; 404 int i;
369 405
370 if(threadnum >= num_threads) 406 if(threadnum >= num_threads[core])
371 return; 407 return;
372 408
373 num_threads--; 409 num_threads[core]--;
374 for (i=threadnum; i<num_threads-1; i++) 410 for (i=threadnum; i<num_threads[core]-1; i++)
375 { /* move all entries which are behind */ 411 { /* move all entries which are behind */
376 thread_name[i] = thread_name[i+1]; 412 thread_name[core][i] = thread_name[core][i+1];
377 thread_stack[i] = thread_stack[i+1]; 413 thread_stack[core][i] = thread_stack[core][i+1];
378 thread_stack_size[i] = thread_stack_size[i+1]; 414 thread_stack_size[core][i] = thread_stack_size[core][i+1];
379 thread_contexts[i] = thread_contexts[i+1]; 415 thread_contexts[core][i] = thread_contexts[core][i+1];
380 } 416 }
381 417
382 if (current_thread == threadnum) /* deleting the current one? */ 418 if (current_thread[core] == threadnum) /* deleting the current one? */
383 current_thread = num_threads; /* set beyond last, avoid store harm */ 419 current_thread[core] = num_threads[core]; /* set beyond last, avoid store harm */
384 else if (current_thread > threadnum) /* within the moved positions? */ 420 else if (current_thread[core] > threadnum) /* within the moved positions? */
385 current_thread--; /* adjust it, point to same context again */ 421 current_thread[core]--; /* adjust it, point to same context again */
386} 422}
387 423
388void init_threads(void) 424void init_threads(void)
389{ 425{
390 num_threads = 1; /* We have 1 thread to begin with */ 426 unsigned int core = CURRENT_CORE;
391 current_thread = 0; /* The current thread is number 0 */ 427
392 thread_name[0] = main_thread_name; 428 num_threads[core] = 1; /* We have 1 thread to begin with */
393 thread_stack[0] = stackbegin; 429 current_thread[core] = 0; /* The current thread is number 0 */
394 thread_stack_size[0] = (int)stackend - (int)stackbegin; 430 thread_name[core][0] = main_thread_name;
431/* In multiple core setups, each core has a different stack. There is probably
432 a much better way to do this. */
433 if(core == CPU)
434 {
435 thread_stack[CPU][0] = stackbegin;
436 thread_stack_size[CPU][0] = (int)stackend - (int)stackbegin;
437 } else {
438#if NUM_CORES > 1 /* This code path will not be run on single core targets */
439 thread_stack[COP][0] = cop_stackbegin;
440 thread_stack_size[COP][0] = (int)cop_stackend - (int)cop_stackbegin;
441#endif
442 }
395#if CONFIG_CPU == TCC730 443#if CONFIG_CPU == TCC730
396 thread_contexts[0].started = 1; 444 thread_contexts[core][0].started = 1;
397#else 445#else
398 thread_contexts[0].start = 0; /* thread 0 already running */ 446 thread_contexts[core][0].start = 0; /* thread 0 already running */
399#endif 447#endif
400 num_sleepers = 0; 448 num_sleepers[core] = 0;
449}
450
451int thread_stack_usage(int threadnum){
452 return thread_stack_usage_on_core(CURRENT_CORE, threadnum);
401} 453}
402 454
403int thread_stack_usage(int threadnum) 455int thread_stack_usage_on_core(unsigned int core, int threadnum)
404{ 456{
405 unsigned int i; 457 unsigned int i;
406 unsigned int *stackptr = thread_stack[threadnum]; 458 unsigned int *stackptr = thread_stack[core][threadnum];
407 459
408 if(threadnum >= num_threads) 460 if(threadnum >= num_threads[core])
409 return -1; 461 return -1;
410 462
411 for(i = 0;i < thread_stack_size[threadnum]/sizeof(int);i++) 463 for(i = 0;i < thread_stack_size[core][threadnum]/sizeof(int);i++)
412 { 464 {
413 if(stackptr[i] != DEADBEEF) 465 if(stackptr[i] != DEADBEEF)
414 break; 466 break;
415 } 467 }
416 468
417 return ((thread_stack_size[threadnum] - i * sizeof(int)) * 100) / 469 return ((thread_stack_size[core][threadnum] - i * sizeof(int)) * 100) /
418 thread_stack_size[threadnum]; 470 thread_stack_size[core][threadnum];
419} 471}