cancel
Showing results for 
Search instead for 
Did you mean: 

STM32U0 Attempting to reach RDP level 1, stuck at RDP level 0 with OPTVERR bit HIGH

DJens
Associate II

I'm struggling with entering RDP level 1 using the ST Cubemx code examples.  I am stuck with OPTVERR bit set and never being successful in getting FLASH_OPTR RDP bits set to 0xBB AND written into flash so that it boots using 0xBB and not 0xAA.  (I can write 0xBB into the register, but 0xBB does not reach flash.)  The programmatic sequence seems straightforward, but I can't get the low level/HAL libraries to do what the examples claim they do.

From a practical standpoint, all I really want is a binary image I can use to program parts (and be able to read back so I can verify Flash contents.   My assumption is that a binary image at RDP level 1 will not allow read verification of the programmed data so to ensure the initial image is 'readable so the device programmer can verify it', I'm trying to enter RDP level 1 programmatically (so my binary image is initially readable but immediately sets RDP 1 when it runs the first time.)

If there is another way to generate a binary image that can be read back after programming but not read back once 'used in application', please let me know.  I either need to programmatically enter RDP or generate a programmer verifiable image that runs in RDP.

Through my efforts, I wind up with OPTVERR being set even though the FLASH_OPTR RDP bits are at 0xAA after hardware SHUTDOWN and WAKE cycle. I'm sure this is a clue.

Thanks for any help!

 

More detail:

Basic problem:  Cannot get FLASH_OPTR bits 0xBB to be written to FLASH, therefore RDP never reaches level 1.  I'm using my code but with the RDP sequence plucked from CubeMx examples.  Along the way, I found OPTVERR is being set immediately on reset.  I have no idea why this is happening.  If I connect a debugger I can see this bit set in the FLASH_SR register and I can clear it in the debugger by writing a one to this bit but at reset this bit gets set again.

Regardless of the setting of this bit (which causes the CubeMx code to never set the OPTSTRT bit) I have attempted manually (through the debugger) to set the appropriate bits and manually walk through the sequence to set the RDP bits to 0xBB (so they land in the flash and wind up in the registers at the next wakeup from shutdown.  I go through the motions but the RDP=0xBB never gets written to flash.  (This includes effectively doing " SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT)" to no avail.

Although I speak of the debugger, when I run this code on bare silicon (the debugger unplugged from the tag-connect connector), the code insists on never entering RDP level 1.

Here is the code that I'm using to implement RDP level 1, basically ripped from the CubeMx example for doing this.

///////////////////////////////////////

//Revision 1.0.3 start:  read protect memory by setting RDP to level 1.
// Only write to flash if RDP is not set to level 1.
    FLASH_OBProgramInitTypeDef OptionsBytesInit={0};
  // read option bytes
     HAL_FLASHEx_OBGetConfig(&OptionsBytesInit);
  /* Choose option byte type. (low level library uses this to determine which bytes to write)*/
      OptionsBytesInit.OptionType = OPTIONBYTE_RDP;
      printf("\n              OPTION BYTE = %lX\n",(unsigned long)OptionsBytesInit.RDPLevel);    (comment:  This always returns 0xAA, never the 0xBB that I expect following the SHUTDOWN to ACTIVE wakeup sequence that happens after this code runs.)

      if (OptionsBytesInit.RDPLevel == OB_RDP_LEVEL_0)
      {
    /* Unlock Flash Control register and Option Bytes */
         printf("\n              Unlocking flash\n");
       HAL_FLASH_Unlock();
       printf("\n              Unlocking option bytes\n");

       HAL_FLASH_OB_Unlock();
   /* Configure option byte parameters values.*/
         OptionsBytesInit.RDPLevel = OB_RDP_LEVEL_1;
         printf("setting RDP level 1\n");
         printf("\n              OPTION BYTE = %lX\n",(unsigned long)OptionsBytesInit.RDPLevel);       (comment: 
his always returned 0xBB as desired.)

    /* Program Option Bytes */
         HAL_FLASHEx_OBProgram(&OptionsBytesInit);
    //HAL_FLASH_OB_Launch();    // I don't do this because my code enters SHUTDOWN mode before it is woken up for the next pass through this function.
         HAL_FLASH_OB_Lock();
         HAL_FLASH_Lock();   
  }
   //////////////Revision 1.0.3 end
.
.
.
HAL_PWR_EnterSHUTDOWNMode();                  // enter final command to turn off processor.

 

 

More detail on the OPTVERR:

PART of my problem is that when attempting to write new values into the OB registers, the HAL follows a path into HAL_StatusTypeDef HAL_FLASHEx_OBProgram(FLASH_OBProgramInitTypeDef *pOBInit)   this is located in stm32u0xx_hal_flash_ex.c

Toward the end of this function is the following code:
 /* Wait for last operation to be completed */
  status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);  (this status returns 0x8000 indicating the OPTVERR bit is set)
  if (status == HAL_OK) comment:  With status = 0x8000, CR_OPSTRT never gets set
  {
    /* Set OPTSTRT Bit */
    SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);

    /* Wait for last operation to be completed */
    status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
    /* If the option byte program operation is completed, disable the OPTSTRT Bit */
    CLEAR_BIT(FLASH->CR, FLASH_CR_OPTSTRT);
  }

  /* Process Unlocked */
  __HAL_UNLOCK(&pFlash);
  /* return status */
  return status;
}

