2024-01-18 11:36 PM
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.
2024-01-19 12:22 AM - edited 2024-01-19 12:27 AM
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"); } }
2024-01-19 02:39 AM
JW
2024-01-19 03:11 AM
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
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)