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.

Notice: You need the embedded software example code to make these changes; if you have not already done so, generate it.

Modify the Bootloader Software with External Memory Enabled

First, you need to modify the bootloader code:
  1. Open the bootloaderConfig.h file in the embedded_sw/<SoC module>/bsp/efinix/EfxSapphireSocRV64/software/standalone/bootloader directory.
  2. 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.

Modify the Bootloader Software without External Memory Enabled

First, you need to modify the bootloader linker script:
  1. Open the bootloader.ld file in the embedded_sw/<SoC module>/bsp/efinix/EfxSapphire RV64Soc/linker directory.
  2. Replace the MEMORY section 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

Next, you need to regenerate the memory initialization files using the binGen.py helper script.
  1. 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.
  2. This command generates the new memory initialization files. Replace the existing files by copying these files into the <SoC module> IP directory.
  3. 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.

Table 1. Multi-Data Lines Interface with 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
In the bootloaderConfig.h file, you can define the configurations by selecting from the various data line modes:
  • 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();
}
 
Note: If the flash device is MX25 (from Ti180J484 development kit), add CFLAGS+=-DMX25_FLASH before the LDSCRIPT?=${BSP_PATH}linker/bootloader.Id into the bootloader application's makefile. Defining the MX25 includes the required commands specific to the MX25 flash device.