13 REPLIES 13

Hello @DJens ,

 

I guess your marking is ES32U031 something. ES means Engineering Sample.

I checked on a Nucleo STM32U031R8.

I don't think bootloader version read by programmer is the good one any way.

The address of bootloader version can be found in AN2606 Rev 64 p42: 0x1FFF37FE

And value should be 0xB0. This is the one I see on the Nucleo board.

JocelynRICARD_0-1727279107797.png

So, I would suggest getting recent parts that are not engineering samples.

Best regards

Jocelyn

 

 

 

 

Thank you Jocelyn:  I would obtain production parts but they are not in production yet.  I will work with my sales folks to obtain real production parts  (STM32U031F8P6)

I confirmed the bootloader version by reading the flash location in STM32CubeProgrammer.  I confirmed that most of my parts have empty flash at this location but I did find one of the parts I have mounted shows a valid 0xB1 in the bootloader version location.  Now I'm not using the bootloader for anything, but I don't know what an empty bootloader version implies as far as the RDP issue I'm having.

All but one of my parts shows this (and the STM32CubeProgrammer cannot modify the option bytes either)

DJens_0-1727280984599.png

I have one part that shows a valid bootloader version in flash.  I will continue testing to confirm if this one will allow option byte changes.  I need to be very careful not to lock up this part because its the only one that might work!

DJens_1-1727281100490.png

All parts are marked like this:

DJens_2-1727281156574.png

 

Let me close with this question:  All I seek is to program parts and verify they have been programmed correctly (which requires reading back the flash contents) but results in RDP level one after programming.  Programming will be done by a distributor programming parts offline.  What is the standard practice for delivering a single binary image for programming that accomplishes this?  I do not know what type of programmer the distributor will use, so I can't depend on them using STM tools with scripts.  is there an app note that covers 'distributing binary images which are read protected'?

Thanks!

 

 

 

Hello @DJens ,

you need to understand what will be the capabilities of the programmer your distributor will use.

The STM32 option bytes programming using production programmers is something quite common, so there shouldn't be any issue here.

As far as I know, there is no specific documentation on this topic. I guess this because it is not under ST's control.

Besides requesting option byte programming with programmer in production you can check proper setting in your firmware. If option bytes don't have the expected values, you can either force good value, erase everything, go in while(1) loop. Anything that fits your requirements.

One more point. On older STM32 it was possible to include the option bytes in the firmware hex file because option bytes were mapped in specific location of system flash.

On the STM32U0 this is no more the case to improve robustness of the protection.

Best regards

Jocelyn

Panic over.

I received production silicon today.  Swapping out the EC silicon resulted in expected RDP=level 1 operation, so the main issue is resolved.

Thanks for the help,

Doug