added support for writing option bytes on STM32L0

pull/830/head
Adrian Imboden 2019-09-06 18:23:37 +02:00
rodzic c492e1df6f
commit e56de83ec5
4 zmienionych plików z 91 dodań i 13 usunięć

Wyświetl plik

@ -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

Wyświetl plik

@ -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 */

Wyświetl plik

@ -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)
@ -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;
@ -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))) {
@ -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 */
@ -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

Wyświetl plik

@ -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)
{