Skip to main content
nikof
Associate II
June 20, 2022
Solved

External loader fails to download

  • June 20, 2022
  • 11 replies
  • 12249 views

Hi all,

I'm trying to put some TouchGFX data (images, text, ...) in an external flash (S25FL128L) on a custom board with STM32H7B0VB mcu. I'm using the octo-spi peripheral as quad-spi.

So, I follow the guide to make an external loader and I did it. It seems to work properly: if I load the .stdlr file in the STM32CubeProgrammer I can read, write, erase sector and mass erase the external flash.

Also, if I try to debug (STM32CubeIDE) a project using the loader without putting elements into external flash all works and I can see all the memories.

The ploblem occur whe I try to put somenthing inside the external flash. I do that in the linker script with TouchGFX sections: IntFlashSection and TextFlashSection. See the script below:

/* Entry Point */
ENTRY(Reset_Handler)
 
/* Highest address of the user mode stack */
_estack = 0x20020000; /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200 ; /* required amount of heap */
_Min_Stack_Size = 0x400 ; /* required amount of stack */
 
/* Specify the memory areas */
MEMORY
{
 FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K
 RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
 AXI_SRAM (xrw) : ORIGIN = 0x24000000, LENGTH = 1024K
 AHB_SRAM (xrw) : ORIGIN = 0x30000000, LENGTH = 128K
 OCTOSPI (r)	 : ORIGIN = 0x90000000, LENGTH = 16M
}
 
/* Define output sections */
SECTIONS
{
 /* The startup code goes first into FLASH */
 .isr_vector :
 {
 . = ALIGN(4);
 KEEP(*(.isr_vector)) /* Startup code */
 . = ALIGN(4);
 } >FLASH
 
 /* The program code and other data goes into FLASH */
 .text :
 {
 . = ALIGN(4);
 *(.text) /* .text sections (code) */
 *(.text*) /* .text* sections (code) */
 *(.glue_7) /* glue arm to thumb code */
 *(.glue_7t) /* glue thumb to arm code */
 *(.eh_frame)
 
 KEEP (*(.init))
 KEEP (*(.fini))
 
 . = ALIGN(4);
 _etext = .; /* define a global symbols at end of code */
 } >FLASH
 
 /* Constant data goes into FLASH */
 .rodata :
 {
 . = ALIGN(4);
 *(.rodata) /* .rodata sections (constants, strings, etc.) */
 *(.rodata*) /* .rodata* sections (constants, strings, etc.) */
 . = ALIGN(4);
 } >FLASH
 
 .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
 .ARM : {
 __exidx_start = .;
 *(.ARM.exidx*)
 __exidx_end = .;
 } >FLASH
 
 .preinit_array :
 {
 PROVIDE_HIDDEN (__preinit_array_start = .);
 KEEP (*(.preinit_array*))
 PROVIDE_HIDDEN (__preinit_array_end = .);
 } >FLASH
 .init_array :
 {
 PROVIDE_HIDDEN (__init_array_start = .);
 KEEP (*(SORT(.init_array.*)))
 KEEP (*(.init_array*))
 PROVIDE_HIDDEN (__init_array_end = .);
 } >FLASH
 .fini_array :
 {
 PROVIDE_HIDDEN (__fini_array_start = .);
 KEEP (*(SORT(.fini_array.*)))
 KEEP (*(.fini_array*))
 PROVIDE_HIDDEN (__fini_array_end = .);
 } >FLASH
 
 /* used by the startup to initialize data */
 _sidata = LOADADDR(.data);
 
 /* Initialized data sections goes into RAM, load LMA copy after code */
 .data :
 {
 . = ALIGN(4);
 _sdata = .; /* create a global symbol at data start */
 *(.data) /* .data sections */
 *(.data*) /* .data* sections */
 *(.RamFunc) /* .RamFunc sections */
 *(.RamFunc*) /* .RamFunc* sections */
 
 . = ALIGN(4);
 _edata = .; /* define a global symbol at data end */
 } >RAM AT> FLASH
 
 /* Uninitialized data section */
 . = ALIGN(4);
 .bss :
 {
 /* This is used by the startup in order to initialize the .bss secion */
 _sbss = .; /* define a global symbol at bss start */
 __bss_start__ = _sbss;
 *(.bss)
 *(.bss*)
 *(COMMON)
 
 . = ALIGN(4);
 _ebss = .; /* define a global symbol at bss end */
 __bss_end__ = _ebss;
 } >RAM
 
 /* User_heap_stack section, used to check that there is enough RAM left */
 ._user_heap_stack :
 {
 . = ALIGN(8);
 PROVIDE ( end = . );
 PROVIDE ( _end = . );
 . = . + _Min_Heap_Size;
 . = . + _Min_Stack_Size;
 . = ALIGN(8);
 } >RAM
 
 /* Remove information from the standard libraries */
 /DISCARD/ :
 {
 libc.a ( * )
 libm.a ( * )
 libgcc.a ( * )
 }
 
 .ARM.attributes 0 : { *(.ARM.attributes) }
 
 IntFlashSection :
 	{
 		*(IntFlashSection IntFlashSection.*)
 		*(.gnu.linkonce.r.*)
 		. = ALIGN(0x4);
 	} >OCTOSPI
 
 TextFlashSection :
 	{
 		*(TextFlashSection TextFlashSection.*)
 		*(.gnu.linkonce.r.*)
 		. = ALIGN(0x4);
 	} >OCTOSPI
 
}

