Skip to content

Commit

Permalink
Merge pull request #830 from thingdust/master
Browse files Browse the repository at this point in the history
added support for writing option bytes on STM32L0
  • Loading branch information
texane committed Sep 7, 2019
2 parents c492e1d + e56de83 commit c3577b5
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 13 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ then it would be written to the memory.

## Writing Option Bytes

Example to read and write option bytes (currently writing only supported for STM32G0)
Example to read and write option bytes (currently writing only supported for STM32G0 and STM32L0)
```
./st-flash --debug --reset --format binary --flash=128k read option_bytes_dump.bin 0x1FFF7800 4
./st-flash --debug --reset --format binary --flash=128k write option_bytes_dump.bin 0x1FFF7800
Expand Down
1 change: 1 addition & 0 deletions include/stm32.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@
#define STM32_FLASH_BASE ((uint32_t)0x08000000)
#define STM32_SRAM_BASE ((uint32_t)0x20000000)
#define STM32_G0_OPTION_BYTES_BASE ((uint32_t)0x1FFF7800)
#define STM32_L0_CAT2_OPTION_BYTES_BASE ((uint32_t)0x1FF80000)

#endif /* STM32_H */
99 changes: 88 additions & 11 deletions src/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,9 @@
//same as 32L1 above
// RM0090 - DM00031020.pdf
#define STM32L0_FLASH_REGS_ADDR ((uint32_t)0x40022000)
#define STM32L0_FLASH_PELOCK_BIT (1u << 0)
#define STM32L0_FLASH_OPTLOCK_BIT (1u << 2)
#define STM32L0_FLASH_OBL_LAUNCH_BIT (1u << 18)
#define FLASH_ACR_OFF ((uint32_t) 0x00)
#define FLASH_PECR_OFF ((uint32_t) 0x04)
#define FLASH_PDKEYR_OFF ((uint32_t) 0x08)
Expand Down Expand Up @@ -2507,7 +2510,7 @@ int stlink_fwrite_flash(stlink_t *sl, const char* path, stm32_addr_t addr) {
* @param base option bytes to write
* @return 0 on success, -ve on failure.
*/
int stlink_write_option_bytes(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t len) {
static int stlink_write_option_bytes_g0x1(stlink_t *sl, uint8_t* base, uint32_t len) {

uint32_t val;

Expand All @@ -2516,15 +2519,6 @@ int stlink_write_option_bytes(stlink_t *sl, stm32_addr_t addr, uint8_t* base, ui
return -1;
}

// Make sure we've loaded the context with the chip details
stlink_core_id(sl);

/* Check if chip is supported and for correct address */
if((sl->chip_id != STLINK_CHIPID_STM32_G0X1) || (addr != STM32_G0_OPTION_BYTES_BASE)) {
ELOG("Option bytes writing is currently only supported for the STM32G0\n");
return -1;
}

/* Unlock flash if necessary (ref manuel page 52) */
stlink_read_debug32(sl, STM32G0_FLASH_CR, &val);
if ((val & (1u << STM32G0_FLASH_CR_LOCK))) {
Expand Down Expand Up @@ -2561,7 +2555,6 @@ int stlink_write_option_bytes(stlink_t *sl, stm32_addr_t addr, uint8_t* base, ui
uint32_t data;
write_uint32((unsigned char*) &data, *(uint32_t*) (base));
WLOG("Writing option bytes 0x%04x\n", data);
//stlink_write_debug32(sl, addr, data);
stlink_write_debug32(sl, STM32G0_FLASH_OPTR, data);

/* Set Options Start bit */
Expand Down Expand Up @@ -2591,6 +2584,90 @@ int stlink_write_option_bytes(stlink_t *sl, stm32_addr_t addr, uint8_t* base, ui
return 0;
}


/**
* Write option bytes
* @param sl
* @param addr of the memory mapped option bytes
* @param base option bytes to write
* @return 0 on success, -ve on failure.
*/
static int stlink_write_option_bytes_l0_cat2(stlink_t *sl, uint8_t* base, uint32_t len) {

uint32_t val;

if(len != 4) {
ELOG("Wrong length for writting option bytes, must be 4 is %d\n", len);
return -1;
}
stlink_read_debug32(sl, STM32L0_FLASH_REGS_ADDR + FLASH_PECR_OFF, &val);
if (val & STM32L0_FLASH_PELOCK_BIT) {
WLOG("Unlocking flash\n");
//Unlock data EEPROM and the FLASH_PECR register (reference page 74)
stlink_write_debug32(sl, STM32L0_FLASH_REGS_ADDR + FLASH_PEKEYR_OFF, 0x89ABCDEF);
stlink_write_debug32(sl, STM32L0_FLASH_REGS_ADDR + FLASH_PEKEYR_OFF, 0x02030405);

stlink_read_debug32(sl, STM32L0_FLASH_REGS_ADDR + FLASH_PECR_OFF, &val);
if (val & STM32L0_FLASH_PELOCK_BIT) {
ELOG("Flash unlock failed! System reset required to be able to unlock it again!\n");
return -1;
}
}

stlink_read_debug32(sl, STM32L0_FLASH_REGS_ADDR + FLASH_PECR_OFF, &val);
if ((val & (STM32L0_FLASH_OPTLOCK_BIT))) {
WLOG("Unlocking options\n");
//Unlock the Option bytes area (reference page 76)
stlink_write_debug32(sl, STM32L0_FLASH_REGS_ADDR + FLASH_OPTKEYR_OFF, 0xFBEAD9C8);
stlink_write_debug32(sl, STM32L0_FLASH_REGS_ADDR + FLASH_OPTKEYR_OFF, 0x24252627);

stlink_read_debug32(sl, STM32L0_FLASH_REGS_ADDR + FLASH_PECR_OFF, &val);
if (val & STM32L0_FLASH_OPTLOCK_BIT) {
ELOG("Options unlock failed! System reset required to be able to unlock it again!\n");
return -1;
}
}

/* Write options bytes */
uint32_t data;
write_uint32((unsigned char*) &data, *(uint32_t*) (base));
WLOG("Writing option bytes 0x%04x\n", data);
stlink_write_debug32(sl, STM32_L0_CAT2_OPTION_BYTES_BASE, data);

/* Reload options */
stlink_read_debug32(sl, STM32L0_FLASH_REGS_ADDR + FLASH_PECR_OFF, &val);
val |= (STM32L0_FLASH_OBL_LAUNCH_BIT);
stlink_write_debug32(sl, STM32L0_FLASH_REGS_ADDR + FLASH_PECR_OFF, val);

return 0;
}

/**
* Write option bytes
* @param sl
* @param addr of the memory mapped option bytes
* @param base option bytes to write
* @return 0 on success, -ve on failure.
*/
int stlink_write_option_bytes(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t len) {

// Make sure we've loaded the context with the chip details
stlink_core_id(sl);

/* Check if chip is supported and for correct address */
if((sl->chip_id == STLINK_CHIPID_STM32_G0X1) && (addr == STM32_G0_OPTION_BYTES_BASE)) {
return stlink_write_option_bytes_g0x1(sl, base, len);
}
else if((sl->chip_id == STLINK_CHIPID_STM32_L0_CAT2) && (addr == STM32_L0_CAT2_OPTION_BYTES_BASE)) {
return stlink_write_option_bytes_l0_cat2(sl, base, len);
}
else {
ELOG("Option bytes writing is currently only supported for the STM32G0 and STM32L0\n");
return -1;
}

}

/**
* Write the given binary file with option bytes
* @param sl
Expand Down
2 changes: 1 addition & 1 deletion src/tools/flash.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ int main(int ac, char** av)
goto on_error;
}
}
else if (o.addr == STM32_G0_OPTION_BYTES_BASE) {
else if (o.addr == STM32_G0_OPTION_BYTES_BASE || o.addr == STM32_L0_CAT2_OPTION_BYTES_BASE) {
err = stlink_fwrite_option_bytes(sl, o.filename, o.addr);
if (err == -1)
{
Expand Down

0 comments on commit c3577b5

Please sign in to comment.