STM32U0 Attempting to reach RDP level 1, stuck at RDP level 0 with OPTVERR bit HIGH
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;
}

