cancel
Showing results for 
Search instead for 
Did you mean: 

32F417 - the definitive way to set RDP2?

PHolt.1
Senior III

Is this the right way?

 

if (FLASH_OB_GetRDP() != OB_RDP_LEVEL_2)
{
   HAL_FLASH_Unlock();  // Unlock the flash memory
   HAL_FLASH_OB_Unlock(); // Unlock the option bytes
   *(__IO uint8_t*) OPTCR_BYTE1_ADDRESS = OB_RDP_LEVEL_2;  // Set RDP2
   HAL_FLASH_OB_Launch();  // Activate it
   HAL_FLASH_OB_Lock();
   HAL_FLASH_Lock();
}

 

You have to test if RDP2 is already set otherwise you get a hard fault - and a bricked unit unless you have some recovery mode.

The above uses existing ST-provided Cube IDE code. There are other examples which are more direct e.g.

HAL_FLASH_Lock() is written as FLASH->CR |= FLASH_CR_LOCK but it is the same code. Lots of people going around in circles e.g.

https://community.st.com/t5/stm32-mcus-embedded-software/what-causes-hal-flash-ob-unlock-to-call-hardfaulthandler-it/td-p/59977/page/3

Can anyone see a problem with my code? I've tested it and it appears to set RDP2 (the debugger stops working with error 19 or some such) but not yet with the IF statement around it, because each time I do it I blow away one board

1 ACCEPTED SOLUTION

Accepted Solutions

> Is this the right way?

Yes, the code written will work, but you don't need to unlock flash to write option bytes.

FLASH_OB_GetRDP is not intended to be called by the user directly. You can use HAL_FLASHEx_OBGetConfig if you want to follow HAL rules.

Launching option bytes does not reset the CPU.

Should be able to test without bricking a chip by setting it to RDP1 instead of RDP2.

 

This sets RDP1 the HAL way. (You can change it to RDP2 in your code, I don't want to post code that bricks chips.)

void SetRDP1() {
  FLASH_OBProgramInitTypeDef config = {0};
  HAL_FLASHEx_OBGetConfig(&config);
  if (config.RDPLevel != OB_RDP_LEVEL_1)
  {
     HAL_FLASH_OB_Unlock();
     config.OptionType = OPTIONBYTE_RDP;
     config.RDPLevel = OB_RDP_LEVEL_1;
     HAL_FLASHEx_OBProgram(&config);
     HAL_FLASH_OB_Launch();
     HAL_FLASH_OB_Lock();
  }
}

 

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

4 REPLIES 4
Pavel A.
Evangelist III

> You have to test if RDP2 is already set otherwise you get a hard fault

Because setting RDP2 prevents change of option bytes. This is documented.

 

 

PHolt.1
Senior III

Sure. But do you think the above code is right? In particular, in the right order.

There is also a question mark regarding whether setting RDP2 resets the CPU. Some found it does. The above code does not do that for me, which is better.

> Is this the right way?

Yes, the code written will work, but you don't need to unlock flash to write option bytes.

FLASH_OB_GetRDP is not intended to be called by the user directly. You can use HAL_FLASHEx_OBGetConfig if you want to follow HAL rules.

Launching option bytes does not reset the CPU.

Should be able to test without bricking a chip by setting it to RDP1 instead of RDP2.

 

This sets RDP1 the HAL way. (You can change it to RDP2 in your code, I don't want to post code that bricks chips.)

void SetRDP1() {
  FLASH_OBProgramInitTypeDef config = {0};
  HAL_FLASHEx_OBGetConfig(&config);
  if (config.RDPLevel != OB_RDP_LEVEL_1)
  {
     HAL_FLASH_OB_Unlock();
     config.OptionType = OPTIONBYTE_RDP;
     config.RDPLevel = OB_RDP_LEVEL_1;
     HAL_FLASHEx_OBProgram(&config);
     HAL_FLASH_OB_Launch();
     HAL_FLASH_OB_Lock();
  }
}

 

If you feel a post has answered your question, please click "Accept as Solution".
PHolt.1
Senior III

OK, very many thanks TDK. So we have

if (FLASH_OB_GetRDP() != OB_RDP_LEVEL_2)
{
   HAL_FLASH_OB_Unlock(); // Unlock the option bytes
   *(__IO uint8_t*) OPTCR_BYTE1_ADDRESS = OB_RDP_LEVEL_2;  // Set RDP2
   HAL_FLASH_OB_Launch();  // Activate it
   HAL_FLASH_OB_Lock();
}

I tend to use bits of MX-generated ("HAL") code as required. ST do like to use structs of structs and typedefs of structs or more structs