diff options
Diffstat (limited to 'picosoc/firmware.c')
-rw-r--r-- | picosoc/firmware.c | 770 |
1 files changed, 0 insertions, 770 deletions
diff --git a/picosoc/firmware.c b/picosoc/firmware.c deleted file mode 100644 index aadf31b..0000000 --- a/picosoc/firmware.c +++ /dev/null @@ -1,770 +0,0 @@ -/* - * PicoSoC - A simple example SoC using PicoRV32 - * - * Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#include <stdint.h> -#include <stdbool.h> - -#ifdef ICEBREAKER -# define MEM_TOTAL 0x20000 /* 128 KB */ -#elif HX8KDEMO -# define MEM_TOTAL 0x200 /* 2 KB */ -#else -# error "Set -DICEBREAKER or -DHX8KDEMO when compiling firmware.c" -#endif - -// a pointer to this is a null pointer, but the compiler does not -// know that because "sram" is a linker symbol from sections.lds. -extern uint32_t sram; - -#define reg_spictrl (*(volatile uint32_t*)0x02000000) -#define reg_uart_clkdiv (*(volatile uint32_t*)0x02000004) -#define reg_uart_data (*(volatile uint32_t*)0x02000008) -#define reg_leds (*(volatile uint32_t*)0x03000000) - -// -------------------------------------------------------- - -extern uint32_t flashio_worker_begin; -extern uint32_t flashio_worker_end; - -void flashio(uint8_t *data, int len, uint8_t wrencmd) -{ - uint32_t func[&flashio_worker_end - &flashio_worker_begin]; - - uint32_t *src_ptr = &flashio_worker_begin; - uint32_t *dst_ptr = func; - - while (src_ptr != &flashio_worker_end) - *(dst_ptr++) = *(src_ptr++); - - ((void(*)(uint8_t*, uint32_t, uint32_t))func)(data, len, wrencmd); -} - -#ifdef HX8KDEMO -void set_flash_qspi_flag() -{ - uint8_t buffer[8]; - uint32_t addr_cr1v = 0x800002; - - // Read Any Register (RDAR 65h) - buffer[0] = 0x65; - buffer[1] = addr_cr1v >> 16; - buffer[2] = addr_cr1v >> 8; - buffer[3] = addr_cr1v; - buffer[4] = 0; // dummy - buffer[5] = 0; // rdata - flashio(buffer, 6, 0); - uint8_t cr1v = buffer[5]; - - // Write Enable (WREN 06h) + Write Any Register (WRAR 71h) - buffer[0] = 0x71; - buffer[1] = addr_cr1v >> 16; - buffer[2] = addr_cr1v >> 8; - buffer[3] = addr_cr1v; - buffer[4] = cr1v | 2; // Enable QSPI - flashio(buffer, 5, 0x06); -} - -void set_flash_latency(uint8_t value) -{ - reg_spictrl = (reg_spictrl & ~0x007f0000) | ((value & 15) << 16); - - uint32_t addr = 0x800004; - uint8_t buffer_wr[5] = {0x71, addr >> 16, addr >> 8, addr, 0x70 | value}; - flashio(buffer_wr, 5, 0x06); -} - -void set_flash_mode_spi() -{ - reg_spictrl = (reg_spictrl & ~0x00700000) | 0x00000000; -} - -void set_flash_mode_dual() -{ - reg_spictrl = (reg_spictrl & ~0x00700000) | 0x00400000; -} - -void set_flash_mode_quad() -{ - reg_spictrl = (reg_spictrl & ~0x00700000) | 0x00200000; -} - -void set_flash_mode_qddr() -{ - reg_spictrl = (reg_spictrl & ~0x00700000) | 0x00600000; -} -#endif - -#ifdef ICEBREAKER -void set_flash_qspi_flag() -{ - uint8_t buffer[8]; - - // Read Configuration Registers (RDCR1 35h) - buffer[0] = 0x35; - buffer[1] = 0x00; // rdata - flashio(buffer, 2, 0); - uint8_t sr2 = buffer[1]; - - // Write Enable Volatile (50h) + Write Status Register 2 (31h) - buffer[0] = 0x31; - buffer[1] = sr2 | 2; // Enable QSPI - flashio(buffer, 2, 0x50); -} - -void set_flash_mode_spi() -{ - reg_spictrl = (reg_spictrl & ~0x007f0000) | 0x00000000; -} - -void set_flash_mode_dual() -{ - reg_spictrl = (reg_spictrl & ~0x007f0000) | 0x00400000; -} - -void set_flash_mode_quad() -{ - reg_spictrl = (reg_spictrl & ~0x007f0000) | 0x00240000; -} - -void set_flash_mode_qddr() -{ - reg_spictrl = (reg_spictrl & ~0x007f0000) | 0x00670000; -} - -void enable_flash_crm() -{ - reg_spictrl |= 0x00100000; -} -#endif - -// -------------------------------------------------------- - -void putchar(char c) -{ - if (c == '\n') - putchar('\r'); - reg_uart_data = c; -} - -void print(const char *p) -{ - while (*p) - putchar(*(p++)); -} - -void print_hex(uint32_t v, int digits) -{ - for (int i = 7; i >= 0; i--) { - char c = "0123456789abcdef"[(v >> (4*i)) & 15]; - if (c == '0' && i >= digits) continue; - putchar(c); - digits = i; - } -} - -void print_dec(uint32_t v) -{ - if (v >= 1000) { - print(">=1000"); - return; - } - - if (v >= 900) { putchar('9'); v -= 900; } - else if (v >= 800) { putchar('8'); v -= 800; } - else if (v >= 700) { putchar('7'); v -= 700; } - else if (v >= 600) { putchar('6'); v -= 600; } - else if (v >= 500) { putchar('5'); v -= 500; } - else if (v >= 400) { putchar('4'); v -= 400; } - else if (v >= 300) { putchar('3'); v -= 300; } - else if (v >= 200) { putchar('2'); v -= 200; } - else if (v >= 100) { putchar('1'); v -= 100; } - - if (v >= 90) { putchar('9'); v -= 90; } - else if (v >= 80) { putchar('8'); v -= 80; } - else if (v >= 70) { putchar('7'); v -= 70; } - else if (v >= 60) { putchar('6'); v -= 60; } - else if (v >= 50) { putchar('5'); v -= 50; } - else if (v >= 40) { putchar('4'); v -= 40; } - else if (v >= 30) { putchar('3'); v -= 30; } - else if (v >= 20) { putchar('2'); v -= 20; } - else if (v >= 10) { putchar('1'); v -= 10; } - - if (v >= 9) { putchar('9'); v -= 9; } - else if (v >= 8) { putchar('8'); v -= 8; } - else if (v >= 7) { putchar('7'); v -= 7; } - else if (v >= 6) { putchar('6'); v -= 6; } - else if (v >= 5) { putchar('5'); v -= 5; } - else if (v >= 4) { putchar('4'); v -= 4; } - else if (v >= 3) { putchar('3'); v -= 3; } - else if (v >= 2) { putchar('2'); v -= 2; } - else if (v >= 1) { putchar('1'); v -= 1; } - else putchar('0'); -} - -char getchar_prompt(char *prompt) -{ - int32_t c = -1; - - uint32_t cycles_begin, cycles_now, cycles; - __asm__ volatile ("rdcycle %0" : "=r"(cycles_begin)); - - reg_leds = ~0; - - if (prompt) - print(prompt); - - while (c == -1) { - __asm__ volatile ("rdcycle %0" : "=r"(cycles_now)); - cycles = cycles_now - cycles_begin; - if (cycles > 12000000) { - if (prompt) - print(prompt); - cycles_begin = cycles_now; - reg_leds = ~reg_leds; - } - c = reg_uart_data; - } - - reg_leds = 0; - return c; -} - -char getchar() -{ - return getchar_prompt(0); -} - -void cmd_print_spi_state() -{ - print("SPI State:\n"); - - print(" LATENCY "); - print_dec((reg_spictrl >> 16) & 15); - print("\n"); - - print(" DDR "); - if ((reg_spictrl & (1 << 22)) != 0) - print("ON\n"); - else - print("OFF\n"); - - print(" QSPI "); - if ((reg_spictrl & (1 << 21)) != 0) - print("ON\n"); - else - print("OFF\n"); - - print(" CRM "); - if ((reg_spictrl & (1 << 20)) != 0) - print("ON\n"); - else - print("OFF\n"); -} - -uint32_t xorshift32(uint32_t *state) -{ - /* Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs" */ - uint32_t x = *state; - x ^= x << 13; - x ^= x >> 17; - x ^= x << 5; - *state = x; - - return x; -} - -void cmd_memtest() -{ - int cyc_count = 5; - int stride = 256; - uint32_t state; - - volatile uint32_t *base_word = (uint32_t *) 0; - volatile uint8_t *base_byte = (uint8_t *) 0; - - print("Running memtest "); - - // Walk in stride increments, word access - for (int i = 1; i <= cyc_count; i++) { - state = i; - - for (int word = 0; word < MEM_TOTAL / sizeof(int); word += stride) { - *(base_word + word) = xorshift32(&state); - } - - state = i; - - for (int word = 0; word < MEM_TOTAL / sizeof(int); word += stride) { - if (*(base_word + word) != xorshift32(&state)) { - print(" ***FAILED WORD*** at "); - print_hex(4*word, 4); - print("\n"); - return; - } - } - - print("."); - } - - // Byte access - for (int byte = 0; byte < 128; byte++) { - *(base_byte + byte) = (uint8_t) byte; - } - - for (int byte = 0; byte < 128; byte++) { - if (*(base_byte + byte) != (uint8_t) byte) { - print(" ***FAILED BYTE*** at "); - print_hex(byte, 4); - print("\n"); - return; - } - } - - print(" passed\n"); -} - -// -------------------------------------------------------- - -void cmd_read_flash_id() -{ - uint8_t buffer[17] = { 0x9F, /* zeros */ }; - flashio(buffer, 17, 0); - - for (int i = 1; i <= 16; i++) { - putchar(' '); - print_hex(buffer[i], 2); - } - putchar('\n'); -} - -// -------------------------------------------------------- - -#ifdef HX8KDEMO -uint8_t cmd_read_flash_regs_print(uint32_t addr, const char *name) -{ - set_flash_latency(8); - - uint8_t buffer[6] = {0x65, addr >> 16, addr >> 8, addr, 0, 0}; - flashio(buffer, 6, 0); - - print("0x"); - print_hex(addr, 6); - print(" "); - print(name); - print(" 0x"); - print_hex(buffer[5], 2); - print("\n"); - - return buffer[5]; -} - -void cmd_read_flash_regs() -{ - print("\n"); - uint8_t sr1v = cmd_read_flash_regs_print(0x800000, "SR1V"); - uint8_t sr2v = cmd_read_flash_regs_print(0x800001, "SR2V"); - uint8_t cr1v = cmd_read_flash_regs_print(0x800002, "CR1V"); - uint8_t cr2v = cmd_read_flash_regs_print(0x800003, "CR2V"); - uint8_t cr3v = cmd_read_flash_regs_print(0x800004, "CR3V"); - uint8_t vdlp = cmd_read_flash_regs_print(0x800005, "VDLP"); -} -#endif - -#ifdef ICEBREAKER -uint8_t cmd_read_flash_reg(uint8_t cmd) -{ - uint8_t buffer[2] = {cmd, 0}; - flashio(buffer, 2, 0); - return buffer[1]; -} - -void print_reg_bit(int val, const char *name) -{ - for (int i = 0; i < 12; i++) { - if (*name == 0) - putchar(' '); - else - putchar(*(name++)); - } - - putchar(val ? '1' : '0'); - putchar('\n'); -} - -void cmd_read_flash_regs() -{ - putchar('\n'); - - uint8_t sr1 = cmd_read_flash_reg(0x05); - uint8_t sr2 = cmd_read_flash_reg(0x35); - uint8_t sr3 = cmd_read_flash_reg(0x15); - - print_reg_bit(sr1 & 0x01, "S0 (BUSY)"); - print_reg_bit(sr1 & 0x02, "S1 (WEL)"); - print_reg_bit(sr1 & 0x04, "S2 (BP0)"); - print_reg_bit(sr1 & 0x08, "S3 (BP1)"); - print_reg_bit(sr1 & 0x10, "S4 (BP2)"); - print_reg_bit(sr1 & 0x20, "S5 (TB)"); - print_reg_bit(sr1 & 0x40, "S6 (SEC)"); - print_reg_bit(sr1 & 0x80, "S7 (SRP)"); - putchar('\n'); - - print_reg_bit(sr2 & 0x01, "S8 (SRL)"); - print_reg_bit(sr2 & 0x02, "S9 (QE)"); - print_reg_bit(sr2 & 0x04, "S10 ----"); - print_reg_bit(sr2 & 0x08, "S11 (LB1)"); - print_reg_bit(sr2 & 0x10, "S12 (LB2)"); - print_reg_bit(sr2 & 0x20, "S13 (LB3)"); - print_reg_bit(sr2 & 0x40, "S14 (CMP)"); - print_reg_bit(sr2 & 0x80, "S15 (SUS)"); - putchar('\n'); - - print_reg_bit(sr3 & 0x01, "S16 ----"); - print_reg_bit(sr3 & 0x02, "S17 ----"); - print_reg_bit(sr3 & 0x04, "S18 (WPS)"); - print_reg_bit(sr3 & 0x08, "S19 ----"); - print_reg_bit(sr3 & 0x10, "S20 ----"); - print_reg_bit(sr3 & 0x20, "S21 (DRV0)"); - print_reg_bit(sr3 & 0x40, "S22 (DRV1)"); - print_reg_bit(sr3 & 0x80, "S23 (HOLD)"); - putchar('\n'); -} -#endif - -// -------------------------------------------------------- - -uint32_t cmd_benchmark(bool verbose, uint32_t *instns_p) -{ - uint8_t data[256]; - uint32_t *words = (void*)data; - - uint32_t x32 = 314159265; - - uint32_t cycles_begin, cycles_end; - uint32_t instns_begin, instns_end; - __asm__ volatile ("rdcycle %0" : "=r"(cycles_begin)); - __asm__ volatile ("rdinstret %0" : "=r"(instns_begin)); - - for (int i = 0; i < 20; i++) - { - for (int k = 0; k < 256; k++) - { - x32 ^= x32 << 13; - x32 ^= x32 >> 17; - x32 ^= x32 << 5; - data[k] = x32; - } - - for (int k = 0, p = 0; k < 256; k++) - { - if (data[k]) - data[p++] = k; - } - - for (int k = 0, p = 0; k < 64; k++) - { - x32 = x32 ^ words[k]; - } - } - - __asm__ volatile ("rdcycle %0" : "=r"(cycles_end)); - __asm__ volatile ("rdinstret %0" : "=r"(instns_end)); - - if (verbose) - { - print("Cycles: 0x"); - print_hex(cycles_end - cycles_begin, 8); - putchar('\n'); - - print("Instns: 0x"); - print_hex(instns_end - instns_begin, 8); - putchar('\n'); - - print("Chksum: 0x"); - print_hex(x32, 8); - putchar('\n'); - } - - if (instns_p) - *instns_p = instns_end - instns_begin; - - return cycles_end - cycles_begin; -} - -// -------------------------------------------------------- - -#ifdef HX8KDEMO -void cmd_benchmark_all() -{ - uint32_t instns = 0; - - print("default "); - reg_spictrl = (reg_spictrl & ~0x00700000) | 0x00000000; - print(": "); - print_hex(cmd_benchmark(false, &instns), 8); - putchar('\n'); - - for (int i = 8; i > 0; i--) - { - print("dspi-"); - print_dec(i); - print(" "); - - set_flash_latency(i); - reg_spictrl = (reg_spictrl & ~0x00700000) | 0x00400000; - - print(": "); - print_hex(cmd_benchmark(false, &instns), 8); - putchar('\n'); - } - - for (int i = 8; i > 0; i--) - { - print("dspi-crm-"); - print_dec(i); - print(" "); - - set_flash_latency(i); - reg_spictrl = (reg_spictrl & ~0x00700000) | 0x00500000; - - print(": "); - print_hex(cmd_benchmark(false, &instns), 8); - putchar('\n'); - } - - for (int i = 8; i > 0; i--) - { - print("qspi-"); - print_dec(i); - print(" "); - - set_flash_latency(i); - reg_spictrl = (reg_spictrl & ~0x00700000) | 0x00200000; - - print(": "); - print_hex(cmd_benchmark(false, &instns), 8); - putchar('\n'); - } - - for (int i = 8; i > 0; i--) - { - print("qspi-crm-"); - print_dec(i); - print(" "); - - set_flash_latency(i); - reg_spictrl = (reg_spictrl & ~0x00700000) | 0x00300000; - - print(": "); - print_hex(cmd_benchmark(false, &instns), 8); - putchar('\n'); - } - - for (int i = 8; i > 0; i--) - { - print("qspi-ddr-"); - print_dec(i); - print(" "); - - set_flash_latency(i); - reg_spictrl = (reg_spictrl & ~0x00700000) | 0x00600000; - - print(": "); - print_hex(cmd_benchmark(false, &instns), 8); - putchar('\n'); - } - - for (int i = 8; i > 0; i--) - { - print("qspi-ddr-crm-"); - print_dec(i); - print(" "); - - set_flash_latency(i); - reg_spictrl = (reg_spictrl & ~0x00700000) | 0x00700000; - - print(": "); - print_hex(cmd_benchmark(false, &instns), 8); - putchar('\n'); - } - - print("instns : "); - print_hex(instns, 8); - putchar('\n'); -} -#endif - -#ifdef ICEBREAKER -void cmd_benchmark_all() -{ - uint32_t instns = 0; - - print("default "); - set_flash_mode_spi(); - print_hex(cmd_benchmark(false, &instns), 8); - putchar('\n'); - - print("dual "); - set_flash_mode_dual(); - print_hex(cmd_benchmark(false, &instns), 8); - putchar('\n'); - - // print("dual-crm "); - // enable_flash_crm(); - // print_hex(cmd_benchmark(false, &instns), 8); - // putchar('\n'); - - print("quad "); - set_flash_mode_quad(); - print_hex(cmd_benchmark(false, &instns), 8); - putchar('\n'); - - print("quad-crm "); - enable_flash_crm(); - print_hex(cmd_benchmark(false, &instns), 8); - putchar('\n'); - - print("qddr "); - set_flash_mode_qddr(); - print_hex(cmd_benchmark(false, &instns), 8); - putchar('\n'); - - print("qddr-crm "); - enable_flash_crm(); - print_hex(cmd_benchmark(false, &instns), 8); - putchar('\n'); - -} -#endif - -void cmd_echo() -{ - print("Return to menu by sending '!'\n\n"); - char c; - while ((c = getchar()) != '!') - putchar(c); -} - -// -------------------------------------------------------- - -void main() -{ - reg_leds = 31; - reg_uart_clkdiv = 104; - print("Booting..\n"); - - reg_leds = 63; - set_flash_qspi_flag(); - - reg_leds = 127; - while (getchar_prompt("Press ENTER to continue..\n") != '\r') { /* wait */ } - - print("\n"); - print(" ____ _ ____ ____\n"); - print(" | _ \\(_) ___ ___/ ___| ___ / ___|\n"); - print(" | |_) | |/ __/ _ \\___ \\ / _ \\| |\n"); - print(" | __/| | (_| (_) |__) | (_) | |___\n"); - print(" |_| |_|\\___\\___/____/ \\___/ \\____|\n"); - print("\n"); - - print("Total memory: "); - print_dec(MEM_TOTAL / 1024); - print(" KiB\n"); - print("\n"); - - //cmd_memtest(); // test overwrites bss and data memory - print("\n"); - - cmd_print_spi_state(); - print("\n"); - - while (1) - { - print("\n"); - - print("Select an action:\n"); - print("\n"); - print(" [1] Read SPI Flash ID\n"); - print(" [2] Read SPI Config Regs\n"); - print(" [3] Switch to default mode\n"); - print(" [4] Switch to Dual I/O mode\n"); - print(" [5] Switch to Quad I/O mode\n"); - print(" [6] Switch to Quad DDR mode\n"); - print(" [7] Toggle continuous read mode\n"); - print(" [9] Run simplistic benchmark\n"); - print(" [0] Benchmark all configs\n"); - print(" [M] Run Memtest\n"); - print(" [S] Print SPI state\n"); - print(" [e] Echo UART\n"); - print("\n"); - - for (int rep = 10; rep > 0; rep--) - { - print("Command> "); - char cmd = getchar(); - if (cmd > 32 && cmd < 127) - putchar(cmd); - print("\n"); - - switch (cmd) - { - case '1': - cmd_read_flash_id(); - break; - case '2': - cmd_read_flash_regs(); - break; - case '3': - set_flash_mode_spi(); - break; - case '4': - set_flash_mode_dual(); - break; - case '5': - set_flash_mode_quad(); - break; - case '6': - set_flash_mode_qddr(); - break; - case '7': - reg_spictrl = reg_spictrl ^ 0x00100000; - break; - case '9': - cmd_benchmark(true, 0); - break; - case '0': - cmd_benchmark_all(); - break; - case 'M': - cmd_memtest(); - break; - case 'S': - cmd_print_spi_state(); - break; - case 'e': - cmd_echo(); - break; - default: - continue; - } - - break; - } - } -} |