cancel
Showing results for 
Search instead for 
Did you mean: 

External loader fails to download

nikof
Associate II

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.

26 REPLIES 26

Init() function fails the second time around. Instrument so you understand why. Perhaps IC is still busy or some other issue.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Managed to solve the file size limit issue. It was due to a counter in the example code was declared as 16bit buffer. Redeclared it as 32bit solved the issue.

Hareesh_S
Associate II

Is this still a problem with CubeProgrammer 2.17? Wanted to get confirmation since I'm facing issues with a custom external loader for the winbond W25Q series flash with the U5F7 MCU. I am able to read external flash and write to it, but the download process seems to fail.

When moving UI elements to external flash, I get the error

Error: failed to download Segment[1]

segment[1] referring to external flash. 

Assume it's your issue, hard to diagnose anything with this level of detail. The thread here is from 2 years ago.

What else can you glean from the logging output prior to it failing thusly? Try increasing to level 3

You can use whatever hardware you have on your board to help debugging and diagnosis. Say LEDs on the UARTs to provide telemetry and diagnostics from the Loader's perspective.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Hareesh_S
Associate II

Admittedly I've provided a very bad description of the issue I am facing.
I've created an external loader for the W25Q32 flash module

I've tested the read and erase operations using my external loader with cubeprogrammer, they are working as expected.
When I try to program/write a random bin file to external flash using cubeprogrammer, the erase operation succeeds, but download operation fails with the error - 

12:33:21 : Error: failed to download Segment[0]
12:33:21 : Error: failed to download the File


(I misreported in my previous comment, apologies)
When I disconnect from the MCU, reconnect and read external flash, I can see some data has been written to it, but only to the starting few addresses.

Similarly, when I try to fill memory with address set to external flash address(start address 0x90000000), size 0x400000, and data 0x01, the operation fails - upon reading, I can see it has been written upto 0x9000FFF0 with 0x01, everything after that, starting from 0x90010000 only contains 0xFF.

Not sure if its a library issue since I didn't write the library from scratch, I followed a guide on YouTube that provided the library, but I can attach the library files if that would help.

Alternatively, do let me know if I should open a new thread for this instead.

Edit : I have attached a level 3 log for when I try to program the random bin file. Not sure how to interpret it though

My thought here is that your Write() function doesn't leave the QSPI part in Memory Mapped Mode, which is needed for ST's code to read memory content directly.

Make sure you mask the address passed to the QSPI memory when doing the Page Write's, that it's got the correct 3/4-byte address mode. To debug internally you can output to a board level UARTto get diagnostics/telemetry.

Specify the pins used for you W25Q32. What's the full part# for your STM32 MCU?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Hareesh_S
Associate II

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)