stnolting / neorv32

:desktop_computer: A small, customizable and extensible MCU-class 32-bit RISC-V soft-core CPU and microcontroller-like SoC written in platform-independent VHDL.
https://neorv32.org
BSD 3-Clause "New" or "Revised" License
1.59k stars 225 forks source link

XIP Flash: Not working as expected #918

Closed fedy0 closed 1 month ago

fedy0 commented 5 months ago

Describe the bug I implemented a neorv32 soc with XIP support. I compiled and uploaded the examples in neorv32/sw/example/demo_xip and neorv32/sw/example/demo_blink_led in turns but it got stuck at the erase flash function. A clear and concise description of the bug is show below.

To Reproduce

git clone --recursive https://github.com/fedy0/neo.git && cd neo && make -f Makefile.xip flash
make MARCH=rv32i_zicsr_zifencei USER_FLAGS+="-Wl,--defsym,__neorv32_rom_base=0xe0400000" clean_all exe

Expected behavior Load executable from flash

Screenshots Screenshot from 2024-06-02 21-24-16

Environment:

Hardware:

stnolting commented 5 months ago

I think everything looks fine so far...

make -f Makefile.xip flash

What is that?

What kind of serial flash are you using? First, you should check that the chip actually supports all the required commands:

https://github.com/stnolting/neorv32/blob/89d0f9d286f9ae2cdc987324b934ab17327a4d6a/sw/example/demo_xip/main.c#L65-L71

If the program keeps stuck in the erase function the write-in-progress flag of the chip's status register might not be clearing. In most cases (talking about my own mistakes 🙈) this is not caused by the chip itself but by some faulty wiring.

Which chip select line are you using?

This is what I would do: try to make a manual access to the SPI flash to check if the chip is responding at all (thus, verifying the wiring). You can use the provided "SPI explorer program" for that (-> sw/example/demo_spi).

Note that this program uses the SPI module and not the XIP module. But you can wire them up in parallel:

  xip_csn_o <= spi_csn(0) and xip_csn;
  xip_clk_o <= spi_sck when (spi_csn(0) = '0') else xip_clk;
  xip_dat_o <= spi_do  when (spi_csn(0) = '0') else xip_do;
  xip_di    <= xip_dat_i;
  spi_di    <= xip_dat_i;

Here is an example session where I am reading the chip's status register after power-up. As you can see, the write-enable latch is cleared at first. After issuing the according enable command the write-enable latch becomes set. If this also works on your side you know that the chip is properly wired up.

spi_explorer

stnolting commented 5 months ago

I think I will add such a "connection check" to the XIP demo program as well.

fedy0 commented 5 months ago

I think everything looks fine so far...

make -f Makefile.xip flash

What is that?

This is a makefile to sythesize XIP in the SoC. I have two top level vhdl file in ./top so I just use a seperate makefile (although the same thing can be achieved with -DDEFINES)

I am using the ULX3S Board and the SPI flash on it is from issi The XIP feature is interesting to me because I would like to have firmware retention in order to speed up the arduino-port developement for all the perpherial. I will try what you suggested. Thanks

stnolting commented 5 months ago

I have updated the XIP demo program. The new version includes a "connection" check that tries to toggle the write-enable latch of the flash chip.

fedy0 commented 5 months ago

Hi @stnolting I have made the modification (a crude one though) here. And the picture below is the outcome. Just a quick question. Can the SPI used for loading FPGA configuration at power-on be used for program memory simultaneously? image

stnolting commented 5 months ago

And the picture below is the outcome.

Seems like you are always receiving ones... So maybe the wiring of your SPI flash is incorrect. Maybe SDI and SDO pins are switched?! 🤔

Just a quick question. Can the SPI used for loading FPGA configuration at power-on be used for program memory simultaneously?

Sure, you can do that. You just need to make sure that the images (bitstream and processor executable) do not overlap inside the flash.

You can customize the bootloader (-> UG: https://stnolting.github.io/neorv32/ug/#_customizing_the_internal_bootloader) to set a different base address for the executable image inside the flash (-> SPI_BOOT_BASE_ADDR).

stnolting commented 1 month ago

Closing this for now. Feel free to open another issue if you have further questions.