Skip to main content
_EFrie
Senior
January 8, 2026
Solved

OBK unusable in non TZ STM32H5

  • January 8, 2026
  • 4 replies
  • 762 views

At present, as of the last Hal version as far as I know, obk cannot be used in a non trust zone project.

FLASH_TYPEPROGRAM_QUADWORD_OBK fails because the NS bits aren't set, among other issues.

Is this by design, IE obk can't be used by non TZ, or is this just simply not a completed or fully fixed feature?

 

Here is what I'm doing

I've edited HAL_FLASHEx_Erase like

#if defined (FLASH_SR_OBKERR)
 else if ((pEraseInit->TypeErase&~(FLASH_NON_SECURE_MASK)) == FLASH_TYPEERASE_OBK_ALT)
 {
 /* OBK erase to be done */
 FLASH_OBKErase();

 /* Wait for last operation to be completed */
 status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
 }
#endif /* FLASH_SR_OBKERR */

And my code is:

int keyStorageSavePrivate(char* key) {
 uint32_t status;
 uint32_t len = strnlen(key, KEY_STORAGE_SIZE - 16);
 int ret = 0;
 static uint32_t FlashWord[4];
 if (len >= KEY_STORAGE_SIZE - 16) {
 return 1;
 }
 len += 1; // Add string 0
 HAL_FLASH_Unlock();
 HAL_FLASHEx_OBK_Unlock();
 if (len & 0b1111) {
 len &= ~(0b1111);
 len += 16;
 }
 uint32_t Address = (uint32_t)private_key;
 uint32_t EndAddress = Address + len;
 const char* next = key;


 static uint32_t SectorError;
 static FLASH_EraseInitTypeDef EraseInitStruct;
 pFlash.ProcedureOnGoing = FLASH_NON_SECURE_MASK;
 FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);//Clear
 EraseInitStruct.TypeErase = FLASH_TYPEERASE_OBK_ALT | FLASH_NON_SECURE_MASK;
 if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) {
 ret = 6;
 goto lock;
 }

 while (Address < EndAddress) {
 memcpy(FlashWord, next, 16);
 status = HAL_FLASH_Program(
 FLASH_TYPEPROGRAM_QUADWORD_OBK | FLASH_NON_SECURE_MASK, Address,
 (uint32_t)FlashWord);
 if (status == HAL_OK) {
 Address = Address + 16; /* increment for the next Flash word*/
 next += 16;
 } else {
 /* Error occurred while programming */
 ret = 2;
 break;
 }
 }
 if (ret == 0) {
 if (HAL_FLASHEx_OBK_Swap(FLASH_OBK_SWAP_OFFSET_ALL) != HAL_OK) {
 ret = 3;
 }
 }
 HAL_ICACHE_Invalidate();
 lock:
 HAL_FLASH_Lock();
 HAL_FLASHEx_OBK_Lock();
 if (memcmp(private_key, key, len)) {
 ret = 3;
 }
 return ret;
}
Best answer by Jocelyn RICARD

Hello @_EFrie ,

If you point on secure peripheral alias (0x5...) this means you have -mcmse compilation flag enabled.

You can see how it works in CMSIS : stm32h573xx.h. This is not related to HAL.

Regarding the OBK address (FLASH_OBK_BASE), I could see in some code that a non trustzone code what forcing usage of FLASH_OBK_BASE_S. I need to double check if both FLASH_OBK_BASE_S and FLASH_OBK_BASE_NS are accessible with TrustZone disabled.

Best regards

Jocelyn

4 replies

Andrew Neil
Super User
January 8, 2026
A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
_EFrie
_EFrieAuthor
Senior
January 9, 2026

I've looked at that link quite a few times, but the OP ended up using a secure zone to do this.

Jocelyn RICARD
ST Employee
January 9, 2026

Hello @_EFrie ,

Please remove FLASH_NON_SECURE_MASK from your code, it should work.

This non secure mask is used only when TZ is enabled, and when executing in secure, to be able to write in non secure flash.

Best regards

Jocelyn

 

_EFrie
_EFrieAuthor
Senior
January 9, 2026

I couldn’t get it to work at all, are you sure? I just went through this with Hal. The problem is that without tweaking it tries to use the 0x5000 secure flash registers which just doesn’t write any flash.

_EFrie
_EFrieAuthor
Senior
January 9, 2026

Just to recap, I just went through this on regular flash, nothing would erase or write until I made sure flash_ns with 4000 base was being used. The way the obk library is presently written only uses the secure 5000 flash base.

Jocelyn RICARD
Jocelyn RICARDBest answer
ST Employee
January 9, 2026

Hello @_EFrie ,

If you point on secure peripheral alias (0x5...) this means you have -mcmse compilation flag enabled.

You can see how it works in CMSIS : stm32h573xx.h. This is not related to HAL.

Regarding the OBK address (FLASH_OBK_BASE), I could see in some code that a non trustzone code what forcing usage of FLASH_OBK_BASE_S. I need to double check if both FLASH_OBK_BASE_S and FLASH_OBK_BASE_NS are accessible with TrustZone disabled.

Best regards

Jocelyn

_EFrie
_EFrieAuthor
Senior
January 15, 2026



If you point on secure peripheral alias (0x5...) this means you have -mcmse compilation flag enabled.

You can see how it works in CMSIS : stm32h573xx.h. This is not related to HAL.


 I'm unclear on your meaning.  If I follow hal to FLASH_Program_QuadWord_OBK it directly chooses depending on IS_FLASH_SECURE_OPERATION() which depends on pFlash.ProcedureOnGoing which can only be set by somewhere setting a non secure flag in hal code.

See stm32h5xx_hal_flash.c around line 876

 reg_cr = IS_FLASH_SECURE_OPERATION() ? &(FLASH->SECCR) : &(FLASH_NS->NSCR);
 reg_obkcfgr = IS_FLASH_SECURE_OPERATION() ? &(FLASH->SECOBKCFGR) : &(FLASH_NS->NSOBKCFGR);
_EFrie
_EFrieAuthor
Senior
January 15, 2026

The manual 7.11.16 FLASH non-secure OBK configuration register
(FLASH_NSOBKCFGR) says 

Register is only available when TZ_STATE = 0xC3. This register is non-secure. It can be
read and written by both secure and non-secure accesses. This register can only be
accessed by privilege code.

Whatever that is supposed to mean, it seems contradictory. 

_EFrie
_EFrieAuthor
Senior
January 20, 2026

This ends up being related to the -mcmse flag being set, in Crossworks this is the `v8M Has CMSE Instructions` value.  This does have the effect of not compiling in FLASH_OBK_HDPL3XX So that has to be added manually.