Skip to main content
Associate III
August 18, 2026
Question

STM32H573 STiROT+OEMuROT example failed provisioning.

  • August 18, 2026
  • 12 replies
  • 128 views

Hi Community,

I’m provisioning an STM32H573 (installed on a NUCLEO-H563ZI board; I replaced H563 with H573). I followed the ST example STiRoT_OEMuROT from STM32Cube FW H5 v1.6.0. During provisioning the script aborts with:

Error when trying to Set SECBOOT_LOCK option byte to 0xC3 (unlock secure boot address)
  Provisioning aborted.

Environment: 
- MCU: STM32H573 (2 MB flash)
- Host tools: STM32_Programmer_CLI v2.19.0
- Product state chosen in provisioning script: OPEN.

after i read the option bytes using STM32_Programmer_CLI -c port=SWD -ob displ 
i found that, 

 

   Product state:

PRODUCT_STATE: 0xED (Open)

BOR Level:

BOR_LEV : 0x0 (BOR Level 1, the threshold level is low (around 2.1 V))
BORH_EN : 0x0 (0x0)

User Configuration:

IO_VDD_HSLV : 0x0 (0x0)
IO_VDDIO2_HSLV: 0x0 (0x0)
IWDG_STOP : 0x1 (0x1)
IWDG_STDBY : 0x1 (0x1)
BOOT_UBE : 0xC3 (ST-iRoT (system flash) selected)
SWAP_BANK : 0x0 (0x0)
IWDG_SW : 0x1 (0x1)
NRST_STOP : 0x1 (0x1)
NRST_STDBY : 0x1 (0x1)
OPTION BYTES BANK: 1

User Configuration 2:

TZEN : 0xB4 (Trust zone enabled)
USBPD_DIS : 0x1 (Disabled)
SRAM2_ECC : 0x0 (SRAM2 ECC check enabled )
SRAM3_ECC : 0x1 (SRAM3 ECC check disabled)
BKPRAM_ECC : 0x1 (BKPRAM ECC check disabled)
SRAM2_RST : 0x0 (SRAM2 erase when system reset)
SRAM1_3_RST : 0x1 (SRAM1 and SRAM3 not erased when a system reset occurs)
OPTION BYTES BANK: 2

Boot Configuration:

NSBOOTADD : 0x80000 (0x8000000)
NSBOOT_LOCK : 0xC3 (The SWAP_BANK and NSBOOTADD can still be modified following their individual rules.)
SECBOOT_LOCK : 0xB4 (The BOOT_UBE and SECBOOTADD are frozen. SWAP_BANK can only be modified with TZEN set to 0xC3 (disabled).)
SECBOOTADD : 0xC0004 (0xC000400)
OPTION BYTES BANK: 3

also, when device goes in boot mode, i am not able to read the option bytes, for reading the option bytes i have to remove boot0 pin from VDD and reset it.

 STM32_Programmer_CLI -c port=SWD mode=HOTPLUG -ob displ
-------------------------------------------------------------------
STM32CubeProgrammer v2.19.0
-------------------------------------------------------------------

ST-LINK SN : 004700463434511634313937
ST-LINK FW : V3J17M10
Board : NUCLEO-H563ZI
Voltage : 3.28V
Error: Unable to get core ID
Error: Cannot connect to access port 1!
If you are trying to connect to a device with TrustZone enabled please try to connect with HotPlug mode.
If you are trying to connect to a device which supports Debug Authentication with certificate or password, please open your device using it.

2nd connect tentative with frequency (8MHz)
ST-LINK SN : 004700463434511634313937
ST-LINK FW : V3J17M10
Board : NUCLEO-H563ZI
Voltage : 3.29V
Error: Unable to get core ID
Error: Cannot connect to access port 1!
If you are trying to connect to a device with TrustZone enabled please try to connect with HotPlug mode.
If you are trying to connect to a device which supports Debug Authentication with certificate or password, please open your device using it.

Question: what’s preventing `SECBOOT_LOCK=0xC3` from being written? Is it:
- OB protected because ST-iRoT is running and re-writing OBs?
- some required precondition in option bytes I haven’t met?
- needing a different connect sequence (Hotplug/hardRst) or specific CLI version?

also, Please find an attached logs of obkey_provision.log 

12 replies

Rohit007Author
Associate III
August 18, 2026

