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;
}

1 ACCEPTED SOLUTION

Accepted Solutions

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

 

 

 

 

View solution in original post

13 REPLIES 13
Jocelyn RICARD
ST Employee

Hello @DJens ,

I'm sorry, no time to dig into your message.

Just one point, did you try the example provided in the CubeFW U0 that is just about setting RDP

STM32Cube_FW_U0_V1.1.0\Projects\NUCLEO-U083RC\Examples\FLASH\FLASH_ChangeOptionBytes\

Best regards

Jocelyn

Thanks for the quick response.  The code I am using is lifted verbatim from the example you mention.  I do not have a development board and I'm working with my production ready PCB, so I can't use unmodified example code.  However - my code uses the same calls in the same sequence to the same (stm32u0xx_hal) library as my admittedly long post explains.

Doug

Pavel A.
Evangelist III

Pardon jumping in... @DJens can you order the NUCLEO-U083RC board and run the original unmodified example? Just $11 and the nucleo is yours. With a custom board and modified code chances for support are lesser. Read the instruction to the original example carefully. 

 

TDK
Guru

If you leave in the call to HAL_FLASH_OB_Launch, does it get set?

Maybe shutdown mode is never getting entered.

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

Hello @DJens ,

I made a quick test with the Nucleo.

Not changing anything in the code.

I load the code into the target. Perform a power on reset so that no debug connection is detected.

The terminal displays RDP0. I press the button. After OBLaunch, the chip resets and firmare is launched with RDP1 set.

Then when pressing again on the button to set RDP0, I don't reach the OBLaunch. Device is stuck. After POR, I have a clean device.

I changed the code to remove the OBLaunch after setting RDP1.

Firmware goes on as expected without having RDP1 not completely set yet. I can connect with programmer and see the code.

After POR, RDP1 is properly set.

So, I suspect your powerdown sequence does not really go to power down.

Could you check DBGMCU_CR and set it to 0.

Best regards

Jocelyn

 

DJens
Associate II

TDK:  Thanks for the hint.  I should have mentioned that point.  Calling HAL_FLASH_OB_Launch does not change behavior (RDP remains at level 0).

I should clarify one of my comments in the original post:

WAS:  ...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.) 

CORRECTED: ...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 OptionsBytesInit.RDPLevel structure but the call which follows to HAL_FLASHEx_OBProgram(&OptionsBytesInit); does not ultimately result in 0xBB reaching flash - and be reloaded at the next shutdown/wake as my part is always powered but I place it into shutdown to be woken up by a GPIO pin.  The datasheet implies this is the same as a power cycle for reloading the RDP bits, therefore the problem seems to be that the 0xBB is not being written to flash.

I also sense the OPTVERR bit being set must be a huge clue, but I can't understand how this would ever get set since the HARDWARE calculates and stores the bits and their complementary values.  I can clear this bit in code but it comes back on the next shutdown/wake cycle.

 

 

> Thanks for the hint.  I should have mentioned that point.  Calling HAL_FLASH_OB_Launch does not change behavior (RDP remains at level 0).

In that case, it sounds like your option byte configuration in flash is invalid, in which case the default options will be set (but the registers will still hold their bogus values). You can verify this by looking at the option byte registers after startup and ensuring the complimentary words are consistent.

To get out of this state, you will need to write ALL of the option bytes, then apply them with OBL_LAUNCH or POR. Only writing RDP will not fix other option bytes which are invalid and you will be stuck in this state. I'd recommend setting them all to their production values as given in the RM.

After that, the code you wrote will work (provided you actually get into shutdown) as verified by @Jocelyn RICARD .

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

Thank you Jocelyn:  What should be dead simple is very frustrating but I can't put my finger on what I could be doing so wrong with so few lines of code copied from an example that you've demonstrated as working fine.  There is something else happening for sure, but I need expert help to determine what is getting in the way of this simple operation.

As mentioned in my reply to TDK above, executing a reboot using OBL_LAUNCH results in staying in RDP level 0.

Also mentioned above is the question about 'why is OPTVERR getting set?  Will that bit block some operation that causes things to freeze at RDP level 0?  I can clear this bit manually but it returns after reboot, so OPTVERR seems to be a clue.  (Also, the datasheet mentions that in this case the default operation is to progress to RDP level 1 when OPTVERR is set, which is definitely not happening to me!)

Quoting from the datasheet:

If the comparison between the word and its complement fails, a status bit OPTVERR is set. Mismatch values are forced into the option registers:

For USR OPT option, the value of mismatch is 1 for all option bits.

For WRP option, the value of mismatch is the default value “No protection”.

For RDP option, the value of mismatch is the default value “level 1”. (not happening to me!)

For BOOT_LOCK, the value of mismatch is “boot forced from main flash memory”."

-----

My device has power always applied, but HAL_PWR_EnterSHUTDOWNMode(); is issued after my operations are completed, and the datasheet says this is equivalent to a POR.

Are there other conditions which prevent the HAL from doing its thing?  Except for the clue from OPTVERR bit above I have nothing to go on here.  As you've confirmed with the nucleo, stepping through the HAL is doing the right thing but the hardware doesn't land the desired 0xBB RDP level into flash.  

Is there any overarching status bit which can help determine where this 'under the hood' hardware erase, write, device reset, and re-read of the option bytes might be derailed?  

Again, I do appreciate the help,

Doug

My code boils down to this:

HAL_Init();

SystemClock_Config();

MX_GPIO_Init();

MX_USART2_UART_Init();
MX_ADC1_Init();
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1_HIGH); 

MX_I2C1_Init();
MX_I2C2_Init();

...read some ADC, write some GPIO pins, send some I2C commands...

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;
/* Unlock Flash Control register and Option Bytes */
HAL_FLASH_Unlock();
HAL_FLASH_OB_Unlock();
/* Configure option byte parameters values.*/
OptionsBytesInit.RDPLevel = OB_RDP_LEVEL_1;
FLASH->SR = FLASH_SR_CLEAR; // force clear of OPTVERR
/* Program Option Bytes */
HAL_FLASHEx_OBProgram(&OptionsBytesInit);
HAL_PWR_EnterSHUTDOWNMode();

DJens
Associate II

Thanks folks:  It just struck me that I should have mentioned this, whether it is a red herring or not: The only parts I have access to were provided by ST are pre-production samples. Using the STM32CubeProgrammer I have exactly the same results with the programmer that I do with my code:  No ability to change the RDP level.  Images are attached below but I'll summarize:

I have attempted to change the BOOT_LOCK bit or the RDP level from 0xAA to 0xBB.  Both changes result in errors for expected values and Option Byte Programming failed Or modified by application after OB_LAUNCH.  (From what I can tell, the STM32CubeProgrammer is unable to change any other option bytes either - with similar errors - and following a full chip erase, so there is no code runable on the device.)  Parts which have never been loaded with software that tries to modify Option Bytes have BOOT_LOCK=1 and OPTVERR=1 and HDP1EN=0 (not 0xB4 as the default should be.)

I have found one part which does NOT have BOOT_LOCK or OPTVERR set (and have HDP1EN=0xB4.)  This part also shows a "Bootloader Version" of 0x0A whereas the others show 0xFF (as shown under Target information in the STM32CubeProgrammer.)

Is it possible I just have unhappy silicon?  If so, I'd like some positive identification of the issue as I need to develop production RDP level 1 code on these devices as of a week ago.

These parts are marked

(st logo) (e4 logo) GYHYK

EC32U0318P6

CHN32701A

DJens_0-1727213799095.png

DJens_1-1727213816524.png