Skip to main content
Graduate II
January 19, 2024
Question

STM32 and FLASH registers

  • January 19, 2024
  • 2 replies
  • 4441 views

I have a question regarding STM32L0. I am interested in which address the registers like FLASH_ACR, FLASH_PECR, etc., are located. In the datasheet, I only see their offsets, but not the absolute value is it maybe 0x1FF8 0000?.
Also I would also like to know if it is possible to read from the mentioned registers like FLASH_SR, etc., when the MCU is locked at Level 1? Because to unlock it (using an external debugger).

 

Why all this? I want to erase mcu no matter if it is or is not in Level1 or Level 0.

Thank you Jan.

    This topic has been closed for replies.

    2 replies

    Graduate
    January 19, 2024

    Have you checked the Reference Manual for your stm32L0?

    For stm32l0x1 for example, it is stated in section 2.2 "System and memory overview:Memory organisation"

     

    Table 3. STM32L0x1 peripheral register boundary addresses(1) (continued)

    RM0377

    Bus

    Boundary address

    Size (bytes)

    Peripheral

    Peripheral register map

    NVM

    0X0800 0000 - 0X0802 FFFF

    up to 192 K

    Flash program memory

    -

    0x0808 0000 - 0x0808 17FF

    up to 6 K

    Data EEPROM

    -

    0x1FF0 0000 - 0x1FF0 1FFF

    8K

    System memory

    -

    0x1FF8 0020 - 0x1FF8 007F

    96

    Factory option bytes

    -

    0x1FF8 0000 - 0x1FF8 001F

    32

    User option bytes

    -

    1. Refer to Table 1: STM32L0x1 memory density, to Table 2: Overview of features per category and to the device datasheets for the GPIO ports and peripherals available on your device. The memory area corresponding to unavailable GPIO ports or peripherals are reserved.

    Edit: Added removal of code protection.

    If your debugger doesn't provide direct control of code-protection level, you might have to do what I do. I download a program like this into RAM: (I use Crossworks; you'll have to have your own way to monitor what's going on to replace the "debug_printf" statements)

    /* main.c for RemoveCodeProtection */
    
    #include <cross_studio_io.h>
    #include "stm32wlxx_hal.h"
    
    void main(void) {
     FLASH_OBProgramInitTypeDef clearRdp;
     HAL_Init();
     HAL_InitTick(TICK_INT_PRIORITY);
     /*	Unlock the Flash to	enable the flash control register access *************/
     HAL_FLASHEx_OBGetConfig(&clearRdp);
     if (clearRdp.RDPLevel == OB_RDP_LEVEL_0) {
     debug_printf("Code protection already disabled\n");
     } else {
     debug_printf("Trying to disable code protection. Power-cycle after 10 seconds\n");
     HAL_FLASH_Unlock();
     /* Clear OPTVERR bit set on virgin samples */
     __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR); 
     /* Unlock	the	Options	Bytes *************************************************/
     HAL_FLASH_OB_Unlock();
     clearRdp.RDPLevel = OB_RDP_LEVEL_0;
     clearRdp.OptionType = OPTIONBYTE_RDP;
     HAL_StatusTypeDef rc = HAL_FLASHEx_OBProgram(&clearRdp);
     if (rc == HAL_OK) {
     HAL_FLASH_OB_Launch();
     HAL_FLASH_OB_Lock();
     debug_printf("Successful\n");
     } else
     debug_printf("Failed\n");
     }
    }
    Super User
    January 19, 2024

    waclawekjan_0-1705660747205.png

    JW

     

    JR2963Author
    Graduate II
    January 19, 2024

    This is exactly what I was looking for, Unfortunately I still can not make mass erase of my MCU. I found this: It should erase MCU when is in Level1

    JR2963_0-1705662445784.png

    So I made it

    RDP_UNLOCK = 0xAA
    
    PRGKEY1 = 0x8C9DAEBF
    PRGKEY2 = 0x13141516 
    PEKEY1 = 0x89ABCDEF
    PEKEY2 = 0x02030405
    OPTKEY1 = 0xFBEAD9C8
    OPTKEY2 = 0x24252627
    
    SECTION_USER_OB = 0x1FF80000
    FLAHS_OB_BASE = 0x40022000
    
    FLASH_PECR = FLAHS_OB_BASE+0x4
    FLASH_PEKEYR= FLAHS_OB_BASE+0x0C
    FLASH_OPTKEYR = FLAHS_OB_BASE+0x14
    FLASH_OPTR = FLAHS_OB_BASE+0x1C
    FLASH_PRGKEYR = FLAHS_OB_BASE+0x10
    FLASH_SR = FLAHS_OB_BASE+0x18
    
    def massErase(self):
     self.unlockOptionBytesArea()
     self.programoptionBytes(0x00AA)
    ...
    def unlockOptionBytesArea(self):
     self.busy_wait()
     tmp = self.readU32Mem(FLASH_PECR)
     if (tmp & PECR_PELOCK_BIT) == 0: # 
     if tmp & PECR_OPTLOCK_BIT == 1 : 
     if self.writeU32ToMem(FLASH_OPTKEYR,OPTKEY1) == True:
     if self.writeU32ToMem(FLASH_OPTKEYR,OPTKEY2) == True:
     self.busy_wait()
     return True
    
     def programoptionBytes(self,val):
     val = self.option_bytes_word(val)
     self.writeU32ToMem(SECTION_USER_OB,val)
     self.busy_wait()
     flash_sr = self.readU32Mem(FLASH_SR)
     if flash_sr & SR_EOP != 0:
     self.writeU32ToMem(FLASH_SR, SR_EOP)