Modify the Bootloader
When you generate the Sapphire RV64 SoC, the IP Manager creates a pre-built bootloader .bin to target the on-chip RAM size you selected. If you assigned the peripheral addresses manually, you need to create a custom bootloader according to the following instructions.
Modify the Bootloader Software with External Memory Enabled
- Open the bootloaderConfig.h file in the embedded_sw/<SoC module>/bsp/efinix/EfxSapphireSocRV64/software/standalone/bootloader directory.
- Change the
#define USER_SOFTWARE_SIZEparameter for the new on-chip RAM size and save.
In Efinity RISC-V Embedded Software IDE, import the bootloader project and build the project to generate a new bootloader.hex file.
Modify the Bootloader Software without External Memory Enabled
- Open the bootloader.ld file in the embedded_sw/<SoC module>/bsp/efinix/EfxSapphire RV64Soc/linker directory.
- Replace the
MEMORYsection with the following code. The <bootloader_address> should be 0x0001000000 + (<memory size>-3072), where <memory size> is your SoC's on-chip RAM size. This will reserve 3,072 bytes for bootloader application.MEMORY { start (wxai!r) : ORIGIN = 0x0001000000, LENGTH = 512 ram (wxai!r) : ORIGIN = <bootloader_address>, LENGTH = 3,072 }
Second you need to modify the bootloader code:
Change
the #define USER_SOFTWARE_SIZE parameter for the new on-chip RAM
size and save.
In Efinity RISC-V Embedded Software IDE, import the bootloader project and build the project to generate a new bootloader.hex file.
Regenerate the Memory Initialization Files
- You can find this script in the
<project>/embedded_sw/<SoC
module>/tool directory. Use the following
command to find the script:
python3 binGen.py -b bootloader.bin -s <RAM size>where: <RAM size> is the on-chip RAM size you want to use. - This command generates the new memory initialization files. Replace the existing files by copying these files into the <SoC module> IP directory.
- Compile your design.
Modify the Bootloader Software to Enable Multi-Data Lines
Before you can utilize the multi-data lines SPI in your bootloader, verify whether your board's flash drive supports Dual or Quad I/O modes.
In the Efinity RISC-V Embedded Software IDE example design, data ports 0 and 1 are exclusively connected. If you intend to use the Quad SPI for data transfer, you must establish connections for data ports 2 and 3. The following table shows the number of connected data lines interfacing with the respective FPGAs and flash devices.
| Development Kit | Flash Device | Number of Data Lines Connected |
|---|---|---|
| T8BGA81 | W25Q80DLSNIG | 2 |
| T20BGA256 | W25Q32JVSSIQ | 2 |
| T120BGA324 | W25Q128JVSIQ | 4 |
| T120BGA576 | W25Q128JVSIQ | 4 |
| Xyloni | W25Q128JVSIM | 2 |
| Ti60F225 | W25Q64JWSSIQ | 2 |
| Ti180J484/ Ti180M484/ Tz170J484 | MX25U25645GZ4I00 | 4 |
- SINGLE_SPI: Single data line
- DUAL_SPI: Dual data line
- QUAD_SPI: Quad data line
#define SPI (spi_hwreg_t* )SYSTEM_SPI_0_IO_CTRL
#define USER_SOFTWARE_MEMORY 0x0800000000
#define USER_SOFTWARE_FLASH 0x00600000
#define USER_SOFTWARE_SIZE 0x01F000 //124KB
#define SINGLE_SPI 1 //define DUAL_SPI for dual data SPI or QUAD_SPI for quad data SPI
spiFlash_instance_t Flash = {
.cs = 0,
.inst = &(spi_instance_t){
.hwreg = SPI,
.cpol = LOW,
.cpha = DATA_SAMPLED_RISE_EDGE,
.mode = FULL_DUPLEX_SINGLE_LINE
},
};
void bsp Main() {
#ifndef SIM
spiFlash_init(SPI, SPI_CS);
spiFlash_wake(SPI, SPI_CS);
spiFlash_exit4ByteAddr(SPI, SPI_CS);
#ifdef SINGLE_SPI
spiFlash_f2m(SPI, SPI_CS, USER_SOFTWARE_FLASH, USER_SOFTWARE_MEMORY, USER_SOFTWARE_SIZE);
#elif DUAL_SPI
spiFlash_f2m_dual(SPI, SPI_CS, USER_SOFTWARE_FLASH, USER_SOFTWARE_MEMORY,
USER_SOFTWARE_SIZE); //dual data line half duplex
#elif QUAD_SPI
spiFlash_f2m_quad(SPI, SPI_CS, USER_SOFTWARE_FLASH, USER_SOFTWARE_MEMORY,
USER_SOFTWARE_SIZE); //quad data line full duplex
#else
#error "You must either define SINGLE_SPI to use single data line SPI, DUAL_SPI to use
dual data line SPI or QUAD_SPI to use quad data line SPI."
#endif
#endif
void (*userMain)() = (void (*)())USER_SOFTWARE_MEMORY;
#ifdef SMP
smp_unlock(userMain);
#endif
userMain();
}