cancel
Showing results for 
Search instead for 
Did you mean: 

How to create an external flash loader for an STM32H7RS

Mohamed_Aziz_REZGUI
ST Employee

Summary

The primary objective of this article is to provide a comprehensive step-by-step guide on creating an external flash loader to interface with external memories. This demonstration uses the STM32H7S3L8H6 microcontroller and XSPI to interface with the external memory, but it can be easily tailored for other microcontrollers.

1. Prerequisites

1.1. Hardware

REZGUI_MohamedAziz_19-1731424373872.png

1.2. Software

1.3. Firmware

2. Steps

To create an external flash loader, follow the steps outlined below. The required tools for this process include STM32CubeProgrammer, STM32CubeMX, and STM32CubeIDE.

2.1. Configure option bytes (STM32CubeProgrammer)

If the microcontroller operates under 2.5 V, High-Speed Low Voltage (HSLV) must be enabled. In this case, according to the datasheet, the flash memory operates at 1.8 V. Consequently, HSLV on I/O port 2 needs to be enabled, where the memory is interfaced. You can determine which port your memory uses by consulting the alternate functions section in your microcontroller's DS14360 Rev 2.

REZGUI_MohamedAziz_27-1731399100876.png

2.2. Choose MCU (STM32CubeMX)

We developed this article using the Nucleo-H7S3L8, but to make it more generic started from the MCU itself. That’s why you should:

  • Select [ACCESS TO MCU SELECTOR]
REZGUI_MohamedAziz_28-1731399135180.png
  • In the [Commercial Part Number], type the product name of your microcontroller. In this case, it's the STM32H7S3L8H6. Select it, and click [Start Project].
REZGUI_MohamedAziz_29-1731399176567.png
  • We’re using the default configuration of the MPU, we add extra configurations further in this article.
REZGUI_MohamedAziz_30-1731399206720.png

2.3. Configure the power supply

To enable the created external flash loader to operate on the microcontroller, you need to select the proper power supply. In this case, the Nucleo-H7S3L8 features a Low-dropout regulator (LDO) and doesn’t include a switched-mode power supply (SMPS) according to UM3276 - Rev 1. To configure it, you need to perform the steps below:

  • Select [RCC]
  • Go to [Power Parameters]
  • Set [SupplySource] to [PWR_LDO_SUPPLY]

REZGUI_MohamedAziz_32-1731399275729.png

 

REZGUI_MohamedAziz_31-1731399263862.png

2.4. Configure XSPI

In this scenario, the external flash memory is interfaced with XSPI1 in [Octo SPI] mode on the second port, with the chip select pin set to [NCS1]. Refer to board schematics MB1737-B02.

REZGUI_MohamedAziz_33-1731399299888.png