The output of the console when I try to Debug or Run with this linker script is:

STMicroelectronics ST-LINK GDB server. Version 6.1.0
Copyright (c) 2022, STMicroelectronics. All rights reserved.
 
Starting server with the following options:
 Persistent Mode : Disabled
 Logging Level : 1
 Listen Port Number : 61234
 Status Refresh Delay : 15s
 Verbose Mode : Disabled
 SWD Debug : Enabled
 InitWhile : Enabled
 
Waiting for debugger connection...
Debugger connected
Waiting for debugger connection...
Debugger connected
Waiting for debugger connection...
 -------------------------------------------------------------------
 STM32CubeProgrammer v2.10.0 
 -------------------------------------------------------------------
 
 
 
Log output file: c:\users\niko~1.fio\appdata\local\temp\stm32cubeprogrammer_a14888.log
ST-LINK SN : 34FF74065250343847111043
ST-LINK FW : V2J39S7
Board : --
Voltage : 3.23V
SWD freq : 4000 KHz
Connect mode: Under Reset
Reset mode : Hardware reset
Device ID : 0x480
Revision ID : Rev Z
Device name : STM32H7A/B
Flash size : 128 KBytes
Device type : MCU
Device CPU : Cortex-M7
BL Version : 0x90
 
 
 
Memory Programming ...
Opening and parsing file: st-link_gdb_server_a14888.srec
 File : st-link_gdb_server_a14888.srec
 Size : 694.94 KB 
 Address : 0x08000000 
 
 
Erasing memory corresponding to segment 0:
Erasing internal memory sectors [0 32]
Erasing memory corresponding to segment 1:
Erasing external memory sectors [0 108]
Download in Progress:
 
 
Error: failed to download Segment[0]
Error: failed to download the File
Shutting down...
Exit.

Best answer by N. SANTINI

Hi,

There is a known issue with custom external loader and recent versions of CubeProgrammer (both standalone and CubeIDE embedded versions).

The issue is being investigated but there is a workaround that I suggest you to try since the error you get may be linked to this issue.

You need to replace the internal flash loader that comes with CubeProgrammer with the one from version 2.6.0.

  1. Download and install CubeProgrammer version 2.6.0
  2. The internal loaders are located in : C:\Program Files\STMicroelectronics\STM32Cube\STM32CubeProgrammer\bin\FlashLoader
  3. The one corresponding to your board is displayed in the CubeProgrammer GUI when connecting to the board
  4. Copy/paste the relevant .stldr from the 2.6.0 to the version you use.

For the STM32H7A the internal flash loader is the 0x480.stldr, I attached it to this post so that you can quickly test if it solves your issue.

Just unzip the file in the internal loader folder of your CubeProgrammer installation folder :

CubeProgrammer standalone version :

C:\Program Files\STMicroelectronics\STM32Cube\STM32CubeProgrammer\bin\FlashLoader

CubeProgrammer CubeIDE (v.1.9) embedded version : C:\ST\STM32CubeIDE_1.9.0\STM32CubeIDE\plugins\com.st.stm32cube.ide.mcu.externaltools.cubeprogrammer.win32_2.0.200.202202231230\tools\bin\FlashLoader

I hope this will help, an FAQ is being created accordingly until a proper fix is implemented,

Best regards,

Nicolas

11 replies

Associate II
September 21, 2024

So my external loader is based on SPI, not QSPI. (The next revision of the board I am using will address this)

I'll try debugging using UART and get back at the earliest.

The MCU I am using is the STM32U5F7VJT6, using the SPI1 peripheral for it

Flash module is the W25Q32JV. Reset and WP are pulled up to 3V3 by design, rest of the pins are for SPI and supply.

I don't fully understand the code in the library honestly, would you mind verifying if there indeed is an issue with the function? ( I plan on building the library from scratch anyway to get an actual understand of flash interfacing, just want to test out if I'm able to move assets to external flash for the time being)