cancel
Showing results for 
Search instead for 
Did you mean: 

How to set RDP level 1 via software on STM32G030

DAlbe.3
Senior

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!

1 ACCEPTED SOLUTION

Accepted Solutions

The problem is that the OPTR read always return the actual OB value, not the value you are currently programming. So the SET_BIT will read RDP value AA, modify nBOOT bits, and write back the AA!

The boot bits need to be programmed first, then OB programming, OBL and then RDP programming. If you use shutdown/standby to force the OBL on RDP, it's necessary to disable the debug interface during shutdown/standby in DBG CR register, so that the MCU is really going through POR.

The documentation is not totally clear on this, my colleague is now working on updated version.

BR,

J

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

View solution in original post

12 REPLIES 12
Bubbles
ST Employee

Hello @DAlbe.3,

try, instead of setting OBL_LAUNCH, perform a reset to reload the OB. Transition to standby or shutdown mode will also do the job. The RDP is behaving differently here, probably to prevent a deadlock on OB mismatch.

BR,

J

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

I tried that before posting...no luck.  Reset, power cycle, re-locking flash, nothing has resulted in the RDP change taking effect.  Do you see something obvious that  I might be missing in the code?

The problem is that the OPTR read always return the actual OB value, not the value you are currently programming. So the SET_BIT will read RDP value AA, modify nBOOT bits, and write back the AA!

The boot bits need to be programmed first, then OB programming, OBL and then RDP programming. If you use shutdown/standby to force the OBL on RDP, it's necessary to disable the debug interface during shutdown/standby in DBG CR register, so that the MCU is really going through POR.

The documentation is not totally clear on this, my colleague is now working on updated version.

BR,

J

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

No need to do separately boot bits programming before RDP programming. Just avoid read-modify-write instructions on FLASH_OPTR and rather just write there your desired 32-bit value directly.

aNt
ST Employee

Side question - which revision of STM32G030 do you use? The errata 2.2.3 should be fixed on Rev. Y, present only on Rev. Z (refer to actual product ES).

BR

Thank you @aNt and @Bubbles , I will try separating the read/modify/write.
We are using K6T6 rev Z; we have a few thousand pcs in stock so a solution that works with rev Z would be ideal.
I just purchased some new stock so I'll test with Rev Y and report back shortly.
I appreciate your help with this!

Thank you again @Bubbles and @aNt that was indeed the issue. I revised the code to read to a local variable, modify it, and then write it back and that does the trick.  Thank you!

My remaining issue is how to get the change to take effect. @Bubbles mentioned a few potential issues. Setting OBL_LAUNCH didn't seem to do the trick. I have the debug interface enabled (because I'm debugging this).  I tried an NVIC_SystemReset() instead of the OBL_LAUNCH and appear to have bricked the chip.  I'll replace it and try again, but if there is a recommended mechanism for reloading the option bytes, I'd appreciate it.  Here's what I'm currently doing (that doesn't seem to work...a POR or maybe a hard reset seems to be required).

 

        // write the desired values
        FLASH->OPTR = optr;
        while (FLASH->SR & FLASH_SR_BSY1); // wait for flash ready
        SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);  // start write of options
        while (FLASH->SR & FLASH_SR_BSY1); // wait for flash ready
        // Read/use new options
        SET_BIT(FLASH->CR, FLASH_CR_OBL_LAUNCH);
        // Lock Flash
        SET_BIT(FLASH->CR, FLASH_CR_LOCK | FLASH_CR_OPTLOCK);

 

 Thanks again!

> try, instead of setting OBL_LAUNCH, perform a reset to reload the OB. Transition to standby or
> shutdown mode will also do the job. The RDP is behaving differently here, probably to prevent
> a deadlock on OB mismatch

Is the OBL_LAUNCH functionality broken? When I set OBL_LAUNCH, the CPU simply hangs until it is power cycled. There are quite a few threads discussing this in a variety of ways. Is it a missing errata or is there something special needed to make it work?

Frantz LEFRERE
ST Employee

Hello @DAlbe.3 ,

you can have a look on this video :
https://www.youtube.com/watch?v=f7vs0NwZPFo&list=PLnMKNibPkDnGxKqGyLbiGygmlrvISIBIT&index=4
Those information are also relevant for STM32G0

Frantz