update,
i tried without resetting the mcu during the boot0 connected to VDD, and it allowed to write the SECBOOT_LOCK to 0xC3, but now i am facing another issue, the erroe shows for 
 

Configure OBKeys HDPL1-DA config area
-------------------------------------------------------------------
STM32CubeProgrammer v2.19.0
-------------------------------------------------------------------

ST-LINK SN : 004700463434511634313937
ST-LINK FW : V3J17M10
Board : NUCLEO-H563ZI
Voltage : 3.28V
SWD freq : 8000 KHz
Connect mode: Hot Plug
Reset mode : Software reset
Device ID : 0x484
Revision ID : Rev X
Error: Fail to read Flash Size
Device name : STM32H56x/573
Flash size : 2 MBytes (default)
Device type : MCU
Device CPU : Cortex-M33
BL Version : 0xE4
SFSP Version: v2.5.0
Debug in Low Power mode enabled


Hard reset is performed
-------------------------------------------------------------------
STM32CubeProgrammer v2.19.0
-------------------------------------------------------------------

ST-LINK SN : 004700463434511634313937
ST-LINK FW : V3J17M10
Board : NUCLEO-H563ZI
Voltage : 3.29V
SWD freq : 1000 KHz
Connect mode: Hot Plug
Reset mode : Software reset
Device ID : 0x484
Revision ID : Rev X
Error: Fail to read Flash Size
Device name : STM32H56x/573
Flash size : 2 MBytes (default)
Device type : MCU
Device CPU : Cortex-M33
BL Version : 0xE4
SFSP Version: v2.5.0
Debug in Low Power mode enabled

ST-LINK SN : 004700463434511634313937
ST-LINK FW : V3J17M10
Board : NUCLEO-H563ZI
Voltage : 3.28V
SWD freq : 1000 KHz
Connect mode: Hot Plug
Reset mode : Software reset
Device ID : 0x484
Revision ID : Rev X
Secure Data Provisioning Start. OBK Input file : ./../DA/Binary/DA_Config.obk
Error: Execution of RSS CMD fail with timeout
Error: call_RSSLIB_SetOBKey Failed
Error: ============================================] 100%
OBKey Provisioning failed

  =====
===== Error while executing Configure OBKeys HDPL1-DA config area.
===== See obkey_provisioning.log for details. Then try again.
=====


Question: why this “execution of RSS CMD fail with timeout error” is showing?
 why in obkey_provisioning.sh file has,
"$stm32programmercli" $connect_no_reset -sdp ./Binary/STiRoT_Data.obk
"$stm32programmercli" $connect_no_reset -sdp ./Binary/OEMuRoT_Data.obk

even i am not using the data images and even in given How_to_start_with_STiRoT_OEMuRoT_on_STM32H573  link does not have any support/information for the data.obk files.
 

Jocelyn RICARD
ST Employee
August 19, 2026

Hello ​@Rohit007 ,

if you stay in open state, once requested you must keep BOOT tied to VDD to force the device to boot on RSS.

In this configuration the provisioning should work.

The The STiROT_Data.obk is documented in AN6007 Appendix D

The OEMuROT_Data.obk is not documented but it basically the same usage as STiROT_Data.obk : this is an empty area initialised with zeros in obk to store images related informations : hash and versions.

Best regards

Jocelyn

Rohit007Author
Associate III
August 19, 2026

Hello ​@Jocelyn RICARD,
Thank you for the reply, i have kept the boot0 tied to VDD and ran the provisioning script and i was able to flash the device. now, i am able to see the logs for OEMuROT Bootloader.

[INF] TAMPER Activated
[INF] Flash operation: Op=0x0, Area=0x0, Address=0x0
[INF] Starting bootloader OEMuROT 1.0.0
[INF] Primary image: magic=good, swap_type=0x1, copy_done=0x3, image_ok=0x1
[INF] Scratch: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
[INF] Boot source: primary slot
[INF] Swap type: none
[INF] Primary image: magic=good, swap_type=0x1, copy_done=0x3, image_ok=0x1
[INF] Scratch: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
[INF] Boot source: primary slot
[INF] Swap type: none
[INF] Starting validation of primary slot(s)
[INF] verify counter 0 1000000 1000000
[INF] counter 0 : ok
[INF] hash ref OK
[INF] verify counter 1 1000000 1000000
[INF] counter 1 : ok
[INF] hash ref OK
[INF] Bootloader chainload address offset: 0x28000
[INF] Jumping to the first image slot
���������������������������������������������������������������������������

