From 46bf0abf77cca47133d3839460cc7679e0f78714 Mon Sep 17 00:00:00 2001 From: Guillaume Revaillot Date: Fri, 3 Apr 2020 16:13:35 +0200 Subject: [PATCH 1/6] add dual bank flash configuration info to chipid database. add a 'has_dual_bank' info to flash param, helping handling a couple of cases - selecting over dual bank specific code path without handling multiple chip id all over the code. - handling dual bank mode dynamic configuration --- include/stlink.h | 2 ++ include/stlink/chipid.h | 1 + src/common.c | 2 ++ 3 files changed, 5 insertions(+) diff --git a/include/stlink.h b/include/stlink.h index a69e357..ba7ef61 100644 --- a/include/stlink.h +++ b/include/stlink.h @@ -159,6 +159,8 @@ typedef struct flash_loader { int serial_size; enum stlink_flash_type flash_type; // stlink_chipid_params.flash_type, set by stlink_load_device_params(), values: STLINK_FLASH_TYPE_xxx + bool has_dual_bank; + stm32_addr_t flash_base; // STM32_FLASH_BASE, set by stlink_load_device_params() size_t flash_size; // calculated by stlink_load_device_params() size_t flash_pgsz; // stlink_chipid_params.flash_pagesize, set by stlink_load_device_params() diff --git a/include/stlink/chipid.h b/include/stlink/chipid.h index 8895cd4..d23596c 100644 --- a/include/stlink/chipid.h +++ b/include/stlink/chipid.h @@ -73,6 +73,7 @@ struct stlink_chipid_params { uint32_t chip_id; char *description; enum stlink_flash_type flash_type; + bool has_dual_bank; uint32_t flash_size_reg; uint32_t flash_pagesize; uint32_t sram_size; diff --git a/src/common.c b/src/common.c index b6496c0..5ccfcf0 100644 --- a/src/common.c +++ b/src/common.c @@ -885,7 +885,9 @@ int stlink_load_device_params(stlink_t *sl) { } else { sl->flash_size = flash_size * 1024; } + sl->flash_type = params->flash_type; + sl->has_dual_bank = params->has_dual_bank; sl->flash_pgsz = params->flash_pagesize; sl->sram_size = params->sram_size; sl->sys_base = params->bootrom_base; From 804c38ead8aef3e4a1640a82a9b9c01f4f60eed1 Mon Sep 17 00:00:00 2001 From: Guillaume Revaillot Date: Mon, 6 Apr 2020 11:18:09 +0200 Subject: [PATCH 2/6] stm32g4: read flash optr to get flash bank mode on cat3 devices. g4 cat3 devices can be configured in two mode via option bytes: - dual bank, 2x256kib, 2KiB pages. - single bank, 1x512KiB, 4KiB pages. in anycase, these have two banks, and need to be handled with more care. -> read optr after loading flash params to patch page size. -> in single bank mode, mass erase _must_ be triggered by applying MER1 and MER2 bits. erasing half of the flash will lead to a pgserr. --- src/chipid.c | 1 + src/common.c | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/src/chipid.c b/src/chipid.c index 426780c..b9d3933 100644 --- a/src/chipid.c +++ b/src/chipid.c @@ -562,6 +562,7 @@ static const struct stlink_chipid_params devices[] = { .chip_id = STLINK_CHIPID_STM32_G4_CAT3, .description = "G4 Category-3", .flash_type = STLINK_FLASH_TYPE_G4, + .has_dual_bank = true, .flash_size_reg = 0x1FFF75E0, // Section 47.2 .flash_pagesize = 0x800, // 2K (sec 3.3.1) // SRAM1 is 80k at 0x20000000 diff --git a/src/common.c b/src/common.c index 5ccfcf0..8cfbece 100644 --- a/src/common.c +++ b/src/common.c @@ -128,9 +128,13 @@ #define STM32Gx_FLASH_CR_OBL_LAUNCH (27) /* Forces the option byte loading */ #define STM32Gx_FLASH_CR_OPTLOCK (30) /* Options Lock */ #define STM32Gx_FLASH_CR_LOCK (31) /* FLASH_CR Lock */ + // G0/G4 FLASH status register #define STM32Gx_FLASH_SR_BSY (16) /* FLASH_SR Busy */ +// G4 FLASH option register +#define STM32G4_FLASH_OPTR_DBANK (22) /* FLASH_OPTR Dual Bank Mode */ + // WB (RM0434) #define STM32WB_FLASH_REGS_ADDR ((uint32_t)0x58004000) #define STM32WB_FLASH_ACR (STM32WB_FLASH_REGS_ADDR + 0x00) @@ -899,6 +903,14 @@ int stlink_load_device_params(stlink_t *sl) { sl->sram_size = 0x1000; } + if (sl->chip_id == STLINK_CHIPID_STM32_G4_CAT3) { + uint32_t flash_optr; + stlink_read_debug32(sl, STM32Gx_FLASH_OPTR, &flash_optr); + if (!(flash_optr & (1 << STM32G4_FLASH_OPTR_DBANK))) { + sl->flash_pgsz <<= 1; + } + } + #if 0 // Old code -- REW ILOG("Device connected is: %s, id %#x\n", params->description, chip_id); From 55ca316cd61a959746d809e1d9b20fa485ec39d8 Mon Sep 17 00:00:00 2001 From: Guillaume Revaillot Date: Mon, 6 Apr 2020 11:09:26 +0200 Subject: [PATCH 3/6] stm32g4: handle mass erase. toggle proper MER bits, taking in account dual bank mode enabled or not. --- src/common.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/common.c b/src/common.c index 8cfbece..b1461c4 100644 --- a/src/common.c +++ b/src/common.c @@ -120,6 +120,7 @@ #define STM32Gx_FLASH_CR_PNB (3) /* Page number */ #define STM32G0_FLASH_CR_PNG_LEN (5) /* STM32G0: 5 page number bits */ #define STM32G4_FLASH_CR_PNG_LEN (7) /* STM32G4: 7 page number bits */ +#define STM32Gx_FLASH_CR_MER2 (15) /* Mass erase (2nd bank)*/ #define STM32Gx_FLASH_CR_STRT (16) /* Start */ #define STM32Gx_FLASH_CR_OPTSTRT (17) /* Start of modification of option bytes */ #define STM32Gx_FLASH_CR_FSTPG (18) /* Fast programming */ @@ -519,7 +520,10 @@ static void set_flash_cr_mer(stlink_t *sl, bool v) { } else if (sl->flash_type == STLINK_FLASH_TYPE_G0 || sl->flash_type == STLINK_FLASH_TYPE_G4) { cr_reg = STM32Gx_FLASH_CR; - cr_mer = (1 << FLASH_CR_MER); + cr_mer = (1 << STM32Gx_FLASH_CR_MER1); + if (sl->has_dual_bank) { + cr_mer |= (1 << STM32Gx_FLASH_CR_MER2); + } cr_pg = (1 << FLASH_CR_PG); } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { cr_reg = STM32WB_FLASH_CR; From 6a2bf1cbe21cf3409926c24f360210ba14d469ff Mon Sep 17 00:00:00 2001 From: Guillaume Revaillot Date: Fri, 3 Apr 2020 14:50:55 +0200 Subject: [PATCH 4/6] stm32g4: allow mass erase. --- src/common.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/common.c b/src/common.c index b1461c4..6016603 100644 --- a/src/common.c +++ b/src/common.c @@ -1980,7 +1980,6 @@ int stlink_erase_flash_mass(stlink_t *sl) { /* TODO: User MER bit to mass-erase G0, G4, WB series. */ if (sl->flash_type == STLINK_FLASH_TYPE_L0 || sl->flash_type == STLINK_FLASH_TYPE_G0 || - sl->flash_type == STLINK_FLASH_TYPE_G4 || sl->flash_type == STLINK_FLASH_TYPE_WB) { /* erase each page */ int i = 0, num_pages = (int) sl->flash_size/sl->flash_pgsz; From 98cd484854b8842452759f8752dea5ca2e98c6ea Mon Sep 17 00:00:00 2001 From: Guillaume Revaillot Date: Mon, 6 Apr 2020 14:00:54 +0200 Subject: [PATCH 5/6] common: add flash error check. use it for mass erase. only implement it for g0/g4 for now, but this is most probably a must for all chips. --- src/common.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/common.c b/src/common.c index 6016603..fd73c16 100644 --- a/src/common.c +++ b/src/common.c @@ -131,7 +131,9 @@ #define STM32Gx_FLASH_CR_LOCK (31) /* FLASH_CR Lock */ // G0/G4 FLASH status register +#define STM32Gx_FLASH_SR_ERROR_MASK (0x3fa) #define STM32Gx_FLASH_SR_BSY (16) /* FLASH_SR Busy */ +#define STM32Gx_FLASH_SR_EOP (0) /* FLASH_EOP End of Operation */ // G4 FLASH option register #define STM32G4_FLASH_OPTR_DBANK (22) /* FLASH_OPTR Dual Bank Mode */ @@ -688,6 +690,22 @@ static void wait_flash_busy_progress(stlink_t *sl) { fprintf(stdout, "\n"); } +static int check_flash_error(stlink_t *sl) +{ + uint32_t res = 0; + if ((sl->flash_type == STLINK_FLASH_TYPE_G0) || + (sl->flash_type == STLINK_FLASH_TYPE_G4)) { + res = read_flash_sr(sl) & STM32Gx_FLASH_SR_ERROR_MASK; + } + + if (res) { + ELOG("Flash programming error : %#010x\n", res); + return -1; + } + + return 0; +} + static inline unsigned int is_flash_eop(stlink_t *sl) { return read_flash_sr(sl) & (1 << FLASH_SR_EOP); } @@ -2018,6 +2036,8 @@ int stlink_erase_flash_mass(stlink_t *sl) { /* wait for completion */ wait_flash_busy_progress(sl); + check_flash_error(sl); + /* relock the flash */ lock_flash(sl); From 4437314d3383798d4518fe169c7de9db9ac39dc5 Mon Sep 17 00:00:00 2001 From: Guillaume Revaillot Date: Mon, 6 Apr 2020 16:45:26 +0200 Subject: [PATCH 6/6] enable mass erase for g0, worksforme --- src/common.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/common.c b/src/common.c index fd73c16..26202fc 100644 --- a/src/common.c +++ b/src/common.c @@ -1997,7 +1997,6 @@ int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr) int stlink_erase_flash_mass(stlink_t *sl) { /* TODO: User MER bit to mass-erase G0, G4, WB series. */ if (sl->flash_type == STLINK_FLASH_TYPE_L0 || - sl->flash_type == STLINK_FLASH_TYPE_G0 || sl->flash_type == STLINK_FLASH_TYPE_WB) { /* erase each page */ int i = 0, num_pages = (int) sl->flash_size/sl->flash_pgsz;