From b866dcb07f3aca8fc86187b0ae3adb9df081537c Mon Sep 17 00:00:00 2001 From: sebastien-riou Date: Sun, 12 Jan 2020 16:08:14 +0100 Subject: [PATCH] XIP on Murax improvements --- .../iCE40-hx8k_breakout_board_xip/Makefile | 22 +-- .../iCE40-hx8k_breakout_board_xip/README.md | 135 ++++++++++++++++-- src/main/c/murax/xipBootloader/crt.S | 14 +- src/main/c/murax/xipBootloader/crt.bin | Bin 120 -> 176 bytes src/main/c/murax/xipBootloader/demo.S | 11 +- src/main/c/murax/xipBootloader/demo.bin | Bin 48 -> 0 bytes src/main/c/murax/xipBootloader/makefile | 22 ++- src/main/c/murax/xipBootloader/mapping_rom.ld | 96 +++++++++++++ src/main/c/murax/xipBootloader/mapping_xip.ld | 96 +++++++++++++ src/main/scala/vexriscv/demo/Murax.scala | 42 +----- 10 files changed, 373 insertions(+), 65 deletions(-) delete mode 100755 src/main/c/murax/xipBootloader/demo.bin create mode 100644 src/main/c/murax/xipBootloader/mapping_rom.ld create mode 100644 src/main/c/murax/xipBootloader/mapping_xip.ld diff --git a/scripts/Murax/iCE40-hx8k_breakout_board_xip/Makefile b/scripts/Murax/iCE40-hx8k_breakout_board_xip/Makefile index 88aa1a2..8feef20 100644 --- a/scripts/Murax/iCE40-hx8k_breakout_board_xip/Makefile +++ b/scripts/Murax/iCE40-hx8k_breakout_board_xip/Makefile @@ -1,19 +1,21 @@ +VBASE = ../../.. +VNAME = Murax_iCE40_hx8k_breakout_board_xip +VERILOG = ${VBASE}/${VNAME}.v -VERILOG = ../../../Murax_iCE40_hx8k_breakout_board_xip.v +all: prog -generate : - #(cd ../../..; sbt "runMain vexriscv.demo.Murax_iCE40_hx8k_breakout_board_xip") +${VERILOG} : + (cd ${VBASE}; sbt "runMain vexriscv.demo.${VNAME}") -../../../Murax_iCE40_hx8k_breakout_board_xip.v : - #(cd ../../..; sbt "runMain vexriscv.demo.Murax_iCE40_hx8k_breakout_board_xip") +generate : ${VERILOG} -../../../Murax_iCE40_hx8k_breakout_board_xip.v*.bin: +${VERILOG}*.bin: -bin/Murax_iCE40_hx8k_breakout_board_xip.blif : ${VERILOG} ../../../Murax_iCE40_hx8k_breakout_board_xip.v*.bin +bin/Murax_iCE40_hx8k_breakout_board_xip.blif : ${VERILOG} ${VERILOG}*.bin mkdir -p bin rm -f Murax_iCE40_hx8k_breakout_board_xip.v*.bin - cp ../../../Murax_iCE40_hx8k_breakout_board_xip.v*.bin . | true + cp ${VERILOG}*.bin . | true yosys -v3 -p "synth_ice40 -top Murax_iCE40_hx8k_breakout_board_xip -blif bin/Murax_iCE40_hx8k_breakout_board_xip.blif" ${VERILOG} bin/Murax_iCE40_hx8k_breakout_board_xip.asc : Murax_iCE40_hx8k_breakout_board_xip.pcf bin/Murax_iCE40_hx8k_breakout_board_xip.blif @@ -28,11 +30,15 @@ time: bin/Murax_iCE40_hx8k_breakout_board_xip.bin icetime -tmd hx8k bin/Murax_iCE40_hx8k_breakout_board_xip.asc prog : bin/Murax_iCE40_hx8k_breakout_board_xip.bin + lsusb -d 0403:6010 iceprog -S bin/Murax_iCE40_hx8k_breakout_board_xip.bin sudo-prog : bin/Murax_iCE40_hx8k_breakout_board_xip.bin + sudo lsusb -d 0403:6010 sudo iceprog -S bin/Murax_iCE40_hx8k_breakout_board_xip.bin clean : rm -rf bin rm -f Murax_iCE40_hx8k_breakout_board_xip.v*.bin + rm -f ${VERILOG}*.bin + rm -f ${VERILOG} diff --git a/scripts/Murax/iCE40-hx8k_breakout_board_xip/README.md b/scripts/Murax/iCE40-hx8k_breakout_board_xip/README.md index 1e50a02..06e9439 100644 --- a/scripts/Murax/iCE40-hx8k_breakout_board_xip/README.md +++ b/scripts/Murax/iCE40-hx8k_breakout_board_xip/README.md @@ -59,12 +59,29 @@ The process should take around 30 seconds on a reasonable fast computer. ## Programming +Make sure the FPGA board is the only USB peripheral with ID 0403:6010 + +For example, this is bad: +``` +user@lafite:~$ lsusb -d 0403:6010 +Bus 001 Device 088: ID 0403:6010 Future Technology Devices International, Ltd FT2232C Dual USB-UART/FIFO IC +Bus 001 Device 090: ID 0403:6010 Future Technology Devices International, Ltd FT2232C Dual USB-UART/FIFO IC +``` +This is good: +``` +user@lafite:~$ lsusb -d 0403:6010 +Bus 001 Device 088: ID 0403:6010 Future Technology Devices International, Ltd FT2232C Dual USB-UART/FIFO IC +``` + + After building you should be able to run `make prog`. You may need to run `make sudo-prog` if root is needed to access your USB devices. You should get output like the following; ``` -iceprog -S bin/toplevel.bin +lsusb -d 0403:6010 +Bus 001 Device 088: ID 0403:6010 Future Technology Devices International, Ltd FT2232C Dual USB-UART/FIFO IC +iceprog -S bin/Murax_iCE40_hx8k_breakout_board_xip.bin init.. cdone: high reset.. @@ -74,13 +91,115 @@ cdone: high Bye. ``` -After programming the LEDs at the top of the board should start flashing in an -interesting pattern. +WARNING: having this output does NOT guarantee you actually programmed anything in the FPGA! -## Connect +After programming nothing visual will happen, except the LEDs being off. +The bootloader is waiting for a valid content in the flash. "valid content" is +identified by a magic word at 0xE0040000: it shall be 0x12340fb7, which is the +value for the instruction "li x31, 0x12340000". -After programming you should be able to connect to the serial port and have the -output echoed back to you. +## Programming flash image -On Linux you can do this using a command like `screen /dev/ttyUSB1`. Then as -you type you should get back the same characters. +### Connect JTAG + +We will use vexrisc JTAG to program the flash, so you need openocd and a +suitable JTAG dongle. + +Pin-out: +``` +TCK: H16 aka J2.25 +TDO: G16 aka J2.26 +TDI: G15 aka J2.27 +TMS: F15 aka J2.28 +``` +In addition you need to connect the ground and VTarget aka VIO: J2.2 on the +board. + +### Start GDB server / OpenOCD +Make sure to use https://github.com/SpinalHDL/openocd_riscv +Make sure to select the configuration file which match your JTAG dongle. + +An example with the dongle "ft2232h_breakout": +``` +src/openocd -f tcl/interface/ftdi/ft2232h_breakout.cfg -c "set MURAX_CPU0_YAML ../VexRiscv/cpu0.yaml" -f tcl/target/murax_xip.cfg +``` + +You should get an output like below: +``` +Open On-Chip Debugger 0.10.0+dev-01214-g0ace94f (2019-10-02-18:23) +Licensed under GNU GPL v2 +For bug reports, read + http://openocd.org/doc/doxygen/bugs.html +../VexRiscv/cpu0.yaml +adapter speed: 100 kHz +adapter_nsrst_delay: 260 +Info : auto-selecting first available session transport "jtag". To override use 'transport select '. +jtag_ntrst_delay: 250 +Info : set servers polling period to 50ms +Error: libusb_get_string_descriptor_ascii() failed with LIBUSB_ERROR_INVALID_PARAM +Info : clock speed 100 kHz +Info : JTAG tap: fpga_spinal.bridge tap/device found: 0x10001fff (mfg: 0x7ff (), part: 0x0001, ver: 0x1) +Info : Listening on port 3333 for gdb connections +requesting target halt and executing a soft reset +Info : Listening on port 6666 for tcl connections +Info : Listening on port 4444 for telnet connections +``` + +### Loading the flash with telnet + +First we connect and stop execution on the device: +``` +user@lafite:~/Downloads/vexrisc_full/VexRiscv/src/main/c/murax/xipBootloader$ telnet 127.0.0.1 4444 +Trying 127.0.0.1... +Connected to 127.0.0.1. +Escape character is '^]'. +Open On-Chip Debugger +> reset +JTAG tap: fpga_spinal.bridge tap/device found: 0x10001fff (mfg: 0x7ff (), part: 0x0001, ver: 0x1) +> +``` + +Now we can safely connect the J7 jumper on the board to be able to access the flash. +After that, we can load the program in flash: +``` +> flash erase_sector 0 4 4 +erased sectors 4 through 4 on flash bank 0 in 0.872235s +> flash write_bank 0 /home/user/dev/vexrisc_fork/VexRiscv/src/main/c/murax/xipBootloader/demo_xip.bin 0x40000 +wrote 48 bytes from file /home/user/dev/vexrisc_fork/VexRiscv/src/main/c/murax/xipBootloader/demo_xip.bin to flash bank 0 at offset 0x00040000 in 0.285539s (0.164 KiB/s) +> flash verify_bank 0 /home/user/dev/vexrisc_fork/VexRiscv/src/main/c/murax/xipBootloader/demo_xip.bin 0x40000 +read 48 bytes from file /home/user/dev/vexrisc_fork/VexRiscv/src/main/c/murax/xipBootloader/demo_xip.bin and flash bank 0 at offset 0x00040000 in 0.192036s (0.244 KiB/s) +contents match +> reset +JTAG tap: fpga_spinal.bridge tap/device found: 0x10001fff (mfg: 0x7ff (), part: 0x0001, ver: 0x1) +> resume +> exit +Connection closed by foreign host. +``` + +From now the device runs the code from flash, LEDs shall display a dot moving from D9 to D2. + +### Loading flash using GDB / eclipse +- ``` +src/openocd -f tcl/interface/ftdi/ft2232h_breakout.cfg -c "set MURAX_CPU0_YAML ../VexRiscv/cpu0.yaml" -f tcl/target/murax_xip.cfg +``` +- Make sure J7 is connected. +- Connect to GDB / eclipse as usual. + +From there code loading, step, break points works as usual (including software break points in flash). + +## Update hardware/bootloader + +- Stop any OpenOCD connection +- Remove J7, then: +- ``` +make clean prog +``` +- Remember to check a single FTDI device is listed in the output. If not: + - Disconnect the other devices + - ``` + make prog + ``` +- Connect J7, flash software shall start executing. + +## Flash software +Refer to "Loading the flash with telnet" or "Loading flash using GDB / eclipse". diff --git a/src/main/c/murax/xipBootloader/crt.S b/src/main/c/murax/xipBootloader/crt.S index 178f788..8668c8a 100644 --- a/src/main/c/murax/xipBootloader/crt.S +++ b/src/main/c/murax/xipBootloader/crt.S @@ -42,13 +42,25 @@ crtStart: li t0, 0x1 sw t0, CTRL_XIP_CONFIG(CTRL) li t0, XIP_BASE + lw t1, (t0) + li t2, 0x12340fb7 + xor t1,t1,t2 + bnez t1,retry jr t0 +retry: + li a0, 0x800 + call spiWrite + li t1,100000 +loop: + addi t1,t1,-1 + bnez t1, loop + j crtStart spiWrite: sw a0,CTRL_DATA(CTRL) spiWrite_wait: lw t0,CTRL_STATUS(CTRL) - srli t0,t0,0x10 + slli t0,t0,0x10 beqz t0,spiWrite_wait ret diff --git a/src/main/c/murax/xipBootloader/crt.bin b/src/main/c/murax/xipBootloader/crt.bin index d64a1cb00efe30e57fa9ae8eb357f1590f780573..bf751967431a1eb58a39071360f4fe56c3dfae48 100755 GIT binary patch delta 141 zcmb=}z&Jsxo`GGMRY2lBLj#*Is{xQ^U^5qGU=U_yZFtY%z`C93Kf~mvO#;e`;#np$ z2{0%xh-cZ(#PWc7F%!dfVH2Ur&Becsor@WgMVJ}V8<-dndK(zcn;98|nVGYMnLq!3 jEXVvW|HJ)n$_v&rG%xaJm^_Jz@o^8+zjXEn1~32sem5w1 delta 84 zcmdnMSTRA%?*OwftANCN1_vN*0HhBvnTs+o2(z*_yk}rw+RpT!VRF+Z0p&&UER&f8 l7?c;pvutN#d63?~1Z1ygXkO&cF!>S_E<%Gcy-XZW030pZ`CWWB!-_Vg5e`AOHYn Cd=EPS diff --git a/src/main/c/murax/xipBootloader/makefile b/src/main/c/murax/xipBootloader/makefile index 56b8ab8..4421131 100644 --- a/src/main/c/murax/xipBootloader/makefile +++ b/src/main/c/murax/xipBootloader/makefile @@ -4,20 +4,34 @@ LFLAGS= -nostdlib -mcmodel=medany -nostartfiles -ffreestanding -fPIC -fPIE all: crt.S demo.S riscv64-unknown-elf-gcc -c $(CFLAGS) -o crt.o crt.S - riscv64-unknown-elf-gcc $(CFLAGS) -o crt.elf crt.o $(LFLAGS) -Wl,-Bstatic,-T,mapping.ld,-Map,crt.map,--print-memory-usage + riscv64-unknown-elf-gcc $(CFLAGS) -o crt.elf crt.o $(LFLAGS) -Wl,-Bstatic,-T,mapping_rom.ld,-Map,crt.map,--print-memory-usage riscv64-unknown-elf-objdump -S -d crt.elf > crt.asm riscv64-unknown-elf-objcopy -O binary crt.elf crt.bin + riscv64-unknown-elf-gcc $(CFLAGS) -o crt_ram.elf crt.o $(LFLAGS) -Wl,-Bstatic,-T,mapping.ld,-Map,crt_ram.map,--print-memory-usage + riscv64-unknown-elf-objdump -S -d crt_ram.elf > crt_ram.asm + riscv64-unknown-elf-objcopy -O binary crt_ram.elf crt_ram.bin + riscv64-unknown-elf-gcc -c $(CFLAGS) -o demo.o demo.S riscv64-unknown-elf-gcc $(CFLAGS) -o demo.elf demo.o $(LFLAGS) -Wl,-Bstatic,-T,mapping.ld,-Map,demo.map,--print-memory-usage riscv64-unknown-elf-objdump -S -d demo.elf > demo.asm riscv64-unknown-elf-objcopy -O binary demo.elf demo.bin + riscv64-unknown-elf-gcc $(CFLAGS) -o demo_rom.elf demo.o $(LFLAGS) -Wl,-Bstatic,-T,mapping_rom.ld,-Map,demo_rom.map,--print-memory-usage + riscv64-unknown-elf-objdump -S -d demo_rom.elf > demo_rom.asm + riscv64-unknown-elf-objcopy -O binary demo_rom.elf demo_rom.bin + riscv64-unknown-elf-gcc $(CFLAGS) -o demo_xip.elf demo.o $(LFLAGS) -Wl,-Bstatic,-T,mapping_xip.ld,-Map,demo_xip.map,--print-memory-usage + riscv64-unknown-elf-objdump -S -d demo_xip.elf > demo_xip.asm + riscv64-unknown-elf-objcopy -O binary demo_xip.elf demo_xip.bin -clean: +clean-for-commit: rm -f *.o - rm -f *.bin rm -f *.elf rm -f *.asm - rm -f *.map \ No newline at end of file + rm -f *.map + rm -f *.d + rm demo_rom.bin demo.bin crt_ram.bin + +clean: clean-tmp + rm -f *.bin diff --git a/src/main/c/murax/xipBootloader/mapping_rom.ld b/src/main/c/murax/xipBootloader/mapping_rom.ld new file mode 100644 index 0000000..aaa0c3c --- /dev/null +++ b/src/main/c/murax/xipBootloader/mapping_rom.ld @@ -0,0 +1,96 @@ +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. +*/ +OUTPUT_FORMAT("elf32-littleriscv", "elf32-littleriscv", "elf32-littleriscv") +OUTPUT_ARCH(riscv) +ENTRY(crtStart) + +MEMORY { + mem : ORIGIN = 0x80000000, LENGTH = 0x00000400 + rom : ORIGIN = 0xF001E000, LENGTH = 0x00000400 +} + +_stack_size = DEFINED(_stack_size) ? _stack_size : 0; + +SECTIONS { + + .vector : { + *crt.o(.text); + } > rom + + .memory : { + *(.text); + end = .; + } > rom + + .rodata : + { + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + } > rom + + .ctors : + { + . = ALIGN(4); + _ctors_start = .; + KEEP(*(.init_array*)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + . = ALIGN(4); + _ctors_end = .; + } > rom + + .data : + { + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.*) + *(.gnu.linkonce.s.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + } > rom + + .bss (NOLOAD) : { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _bss_start = .; + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _bss_end = .; + } > mem + + .noinit (NOLOAD) : { + . = ALIGN(4); + *(.noinit .noinit.*) + . = ALIGN(4); + } > mem + + ._stack (NOLOAD): + { + . = ALIGN(16); + PROVIDE (_stack_end = .); + . = . + _stack_size; + . = ALIGN(16); + PROVIDE (_stack_start = .); + } > mem + +} diff --git a/src/main/c/murax/xipBootloader/mapping_xip.ld b/src/main/c/murax/xipBootloader/mapping_xip.ld new file mode 100644 index 0000000..ed56400 --- /dev/null +++ b/src/main/c/murax/xipBootloader/mapping_xip.ld @@ -0,0 +1,96 @@ +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. +*/ +OUTPUT_FORMAT("elf32-littleriscv", "elf32-littleriscv", "elf32-littleriscv") +OUTPUT_ARCH(riscv) +ENTRY(crtStart) + +MEMORY { + mem : ORIGIN = 0x80000000, LENGTH = 0x00000400 + xip : ORIGIN = 0xE0040000, LENGTH = 0x00000400 +} + +_stack_size = DEFINED(_stack_size) ? _stack_size : 0; + +SECTIONS { + + .vector : { + *crt.o(.text); + } > xip + + .memory : { + *(.text); + end = .; + } > xip + + .rodata : + { + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + } > xip + + .ctors : + { + . = ALIGN(4); + _ctors_start = .; + KEEP(*(.init_array*)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + . = ALIGN(4); + _ctors_end = .; + } > xip + + .data : + { + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.*) + *(.gnu.linkonce.s.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + } > xip + + .bss (NOLOAD) : { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _bss_start = .; + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _bss_end = .; + } > mem + + .noinit (NOLOAD) : { + . = ALIGN(4); + *(.noinit .noinit.*) + . = ALIGN(4); + } > mem + + ._stack (NOLOAD): + { + . = ALIGN(16); + PROVIDE (_stack_end = .); + . = . + _stack_size; + . = ALIGN(16); + PROVIDE (_stack_start = .); + } > mem + +} diff --git a/src/main/scala/vexriscv/demo/Murax.scala b/src/main/scala/vexriscv/demo/Murax.scala index d78beeb..846fa04 100644 --- a/src/main/scala/vexriscv/demo/Murax.scala +++ b/src/main/scala/vexriscv/demo/Murax.scala @@ -385,7 +385,8 @@ object Murax_iCE40_hx8k_breakout_board_xip{ val led = out Bits(8 bits) } - val murax = Murax(MuraxConfig.default(withXip = true)) + //val murax = Murax(MuraxConfig.default(withXip = true)) + val murax = Murax(MuraxConfig.default(withXip = true).copy(onChipRamSize = 8 kB)) murax.io.asyncReset := False val mainClkBuffer = SB_GB() @@ -438,45 +439,6 @@ object Murax_iCE40_hx8k_breakout_board_xip{ def main(args: Array[String]) { SpinalVerilog(Murax_iCE40_hx8k_breakout_board_xip()) - /*SpinalVerilog{ - val c = Murax(MuraxConfig.default(withXip = true)) - - - - - c.rework { - c.resetCtrlClockDomain { - c.io.xip.setAsDirectionLess.allowDirectionLessIo.flattenForeach(_.unsetName()) - - out(RegNext(c.io.xip.ss)).setName("io_xip_ss") - - val sclk = SB_IO_SCLK() - sclk.PACKAGE_PIN := inout(Analog(Bool)).setName("io_xip_sclk") - sclk.CLOCK_ENABLE := True - - sclk.OUTPUT_CLK := ClockDomain.current.readClockWire - sclk.D_OUT_0 <> c.io.xip.sclk.write(0) - sclk.D_OUT_1 <> RegNext(c.io.xip.sclk.write(1)) - - for (i <- 0 until c.io.xip.p.dataWidth) { - val data = c.io.xip.data(i) - val bb = SB_IO_DATA() - bb.PACKAGE_PIN := inout(Analog(Bool)).setName(s"io_xip_data_$i" ) - bb.CLOCK_ENABLE := True - - bb.OUTPUT_CLK := ClockDomain.current.readClockWire - bb.OUTPUT_ENABLE <> data.writeEnable - bb.D_OUT_0 <> data.write(0) - bb.D_OUT_1 <> RegNext(data.write(1)) - - bb.INPUT_CLK := ClockDomain.current.readClockWire - data.read(0) := bb.D_IN_0 - data.read(1) := RegNext(bb.D_IN_1) - } - } - } - c - }*/ } }