But, after the bootloader jumps to application fw, the uart is printing the garbage. but as per the tutorial link https://wiki.st.com/stm32mcu/wiki/Security:How_to_start_with_STiRoT_OEMuRoT_on_STM32H573 the mcu should have printed the logs from application fw. which i am not able to get.

Question: why is this happening, does this have anything related to working in open product lifecycle, because the example given in tutorial is for Closed product lifecycle.

Jocelyn RICARD
ST Employee
August 19, 2026

Hello ​@Rohit007 ,

as you have changed the UART configuration in the secure boot because of board change you should have also changed this configuration in the application.

Please check this configuration.

You should get this trace:

======================================================================
= (C) COPYRIGHT 2023 STMicroelectronics =
= =
= User App #A =
======================================================================


=================== Main Menu ============================

Start BootLoader -------------------------------------- 1

Selection :

Best regards

Jocelyn

Rohit007Author
Associate III
August 20, 2026

@Jocelyn RICARD ,
i havent changed the UART settings in secure boot, all the example firmware remains same, which is using the USART1 at PA9 and PA10. also, the i am able to recieve the bootloader data, as i have shared above, but the same OEMiROT_Appli_Trustzone project using the USART1 is not printing the logs that are given in firmware.


I have attached the USART1 configuations from both the projects.  
1. this is from OEMiROT_Boot project.

#define COM_INSTANCE                           USART1
#define COM_CLK_ENABLE() __HAL_RCC_USART1_CLK_ENABLE()
#define COM_CLK_DISABLE() __HAL_RCC_USART1_CLK_DISABLE()
#define COM_TX_GPIO_PORT GPIOA
#define COM_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define COM_TX_PIN GPIO_PIN_9
#define COM_TX_AF GPIO_AF7_USART1

#define COM_RX_GPIO_PORT GPIOA
#define COM_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define COM_RX_PIN GPIO_PIN_10
#define COM_RX_AF GPIO_AF7_USART1

static UART_HandleTypeDef uart_device;
static int32_t USART0_Initialize(ARM_USART_SignalEvent_t cb_event)
{

#if !defined(__DOMAIN_NS)
GPIO_InitTypeDef GPIO_Init;
/* Configure COM Tx as alternate function */
COM_TX_GPIO_CLK_ENABLE();
COM_RX_GPIO_CLK_ENABLE();
COM_CLK_ENABLE();
GPIO_Init.Pin = COM_TX_PIN;
GPIO_Init.Mode = GPIO_MODE_AF_PP;
GPIO_Init.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_Init.Pull = GPIO_PULLUP;
GPIO_Init.Alternate = COM_TX_AF;
HAL_GPIO_Init(COM_TX_GPIO_PORT, &GPIO_Init);

/* Configure COM Rx as alternate function */
GPIO_Init.Pin = COM_RX_PIN;
GPIO_Init.Alternate = COM_RX_AF;
HAL_GPIO_Init(COM_RX_GPIO_PORT, &GPIO_Init);
#endif /* __DOMAIN_NS */
uart_device.Instance = COM_INSTANCE;
uart_device.Init.BaudRate = 115200;
uart_device.Init.WordLength = UART_WORDLENGTH_8B;
uart_device.Init.StopBits = UART_STOPBITS_1;
uart_device.Init.Parity = UART_PARITY_NONE;
uart_device.Init.Mode = UART_MODE_TX_RX;
uart_device.Init.HwFlowCtl = UART_HWCONTROL_NONE;
uart_device.Init.OverSampling = UART_OVERSAMPLING_8;
uart_device.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
uart_device.Init.ClockPrescaler = UART_PRESCALER_DIV1;

/* Initialize COM */
if (HAL_UART_Init(&uart_device) != HAL_OK)
{
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
  1. This is from OEMiROT_Appli_Trustzone project
    HAL_StatusTypeDef  COM_Init(void)
    {
    #if defined(__GNUC__)
    setvbuf(stdout, NULL, _IONBF, 0);
    #endif /* __GNUC__ */

    /* USART resources configuration (Clock, GPIO pins and USART registers) ----*/
    /* USART configured as follow:
    - BaudRate = 115200 baud
    - Word Length = 8 Bits
    - One Stop Bit
    - No parity
    - Hardware flow control disabled (RTS and CTS signals)
    - Receive and transmit enabled
    */
    UartHandle.Instance = COM_UART;
    UartHandle.Init.BaudRate = 115200U;
    UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
    UartHandle.Init.StopBits = UART_STOPBITS_1;
    UartHandle.Init.Parity = UART_PARITY_NONE;
    UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    UartHandle.Init.Mode = UART_MODE_RX | UART_MODE_TX;
    UartHandle.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_RXOVERRUNDISABLE_INIT;
    UartHandle.AdvancedInit.OverrunDisable = UART_ADVFEATURE_OVERRUN_DISABLE;
    UartHandle.FifoMode = UART_FIFOMODE_ENABLE;
    return HAL_UART_Init(&UartHandle);
    }

    #define COM_UART USART1
    #define COM_UART_CLK_ENABLE() __HAL_RCC_USART1_CLK_ENABLE()
    #define COM_UART_CLK_DISABLE() __HAL_RCC_USART1_CLK_DISABLE()

    #define COM_UART_TX_AF GPIO_AF7_USART1
    #define COM_UART_TX_GPIO_PORT GPIOA
    #define COM_UART_TX_PIN GPIO_PIN_9
    #define COM_UART_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
    #define COM_UART_TX_GPIO_CLK_DISABLE() __HAL_RCC_GPIOA_CLK_DISABLE()

    #define COM_UART_RX_AF GPIO_AF7_USART1
    #define COM_UART_RX_GPIO_PORT GPIOA
    #define COM_UART_RX_PIN GPIO_PIN_10
    #define COM_UART_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
    #define COM_UART_RX_GPIO_CLK_DISABLE() __HAL_RCC_GPIOA_CLK_DISABLE()

     

Jocelyn RICARD
ST Employee
August 20, 2026

Hello ​@Rohit007 ,

OK so issue is related to the SystemClock_Config that is using HSE.

HSE frequency is not the same between DK and Nucleo.

So, just update the clocking to correct values and it should work.

You can take one from any example made for Nucleo STM32H563 

Best regards

Jocelyn

Rohit007Author
Associate III
August 21, 2026

@Jocelyn RICARD ,

Thanks again for the support. I can now see UART logs and I’ve successfully flashed the secondary image into the download slot. I have two questions about how the bootloader and field updates behave with security enabled:

  1. Today the application has to explicitly start its bootloader menu before I can flash the secondary image (I use STM32CubeProgrammer over SWD to perform the flash). On non-secure STM32 devices I used to force the chip into the system bootloader by asserting BOOT0 and then flash over I²C in the field. With STiRoT/OEMuROT and security enabled, how can I reproduce that behavior — i.e., force entry to the system bootloader via BOOT0 and perform a field update over a peripheral?
  2. Concerning product lifecycle: once the device moves beyond the OPEN state, do I still need to tie BOOT0 to VDD to allow flashing? If not, how are field updates expected to work in later lifecycle states?
Jocelyn RICARD
ST Employee
August 21, 2026

Hello ​@Rohit007 ,

yes on STM32H5 you can use the system bootloader even when the device is closed. This is because through TrustZone you can provide visibility only to the non secure.Now this jump to the system bootloader needs to be done from the application, the same way you would jump in your own loader for instance.

Now I wouldn’t advice using the system bootloader but rather your own loader.

BOOT0 is only useful in OPEN state.

In provisioning state the device boots on the system bootloader whatever BOOT0 value

In other states, the device boots in the user flash whatever BOOT0 value.

Best regards

Jocelyn

 

 

Rohit007Author
Associate III
August 25, 2026

@Jocelyn RICARD ,

I tested the STM32 system bootloader over I²C using a Linux-based embedded master, with the MCU acting as the slave. After jumping to the system bootloader, I attempted to detect the device using i2cdetect, but the MCU consistently resets. This behavior is observed in both OPEN and CLOSED product states.

Based on this observation, it appears that the system bootloader over I²C may not be usable for firmware upgrades when TrustZone is enabled.

Questions:

  1. Is this behavior expected, or could I be missing something in my implementation?
  2. If the system bootloader cannot be used in this scenario, does ST provide any example or reference implementation of a loader that supports both secure boot and firmware upgrade?
Rohit007Author
Associate III
August 26, 2026

Hi @Jocelyn RICARD,

Gentle reminder—could you please share any available source or reference for this?

Additionally, is it possible to implement the I²C-based bootloader logic within OEMuROT_Boot?