2024-05-27 01:07 PM - edited 2024-05-27 02:58 PM
I would like to increase the code readout protection level from 0 to 1 programmatically in an STM32G030. I must be doing something silly and if anyone sees it, I'd be grateful. I've stepped through it with the debugger and the flash and option byte locks are indeed removed. The write to the option register doesn't show up in the debugger (still shows 0xAA), There are no errors in the FLASH SR or CR registers after the OPTSTART bit is set. The debugger loses connection when OBL_LAUNCH is set (presumably due to the reset). After the reset, the RDP byte in the flash OPTR is still set to 0xAA. It is still 0xAA after the device is power cycled. The code is:
// Set code readout protection
__disable_irq();
// unlock flash memory (LOCK bit in FLASH_CR)
FLASH->KEYR = 0x45670123;
FLASH->KEYR = 0xCDEF89AB;
// wait for flash unlocked
while (FLASH->CR & FLASH_CR_LOCK);
// clear option lock (OPTLOCK bit in FLASH_CR)
FLASH->OPTKEYR = 0x08192A3B;
FLASH->OPTKEYR = 0x4C5D6E7F;
// wait for option bytes unlocked
while (FLASH->CR & FLASH_CR_OPTLOCK);
// Set flash readout protection level 1
MODIFY_REG(FLASH->OPTR, FLASH_OPTR_RDP, 0xBB);
// NOTE: errata 2.2.3: boot mode selection pin cannot be enabled at the
// same time as RDP level 1 or the uC will intermittently fail to boot
// So use nBOOT0 bit to select main flash memory for boot
SET_BIT(FLASH->OPTR, FLASH_OPTR_nBOOT_SEL | FLASH_OPTR_nBOOT0);
// write the desired values
while (FLASH->SR & FLASH_SR_BSY1); // wait for flash ready
FLASH->CR |= FLASH_CR_OPTSTRT; // start write of options
while (FLASH->SR & FLASH_SR_BSY1); // wait for flash ready
FLASH->CR |= FLASH_CR_OBL_LAUNCH; // read/use new options
In digging into the HAL code, I thought this might be a problem with the option byte region being write protected, but I don't see it and the write attempt doesn't set the WRPERR bit in the FLASH->SR (no error bits are set).
Thanks!
Solved! Go to Solution.
2024-05-31 06:34 AM
It depends on what you are trying to achieve here, as you can't really debug once RDP lvl1 become active - when flash read is detected while there was debug connection since last power-on, intrusion will be detected and part blocked (till next POR). It is explained in the video shared by Frantz.
Generally, if you want to just update RDP and there will be no debug connection since POR, OBL_LAUNCH should be sufficient to apply new OBs. If you want a smooth transition from debug with RDP lvl0 to no debug with RDP lvl1 you can try going through Standby or Shutdown modes. And then, in all cases POR will work as well.
However, in any case, you can't really debug under RDP lvl1...
2024-05-31 08:19 AM
Hi @Frantz LEFRERE, thank you for the reply. I watched the video and it appears to confirm what I have reported above: that setting OBL_LAUNCH simply locks up the core until a POR reset. Since a POR causes the option bytes to be read anyway, setting the OBL_LAUNCH seems pointless.
I understand that I can either POR or enter/exit Standby mode to cause the option bytes to be re-loaded. I will play with the Standby method soon, but because I have to disable the BOOT0 pin selection due to erratum 2.2.3, I've had to remove/re-mount several chips that I bricked in testing.
Is there a scenario where OBL_LAUNCH actually works? If not, it seems like something that should be added to the erratum. Either I'm not using it properly or it does not work as advertised in the reference manual.
2024-05-31 08:40 AM - edited 2024-05-31 08:42 AM
Thank you @aNt, and sorry, I posted my last comment before seeing yours.
In my particular case, the STM32G0 is a co-processor and I'd expected to be able to do field firmware updates from the main processor by placing it in DFU mode, then READ UNPROTECT, WRITE MEMORY, LEAVE DFU. The new firmware would then set RDP to level 1 and apply it using OBL_LAUNCH.
It sounds like that may not be possible and that I will need to use the transition to/from standby rather than OBL_LAUNCH if I've used DFU to update the firmware. If I understand this correctly, it sounds like OBL_LAUNCH is only useful for upgrades done via user software rather than DFU in which case it doesn't seem terribly useful for small-memory parts like the STM32G030 where a user firmware update mechanism would consume a significant portion of available flash.
If OBL_LAUNCH doesn't work after DFU, that seems like something important to document in the user manual. Any situation that will cause the CPU core to lock up, IWDG to fail to reboot, and require a POR to recover seems like critical information for the developer.