Showing results for 
Search instead for 
Did you mean: 

STM32L5: External loader does not work



With the STM32L562E-DK devoplement kit, I have developed a working touchGFX application without Trustzone. The external loader MX25LM51245G_STM32L562E-DK works as expected with STM32CubeProgrammer (version 2.14.0)

However, I need trustzone, so I enabled the trustzone bit. Now, with the Trustzone bit, the external loader MX25LM51245G_STM32L562E-DK does not work (the MX25LM51245G_STM32L562E-DK-SFIx is also not working).

Not working means: erase one section gives no error (only a message that protected sections are not erased), but programming failes with the message: failed to erase sectors.

The sectors are not protected, with the cubeMX example projects the external flash is working with TrustZone enabled. 

I have downloaded the source code of the external loader ( STM32L5x_boards/MX25LM51245G_STM32L562E-DK) and requested a trial version of the IAR IDE Arm (version 9.40.1). I build the stldr file and put the loader in the ExternalLoader directory of STM32CubeProgrammer. With this version, even the erase one sector fails.

Why is the behaviour of the unchanged version of the external loader different after a recompile?

I have followed a tutorial for creating your own external loader, however, they also are not working. From the debug output, it seems that the MSP is set to zero.

Is the MX25LM51245G_STM32L562E-DK suppost to work with a STM32L562 with trustzone enabled?

Is there another external loader which I can use?

I have a lot of logs of the verbose level 3 of the cube programmer, but I doubt if that gives usefull information.

Any help is much appriciated.

Best regards, Pieter

ST Employee

Hello @daCodeMonkey and welcome to the community 🙂,

I confirm the issue and I reported internally.

 Internal ticket number: 81852 (This is an internal tracking number and is not accessible or usable by customers).

Thank you.


To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.



In the mean time, I developed my own external loader.

To be able to develop this, I first needed to reverse engineer how the STM32CubeProgrammer use the external loaders. By enabling level 3 verbose logging and try to make sense out of the logs generated by other loaders and my own.

Here is what is not documented in the manual from STM:

The first 4 bytes of the SRAM need to be kept free (STM32CubeProgrammer uses this word to program a breakpoint instruction and sets the linker register to this address to detect when the function is finished).

For chips with TrustZone disabled, the used address is 0x20000004 (start of SRAM1) (tested on an STM32L5).
For chips with TrustZone enabled, the used address is 0x20018004 (halfway in SRAM1) (tested on an STM32L5).

The program need to be smaller than 0x1000. If it is larger, STM32CubeProgrammer does not give an error but does not download the software to SRAM (when verbose logging level 3 is enabled, you can see the download of the software).

STM32CubeProgrammer sets the stackpointer, link and program counter registers prio to call the functions. All other initialisation is left for the programmer of the Init function.

The return of the called functions indicate if the function succeded or failed. R0 is the return register. STM32CubeProgrammer shows this register in the log. Since debugging via ST-link is not possible when using STM32CubeProgrammer, you can use the R0 to write magic numbers to and execute a breakpoint instruction and STM32CubeProgrammer writes them in the log.

Also, inspecting the registers in STM32CubeProgrammer can be an indication of what went wrong during execution of the external loader.

Maybe this helps others too with creating an custom external loader when TrustZone is enabled. I have gained some experience with this system by now.

Best regards,