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/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 b6496c0..26202fc 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 */ @@ -128,8 +129,14 @@ #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_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 */ // WB (RM0434) #define STM32WB_FLASH_REGS_ADDR ((uint32_t)0x58004000) @@ -515,7 +522,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; @@ -680,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); } @@ -885,7 +911,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; @@ -897,6 +925,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); @@ -1961,8 +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_G4 || sl->flash_type == STLINK_FLASH_TYPE_WB) { /* erase each page */ int i = 0, num_pages = (int) sl->flash_size/sl->flash_pgsz; @@ -2001,6 +2035,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);