Author Topic: STM32L0 Readout Protection and OBL_LAUNCH  (Read 1125 times)

0 Members and 1 Guest are viewing this topic.

Offline voltsandjoltsTopic starter

  • Supporter
  • ****
  • Posts: 2129
  • Country: gb
STM32L0 Readout Protection and OBL_LAUNCH
« on: December 20, 2022, 11:27:05 am »
I have the following code for an STM32L051 which programs the option bytes to change RDP level from 0 to 1.
The change is implemented at the next power-on reset, when FLASH->OPTR is loaded from the option bytes.

Code: [Select]
/* Increase readout protection level from 0 to 1 */
void RDP_level0_to_level1(void) {
uint32_t primask_bit;

primask_bit = __get_PRIMASK();
__disable_irq();
FLASH->PEKEYR = FLASH_PEKEY1; /* Unlock eeprom data memory and FLASH->PECR register access */
FLASH->PEKEYR = FLASH_PEKEY2;
FLASH->OPTKEYR = FLASH_OPTKEY1; /* Unlock option bytes */
FLASH->OPTKEYR = FLASH_OPTKEY2;
__set_PRIMASK(primask_bit);

CLEAR_BIT(FLASH->PECR, FLASH_PECR_ERASE);

/* PELOCK = 0, OPTLOCK = 0, ERASE = 0 as per RM section 3.3.4 Writing/erasing the NVM > Write Option bytes */

/* 16-bit data is extended with its complemented value */
/* WPRMOD=0 */
OB->RDP = (~((uint32_t)OB_RDP_LEVEL_1) << 16) | (uint32_t)OB_RDP_LEVEL_1;

while ((FLASH->SR & FLASH_SR_BSY) != 0)
(void)0;

SET_BIT(FLASH->PECR, FLASH_PECR_OPTLOCK);
SET_BIT(FLASH->PECR, FLASH_PECR_PELOCK);

/* FLASH->OPTR will have the updated value (from OB->RDP) after next power on reset */

}

That works but rather than wait for a power on reset, I would like to force a reload of the option bytes immediately use the OBL_LAUNCH bit:

Code: [Select]
SET_BIT(FLASH->PECR, FLASH_PECR_OBL_LAUNCH); /* Reboot and Force Option Bytes Load, OPTLOCK must be 0 */

But adding that in causes the the device to hang:

Code: [Select]
void RDP_level0_to_level1_REBOOT(void) {

__disable_irq();
FLASH->PEKEYR = FLASH_PEKEY1; /* Unlock eeprom data memory and FLASH->PECR register access */
FLASH->PEKEYR = FLASH_PEKEY2;
FLASH->OPTKEYR = FLASH_OPTKEY1; /* Unlock option bytes */
FLASH->OPTKEYR = FLASH_OPTKEY2;

CLEAR_BIT(FLASH->PECR, FLASH_PECR_ERASE);

/* PELOCK = 0, OPTLOCK = 0, ERASE = 0 as per RM section 3.3.4 Writing/erasing the NVM > Write Option bytes */

/* 16-bit data is extended with its complemented value */
/* WPRMOD=0 */
OB->RDP = (~((uint32_t)OB_RDP_LEVEL_1) << 16) | (uint32_t)OB_RDP_LEVEL_1;

while ((FLASH->SR & FLASH_SR_BSY) != 0)
(void)0;

SET_BIT(FLASH->PECR, FLASH_PECR_OBL_LAUNCH); /* Reboot and Force Option Bytes Load, OPTLOCK must be 0 */

/* shouldn't get here */
}

I've tried various things, including running that function in RAM but am kinda stuck. The RM is somewhat lacking on OBL_LAUNCH information other than 'set this bit to load and reboot'.
The RESET pin just has 100nF to GND so device should be able to drive RESET without problem.


Has anyone successfully used OBL_LAUNCH ?
 

Offline wek

  • Frequent Contributor
  • **
  • Posts: 462
  • Country: sk
Re: STM32L0 Readout Protection and OBL_LAUNCH
« Reply #1 on: December 20, 2022, 11:49:53 am »
> But adding that in causes the the device to hang:

Define "hang".

JW
 

Offline voltsandjoltsTopic starter

  • Supporter
  • ****
  • Posts: 2129
  • Country: gb
Re: STM32L0 Readout Protection and OBL_LAUNCH
« Reply #2 on: December 20, 2022, 11:58:29 am »
By 'hang', I mean the function doesn't return (as expected) but the device doesn't reboot either.
The function does return if the line that sets OBL_LAUNCH is removed, so it is 'hanging' at that point.

After a power on reset, the RDP is at level 1, so the option byte programming (prior to OBL_LAUNCH) still worked.
« Last Edit: December 20, 2022, 12:05:06 pm by voltsandjolts »
 

Offline voltsandjoltsTopic starter

  • Supporter
  • ****
  • Posts: 2129
  • Country: gb
 

Offline voltsandjoltsTopic starter

  • Supporter
  • ****
  • Posts: 2129
  • Country: gb
Re: STM32L0 Readout Protection and OBL_LAUNCH
« Reply #4 on: December 20, 2022, 12:17:09 pm »
OK, the thread above links to this solution:

