Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added support for writing option bytes on STM32L0 #830

Merged
merged 1 commit into from
Sep 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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