From 77fff346aa9d075e7fd01668d8418818f9c262ac Mon Sep 17 00:00:00 2001 From: Alex Klimaj Date: Tue, 15 Feb 2022 22:28:19 -0700 Subject: [PATCH] Add writing and reading STM32WL option bytes --- config/chips/WLx5.chip | 2 +- inc/stm32flash.h | 8 +-- src/option_bytes.c | 108 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+), 4 deletions(-) diff --git a/config/chips/WLx5.chip b/config/chips/WLx5.chip index 5bc9d90..8337b0a 100644 --- a/config/chips/WLx5.chip +++ b/config/chips/WLx5.chip @@ -9,6 +9,6 @@ flash_pagesize 0x800 // 2 KB sram_size 0x10000 // 64 KB bootrom_base 0x1fff0000 bootrom_size 0x7000 // 28 KB -option_base 0x1fffc000 +option_base 0x1fff7800 option_size 0x10 // 16 B flags swo diff --git a/inc/stm32flash.h b/inc/stm32flash.h index c28d67c..7e96d3f 100644 --- a/inc/stm32flash.h +++ b/inc/stm32flash.h @@ -162,9 +162,11 @@ #define STM32WB_FLASH_SRRVR (STM32WB_FLASH_REGS_ADDR + 0x84) // WB Flash control register. -#define STM32WB_FLASH_CR_STRT (16) /* Start */ -#define STM32WB_FLASH_CR_OPTLOCK (30) /* Option Lock */ -#define STM32WB_FLASH_CR_LOCK (31) /* Lock */ +#define STM32WB_FLASH_CR_STRT (16) /* Start */ +#define STM32WB_FLASH_CR_OPTSTRT (17) /* Start writing option bytes */ +#define STM32WB_FLASH_CR_OBL_LAUNCH (27) /* Forces the option byte loading */ +#define STM32WB_FLASH_CR_OPTLOCK (30) /* Option Lock */ +#define STM32WB_FLASH_CR_LOCK (31) /* Lock */ // WB Flash status register. #define STM32WB_FLASH_SR_ERROR_MASK (0x3f8) /* SR [9:3] */ #define STM32WB_FLASH_SR_PROGERR (3) /* Programming alignment error */ diff --git a/src/option_bytes.c b/src/option_bytes.c index f5d8c00..c1a4182 100644 --- a/src/option_bytes.c +++ b/src/option_bytes.c @@ -472,6 +472,57 @@ static int stlink_write_option_bytes_h7(stlink_t *sl, uint8_t *base, 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_wb(stlink_t *sl, uint8_t *base, + stm32_addr_t addr, uint32_t len) { + /* Write options bytes */ + uint32_t val; + int ret = 0; + (void)len; + uint32_t data; + + clear_flash_error(sl); + + while (len != 0) { + write_uint32((unsigned char *)&data, + *(uint32_t *)(base)); // write options bytes + + WLOG("Writing option bytes %#10x to %#10x\n", data, addr); + stlink_write_debug32(sl, addr, data); + wait_flash_busy(sl); + + if ((ret = check_flash_error(sl))) { + break; + } + + len -= 4; + addr += 4; + base += 4; + } + + // Set Options Start bit + stlink_read_debug32(sl, STM32WB_FLASH_CR, &val); + val |= (1 << STM32WB_FLASH_CR_OPTSTRT); + stlink_write_debug32(sl, STM32WB_FLASH_CR, val); + + wait_flash_busy(sl); + + ret = check_flash_error(sl); + + // Reload options + stlink_read_debug32(sl, STM32WB_FLASH_CR, &val); + val |= (1 << STM32WB_FLASH_CR_OBL_LAUNCH); + stlink_write_debug32(sl, STM32WB_FLASH_CR, val); + + return (ret); +} + /** * Write option bytes * @param sl @@ -536,6 +587,9 @@ int stlink_write_option_bytes(stlink_t *sl, stm32_addr_t addr, uint8_t *base, case STM32_FLASH_TYPE_H7: ret = stlink_write_option_bytes_h7(sl, base, addr, len); break; + case STM32_FLASH_TYPE_WB_WL: + ret = stlink_write_option_bytes_wb(sl, base, addr, len); + break; default: ELOG("Option bytes writing is currently not implemented for connected " "chip\n"); @@ -715,6 +769,42 @@ stlink_write_option_control_register_f7(stlink_t *sl, return ret; } +/** + * Write option bytes + * @param sl + * @param option_byte value to write + * @return 0 on success, -ve on failure. + */ +static int +stlink_write_option_control_register_wb(stlink_t *sl, + uint32_t option_control_register) { + int ret = 0; + + // Clear errors + clear_flash_error(sl); + + ILOG("Asked to write option control register 1 %#10x to %#010x.\n", + option_control_register, STM32WB_FLASH_OPTR); + + /* write option byte, ensuring we dont lock opt, and set strt bit */ + stlink_write_debug32(sl, STM32WB_FLASH_OPTR, option_control_register); + + wait_flash_busy(sl); + + // Set Options Start bit + uint32_t val = (1 << STM32WB_FLASH_CR_OPTSTRT); + stlink_write_debug32(sl, STM32WB_FLASH_CR, val); + + wait_flash_busy(sl); + + ret = check_flash_error(sl); + if (!ret) + ILOG("Wrote option bytes %#010x to %#010x!\n", option_control_register, + STM32WB_FLASH_OPTR); + + return ret; +} + /** * Write option bytes * @param sl @@ -746,6 +836,10 @@ int stlink_write_option_control_register32(stlink_t *sl, case STM32_FLASH_TYPE_F7: ret = stlink_write_option_control_register_f7(sl, option_control_register); break; + case STM32_FLASH_TYPE_WB_WL: + ret = + stlink_write_option_control_register_wb(sl, option_control_register); + break; default: ELOG("Option control register writing is currently not implemented for " "connected chip\n"); @@ -1003,6 +1097,18 @@ int stlink_read_option_control_register_f0(stlink_t *sl, return stlink_read_debug32(sl, FLASH_OBR, option_byte); } +/** + * Read option bytes + * @param sl + * @param option_byte value to read + * @return 0 on success, -ve on failure. + */ +int stlink_read_option_control_register_wb(stlink_t *sl, + uint32_t *option_byte) { + DLOG("@@@@ Read option control register byte from %#10x\n", STM32WB_FLASH_OPTR); + return stlink_read_debug32(sl, STM32WB_FLASH_OPTR, option_byte); +} + /** * Read option bytes * @param sl @@ -1021,6 +1127,8 @@ int stlink_read_option_control_register32(stlink_t *sl, uint32_t *option_byte) { return stlink_read_option_control_register_f0(sl, option_byte); case STM32_FLASH_TYPE_F7: return stlink_read_option_control_register_f7(sl, option_byte); + case STM32_FLASH_TYPE_WB_WL: + return stlink_read_option_control_register_wb(sl, option_byte); default: return -1; }