From 0948cd19b27b0f66e12145dbf1c911f50c31d039 Mon Sep 17 00:00:00 2001 From: Davey Struijk Date: Fri, 25 Oct 2019 14:32:36 +0200 Subject: [PATCH] Allow writing option bytes to STM32F4 devices --- include/stlink.h | 1 + src/common.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++- src/tools/flash.c | 6 +++- 3 files changed, 93 insertions(+), 2 deletions(-) diff --git a/include/stlink.h b/include/stlink.h index 0715166..5defe4e 100644 --- a/include/stlink.h +++ b/include/stlink.h @@ -223,6 +223,7 @@ typedef struct flash_loader { int stlink_fread(stlink_t* sl, const char* path, bool is_ihex, stm32_addr_t addr, size_t size); int stlink_load_device_params(stlink_t *sl); int stlink_read_option_bytes_f2(stlink_t *sl, uint32_t* option_byte); + int stlink_read_option_bytes_f4(stlink_t *sl, uint32_t* option_byte); #include "stlink/sg.h" #include "stlink/usb.h" diff --git a/src/common.c b/src/common.c index bfcbe71..99bd7a8 100644 --- a/src/common.c +++ b/src/common.c @@ -187,6 +187,7 @@ #define FLASH_F4_SR (FLASH_F4_REGS_ADDR + 0x0c) #define FLASH_F4_CR (FLASH_F4_REGS_ADDR + 0x10) #define FLASH_F4_OPT_CR (FLASH_F4_REGS_ADDR + 0x14) +#define FLASH_F4_OPT_LOCK_BIT (1u << 0) #define FLASH_F4_CR_STRT 16 #define FLASH_F4_CR_LOCK 31 #define FLASH_F4_CR_SER 1 @@ -2711,6 +2712,56 @@ static int stlink_write_option_bytes_f2(stlink_t *sl, uint32_t option_byte) { return 0; } +/** + * Write option bytes + * @param sl + * @param option_byte value to write + * @return 0 on success, -ve on failure. + */ +static int stlink_write_option_bytes_f4(stlink_t *sl, uint32_t option_byte) { + uint32_t val; + + stlink_read_debug32(sl, FLASH_F4_OPT_CR, &val); + if (val & FLASH_F4_OPT_LOCK_BIT) { + WLOG("Unlocking option flash\n"); + //Unlock the FLASH_OPT_CR register (FLASH Programming manual page 15) + //https://www.st.com/resource/en/programming_manual/cd00233952.pdf + stlink_write_debug32(sl, FLASH_F4_OPT_KEYR, 0x08192A3B); + stlink_write_debug32(sl, FLASH_F4_OPT_KEYR, 0x4C5D6E7F); + + stlink_read_debug32(sl, FLASH_F4_OPT_CR, &val); + if (val & FLASH_F4_OPT_LOCK_BIT) { + ELOG("Option flash unlock failed! System reset required to be able to unlock it again!\n"); + return -1; + } + } + + stlink_read_debug32(sl, FLASH_F4_OPT_CR, &val); + WLOG("option bytes CR = %x\n",val); + + stlink_write_debug32(sl, FLASH_F4_OPT_CR, option_byte & 0x0FFFFFFC); + + stlink_write_debug32(sl, FLASH_F4_OPT_CR, (option_byte & 0x0FFFFFFC)|0x00000002); + + + stlink_read_debug32(sl, FLASH_F4_SR, &val); + WLOG("wait BSY flag to be 0\n"); + + while(val & 0x00010000){ + stlink_read_debug32(sl, FLASH_F4_SR, &val); + } + WLOG("BSY flag is 0\n"); + + stlink_read_debug32(sl, FLASH_F4_OPT_CR, &val); + WLOG("option bytes CR = %x\n",val); + WLOG("Option flash re-lock\n"); + stlink_write_debug32(sl, FLASH_F4_OPT_CR, val | 0x00000001); + + DLOG("STM32 F4 option bytes are written\n"); + + return 0; +} + /** * Read option bytes * @param sl @@ -2744,6 +2795,39 @@ int stlink_read_option_bytes_f2(stlink_t *sl, uint32_t* option_byte) { return 0; } +/** + * Read option bytes + * @param sl + * @param option_byte value to write + * @return 0 on success, -ve on failure. + */ +int stlink_read_option_bytes_f4(stlink_t *sl, uint32_t* option_byte) { + uint32_t val; + + stlink_read_debug32(sl, FLASH_F4_OPT_CR, &val); + if (val & FLASH_F4_OPT_LOCK_BIT) { + WLOG("Unlocking option flash\n"); + //Unlock the FLASH_OPT_CR register (FLASH Programming manual page 15) + //https://www.st.com/resource/en/programming_manual/cd00233952.pdf + stlink_write_debug32(sl, FLASH_F4_OPT_KEYR, 0x08192A3B); + stlink_write_debug32(sl, FLASH_F4_OPT_KEYR, 0x4C5D6E7F); + + stlink_read_debug32(sl, FLASH_F4_OPT_CR, &val); + if (val & FLASH_F4_OPT_LOCK_BIT) { + ELOG("Option flash unlock failed! System reset required to be able to unlock it again!\n"); + return -1; + } + } + + stlink_read_debug32(sl, FLASH_F4_OPT_CR, option_byte); + WLOG("option bytes CR = %x\n",option_byte); + + WLOG("Option flash re-lock\n"); + stlink_write_debug32(sl, FLASH_F4_OPT_CR, val | 0x00000001); + + return 0; +} + /** * Write option bytes * @param sl @@ -2803,10 +2887,12 @@ int stlink_fwrite_option_bytes_32bit(stlink_t *sl, uint32_t val) { if(sl->chip_id == STLINK_CHIPID_STM32_F2){ return stlink_write_option_bytes_f2(sl, val); + }else if(sl->chip_id == STLINK_CHIPID_STM32_F446){ + return stlink_write_option_bytes_f4(sl, val); } else { - ELOG("Option bytes writing is currently only supported for the STM32F2, STM32G0 and STM32L0\n"); + ELOG("Option bytes writing is currently only supported for the STM32F2, STM32F4, STM32G0 and STM32L0\n"); return -1; } } diff --git a/src/tools/flash.c b/src/tools/flash.c index 33e1c8d..f5fd1a3 100644 --- a/src/tools/flash.c +++ b/src/tools/flash.c @@ -214,8 +214,12 @@ int main(int ac, char** av) uint32_t option_byte = 0; err = stlink_read_option_bytes_f2(sl,&option_byte); printf("%x\n",option_byte); + }else if(sl->chip_id == STLINK_CHIPID_STM32_F446){ + uint32_t option_byte = 0; + err = stlink_read_option_bytes_f4(sl,&option_byte); + printf("%x\n",option_byte); }else{ - printf("This format is available for STM32F2 Only\n"); + printf("This format is available for STM32F2 and STM32F4 Only\n"); } }else{ if ((o.addr >= sl->flash_base) && (o.size == 0) &&