Skip to main content
DJean.3
Associate II
February 17, 2026
Solved

SecureFault in SECURE_RegisterCallback after porting SBSFU from B-U585I-IOT02A

  • February 17, 2026
  • 1 reply
  • 201 views

Hello everyone,

I am working on a custom board based on the STM32U575RGT6 (1MB Flash). I am encountering a hard fault (SecureFault) during the initialization of the Non-Secure application after integrating the SBSFU.

Context:

Hardware: Custom board with STM32U575RGT6.
Initial Project: A working application using TrustZone active + FreeRTOS (generated via CubeMX). The Option Bytes were set to a default 50/50 split (Secure/Non-Secure).
Goal: Implement a Secure Boot / Firmware Update mechanism.
What I did:

I used the ST example for B-U585I-IOT02A as a reference.
I integrated SBSFU_Boot and SBSFU_Loader into my project folder.
I adapted the linker scripts (.ld), postbuild.sh, and flash_layout.h to match the 1MB Flash size of the U575RGT6 (vs 2MB on the B-U585I).
In my original application, I replaced the .ld files and startup_xx.s files with those provided in the SBSFU_Appli example.
Configuration:
To simplify debugging, I disabled Tamper, Write Protection (WRP), and HDP protection in SBSFU_Boot.
RDP Level is set to Level 0.
The Behavior: The project compiles and links successfully. After flashing:

The Bootloader starts correctly.
It jumps to the Secure Application.
The Secure Application jumps to the Non-Secure Application.
Inside the Non-Secure main():
HAL_Init() executes fine.
HAL_PWREx_EnableVddA() executes fine.
CRASH: When calling SECURE_RegisterCallback(SECURE_FAULT_CB_ID, (void *)SecureFault_Callback);, the system jumps immediately to SecureFault_Handler().
Debugging Info: It seems related to the Non-Secure Callable (NSC) region or a GTZC configuration issue, but I am stuck. Since I adapted the flash layout for 1MB, I suspect I might have messed up a boundary definition.

Has anyone faced a similar issue when porting the U5 SBSFU to a smaller flash variant?

Any help or pointers on where to look would be greatly appreciated.

Thanks in advance!

Best answer by Jocelyn RICARD

Hello @DJean.3 ,

Secure fault means you have an issue in your SAU configuration.

You need to check with debugger, when you are in the secure application the SAU area address range for first area.

This is where the Non secure callable address is setup using CMSE_VENEER_REGION_START and CMSE_VENEER_REGION_SIZE.

Then check when calling the SECURE_RegisterCallback if address is in the good range...likely not.

To do this, you will need to step in assembly and check register before the call.

Best regards

Jocelyn

1 reply

Jocelyn RICARD
Jocelyn RICARDBest answer
ST Employee
February 18, 2026

Hello @DJean.3 ,

Secure fault means you have an issue in your SAU configuration.

You need to check with debugger, when you are in the secure application the SAU area address range for first area.

This is where the Non secure callable address is setup using CMSE_VENEER_REGION_START and CMSE_VENEER_REGION_SIZE.

Then check when calling the SECURE_RegisterCallback if address is in the good range...likely not.

To do this, you will need to step in assembly and check register before the call.

Best regards

Jocelyn

DJean.3
DJean.3Author
Associate II
February 19, 2026

Following your advice regarding the SAU configuration, I performed a deep dive into the generated .map and .list files of both Secure and Non-Secure projects.

I have identified the root cause of the SecureFault: The Non-Secure application is not calling the correct address for the Secure Gateway Veneer due to a memory aliasing mismatch.

Here is the evidence:

  1. Secure Build (Lightstraight_Secure.map / .list) The Secure Linker correctly places the Veneer table in the NSC region (Flash Bank 1, Secure view 0x0C...).
  • NSC Region Start: 0x0C02FC80
  • SECURE_RegisterCallback Veneer address: 0x0C02FCE8
  1. Non-Secure Build (Lightstraight_NonSecure.list) The Non-Secure application (running at 0x08...) calls the function via the secure_nsclib.o import library.
  • The generated assembly shows: bl 80537f8 <__SECURE_RegisterCallback_veneer>
  • Call address: 0x080537F8

The Issue: The Non-Secure linker sees the symbol defined at 0x0C02FCE8 inside secure_nsclib.o. Since the NS code is running in the 0x08 range, the linker considers 0x0C as "out of range" or a different memory space, and seemingly generates a local trampoline/stub at 0x080537F8 (which is inside the NS Flash, far after the actual Secure partition) instead of branching to the Non-Secure Alias of the Veneer.

The correct target address should be: 0x0C02FCE8 (Secure Address) - 0x04000000 (Alias Offset) = 0x0802FCE8.

My Configuration:

  • IDE: STM32CubeIDE (GCC)
  • Secure Linker Flags: -Wl,--cmse-implib -Wl,--out-implib=./secure_nsclib.o
  • Non-Secure Linker: I link secure_nsclib.o as an additional object.
  • Defines: FLASH_1MB is defined in both projects (Veneer placement at 0x...2FC80 is consistent with my 96KB Secure partition size).

My Question: What is the standard/clean way in the SBSFU/STM32U5 ecosystem to tell the Non-Secure Linker that symbols imported from secure_nsclib.o (defined at 0x0C...) must be called via their Non-Secure alias (0x08...)?

I tried manipulating the Non-Secure linker script to define ROM_NSC at 0x0802FC80, but since the symbol address is fixed inside the .o object, the linker still struggles. Do I need a specific objcopy step to re-map the import library, or is there a specific GCC linker flag I am missing to handle this TrustZone aliasing automatically?

Thanks for your help!