From e5be10270461f2a0199804c3ae33bab2af156f9b Mon Sep 17 00:00:00 2001 From: Rick van Rein <rick@openfortress.nl> Date: Tue, 24 Oct 2023 16:34:07 +0200 Subject: [PATCH] Write and erase flash when the Internal RC Oscillator is off - By first enabling it - This worked for me on STM32F103 - Quite likely not the best structure - Willing to take instructions, or hand it over Fixed the check to include HSIRDY alongside HSION - When writing HSION, the HSIRDY takes some time to come up - This may in theory have delays - It is entirely proper to check the bits together; they are "ist & soll" --- inc/stm32.h | 1 + src/stlink-lib/common_flash.c | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/inc/stm32.h b/inc/stm32.h index cf9a8a2ad..902977655 100644 --- a/inc/stm32.h +++ b/inc/stm32.h @@ -189,6 +189,7 @@ enum stm32_chipids { #define STM32WB_DBGMCU_APB1FZR1_WWDG_STOP 11 #define STM32WB_DBGMCU_APB1FZR1_IWDG_STOP 12 +#define STM32F1_RCC_CR 0x40021000 #define STM32F1_RCC_AHBENR 0x40021014 #define STM32F1_RCC_DMAEN 0x00000003 // DMA2EN | DMA1EN diff --git a/src/stlink-lib/common_flash.c b/src/stlink-lib/common_flash.c index 3038b53e7..4cdaf4916 100644 --- a/src/stlink-lib/common_flash.c +++ b/src/stlink-lib/common_flash.c @@ -424,6 +424,9 @@ static void unlock_flash(stlink_t *sl) { uint32_t key_reg, key2_reg = 0; uint32_t flash_key1 = FLASH_KEY1; uint32_t flash_key2 = FLASH_KEY2; + uint32_t clk_reg = 0; + uint32_t hsion = 0x00000001; + uint32_t hsirdy = 0x00000002; /* The unlock sequence consists of 2 write cycles where 2 key values are * written to the FLASH_KEYR register. An invalid sequence results in a * definitive lock of the FPEC block until next reset. @@ -431,6 +434,7 @@ static void unlock_flash(stlink_t *sl) { if (sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3) { key_reg = FLASH_KEYR; + clk_reg = STM32F1_RCC_CR; } else if (sl->flash_type == STM32_FLASH_TYPE_F1_XL) { key_reg = FLASH_KEYR; key2_reg = FLASH_KEYR2; @@ -468,6 +472,22 @@ static void unlock_flash(stlink_t *sl) { return; } + /* First make sure that the HSI is running, the internal RC clock. + * This is a requisite for flash erase and write. + */ + if (clk_reg) { + uint32_t oldcr; + stlink_read_debug32 (sl, clk_reg, &oldcr); + while (0 != ((hsion | hsirdy) & ~oldcr)) { + stlink_write_debug32 (sl, clk_reg, oldcr | hsion); + stlink_read_debug32 (sl, clk_reg, &oldcr); + } + } else { + WLOG("unsure about internal oscillator activity, flash write and erase may block\n"); + } + + /* Now unlock the flash itself. + */ stlink_write_debug32(sl, key_reg, flash_key1); stlink_write_debug32(sl, key_reg, flash_key2);