cancel
Showing results for 
Search instead for 
Did you mean: 

How to program RDP OEM1 keys from the application code

Artur IWANICKI
ST Employee

Summary 

Recent STM32 series have an interesting feature called readout protection with password. It is possible to configure it using the SWD/JTAG debug interface or within user application code.

The theory and an example of the first method is fully described in one of our MOOC videos [MOOC STM32U5 Keyed RDP].

In this article, I provide sample code snippets allowing OEM1 keys to set up and reset from user code. The STM32U575 MCU is used and the application is tested on a NUCLEO-U575ZI-Q board. It can be ported to any other STM32 MCU that has a Keyed RDP mechanism.

Code snippets - main.c file

OEMKEYs are stored within the option bytes area, so it is necessary to declare a variable to store option bytes settings. It can be done within the user code private variables area. The best practice is to initialize the structure with "0" values to avoid having random values within structure fields.

/* USER CODE BEGIN PV */
FLASH_OBProgramInitTypeDef OptionsBytesInit = {0};

Before accessing option bytes, we need to unlock the access to the FLASH and OptionBytes area.

/* Unlock Flash Control register and Option Bytes */
HAL_FLASH_Unlock();
HAL_FLASH_OB_Unlock();

To be sure what the current state of readout protection is, we need to read and store it in our already declared variable OptionsBytesInit. More information about all available fields of HAL_FLASHEx_OBGetConfig structure you can refer to stm32xxx_hal_flash.h file.

/* Get the OB initial status */
HAL_FLASHEx_OBGetConfig(&OptionsBytesInit);

In case there is no readout protection, we can provide OEM1 keys. For this, we update the recently read Option Bytes on the field RDPKEY->RDP_KEY_OEM1->Key1, Key2. After filling updated data, the, we need to program them within the option bytes area (line 8 below). In case of no issues, we should reload them by triggering the POR reset. In our case, the HAL_FLASH_OB_Launch() function is proposed for that.

In the code, you can see a verification whether the operation has been performed successfully (HAL_OK returned value). In case of an issue, an empty "else" branches have been added for own development (LED blink, printf messages can be used there).

if(OptionsBytesInit.RDPLevel == OB_RDP_LEVEL_0)
{
   OptionsBytesInit.OptionType = OPTIONBYTE_RDPKEY;
   OptionsBytesInit.RDPKey1 = 0x12345678;
   OptionsBytesInit.RDPKey2 = 0x87654321;
   OptionsBytesInit.RDPKeyType = OB_RDP_KEY_OEM1;
   /* Program Option Bytes */
   if(HAL_OK == HAL_FLASHEx_OBProgram(&OptionsBytesInit))
   {
     /* Launch Option Bytes Loading */
     HAL_FLASH_OB_Launch();
   }
   else
     //Issues with OEMKEY1 programming
}
else
  //No conditions (RDP0) met to set OEMKEY1 - abort condition

In case we would like to add an option to disable OEM1 keys, we can use the above code snippets with RDPKey1 and RDPKey2 set to 0xFFFFFFFF. It could look as shown below:

if(OptionsBytesInit.RDPLevel == OB_RDP_LEVEL_0)
{
   OptionsBytesInit.OptionType = OPTIONBYTE_RDPKEY;
   OptionsBytesInit.RDPKey1 = 0xFFFFFFFF;
   OptionsBytesInit.RDPKey2 = 0xFFFFFFFF;
   OptionsBytesInit.RDPKeyType = OB_RDP_KEY_OEM1;
   /* Program Option Bytes */
   if(HAL_OK == HAL_FLASHEx_OBProgram(&OptionsBytesInit))
   {
     /* Launch Option Bytes Loading */
     HAL_FLASH_OB_Launch();
   }
   else
     //Issues with OEMKEY1 resetting
}
else
  //No conditions (RDP0) met to reset OEMKEY1 - abort condition

Related links

Version history
Last update:
‎2025-04-25 4:26 AM
Updated by: