summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/debug_menu.c205
-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
6 files changed, 307 insertions, 205 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 @@
78/*---------------------------------------------------*/ 78/*---------------------------------------------------*/
79extern char ata_device; 79extern char ata_device;
80extern int ata_io_address; 80extern int ata_io_address;
81extern int num_threads; 81extern int num_threads[];
82extern const char *thread_name[]; 82extern const char *thread_name[][MAXTHREADS];
83 83
84#ifdef HAVE_LCD_BITMAP 84#ifdef HAVE_LCD_BITMAP
85/* Test code!!! */ 85/* Test code!!! */
@@ -88,6 +88,8 @@ bool dbg_os(void)
88 char buf[32]; 88 char buf[32];
89 int i; 89 int i;
90 int usage; 90 int usage;
91 unsigned int core;
92 int line;
91 93
92 lcd_setmargins(0, 0); 94 lcd_setmargins(0, 0);
93 lcd_setfont(FONT_SYSFIXED); 95 lcd_setfont(FONT_SYSFIXED);
@@ -95,12 +97,16 @@ bool dbg_os(void)
95 97
96 while(1) 98 while(1)
97 { 99 {
98 lcd_puts(0, 0, "Stack usage:"); 100 lcd_puts(0, 0, "Core and stack usage:");
99 for(i = 0; i < num_threads;i++) 101 line = 0;
102 for(core = 0; core < NUM_CORES; core++)
100 { 103 {
101 usage = thread_stack_usage(i); 104 for(i = 0; i < num_threads[core]; i++)
102 snprintf(buf, 32, "%s: %d%%", thread_name[i], usage); 105 {
103 lcd_puts(0, 1+i, buf); 106 usage = thread_stack_usage_on_core(core, i);
107 snprintf(buf, 32, "(%d) %s: %d%%", core, thread_name[core][i], usage);
108 lcd_puts(0, ++line, buf);
109 }
104 } 110 }
105 111
106 lcd_update(); 112 lcd_update();
@@ -124,10 +130,11 @@ bool dbg_os(void)
124 { 130 {
125 lcd_puts(0, 0, "Stack usage"); 131 lcd_puts(0, 0, "Stack usage");
126 132
133 /* Only Archos Player uses this - so assume a single core */
127 usage = thread_stack_usage(currval); 134 usage = thread_stack_usage(currval);
128 snprintf(buf, 32, "%d: %d%% ", currval, usage); 135 snprintf(buf, 32, "%d: %d%% ", currval, usage);
129 lcd_puts(0, 1, buf); 136 lcd_puts(0, 1, buf);
130 137
131 button = get_action(CONTEXT_SETTINGS,HZ/10); 138 button = get_action(CONTEXT_SETTINGS,HZ/10);
132 139
133 switch(button) 140 switch(button)
@@ -162,14 +169,14 @@ bool dbg_audio_thread(void)
162 169
163 lcd_setmargins(0, 0); 170 lcd_setmargins(0, 0);
164 lcd_setfont(FONT_SYSFIXED); 171 lcd_setfont(FONT_SYSFIXED);
165 172
166 while(1) 173 while(1)
167 { 174 {
168 if (action_userabort(HZ/5)) 175 if (action_userabort(HZ/5))
169 return false; 176 return false;
170 177
171 audio_get_debugdata(&d); 178 audio_get_debugdata(&d);
172 179
173 lcd_clear_display(); 180 lcd_clear_display();
174 181
175 snprintf(buf, sizeof(buf), "read: %x", d.audiobuf_read); 182 snprintf(buf, sizeof(buf), "read: %x", d.audiobuf_read);
@@ -186,17 +193,17 @@ bool dbg_audio_thread(void)
186 lcd_puts(0, 5, buf); 193 lcd_puts(0, 5, buf);
187 194
188 /* Playable space left */ 195 /* Playable space left */
189 scrollbar(0, 6*8, 112, 4, d.audiobuflen, 0, 196 scrollbar(0, 6*8, 112, 4, d.audiobuflen, 0,
190 d.playable_space, HORIZONTAL); 197 d.playable_space, HORIZONTAL);
191 198
192 /* Show the watermark limit */ 199 /* Show the watermark limit */
193 scrollbar(0, 6*8+4, 112, 4, d.audiobuflen, 0, 200 scrollbar(0, 6*8+4, 112, 4, d.audiobuflen, 0,
194 d.low_watermark_level, HORIZONTAL); 201 d.low_watermark_level, HORIZONTAL);
195 202
196 snprintf(buf, sizeof(buf), "wm: %x - %x", 203 snprintf(buf, sizeof(buf), "wm: %x - %x",
197 d.low_watermark_level, d.lowest_watermark_level); 204 d.low_watermark_level, d.lowest_watermark_level);
198 lcd_puts(0, 7, buf); 205 lcd_puts(0, 7, buf);
199 206
200 lcd_update(); 207 lcd_update();
201 } 208 }
202 return false; 209 return false;
@@ -229,7 +236,7 @@ bool dbg_audio_thread(void)
229 ticks = boost_ticks = 0; 236 ticks = boost_ticks = 0;
230 237
231 tick_add_task(dbg_audio_task); 238 tick_add_task(dbg_audio_task);
232 239
233 lcd_setmargins(0, 0); 240 lcd_setmargins(0, 0);
234 lcd_setfont(FONT_SYSFIXED); 241 lcd_setfont(FONT_SYSFIXED);
235 while(!done) 242 while(!done)
@@ -249,7 +256,7 @@ bool dbg_audio_thread(void)
249 } 256 }
250 action_signalscreenchange(); 257 action_signalscreenchange();
251 line = 0; 258 line = 0;
252 259
253 lcd_clear_display(); 260 lcd_clear_display();
254 261
255 bufused = bufsize - pcmbuf_free(); 262 bufused = bufsize - pcmbuf_free();
@@ -283,12 +290,12 @@ bool dbg_audio_thread(void)
283 snprintf(buf, sizeof(buf), "pcmbufdesc: %2d/%2d", 290 snprintf(buf, sizeof(buf), "pcmbufdesc: %2d/%2d",
284 pcmbuf_used_descs(), pcmbufdescs); 291 pcmbuf_used_descs(), pcmbufdescs);
285 lcd_puts(0, line++, buf); 292 lcd_puts(0, line++, buf);
286 293
287 lcd_update(); 294 lcd_update();
288 } 295 }
289 296
290 tick_remove_task(dbg_audio_task); 297 tick_remove_task(dbg_audio_task);
291 298
292 return false; 299 return false;
293} 300}
294#endif /* CONFIG_CODEC */ 301#endif /* CONFIG_CODEC */
@@ -303,7 +310,7 @@ static void flash_write_word(unsigned addr, unsigned value) {
303 flash_word_temp = value; 310 flash_word_temp = value;
304 311
305 long extAddr = (long)addr << 1; 312 long extAddr = (long)addr << 1;
306 ddma_transfer(1, 1, &flash_word_temp, extAddr, 2); 313 ddma_transfer(1, 1, &flash_word_temp, extAddr, 2);
307} 314}
308 315
309static unsigned flash_read_word(unsigned addr) __attribute__ ((section(".icode"))); 316static unsigned flash_read_word(unsigned addr) __attribute__ ((section(".icode")));
@@ -324,7 +331,7 @@ bool dbg_flash_id(unsigned* p_manufacturer, unsigned* p_device,
324 __attribute__ ((section (".icode"))); 331 __attribute__ ((section (".icode")));
325bool dbg_flash_id(unsigned* p_manufacturer, unsigned* p_device, 332bool dbg_flash_id(unsigned* p_manufacturer, unsigned* p_device,
326 unsigned addr1, unsigned addr2) 333 unsigned addr1, unsigned addr2)
327 334
328{ 335{
329#if (CONFIG_CPU == PP5002) || (CONFIG_CPU == PP5020) 336#if (CONFIG_CPU == PP5002) || (CONFIG_CPU == PP5020)
330 /* TODO: Implement for iPod */ 337 /* TODO: Implement for iPod */
@@ -382,9 +389,9 @@ bool dbg_flash_id(unsigned* p_manufacturer, unsigned* p_device,
382 /* sleep(HZ/50); no sleeping possible while interrupts are disabled */ 389 /* sleep(HZ/50); no sleeping possible while interrupts are disabled */
383 390
384 set_irq_level(old_level); /* enable interrupts again */ 391 set_irq_level(old_level); /* enable interrupts again */
385 392
386 /* I assume success if the obtained values are different from 393 /* I assume success if the obtained values are different from
387 the normal flash content. This is not perfectly bulletproof, they 394 the normal flash content. This is not perfectly bulletproof, they
388 could theoretically be the same by chance, causing us to fail. */ 395 could theoretically be the same by chance, causing us to fail. */
389 if (not_manu != manu || not_id != id) /* a value has changed */ 396 if (not_manu != manu || not_id != id) /* a value has changed */
390 { 397 {
@@ -431,7 +438,7 @@ bool dbg_hw_info(void)
431 got_id = dbg_flash_id(&manu, &id, 0x5555, 0x2AAA); /* try SST, Atmel, NexFlash */ 438 got_id = dbg_flash_id(&manu, &id, 0x5555, 0x2AAA); /* try SST, Atmel, NexFlash */
432 if (!got_id) 439 if (!got_id)
433 got_id = dbg_flash_id(&manu, &id, 0x555, 0x2AA); /* try AMD, Macronix */ 440 got_id = dbg_flash_id(&manu, &id, 0x555, 0x2AA); /* try AMD, Macronix */
434 441
435 /* check if the boot ROM area is a flash mirror */ 442 /* check if the boot ROM area is a flash mirror */
436 has_bootrom = (memcmp((char*)0, (char*)0x02000000, 64*1024) != 0); 443 has_bootrom = (memcmp((char*)0, (char*)0x02000000, 64*1024) != 0);
437 if (has_bootrom) /* if ROM and Flash different */ 444 if (has_bootrom) /* if ROM and Flash different */
@@ -450,16 +457,16 @@ bool dbg_hw_info(void)
450 457
451 snprintf(buf, 32, "ROM: %d.%02d", rom_version/100, rom_version%100); 458 snprintf(buf, 32, "ROM: %d.%02d", rom_version/100, rom_version%100);
452 lcd_puts(0, 1, buf); 459 lcd_puts(0, 1, buf);
453 460
454 snprintf(buf, 32, "Mask: 0x%04x", bitmask); 461 snprintf(buf, 32, "Mask: 0x%04x", bitmask);
455 lcd_puts(0, 2, buf); 462 lcd_puts(0, 2, buf);
456 463
457 snprintf(buf, 32, "USB: %s", usb_polarity?"positive":"negative"); 464 snprintf(buf, 32, "USB: %s", usb_polarity?"positive":"negative");
458 lcd_puts(0, 3, buf); 465 lcd_puts(0, 3, buf);
459 466
460 snprintf(buf, 32, "PR: %s", pr_polarity?"positive":"negative"); 467 snprintf(buf, 32, "PR: %s", pr_polarity?"positive":"negative");
461 lcd_puts(0, 4, buf); 468 lcd_puts(0, 4, buf);
462 469
463 if (got_id) 470 if (got_id)
464 snprintf(buf, 32, "Flash: M=%02x D=%02x", manu, id); 471 snprintf(buf, 32, "Flash: M=%02x D=%02x", manu, id);
465 else 472 else
@@ -483,7 +490,7 @@ bool dbg_hw_info(void)
483 snprintf(buf, 32, "ATA: 0x%x,%s", ata_io_address, 490 snprintf(buf, 32, "ATA: 0x%x,%s", ata_io_address,
484 ata_device ? "slave":"master"); 491 ata_device ? "slave":"master");
485 lcd_puts(0, 7, buf); 492 lcd_puts(0, 7, buf);
486#endif 493#endif
487 lcd_update(); 494 lcd_update();
488 495
489 while(1) 496 while(1)
@@ -503,7 +510,7 @@ bool dbg_hw_info(void)
503 got_id = dbg_flash_id(&manu, &id, 0x5555, 0x2AAA); /* try SST, Atmel, NexFlash */ 510 got_id = dbg_flash_id(&manu, &id, 0x5555, 0x2AAA); /* try SST, Atmel, NexFlash */
504 if (!got_id) 511 if (!got_id)
505 got_id = dbg_flash_id(&manu, &id, 0x555, 0x2AA); /* try AMD, Macronix */ 512 got_id = dbg_flash_id(&manu, &id, 0x555, 0x2AA); /* try AMD, Macronix */
506 513
507 system_memory_guard(oldmode); /* re-enable memory guard */ 514 system_memory_guard(oldmode); /* re-enable memory guard */
508 515
509 lcd_setmargins(0, 0); 516 lcd_setmargins(0, 0);
@@ -533,7 +540,7 @@ bool dbg_hw_info(void)
533 lcd_clear_display(); 540 lcd_clear_display();
534 541
535 lcd_puts(0, 0, "[Hardware info]"); 542 lcd_puts(0, 0, "[Hardware info]");
536 543
537 snprintf(buf, sizeof(buf), "HW rev: 0x%08x", ipod_hw_rev); 544 snprintf(buf, sizeof(buf), "HW rev: 0x%08x", ipod_hw_rev);
538 lcd_puts(0, 1, buf); 545 lcd_puts(0, 1, buf);
539 546
@@ -581,7 +588,7 @@ bool dbg_hw_info(void)
581 /* calculate CRC16 checksum of boot ROM */ 588 /* calculate CRC16 checksum of boot ROM */
582 rom_crc = crc_32((unsigned char*)0x0000, 64*1024, 0xffffffff); 589 rom_crc = crc_32((unsigned char*)0x0000, 64*1024, 0xffffffff);
583 } 590 }
584 591
585 system_memory_guard(oldmode); /* re-enable memory guard */ 592 system_memory_guard(oldmode); /* re-enable memory guard */
586 593
587 lcd_clear_display(); 594 lcd_clear_display();
@@ -617,7 +624,7 @@ bool dbg_hw_info(void)
617 { 624 {
618 if (rom_crc == 0x56DBA4EE) /* known Version 1 */ 625 if (rom_crc == 0x56DBA4EE) /* known Version 1 */
619 snprintf(buf, 32, "BootROM: V1"); 626 snprintf(buf, 32, "BootROM: V1");
620 else if (rom_crc == 0x358099E8) 627 else if (rom_crc == 0x358099E8)
621 snprintf(buf, 32, "BootROM: V2"); 628 snprintf(buf, 32, "BootROM: V2");
622 /* alternative boot ROM found in one single player so far */ 629 /* alternative boot ROM found in one single player so far */
623 else 630 else
@@ -626,10 +633,10 @@ bool dbg_hw_info(void)
626 else 633 else
627 snprintf(buf, 32, "BootROM: no"); 634 snprintf(buf, 32, "BootROM: no");
628 } 635 }
629 636
630 lcd_puts(0, 1, buf); 637 lcd_puts(0, 1, buf);
631 lcd_update(); 638 lcd_update();
632 639
633 button = get_action(CONTEXT_SETTINGS,TIMEOUT_BLOCK); 640 button = get_action(CONTEXT_SETTINGS,TIMEOUT_BLOCK);
634 641
635 switch(button) 642 switch(button)
@@ -643,7 +650,7 @@ bool dbg_hw_info(void)
643 if(currval < 0) 650 if(currval < 0)
644 currval = 5; 651 currval = 5;
645 break; 652 break;
646 653
647 case ACTION_SETTINGS_INC: 654 case ACTION_SETTINGS_INC:
648 currval++; 655 currval++;
649 if(currval > 5) 656 if(currval > 5)
@@ -677,7 +684,7 @@ bool dbg_partitions(void)
677 snprintf(buf, sizeof buf, "T:%x %ld MB", p->type, p->size / 2048); 684 snprintf(buf, sizeof buf, "T:%x %ld MB", p->type, p->size / 2048);
678 lcd_puts(0, 1, buf); 685 lcd_puts(0, 1, buf);
679 lcd_update(); 686 lcd_update();
680 687
681 button = get_action(CONTEXT_SETTINGS,TIMEOUT_BLOCK); 688 button = get_action(CONTEXT_SETTINGS,TIMEOUT_BLOCK);
682 689
683 switch(button) 690 switch(button)
@@ -691,7 +698,7 @@ bool dbg_partitions(void)
691 if (partition < 0) 698 if (partition < 0)
692 partition = 3; 699 partition = 3;
693 break; 700 break;
694 701
695 case ACTION_SETTINGS_INC: 702 case ACTION_SETTINGS_INC:
696 partition++; 703 partition++;
697 if (partition > 3) 704 if (partition > 3)
@@ -751,22 +758,22 @@ bool dbg_spdif(void)
751 lcd_puts(0, line++, buf); 758 lcd_puts(0, line++, buf);
752 759
753 line++; 760 line++;
754 761
755 x = control >> 31; 762 x = control >> 31;
756 snprintf(buf, sizeof(buf), "PRO: %d (%s)", 763 snprintf(buf, sizeof(buf), "PRO: %d (%s)",
757 x, x?"Professional":"Consumer"); 764 x, x?"Professional":"Consumer");
758 lcd_puts(0, line++, buf); 765 lcd_puts(0, line++, buf);
759 766
760 x = (control >> 30) & 1; 767 x = (control >> 30) & 1;
761 snprintf(buf, sizeof(buf), "Audio: %d (%s)", 768 snprintf(buf, sizeof(buf), "Audio: %d (%s)",
762 x, x?"Non-PCM":"PCM"); 769 x, x?"Non-PCM":"PCM");
763 lcd_puts(0, line++, buf); 770 lcd_puts(0, line++, buf);
764 771
765 x = (control >> 29) & 1; 772 x = (control >> 29) & 1;
766 snprintf(buf, sizeof(buf), "Copy: %d (%s)", 773 snprintf(buf, sizeof(buf), "Copy: %d (%s)",
767 x, x?"Permitted":"Inhibited"); 774 x, x?"Permitted":"Inhibited");
768 lcd_puts(0, line++, buf); 775 lcd_puts(0, line++, buf);
769 776
770 x = (control >> 27) & 7; 777 x = (control >> 27) & 7;
771 switch(x) 778 switch(x)
772 { 779 {
@@ -786,7 +793,7 @@ bool dbg_spdif(void)
786 x = (control >> 24) & 3; 793 x = (control >> 24) & 3;
787 snprintf(buf, sizeof(buf), "Mode: %d", x); 794 snprintf(buf, sizeof(buf), "Mode: %d", x);
788 lcd_puts(0, line++, buf); 795 lcd_puts(0, line++, buf);
789 796
790 category = (control >> 17) & 127; 797 category = (control >> 17) & 127;
791 switch(category) 798 switch(category)
792 { 799 {
@@ -801,7 +808,7 @@ bool dbg_spdif(void)
801 } 808 }
802 snprintf(buf, sizeof(buf), "Category: 0x%02x (%s)", category, s); 809 snprintf(buf, sizeof(buf), "Category: 0x%02x (%s)", category, s);
803 lcd_puts(0, line++, buf); 810 lcd_puts(0, line++, buf);
804 811
805 x = (control >> 16) & 1; 812 x = (control >> 16) & 1;
806 generation = x; 813 generation = x;
807 if(((category & 0x70) == 0x10) || 814 if(((category & 0x70) == 0x10) ||
@@ -813,11 +820,11 @@ bool dbg_spdif(void)
813 snprintf(buf, sizeof(buf), "Generation: %d (%s)", 820 snprintf(buf, sizeof(buf), "Generation: %d (%s)",
814 x, generation?"Original":"No ind."); 821 x, generation?"Original":"No ind.");
815 lcd_puts(0, line++, buf); 822 lcd_puts(0, line++, buf);
816 823
817 x = (control >> 12) & 15; 824 x = (control >> 12) & 15;
818 snprintf(buf, sizeof(buf), "Source: %d", x); 825 snprintf(buf, sizeof(buf), "Source: %d", x);
819 lcd_puts(0, line++, buf); 826 lcd_puts(0, line++, buf);
820 827
821 x = (control >> 8) & 15; 828 x = (control >> 8) & 15;
822 switch(x) 829 switch(x)
823 { 830 {
@@ -836,7 +843,7 @@ bool dbg_spdif(void)
836 } 843 }
837 snprintf(buf, sizeof(buf), "Channel: %d (%s)", x, s); 844 snprintf(buf, sizeof(buf), "Channel: %d (%s)", x, s);
838 lcd_puts(0, line++, buf); 845 lcd_puts(0, line++, buf);
839 846
840 x = (control >> 4) & 15; 847 x = (control >> 4) & 15;
841 switch(x) 848 switch(x)
842 { 849 {
@@ -857,7 +864,7 @@ bool dbg_spdif(void)
857 snprintf(buf, sizeof(buf), "Clock accuracy: %d", x); 864 snprintf(buf, sizeof(buf), "Clock accuracy: %d", x);
858 lcd_puts(0, line++, buf); 865 lcd_puts(0, line++, buf);
859 line++; 866 line++;
860 867
861 snprintf(buf, sizeof(buf), "Measured freq: %ldHz", 868 snprintf(buf, sizeof(buf), "Measured freq: %ldHz",
862 (long)((long long)FREQMEAS*CPU_FREQ/((1 << 15)*3*(1 << 13))/128)); 869 (long)((long long)FREQMEAS*CPU_FREQ/((1 << 15)*3*(1 << 13))/128));
863 lcd_puts(0, line++, buf); 870 lcd_puts(0, line++, buf);
@@ -914,7 +921,7 @@ bool dbg_ports(void)
914 battery_voltage = (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) / 10000; 921 battery_voltage = (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) / 10000;
915 batt_int = battery_voltage / 100; 922 batt_int = battery_voltage / 100;
916 batt_frac = battery_voltage % 100; 923 batt_frac = battery_voltage % 100;
917 924
918 snprintf(buf, 32, "Batt: %d.%02dV %d%% ", batt_int, batt_frac, 925 snprintf(buf, 32, "Batt: %d.%02dV %d%% ", batt_int, batt_frac,
919 battery_level()); 926 battery_level());
920 lcd_puts(0, 6, buf); 927 lcd_puts(0, 6, buf);
@@ -960,7 +967,7 @@ bool dbg_ports(void)
960 gpio1_function = GPIO1_FUNCTION; 967 gpio1_function = GPIO1_FUNCTION;
961 gpio_enable = GPIO_ENABLE; 968 gpio_enable = GPIO_ENABLE;
962 gpio1_enable = GPIO1_ENABLE; 969 gpio1_enable = GPIO1_ENABLE;
963 970
964 snprintf(buf, sizeof(buf), "GPIO_READ: %08x", gpio_read); 971 snprintf(buf, sizeof(buf), "GPIO_READ: %08x", gpio_read);
965 lcd_puts(0, line++, buf); 972 lcd_puts(0, line++, buf);
966 snprintf(buf, sizeof(buf), "GPIO_OUT: %08x", gpio_out); 973 snprintf(buf, sizeof(buf), "GPIO_OUT: %08x", gpio_out);
@@ -985,7 +992,7 @@ bool dbg_ports(void)
985#if defined(IRIVER_H100_SERIES) || defined(IRIVER_H300_SERIES) 992#if defined(IRIVER_H100_SERIES) || defined(IRIVER_H300_SERIES)
986 adc_remotedetect = adc_read(ADC_REMOTEDETECT); 993 adc_remotedetect = adc_read(ADC_REMOTEDETECT);
987#endif 994#endif
988 995
989 snprintf(buf, sizeof(buf), "ADC_BUTTONS: %02x", adc_buttons); 996 snprintf(buf, sizeof(buf), "ADC_BUTTONS: %02x", adc_buttons);
990 lcd_puts(0, line++, buf); 997 lcd_puts(0, line++, buf);
991 snprintf(buf, sizeof(buf), "ADC_REMOTE: %02x", adc_remote); 998 snprintf(buf, sizeof(buf), "ADC_REMOTE: %02x", adc_remote);
@@ -1000,16 +1007,16 @@ bool dbg_ports(void)
1000 battery_voltage = (adc_battery * BATTERY_SCALE_FACTOR) / 10000; 1007 battery_voltage = (adc_battery * BATTERY_SCALE_FACTOR) / 10000;
1001 batt_int = battery_voltage / 100; 1008 batt_int = battery_voltage / 100;
1002 batt_frac = battery_voltage % 100; 1009 batt_frac = battery_voltage % 100;
1003 1010
1004 snprintf(buf, 32, "Batt: %d.%02dV %d%% ", batt_int, batt_frac, 1011 snprintf(buf, 32, "Batt: %d.%02dV %d%% ", batt_int, batt_frac,
1005 battery_level()); 1012 battery_level());
1006 lcd_puts(0, line++, buf); 1013 lcd_puts(0, line++, buf);
1007 1014
1008#if defined(IRIVER_H100_SERIES) || defined(IRIVER_H300_SERIES) 1015#if defined(IRIVER_H100_SERIES) || defined(IRIVER_H300_SERIES)
1009 snprintf(buf, sizeof(buf), "remotetype:: %d", remote_type()); 1016 snprintf(buf, sizeof(buf), "remotetype:: %d", remote_type());
1010 lcd_puts(0, line++, buf); 1017 lcd_puts(0, line++, buf);
1011#endif 1018#endif
1012 1019
1013 lcd_update(); 1020 lcd_update();
1014 if (action_userabort(HZ/10)) 1021 if (action_userabort(HZ/10))
1015 return false; 1022 return false;
@@ -1128,15 +1135,15 @@ bool dbg_ports(void)
1128 break; 1135 break;
1129 } 1136 }
1130 lcd_puts(0, 0, buf); 1137 lcd_puts(0, 0, buf);
1131 1138
1132 battery_voltage = (adc_read(ADC_UNREG_POWER) * 1139 battery_voltage = (adc_read(ADC_UNREG_POWER) *
1133 BATTERY_SCALE_FACTOR) / 10000; 1140 BATTERY_SCALE_FACTOR) / 10000;
1134 batt_int = battery_voltage / 100; 1141 batt_int = battery_voltage / 100;
1135 batt_frac = battery_voltage % 100; 1142 batt_frac = battery_voltage % 100;
1136 1143
1137 snprintf(buf, 32, "Batt: %d.%02dV", batt_int, batt_frac); 1144 snprintf(buf, 32, "Batt: %d.%02dV", batt_int, batt_frac);
1138 lcd_puts(0, 1, buf); 1145 lcd_puts(0, 1, buf);
1139 1146
1140 button = get_action(CONTEXT_SETTINGS,HZ/5); 1147 button = get_action(CONTEXT_SETTINGS,HZ/5);
1141 1148
1142 switch(button) 1149 switch(button)
@@ -1179,7 +1186,7 @@ bool dbg_cpufreq(void)
1179 while(1) 1186 while(1)
1180 { 1187 {
1181 line = 0; 1188 line = 0;
1182 1189
1183 snprintf(buf, sizeof(buf), "Frequency: %ld", FREQ); 1190 snprintf(buf, sizeof(buf), "Frequency: %ld", FREQ);
1184 lcd_puts(0, line++, buf); 1191 lcd_puts(0, line++, buf);
1185 1192
@@ -1212,7 +1219,7 @@ bool dbg_cpufreq(void)
1212 return false; 1219 return false;
1213} 1220}
1214#endif /* HAVE_ADJUSTABLE_CPU_FREQ */ 1221#endif /* HAVE_ADJUSTABLE_CPU_FREQ */
1215 1222
1216#ifdef HAVE_LCD_BITMAP 1223#ifdef HAVE_LCD_BITMAP
1217/* 1224/*
1218 * view_battery() shows a automatically scaled graph of the battery voltage 1225 * view_battery() shows a automatically scaled graph of the battery voltage
@@ -1229,7 +1236,7 @@ bool view_battery(void)
1229 int i, x, y; 1236 int i, x, y;
1230 unsigned short maxv, minv; 1237 unsigned short maxv, minv;
1231 char buf[32]; 1238 char buf[32];
1232 1239
1233 lcd_setmargins(0, 0); 1240 lcd_setmargins(0, 0);
1234 lcd_setfont(FONT_SYSFIXED); 1241 lcd_setfont(FONT_SYSFIXED);
1235 1242
@@ -1248,20 +1255,20 @@ bool view_battery(void)
1248 minv = power_history[i]; 1255 minv = power_history[i];
1249 } 1256 }
1250 } 1257 }
1251 1258
1252 if ((minv < 1) || (minv >= 65535)) 1259 if ((minv < 1) || (minv >= 65535))
1253 minv = 1; 1260 minv = 1;
1254 if (maxv < 2) 1261 if (maxv < 2)
1255 maxv = 2; 1262 maxv = 2;
1256 1263
1257 lcd_clear_display(); 1264 lcd_clear_display();
1258 snprintf(buf, 30, "Battery %d.%02d", power_history[0] / 100, 1265 snprintf(buf, 30, "Battery %d.%02d", power_history[0] / 100,
1259 power_history[0] % 100); 1266 power_history[0] % 100);
1260 lcd_puts(0, 0, buf); 1267 lcd_puts(0, 0, buf);
1261 snprintf(buf, 30, "scale %d.%02d-%d.%02d V", 1268 snprintf(buf, 30, "scale %d.%02d-%d.%02d V",
1262 minv / 100, minv % 100, maxv / 100, maxv % 100); 1269 minv / 100, minv % 100, maxv / 100, maxv % 100);
1263 lcd_puts(0, 1, buf); 1270 lcd_puts(0, 1, buf);
1264 1271
1265 x = 0; 1272 x = 0;
1266 for (i = BAT_LAST_VAL - 1; i >= 0; i--) { 1273 for (i = BAT_LAST_VAL - 1; i >= 0; i--) {
1267 y = (power_history[i] - minv) * BAT_YSPACE / (maxv - minv); 1274 y = (power_history[i] - minv) * BAT_YSPACE / (maxv - minv);
@@ -1274,7 +1281,7 @@ bool view_battery(void)
1274 } 1281 }
1275 1282
1276 break; 1283 break;
1277 1284
1278 case 1: /* status: */ 1285 case 1: /* status: */
1279 lcd_clear_display(); 1286 lcd_clear_display();
1280 lcd_puts(0, 0, "Power status:"); 1287 lcd_puts(0, 0, "Power status:");
@@ -1289,7 +1296,7 @@ bool view_battery(void)
1289#endif 1296#endif
1290#ifdef CONFIG_CHARGING 1297#ifdef CONFIG_CHARGING
1291#if CONFIG_CHARGING == CHARGING_CONTROL 1298#if CONFIG_CHARGING == CHARGING_CONTROL
1292 snprintf(buf, 30, "Chgr: %s %s", 1299 snprintf(buf, 30, "Chgr: %s %s",
1293 charger_inserted() ? "present" : "absent", 1300 charger_inserted() ? "present" : "absent",
1294 charger_enabled ? "on" : "off"); 1301 charger_enabled ? "on" : "off");
1295 lcd_puts(0, 3, buf); 1302 lcd_puts(0, 3, buf);
@@ -1329,15 +1336,15 @@ bool view_battery(void)
1329#endif /* CONFIG_CHARGING != CHARGING_CONTROL */ 1336#endif /* CONFIG_CHARGING != CHARGING_CONTROL */
1330#endif /* CONFIG_CHARGING */ 1337#endif /* CONFIG_CHARGING */
1331 break; 1338 break;
1332 1339
1333 case 2: /* voltage deltas: */ 1340 case 2: /* voltage deltas: */
1334 lcd_clear_display(); 1341 lcd_clear_display();
1335 lcd_puts(0, 0, "Voltage deltas:"); 1342 lcd_puts(0, 0, "Voltage deltas:");
1336 1343
1337 for (i = 0; i <= 6; i++) { 1344 for (i = 0; i <= 6; i++) {
1338 y = power_history[i] - power_history[i+i]; 1345 y = power_history[i] - power_history[i+i];
1339 snprintf(buf, 30, "-%d min: %s%d.%02d V", i, 1346 snprintf(buf, 30, "-%d min: %s%d.%02d V", i,
1340 (y < 0) ? "-" : "", ((y < 0) ? y * -1 : y) / 100, 1347 (y < 0) ? "-" : "", ((y < 0) ? y * -1 : y) / 100,
1341 ((y < 0) ? y * -1 : y ) % 100); 1348 ((y < 0) ? y * -1 : y ) % 100);
1342 lcd_puts(0, i+1, buf); 1349 lcd_puts(0, i+1, buf);
1343 } 1350 }
@@ -1375,21 +1382,21 @@ bool view_battery(void)
1375 lcd_puts(0, 7, buf); 1382 lcd_puts(0, 7, buf);
1376 break; 1383 break;
1377 } 1384 }
1378 1385
1379 lcd_update(); 1386 lcd_update();
1380 1387
1381 switch(get_action(CONTEXT_SETTINGS,HZ/2)) 1388 switch(get_action(CONTEXT_SETTINGS,HZ/2))
1382 { 1389 {
1383 case ACTION_SETTINGS_DEC: 1390 case ACTION_SETTINGS_DEC:
1384 if (view) 1391 if (view)
1385 view--; 1392 view--;
1386 break; 1393 break;
1387 1394
1388 case ACTION_SETTINGS_INC: 1395 case ACTION_SETTINGS_INC:
1389 if (view < 3) 1396 if (view < 3)
1390 view++; 1397 view++;
1391 break; 1398 break;
1392 1399
1393 case ACTION_STD_CANCEL: 1400 case ACTION_STD_CANCEL:
1394 action_signalscreenchange(); 1401 action_signalscreenchange();
1395 return false; 1402 return false;
@@ -1399,7 +1406,7 @@ bool view_battery(void)
1399} 1406}
1400 1407
1401#endif /* HAVE_LCD_BITMAP */ 1408#endif /* HAVE_LCD_BITMAP */
1402 1409
1403static bool view_runtime(void) 1410static bool view_runtime(void)
1404{ 1411{
1405 char s[32]; 1412 char s[32];
@@ -1441,7 +1448,7 @@ static bool view_runtime(void)
1441 t = global_settings.topruntime; 1448 t = global_settings.topruntime;
1442 lcd_puts(0, y++, "Top time"); 1449 lcd_puts(0, y++, "Top time");
1443 } 1450 }
1444 1451
1445 snprintf(s, sizeof(s), "%dh %dm %ds", 1452 snprintf(s, sizeof(s), "%dh %dm %ds",
1446 t / 3600, (t % 3600) / 60, t % 60); 1453 t / 3600, (t % 3600) / 60, t % 60);
1447 lcd_puts(0, y++, s); 1454 lcd_puts(0, y++, s);
@@ -1498,7 +1505,7 @@ bool dbg_mmc_info(void)
1498 static const unsigned char i_vmax[] = { 1, 5, 10, 25, 35, 45, 80, 200 }; 1505 static const unsigned char i_vmax[] = { 1, 5, 10, 25, 35, 45, 80, 200 };
1499 static const unsigned char *kbit_units[] = { "kBit/s", "MBit/s", "GBit/s" }; 1506 static const unsigned char *kbit_units[] = { "kBit/s", "MBit/s", "GBit/s" };
1500 static const unsigned char *nsec_units[] = { "ns", "µs", "ms" }; 1507 static const unsigned char *nsec_units[] = { "ns", "µs", "ms" };
1501 1508
1502 card_name[6] = '\0'; 1509 card_name[6] = '\0';
1503 1510
1504 lcd_setmargins(0, 0); 1511 lcd_setmargins(0, 0);
@@ -1574,7 +1581,7 @@ bool dbg_mmc_info(void)
1574 case ACTION_STD_CANCEL: 1581 case ACTION_STD_CANCEL:
1575 done = true; 1582 done = true;
1576 break; 1583 break;
1577 1584
1578 case ACTION_SETTINGS_DEC: 1585 case ACTION_SETTINGS_DEC:
1579 currval--; 1586 currval--;
1580 if (currval < 0) 1587 if (currval < 0)
@@ -1606,7 +1613,7 @@ static bool dbg_disk_info(void)
1606#ifdef HAVE_LCD_BITMAP 1613#ifdef HAVE_LCD_BITMAP
1607 lcd_setmargins(0, 0); 1614 lcd_setmargins(0, 0);
1608#endif 1615#endif
1609 1616
1610 while(!done) 1617 while(!done)
1611 { 1618 {
1612 int y=0; 1619 int y=0;
@@ -1639,7 +1646,7 @@ static bool dbg_disk_info(void)
1639 1646
1640 case 2: 1647 case 2:
1641 snprintf(buf, sizeof buf, "%ld MB", 1648 snprintf(buf, sizeof buf, "%ld MB",
1642 ((unsigned long)identify_info[61] << 16 | 1649 ((unsigned long)identify_info[61] << 16 |
1643 (unsigned long)identify_info[60]) / 2048 ); 1650 (unsigned long)identify_info[60]) / 2048 );
1644 lcd_puts(0, y++, "Size"); 1651 lcd_puts(0, y++, "Size");
1645 lcd_puts(0, y++, buf); 1652 lcd_puts(0, y++, buf);
@@ -1739,7 +1746,7 @@ static bool dbg_disk_info(void)
1739 if (--page < 0) 1746 if (--page < 0)
1740 page = max_page; 1747 page = max_page;
1741 break; 1748 break;
1742 1749
1743 case ACTION_SETTINGS_INC: 1750 case ACTION_SETTINGS_INC:
1744 if (++page > max_page) 1751 if (++page > max_page)
1745 page = 0; 1752 page = 0;
@@ -1765,9 +1772,9 @@ static bool dbg_dircache_info(void)
1765 while (!done) 1772 while (!done)
1766 { 1773 {
1767 line = 0; 1774 line = 0;
1768 1775
1769 lcd_clear_display(); 1776 lcd_clear_display();
1770 snprintf(buf, sizeof(buf), "Cache initialized: %s", 1777 snprintf(buf, sizeof(buf), "Cache initialized: %s",
1771 dircache_is_enabled() ? "Yes" : "No"); 1778 dircache_is_enabled() ? "Yes" : "No");
1772 lcd_puts(0, line++, buf); 1779 lcd_puts(0, line++, buf);
1773 1780
@@ -1819,25 +1826,25 @@ static bool dbg_tagcache_info(void)
1819 while (!done) 1826 while (!done)
1820 { 1827 {
1821 line = 0; 1828 line = 0;
1822 1829
1823 lcd_clear_display(); 1830 lcd_clear_display();
1824 stat = tagcache_get_stat(); 1831 stat = tagcache_get_stat();
1825 snprintf(buf, sizeof(buf), "Initialized: %s", stat->initialized ? "Yes" : "No"); 1832 snprintf(buf, sizeof(buf), "Initialized: %s", stat->initialized ? "Yes" : "No");
1826 lcd_puts(0, line++, buf); 1833 lcd_puts(0, line++, buf);
1827 snprintf(buf, sizeof(buf), "DB Ready: %s", stat->ready ? "Yes" : "No"); 1834 snprintf(buf, sizeof(buf), "DB Ready: %s", stat->ready ? "Yes" : "No");
1828 lcd_puts(0, line++, buf); 1835 lcd_puts(0, line++, buf);
1829 snprintf(buf, sizeof(buf), "RAM Cache: %s", stat->ramcache ? "Yes" : "No"); 1836 snprintf(buf, sizeof(buf), "RAM Cache: %s", stat->ramcache ? "Yes" : "No");
1830 lcd_puts(0, line++, buf); 1837 lcd_puts(0, line++, buf);
1831 snprintf(buf, sizeof(buf), "RAM: %d/%d B", 1838 snprintf(buf, sizeof(buf), "RAM: %d/%d B",
1832 stat->ramcache_used, stat->ramcache_allocated); 1839 stat->ramcache_used, stat->ramcache_allocated);
1833 lcd_puts(0, line++, buf); 1840 lcd_puts(0, line++, buf);
1834 snprintf(buf, sizeof(buf), "Progress: %d%% (%d entries)", 1841 snprintf(buf, sizeof(buf), "Progress: %d%% (%d entries)",
1835 stat->progress, stat->processed_entries); 1842 stat->progress, stat->processed_entries);
1836 lcd_puts(0, line++, buf); 1843 lcd_puts(0, line++, buf);
1837 snprintf(buf, sizeof(buf), "Commit step: %d", stat->commit_step); 1844 snprintf(buf, sizeof(buf), "Commit step: %d", stat->commit_step);
1838 lcd_puts(0, line++, buf); 1845 lcd_puts(0, line++, buf);
1839 snprintf(buf, sizeof(buf), "Commit delayed: %s", 1846 snprintf(buf, sizeof(buf), "Commit delayed: %s",
1840 stat->commit_delayed ? "Yes" : "No"); 1847 stat->commit_delayed ? "Yes" : "No");
1841 lcd_puts(0, line++, buf); 1848 lcd_puts(0, line++, buf);
1842 1849
1843 lcd_update(); 1850 lcd_update();
@@ -1892,7 +1899,7 @@ bool dbg_save_roms(void)
1892 close(fd); 1899 close(fd);
1893 } 1900 }
1894 system_memory_guard(oldmode); 1901 system_memory_guard(oldmode);
1895 1902
1896#ifdef HAVE_EEPROM 1903#ifdef HAVE_EEPROM
1897 fd = creat("/internal_eeprom.bin", O_WRONLY); 1904 fd = creat("/internal_eeprom.bin", O_WRONLY);
1898 if (fd >= 0) 1905 if (fd >= 0)
@@ -1916,7 +1923,7 @@ bool dbg_save_roms(void)
1916 close(fd); 1923 close(fd);
1917 } 1924 }
1918#endif 1925#endif
1919 1926
1920 return false; 1927 return false;
1921} 1928}
1922#endif /* CPU */ 1929#endif /* CPU */
@@ -1938,10 +1945,10 @@ bool dbg_fm_radio(void)
1938 1945
1939 lcd_clear_display(); 1946 lcd_clear_display();
1940 fm_detected = radio_hardware_present(); 1947 fm_detected = radio_hardware_present();
1941 1948
1942 snprintf(buf, sizeof buf, "HW detected: %s", fm_detected?"yes":"no"); 1949 snprintf(buf, sizeof buf, "HW detected: %s", fm_detected?"yes":"no");
1943 lcd_puts(0, row++, buf); 1950 lcd_puts(0, row++, buf);
1944 1951
1945#if (CONFIG_TUNER & S1A0903X01) 1952#if (CONFIG_TUNER & S1A0903X01)
1946 regs = samsung_get(RADIO_ALL); 1953 regs = samsung_get(RADIO_ALL);
1947 snprintf(buf, sizeof buf, "Samsung regs: %08lx", regs); 1954 snprintf(buf, sizeof buf, "Samsung regs: %08lx", regs);
@@ -1954,7 +1961,7 @@ bool dbg_fm_radio(void)
1954#endif 1961#endif
1955 1962
1956 lcd_update(); 1963 lcd_update();
1957 1964
1958 if (action_userabort(HZ)) 1965 if (action_userabort(HZ))
1959 return false; 1966 return false;
1960 } 1967 }
@@ -1983,7 +1990,7 @@ bool dbg_set_memory_guard(void)
1983 { "Zero area (all)", -1 } 1990 { "Zero area (all)", -1 }
1984 }; 1991 };
1985 int mode = system_memory_guard(MEMGUARD_KEEP); 1992 int mode = system_memory_guard(MEMGUARD_KEEP);
1986 1993
1987 set_option( "Catch mem accesses", &mode, INT, names, MAXMEMGUARD, NULL); 1994 set_option( "Catch mem accesses", &mode, INT, names, MAXMEMGUARD, NULL);
1988 system_memory_guard(mode); 1995 system_memory_guard(mode);
1989 1996
@@ -1999,7 +2006,7 @@ bool dbg_write_eeprom(void)
1999 int old_irq_level; 2006 int old_irq_level;
2000 char buf[EEPROM_SIZE]; 2007 char buf[EEPROM_SIZE];
2001 int err; 2008 int err;
2002 2009
2003 fd = open("/internal_eeprom.bin", O_RDONLY); 2010 fd = open("/internal_eeprom.bin", O_RDONLY);
2004 2011
2005 if (fd >= 0) 2012 if (fd >= 0)
@@ -2093,7 +2100,7 @@ bool debug_menu(void)
2093 NULL, NULL, NULL); 2100 NULL, NULL, NULL);
2094 result = menu_run(m); 2101 result = menu_run(m);
2095 menu_exit(m); 2102 menu_exit(m);
2096 2103
2097 return result; 2104 return result;
2098} 2105}
2099 2106
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}