https://community.st.com/s/question/0D50X0000AwWZjDSQW/problem-with-reloading-option-bytes-stm32l452re

Quote
Yes it's clearly chip bug. I've been on ST presentation and one thing they showed was about using protection levels.
Their program requested the powercycle after changing it.
But there is a workaround.

1) Write option bytes as you like
2) DO NOT set OBL_LAUNCH
3) Set up RTC so it will wake up after a second
4) Enter standby mode and wakeup by RTC.

4 will effectively reset everything after a second and it WILL work then properly.
I already use this method in our product - that already have tadiran lithium capacitor/battery soldered while it is first programmed in production.
You cannot powercycle without desoldering.

I will give that a try....
 

Offline wek

  • Frequent Contributor
  • **
  • Posts: 462
  • Country: sk
Re: STM32L0 Readout Protection and OBL_LAUNCH
« Reply #5 on: December 20, 2022, 12:44:31 pm »
I don't have first-hand experience, but I also consider outright hardware bugs to be quite rare.

> device doesn't reboot either

It may have performed the system reset but causing a surprise by not running your code, or not in a way you expected. For examle, it may have entered the bootloader for any reason, or you may have debug active before setting OBL_LAUNCH
Quote from: RM0377
If the read protection is set while the debugger has been active (through SWD) after last
POR (power-on reset), apply a POR (power-on reset) or wakeup from Standby mode
instead of a system reset (the option bytes loading is not sufficient).

Anyway, exit from Standby should work, it's documented too in Option bytes chapter of RM0377.

JW
 
The following users thanked this post: voltsandjolts

Offline voltsandjoltsTopic starter

  • Supporter
  • ****
  • Posts: 2129
  • Country: gb
Re: STM32L0 Readout Protection and OBL_LAUNCH
« Reply #6 on: December 20, 2022, 12:49:00 pm »
That could indeed be the issue, but the first fix they give is apply a POR which I want to avoid!

The standby mode solution is working for me, no POR required so I'll go with that.

Thanks for your time.

Edit:

Another option given in the above linked threads was to setup a watchdog to reset the mcu, then set the OBL_LAUNCH bit.
The idea being the watchdog resets the mcu and clears the 'hung' state caused by OBL_LAUNCH.
Tried it using IWDG, but didn't work for me, mcu remained in 'hung' state, no reset occurred.
« Last Edit: December 20, 2022, 01:36:54 pm by voltsandjolts »
 

Offline wek

  • Frequent Contributor
  • **
  • Posts: 462
  • Country: sk
Re: STM32L0 Readout Protection and OBL_LAUNCH
« Reply #7 on: December 20, 2022, 05:40:05 pm »
Another option given in the above linked threads was to setup a watchdog to reset the mcu, then set the OBL_LAUNCH bit.
The idea being the watchdog resets the mcu and clears the 'hung' state caused by OBL_LAUNCH.
Tried it using IWDG, but didn't work for me, mcu remained in 'hung' state, no reset occurred.
Watchdog reset is "just" a system reset, you might've as well done a software reset. Neither of them is supposed to reload the Option bytes; contrary to explicit OBL_LAUNCH and the Standby wakeup, and of course the power-up reset.

I wonder what exactly the differences are, but we'd need an ST insider to get a conclusive answer to this.

JW
 

Offline voltsandjoltsTopic starter

  • Supporter
  • ****
  • Posts: 2129
  • Country: gb
Re: STM32L0 Readout Protection and OBL_LAUNCH
« Reply #8 on: December 21, 2022, 06:45:38 pm »
Another option given in the above linked threads was to setup a watchdog to reset the mcu, then set the OBL_LAUNCH bit.
The idea being the watchdog resets the mcu and clears the 'hung' state caused by OBL_LAUNCH.
Tried it using IWDG, but didn't work for me, mcu remained in 'hung' state, no reset occurred.
Watchdog reset is "just" a system reset, you might've as well done a software reset.

I couldn't do a software reset because the mcu hangs after setting OBL_LAUNCH.
Hence using the IWDG (setup beforehand) to do the reset, in the hope that setting OBL_LAUNCH would cause option byte reload.
That didn't work.

I ended up using the IWDG to exit standby mode so early in main() I have something this:

Code: [Select]
if ((FLASH->OPTR & FLASH_OPTR_RDPROT) == (uint32_t)OB_RDP_LEVEL_0) {

RDP_level0_to_level1(); /* enable readout protection level 1 */

/* To load new options into FLASH->OPTR from OB->RDP we need to wake from standby mode.
* Execution after exit from standby mode is same as a reset.
* For simplicity, use the IWDG to exit from standby.
*/
IWDG->KR = 0xCCCC; /* start */
IWDG->KR = 0x5555; /* enable access to PR and RLR regs */
IWDG->PR = IWDG_PR_PR_2; /* /64 prescaler for the dedicated 32kHz LSI clock = 512Hz */
IWDG->RLR = 256; /* count down from this value (256 is about 0.5secs at 512Hz) */
while (IWDG->SR) /* wait for setup to complete (slow clock domain) */
(void)0;
IWDG->KR = 0xAAAA; /* refresh (feed) the watchdog */

__disable_irq();
enter_standby_mode();

/* never get here, standby exit is same as reset */
}
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf