0
votes

I'm playing with RDP Levels on a STM32H743 (Nucleo board, STM32CubeIDE).

Here is the code I've tested:

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART3_UART_Init();

  OBInit.Banks     = FLASH_BANK_1;
  HAL_FLASHEx_OBGetConfig(&OBInit);
  RdpLevel = OBInit.RDPLevel;

  BSP_PB_Init(BUTTON_USER,BUTTON_MODE_GPIO);
  BSP_LED_Init(LED1);

  if ( RdpLevel == OB_RDP_LEVEL_0 )
  {
    // toggle LED1 to show RDP level
    BSP_LED_Toggle(LED1);

    /* Wait for User push-button press before starting the Communication */
    while (BSP_PB_GetState(BUTTON_USER) != GPIO_PIN_SET);

    // program OB
    HAL_FLASH_OB_Unlock();
    HAL_FLASH_Unlock();

    OBInit.OptionType = OPTIONBYTE_RDP;
    OBInit.RDPLevel   = OB_RDP_LEVEL_1;
    HAL_FLASHEx_OBProgram(&OBInit);

    /* Start the Option Bytes programming process */
    if (HAL_FLASH_OB_Launch() != HAL_OK)
    {
        /* User can add here some code to deal with this error */
        while (1)
        {
            BSP_LED_Toggle(LED1);
            HAL_Delay(200);
        }
    }

  }
  else
  {
        BSP_LED_Toggle(LED2);

      /* Wait for User push-button press before starting the Communication */
        while (BSP_PB_GetState(BUTTON_USER) != GPIO_PIN_SET);


        // program OB
        HAL_FLASH_OB_Unlock();
        HAL_FLASH_Unlock();

        OBInit.OptionType = OPTIONBYTE_RDP;
        OBInit.RDPLevel   = OB_RDP_LEVEL_0;
        HAL_FLASHEx_OBProgram(&OBInit);

        /* Start the Option Bytes programming process */
        if (HAL_FLASH_OB_Launch() != HAL_OK)
        {
            /* User can add here some code to deal with this error */
            while (1)
            {
                BSP_LED_Toggle(LED2);
                HAL_Delay(200);
            }
        }
  }
  while (1)
  {
  }
}

The switch to Level 1 works fine. I see that the Level is taken into account (at next reset the debugger is not working any more). The LED shows also the level.

But when I try to come back to Level 0 I'm not sure what's going on, since I cannot debug: I know a full erase of the flash occurs. But I expect that after that I'm able to connect through the debugger. but it's not the case and the software doesn't seem to run anymore.

Is there something wrong in this piece of code ?

EDIT: i tried to power off the board after the regression

3
Powering off the board must include also disconnecting any communication cables like SWD or serial debug which could inject enough current to the keep the processor state partially alive. Additionally you should make your code read back the changed value and print it, it's quite possible you are not accomplishing all the steps of the change, for example it is typically necessary to write the value and its complement and it is unclear if the library function you are trying to use does all of that for you.Chris Stratton
Also try using your debugger and its software to change the protection value and trigger the mass erase. You will still need to power cycle with all cables disconnected afterwards, then upon reconnection you should be back in - at least unless you have accomplished a permanent change.Chris Stratton

3 Answers

2
votes

Apparently it was due to the bug described in the errata sheet "Option byte loading can be done with the user wait-state configuration". I changed the wait state number in my software from 4 to 7 and it fixed the issue. I can switch back to Level 0 without problem.

0
votes

The answer is very easy and explained in the STM32 documentation. When you change RDP from level 1 to level 0 the Power On Reset is needed. So you need to disconnect the power, and connect it again.

0
votes

I know this is an older post but... I have spent quite some time on this in the past. If you set RDP correctly to level 0, the CPU will erase all the flash, clear the RDP level to zero then reset itself. However, if a debugger like ST-Link is connected, it will erase the flash, set RDP to level zero, then the CPU will hang. A manual reset/power cycle is required. This is documented in the reference manual somewhere from memory. So, the RDP procedure with an automatic reset works fine in production code where no debugger is attached, we use this daily.