Next, you need to select the memory manufacturer (memory type), memory size, chip select high time cycle, and delay hold quarter cycle from the memory datasheet and application note AN5050. In this case:

  • Memory type: Macronix

  • Memory size: 256 Mbit/s (maximum size is 256 Mbit/s according to the memory datasheet)

  • Chip select high time: 2 (found in the memory datasheet under "AC CHARACTERISTICS”)

  • Delay hold quarter cycle: Enabled (as the memory is used in DTR mode, per application note AN5050)

 

REZGUI_MohamedAziz_0-1731423579991.png

2.5. GPIO configuration

After configuring XSPI, your GPIO configuration should be like the following:  
REZGUI_MohamedAziz_1-1731423601521.png

2.6 Configure the memory protection unit (MPU)

To prevent speculative reads from undesired external memory regions, the memory protection unit (MPU) needs to be enabled to allow access only from specific regions. In this case there are two MPU instances, one for the boot subproject, and the other for the application subproject. To configure the one relative to boot context, (CORTEX_M7_BOOT) the steps are as follows:

  • MPU region one: Enabled 
  • MPU region base address:  0x9000_0000 (XSPI instance start address, RM0477)
  • MPU region size: 32 Mbytes (your external memory size)
  • Instruction access: Enabled
  • Cacheability: Enabled
  • Bufferability: Enabled

For further information about MPU attributes, refer to AN4838

REZGUI_MohamedAziz_2-1731423648287.png

As for the application context (CORTEX_M7_APPLI):

  • MPU control mode: MPU NOT USED (it uses the configuration from CORTEX_M7_BOOT). 
REZGUI_MohamedAziz_3-1731423667301.png

2.7. Configure SBS.

As mentioned above (section 2.1) HSLV needs to be used in this case. To activate it, you need to configure option bytes and SBS (secure boot system). In this case, I/O HSLV FOR XSPIM2 needs to be enabled.

REZGUI_MohamedAziz_4-1731423722104.png

2.8. Configure the external memory manager middleware

External memory manager is a middleware that generates necessary drivers to interface with external memories and generates boot code. It needs to be configured as follows:

  • Enable this middleware in the boot context
REZGUI_MohamedAziz_5-1731423799278.png
  • In [Memory 1]:
    • Memory driver: EXTMEM_NOR_SFDP (Used memory is Nor SFDP flash based on its datasheet). 
    • XSPI instance: XSPI1 (Use the same as section 2.2).
    • Number of memory data lines: 8 (refer to your memory datasheet).
REZGUI_MohamedAziz_6-1731423824376.png
  • In [boot use case]:
    • Boot code generation: Selected. This generates the code that jumps from internal flash to external flash memory.
    • Selection of the boot system: Execute in place (code is executed directly from external flash memory).
    • Select memory 1 as the memory in which the code will be executed.
REZGUI_MohamedAziz_7-1731423854682.png

2.9. Configure the external memory loader middleware

External memory loader is a middleware that makes generating custom external memory loaders more user-friendly. That’s why it needs to be configured.

  • In [external memory loader]: 
    • Select the memory: Memory 1 (memory to create loader for) 
    • Target IDE: Selected Toolchain (This will create a flashloader for the toolchain selected in project settings.
    • Loader name: Choose a name for your loader.
    • Sector size: 4096 bytes (refer to memory datasheet)
    • Number of sectors: 8192 (Number of sectors = Memory size/ sector size).
    • Page size: 256 (0x100) bytes (refer to memory datasheet).
    • Page program timeout: 2 ms*
    • Erase sector timeout: 400 ms*

*Refer to memory datasheet under “ERASE AND PROGRAMMING PERFORMANCE” 

 

REZGUI_MohamedAziz_8-1731423881713.png

2.10. Clock configuration

The operating frequency is up to 600 MHz for the STM32H7Rx/Sx family. For maximum performance, set the CPUCLK value to the mentioned frequency.

REZGUI_MohamedAziz_9-1731423906667.pngAccording to the memory datasheet, the maximum operating speed of the memory in DTR mode is 200 MHz However, the microcontroller, datasheet states that the XSPI interface can reach 190 MHz To fully use the clock speed of XSPI, you need to:
  • Set DIVM2 to /4.
  • Set DIVN2 to X35.
  • Set DIVS2 to /3.
  • Set DIVT2 to /2.
REZGUI_MohamedAziz_10-1731423923536.png
  • In the [XSPI1] clock Mux select [PLL2S] (choose your XSPI instance)

 

REZGUI_MohamedAziz_11-1731423938896.png

 

2.11. Project manager configuration

Before generating your custom external flash loader, you need to access the [Project Manager] and configure the following settings:

  • Choose a name for your project.
  • In the project structure, check the ExtMemLoader Project as it will generate a specific project for our loader which is needed in the next section.
  • Select your desired toolchain/IDE.
REZGUI_MohamedAziz_12-1731423971578.png
  • Generate your project.

Using STM32CubeIDE:

2.12. Build the external memory loader

After generating your project using STM32CubeMX, the next step is selecting the external memory loader subproject and building it. This step will generate your external flash loader.

Note: If your STM32CubePogrammer is installed in a privileged location, open STM32CubeIDE as administrator to authorize the copying of your generated folder under STM32CubeProgrammer path.

Note: If a "cp: can’t create 'C:\XX\XX' warning: File copy failed" error occurs, make sure that STM32CubeProgrammer is installed in an unprivileged directory, and that your project path doesn’t contain spaces.

REZGUI_MohamedAziz_13-1731424012490.png

A message should appear in the console, indicating that your loader has been successfully built. This occurs because the "Selected Toolchain" option is chosen in section 2.8.                                                                                                              

REZGUI_MohamedAziz_14-1731424032727.pngFinally, you can find your external loader added to your project configuration if you are using STM32CubeIDE or are added into external loaders if you are using STM32CubeProgrammer. Furthermore, you can locate your loader in STM32CubeProgrammerPATH\bin\ExternalLoader\.

2.13. Using the external loader in STM32CubeIDE

If you’re using STM32CubeIDE, your loader should be added automatically. You can verify this in the [Debug Configurations] under [Debugger].

REZGUI_MohamedAziz_15-1731424190640.png

Then, an extra step should be done before debugging, which is adding the boot context image to be built and executed. Proceed with the following steps in debug configurations under startup:

  • In the [Load Image and Symbols] menu click on [add].
BitFlipper_2-1732265388489.png
  • Add your boot context and click ok.
REZGUI_MohamedAziz_17-1731424245892.png

Using STM32CubeProgrammer:

Under [External Loaders] select your loader to interact with your external memory by its address.

BitFlipper_1-1732264829051.png
Under [Memory & File editing] type the start address of your external loader and click enter key on your keyboard. This will give you access to your external memory. 
Version history
Last update:
‎2024-11-26 04:33 AM
Updated by: