#include "fw.h" #include "io.h" #include "sdcard.h" #include "abcio.h" #include "sys.h" #include "console.h" #define DEBUG 0 #define MINITESTS 1 #define DELAY 0 static void __hot con_print_hex(unsigned int n) { for (int i = 0; i < 8; i++) { unsigned int c = n >> 28; n <<= 4; con_putc(c + ((c >= 10) ? 'a'-10 : '0')); } } /* Don't mark no_return or gcc moves it to SDRAM */ static void __hot __text_hot killed(const char *how, size_t pc) { /* Cannot use con_printf() here */ const uint16_t *pcp; size_t mtval; asm volatile("csrr %0,mtval" : "=r" (mtval)); /* Try to move back to the previous instruction (if not a jump...) */ pc += -4 + (pc & 1); pcp = (const uint16_t *)pc; con_puts(hotstr("ERROR: ")); con_puts(how); con_puts(hotstr(" at 0x")); con_print_hex(pc); con_puts(hotstr(" (0x")); con_print_hex((pcp[1] << 16) + pcp[0]); con_puts(hotstr(")\nBad address: 0x")); con_print_hex(mtval); con_putc('\n'); for (int i = 0; i < 32; i += 8) { for (int j = 0; j < 8; j++) { uint32_t v = rdxreg(i+j); con_print_hex(v); con_putc((j == 7) ? '\n' : ' '); } } con_flush(); udelay(5000000); reset(SYS_RESET_SOFT); } IRQHANDLER(buserr) { killed(hotstr("misaligned"), pc); } IRQHANDLER(ebreak) { killed(hotstr("invalid instruction"), pc); } volatile __sbss uint32_t timer_irq_count; IRQHANDLER(sysclock) { uint32_t count = timer_irq_count; count++; timer_irq_count = count; if ( MINITESTS ) CON_DATA = (count & 63) + '0'; /* Liveness... */ } static void __cold __noinline late_init(void); uint32_t __sbss timer_irq_start; void __hot init(void) { static __string_hot const char hello[] = "\n\n*** Hello, World! ***\n" "MAX80 " #ifdef TEST "testing" #endif "firmware compiled on: " __DATE__ " " __TIME__ "\n"; timer_irq_start = rdtime(); /* Start ROM copy engine, unmask timer and fatal exceptions */ unmask_irqs((1U << ROMCOPY_IRQ)|(1U << EBREAK_IRQ)| (1U << BUSERR_IRQ)|(1U << SYSCLOCK_IRQ)); set_leds(7); wait_romcopy_done(); if ( MINITESTS ) { extern uint32_t __dram_init_start[], __dram_init_end[]; extern uint32_t __dram_bss_start[], __dram_bss_end[]; const uint32_t *dp; uint32_t v; v = 0; for (dp = __dram_init_start; dp < __dram_init_end; dp++) v += *dp; con_puts("SDRAM data checksum: "); con_print_hex(v); con_putc('\n'); v = 0; for (dp = __dram_bss_start; dp < __dram_bss_end; dp++) { uint32_t x = *dp; v |= x; } if (v) con_puts("SDRAM .bss is not zero!\n"); } set_leds(6); con_puts(hello); con_flush(); set_leds(5); #if DELAY con_puts("Waiting 5 s for testing..."); udelay(5000000); con_putc('\n'); con_flush(); #endif late_init(); } volatile uint32_t __dram_bss test_dram[8]; static void __cold __noinline late_init(void) { /* This needs to be done as early as possible!!! */ con_puts("Running abc_init_memmap: "); con_flush(); abc_init_memmap(); con_puts("ok\n"); if (SYS_MAGIC != SYS_MAGIC_MAX80) { con_puts("Not a MAX80 board?!?!\n\n"); _die(); } else { con_printf("MAX80 ver %u.%u rework flags %02x fpga %u\n", SYS_BOARDMAJOR, SYS_BOARDMINOR, SYS_BOARDFIX, SYS_BOARDFPGA); if (SYS_BOARDMAJOR != SYS_BOARDFPGA) { con_puts("Invalid FPGA firmware for this board revision\n"); _die(); } } con_putc('\n'); if ( MINITESTS ) { con_puts("Quick DRAM test:\n"); for (int i = 0; i < 8; i++) { uint32_t v = (i*0x11111111) + 0x44332211; test_dram[i] = v; (void)test_dram[i]; /* Force immediate readback */ con_printf("%08x ", v); } con_putc('\n'); for (int i = 0; i < 8; i++) { con_printf("%08x ", test_dram[i]); } con_puts("\n\nRandom number generator test:\n"); for (int i = 0; i < 8; i++) con_printf("%08x ", rdrand()); con_puts("\n\n"); } rom_get_serial(); set_leds(4); read_rtc(); rtc_abc_init(); set_leds(3); sdcard_reset(); disk_cache_init(); abcdisk_init(); set_leds(2); abc_init(); set_leds(1); /* Release WAIT# if asserted */ ABC_BUSCTL = 0; set_leds(0); }