Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OrangeCrab, bootloader and QSPI #103

Closed
umarcor opened this issue Jul 7, 2021 · 4 comments
Closed

OrangeCrab, bootloader and QSPI #103

umarcor opened this issue Jul 7, 2021 · 4 comments

Comments

@umarcor
Copy link
Collaborator

umarcor commented Jul 7, 2021

Coming from #98.

#98 (comment)

And one problem for me to work on is that I have not tested anything to do with the flash (in this case, W25Q128JVP). Does this core/bootloader support QSPI? I ask because I think the default USB bootloader on the OrangeCrab switches the flash to QSPI mode, so if this original bootloader is kept, then the neorv32 core will not be able to communicate with the flash if it can't do QSPI. As far as I can tell there is no way to reset the flash back to normal SPI from the FPGA, it must be power cycled (which will then invoke the original bootloader to switch the flash into QSPI, etc).

Ideally I would like to keep the USB bootloader, and then store the neorv32 bit file at an offset in the flash past this bootloader, and then store the actual executable at a further offset in the flash (it's a 16MByte flash, so there should be plenty of room for all of this). I assume that the steps to do this are something like the following

  1. Adjust the bootloader code to read/write into an offset of the flash (which will be original bootloader size + FPGA bitfile size)
  2. and/or adjust the core to add this offset to all flash read/writes

Any ideas, suggestions or pointers here would be appreciated.

#98 (comment)

I see that I should have read the documentation closer around the flash offset: https://stnolting.github.io/neorv32/ug/#_customizing_the_internal_bootloader

#98 (comment)

I should have also read the flash datasheet further as well… it seems that SPI commands are always accepted. So I’m thinking that all I need to do to get application loading from flash is to rebuild the bootloader with the correct flash offset, then copy that newly built executable into the vhd file which contains the bootloader, and it should work from there?

/cc @jeremyherbert

@stnolting
Copy link
Owner

#98 (comment):

@jeremyherbert

Ok, I fetched all of these changes and built it, loaded the newly generated svf and it works great:

Good to hear! 👍 🎉

it seems that SPI commands are always accepted.

I think that all SPI flashs always support "normal" (= single-bit) SPI as a fallback.

So I’m thinking that all I need to do to get application loading from flash is to rebuild the bootloader with the correct flash offset, then copy that newly built executable into the vhd file which contains the bootloader, and it should work from there?

That's right! But you do not need to copy anything - the makefile will take care of all that.
You can do the following:

neorv32/sw/bootloader$ make USER_FLAGS+=-DSPI_BOOT_BASE_ADDR=0x12345678 clean_all bootloader

This will override the default SPI boot address with 0x12345678, re-compile the bootloader sources and also install the executable image to the according VHDL file. You just need to re-synthesize the design.

ℹ️ All default defines that shall be overridden have to be added to the USER_FLAGS variable using the -D prefix.

Btw, qSPI support sounds interesting. Maybe this is something we could add to the default NEORV32 SPI module.

@jeremyherbert
Copy link
Contributor

Yes, my mistake on the flash (sorry, it was late at night and my brain had already gone to sleep). QSPI in the core itself would make a lot of sense, especially if this could eventually be used for execute-in-place.

@stnolting
Copy link
Owner

QSPI in the core itself would make a lot of sense, especially if this could eventually be used for execute-in-place.

QSPI should be no problem I think. SPI is just a shift register, classic SPI uses 1 bit and shifts by 1 position and QSPI uses 4 bits and shifts by 4 positions. So I think this could be also supported via a new configuration flag in the module.

Directly executing code "in-place" via SPI is not supported as the SPI controller is a peripheral. Hence, any CPU-SPI access is not "transparent" for CPU (CPU accesses are not directly transformed into SPI transmissions). This could be emulated in software via some virtualization approach.

Anyway, an external component that directly transforms bus accesses into SPI transactions seem to be a nice idea. Especially in combination with the instruction cache.

@stnolting
Copy link
Owner

I have implemented a Wishbone-to-SPI bridge supporting XIP: -> #224
It only implements "single-bit" SPI mode so far (no dSPI/qSPI).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants