Skip to main content
Associate
July 28, 2026
Question

Reading FLASH_EXT_USER_BASE gives always 0 from User Application after OEMiRoT jumped with EXITHDPLIB_PFUNC->JumpHDPLvl2

  • July 28, 2026
  • 1 reply
  • 23 views

On the STM32C542RC, this is my current FLASH layout:

-- OEMiRoT flash layout:
-- Bootloader : 0x08000000 .. +0x10000
-- Keys : +0x10000 (0x2000)
-- NV counters : +0x12000 (0x2000)
-- Primary app slot : 0x8014000 size=0x16000
-- App code (post-hdr) : 0x8014400 size=0x15c00
-- Secondary app slot : 0x802a000 size=0x16000
-- OEMiRoT option bytes to program:
-- HDP1_END = 0x9 WRPSGn1 = 0xfe00

Everything is working well (update of user application, boot, etc...) (MCUBOOT_USE_HASH_REF is not defined).

But I have an issue:

I want to use the external User Data Flash at the address FLASH_EXT_USER_BASE 0x08400000UL, requiring the option byte EDATA_EN = 0. When I read from that address in the User Application, I only read zeroes (RAZ) -- simple as `*(const int *)FLASH_EXT_USER_BASE == 0`, so this feels like the cause is some sort of HDP. By the way, the writes do work (at least when the MCU is reset, as STM32CubeProgrammer did read the data I wrote to that address).

Note: I get RAZ only from User Application after OEMiRoT jumped, while I get a correct read non-zero value if I flash the User Application alone on the MCU. The problem is the combination OEMiRoT+User App.

I tried different things: enabling/invalidating/disabling cache (with ICACHE and/or MPU), setting HDPEXT to 0

HAL_FLASH_ITF_Unlock(mx_flash_gethandle()->instance);

HAL_FLASH_ITF_SetHDPExtArea(mx_flash_gethandle()->instance, HAL_FLASH_BANK_1, 0);

HAL_FLASH_ITF_SetHDPExtArea(mx_flash_gethandle()->instance, HAL_FLASH_BANK_2, 0);

HAL_FLASH_ITF_Lock(mx_flash_gethandle()->instance);

(but from what I understand the HDPEXT can only be incremented, and is reset only at reboot). I also made sure that the code reading at that address is executed in privileged mode.

 

The code base I'm using is this ST example https://github.com/STMicroelectronics/STM32CubeC5/tree/main/examples/advanced/rot/oemirot_dualslot/NUCLEO-C542RC which uses this HAL2 branch of mcuboot: https://github.com/STMicroelectronics/stm32-mw-mcuboot/tree/hal2 , but I do not find any evidence of HDPEXT changes.

 

So I was wondering if the cause could be EXITHDPLIB_PFUNC->JumpHDPLvl2, which is used to jump to user application. RM0522 says:

User calls JumpHDPLvl2 to:
• Close user Flash HDPL1 area by incrementing HDPL to 2
• Jump to the reset handler embedded within the Vector Table which address is passed as input parameter
After closing HDPL1, JumpHDPLvl2 enables the MPU region provided as input parameter. Once the MPU is enabled, the function sets the SP to the address provided by the passed Vector Table and jumps to the Reset Handler function supported by the Vector Table too. JumpHDPLvl2 does not set the new vector table. On successful execution, the function does not return and does not push LR onto the stack.

And the MPU region used for the jump is the following one:

HAL_CORTEX_MPU_REGION_1,
{
0x8014400,
0x802a000 - 1U,
HAL_CORTEX_MPU_REGION_ONLY_PRIV_RO,
HAL_CORTEX_MPU_EXECUTION_ATTR_ENABLE,
MPU_MEM_ATTR_CODE_IDX // which is using attribute HAL_CORTEX_MPU_NORMAL_MEM_WT_RA
}

In the User Application I can read nonzero values from the App Slot 2.

To be honnest I’m kinda lost here. I do not know what kind of security thing I’m not following in order to read from FLASH_EXT_USER_BASE without RAZ, and I don’t know where to look. I tried to read from that address directly in the OEMiRoT too:

  • in `boot_platform_init(), before `SECURITY_ApplyRunTimeProtections()`, the value is read correctly (non-zero)
  • after `SECURITY_ApplyRunTimeProtections()`, the read causes a HardFault. And if I insert the read just at the very beginning of that function (before everything else !) I get also a HardFault. So I guess the compiler is doing some reordering and therefore I cannot point out a single point of failure. All I can say is that in OEMiRoT, reading FLASH_EXT_USER_BASE never returns 0.

 

I’m aware that MCUBoot features Data slots, but I don’t want to use these as I’m already short in main FLASH size (256KB), so using the additional 64KB user data Flash would be really great. I’m just storing non-sensible information.

 

Any help is very welcomed.

1 reply

Associate
July 29, 2026

I have some news.

The HardFault from reading FLASH_EXT_USER_BASE in OEMiRoT is because non-defined MPU areas will HardFault, configured by this code:

HAL_CORTEX_MPU_Enable(HAL_CORTEX_MPU_HARDFAULT_NMI_ENABLE, HAL_CORTEX_MPU_ACCESS_FAULT_ALL);

So it’s expected.

My issue seems to me like a HDP protection, somehow making FLASH_EXT_USER_BASE read-as-zero and write-ignored (RAZ/WI). So let’s drop anything not related to MPU and CACHE.

 

In the User Application, after the jump from OEMiRoT, I just tried to read all data in FLASH_EXT_USER_BASE. And it appears that the first 0x8000 Bytes are RAZ/WI, while the rest 0x8000 is correctly read as non-zero values. Thus the bank 1 is somehow HDP protected.

From the RM0522, section 6.5.6:

The FLASH can be configured to have 64-Kbyte (or 48-Kbyte if EDATA_EN is set) memory area to store data and emulate EEPROM (see Section 6.3.10: FLASH data area). These pages can not be protected by HDP or WRPGS whatever the setting of EDATA_EN.

But…. in practice, this statement is wrong, as my Option Bytes `HDP1_STRT = 0; HDP1_END = 0x9; HDP2_STRT = 1; HDP2_END = 0` should only hide the first 10 pages of the FLASH_BASE (so 0x08000000 .. 0x08014000 included), but it also hides FLASH_EXT_USER_BASE bank 1 (so 0x08400000 .. 0x08408000 included).

I think this is either a bug, or a incorrect statement from the RM0522 reference manual. I did check the erratasheet ES0676, but it does not say anything about HDP. Or there’s something I really don’t understand.

It would be great if someone can reproduce this issue.