From 7639e6ebac26fafbff2c3e2a72e83cf5cd0c3a3e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 19 Sep 2017 15:32:41 +0200 Subject: [PATCH] PicoSoC QSPI and XIP now working (tested in hardware) --- picosoc/firmware.c | 54 ++++++++++++++++++++++++++----------------- picosoc/hx8kdemo_tb.v | 2 +- picosoc/spiflash.v | 5 ++-- picosoc/start.s | 19 +++++++++++++-- 4 files changed, 54 insertions(+), 26 deletions(-) diff --git a/picosoc/firmware.c b/picosoc/firmware.c index 70ab5eb..ecc8657 100644 --- a/picosoc/firmware.c +++ b/picosoc/firmware.c @@ -14,7 +14,7 @@ extern uint32_t sram; extern uint32_t flashio_worker_begin; extern uint32_t flashio_worker_end; -void flashio(uint8_t *data, int len) +void flashio(uint8_t *data, int len, uint8_t wrencmd) { uint32_t func[&flashio_worker_end - &flashio_worker_begin]; @@ -24,7 +24,17 @@ void flashio(uint8_t *data, int len) while (src_ptr != &flashio_worker_end) *(dst_ptr++) = *(src_ptr++); - ((void(*)(uint8_t*, int))func)(data, len); + ((void(*)(uint8_t*, uint32_t, uint32_t))func)(data, len, wrencmd); +} + +void set_quad_spi_flag() +{ + uint32_t addr = 0x800002; + uint8_t buffer_rd[6] = {0x65, addr >> 16, addr >> 8, addr, 0, 0}; + flashio(buffer_rd, 6, 0); + + uint8_t buffer_wr[5] = {0x71, addr >> 16, addr >> 8, addr, buffer_rd[5] | 2}; + flashio(buffer_wr, 5, 0x06); } // -------------------------------------------------------- @@ -114,10 +124,10 @@ char getchar() // -------------------------------------------------------- -void cmd_read_spi_flash_id() +void cmd_read_flash_id() { uint8_t buffer[17] = { 0x9F, /* zeros */ }; - flashio(buffer, 17); + flashio(buffer, 17, 0); for (int i = 1; i <= 16; i++) { putchar(' '); @@ -128,10 +138,10 @@ void cmd_read_spi_flash_id() // -------------------------------------------------------- -uint8_t cmd_read_spi_flash_regs_print(uint32_t addr, const char *name) +uint8_t cmd_read_flash_regs_print(uint32_t addr, const char *name) { uint8_t buffer[6] = {0x65, addr >> 16, addr >> 8, addr, 0, 0}; - flashio(buffer, 6); + flashio(buffer, 6, 0); print("0x"); print_hex(addr, 6); @@ -144,15 +154,15 @@ uint8_t cmd_read_spi_flash_regs_print(uint32_t addr, const char *name) return buffer[5]; } -void cmd_read_spi_flash_regs() +void cmd_read_flash_regs() { print("\n"); - uint8_t sr1v = cmd_read_spi_flash_regs_print(0x800000, "SR1V"); - uint8_t sr2v = cmd_read_spi_flash_regs_print(0x800001, "SR2V"); - uint8_t cr1v = cmd_read_spi_flash_regs_print(0x800002, "CR1V"); - uint8_t cr2v = cmd_read_spi_flash_regs_print(0x800003, "CR2V"); - uint8_t cr3v = cmd_read_spi_flash_regs_print(0x800004, "CR3V"); - uint8_t vdlp = cmd_read_spi_flash_regs_print(0x800005, "VDLP"); + 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"); } // -------------------------------------------------------- @@ -212,6 +222,8 @@ void cmd_benchmark() void main() { reg_uart_clkdiv = 104; + set_quad_spi_flag(); + while (getchar_prompt("Press ENTER to continue..\n") != '\r') { /* wait */ } print("\n"); @@ -227,15 +239,15 @@ void main() print("\n"); print("SPI State:\n"); + print(" LATENCY "); + print_dec((reg_spictrl >> 16) & 15); + print("\n"); + print(" DDR "); if ((reg_spictrl & (1 << 22)) != 0) - print("ON"); + print("ON\n"); else - print("OFF"); - - print(" (latency="); - print_dec((reg_spictrl >> 16) & 15); - print(")\n"); + print("OFF\n"); print(" QSPI "); if ((reg_spictrl & (1 << 21)) != 0) @@ -271,10 +283,10 @@ void main() switch (cmd) { case '1': - cmd_read_spi_flash_id(); + cmd_read_flash_id(); break; case '2': - cmd_read_spi_flash_regs(); + cmd_read_flash_regs(); break; case '3': reg_spictrl ^= 1 << 22; diff --git a/picosoc/hx8kdemo_tb.v b/picosoc/hx8kdemo_tb.v index 585c8dd..83b1340 100644 --- a/picosoc/hx8kdemo_tb.v +++ b/picosoc/hx8kdemo_tb.v @@ -27,7 +27,7 @@ module testbench; $dumpfile("testbench.vcd"); $dumpvars(0, testbench); - repeat (100000) @(posedge clk); + repeat (200000) @(posedge clk); $finish; end diff --git a/picosoc/spiflash.v b/picosoc/spiflash.v index d06f6cd..18cd68d 100644 --- a/picosoc/spiflash.v +++ b/picosoc/spiflash.v @@ -42,6 +42,7 @@ module spiflash ( inout io3 ); localparam verbose = 0; + localparam integer latency = 8; reg [7:0] buffer; integer bitcount = 0; @@ -148,7 +149,7 @@ module spiflash ( if (bytecount == 5) begin xip_cmd = (buffer == 8'h a5) ? spi_cmd : 8'h 00; mode = mode_qspi_wr; - dummycount = 1; + dummycount = latency; end if (bytecount >= 5) begin @@ -173,7 +174,7 @@ module spiflash ( if (bytecount == 5) begin xip_cmd = (buffer == 8'h a5) ? spi_cmd : 8'h 00; mode = mode_qspi_ddr_wr; - dummycount = 1; + dummycount = latency; end if (bytecount >= 5) begin diff --git a/picosoc/start.s b/picosoc/start.s index 5b051b0..9a285d1 100644 --- a/picosoc/start.s +++ b/picosoc/start.s @@ -45,6 +45,7 @@ j loop flashio_worker_begin: # a0 ... data pointer # a1 ... data length +# a2 ... optional WREN cmd (0 = disable) # address of SPI ctrl reg li t0, 0x02000000 @@ -54,8 +55,22 @@ li t1, 0x120 sh t1, 0(t0) # Enable Manual SPI Ctrl -li t1, 0x00 -sb t1, 3(t0) +sb zero, 3(t0) + +# Send optional WREN cmd +beqz a2, flashio_worker_L1 +li t5, 8 +andi t2, a2, 0xff +flashio_worker_L4: +srli t4, t2, 7 +sb t4, 0(t0) +ori t4, t4, 0x10 +sb t4, 0(t0) +slli t2, t2, 1 +andi t2, t2, 0xff +addi t5, t5, -1 +bnez t5, flashio_worker_L4 +sb t1, 0(t0) # SPI transfer flashio_worker_L1: