From 9b4d45edb1f5631b30d3e305b7853063173eba04 Mon Sep 17 00:00:00 2001 From: Laurent GONZALEZ Date: Fri, 26 Jun 2020 16:40:00 +0200 Subject: [PATCH] Add L5 support --- inc/stlink.h | 1 + inc/stm32.h | 1 + src/common.c | 105 ++++++++++++++++++++++++++++++++++++++++ src/stlink-lib/chipid.c | 14 ++++++ src/stlink-lib/chipid.h | 1 + 5 files changed, 122 insertions(+) diff --git a/inc/stlink.h b/inc/stlink.h index 140d68866..5957995bd 100644 --- a/inc/stlink.h +++ b/inc/stlink.h @@ -123,6 +123,7 @@ enum stlink_flash_type { STLINK_FLASH_TYPE_F4, // used by f2, f4, f7 */ STLINK_FLASH_TYPE_L0, // l0, l1 */ STLINK_FLASH_TYPE_L4, // l4, l4+ */ + STLINK_FLASH_TYPE_L5, // l5x2 */ STLINK_FLASH_TYPE_G0, STLINK_FLASH_TYPE_G4, STLINK_FLASH_TYPE_WB diff --git a/inc/stm32.h b/inc/stm32.h index 36c14ee23..eab914a2c 100644 --- a/inc/stm32.h +++ b/inc/stm32.h @@ -20,5 +20,6 @@ #define STM32_F2_OPTION_BYTES_BASE ((uint32_t)0x1FFFC000) #define STM32_L4_OPTION_BYTES_BASE ((uint32_t)0x1FFF7800) #define STM32_L1_OPTION_BYTES_BASE ((uint32_t)0x1FF80000) +#define STM32_L5_OPTION_BYTES_BASE ((uint32_t)0x40022040) #endif // STM32_H diff --git a/src/common.c b/src/common.c index 3459a53a0..4aaeaa83f 100644 --- a/src/common.c +++ b/src/common.c @@ -191,6 +191,47 @@ // WB Flash status register. #define STM32WB_FLASH_SR_BSY (16) /* FLASH_SR Busy */ +// L5 (RM0438) +#define STM32L5_FLASH_REGS_ADDR ((uint32_t)0x40022000) +#define STM32L5_FLASH_ACR (STM32L5_FLASH_REGS_ADDR + 0x00) +#define STM32L5_FLASH_PDKEYR (STM32L5_FLASH_REGS_ADDR + 0x04) +#define STM32L5_FLASH_NSKEYR (STM32L5_FLASH_REGS_ADDR + 0x08) +#define STM32L5_FLASH_SECKEYR (STM32L5_FLASH_REGS_ADDR + 0x0C) +#define STM32L5_FLASH_OPTKEYR (STM32L5_FLASH_REGS_ADDR + 0x10) +#define STM32L5_FLASH_LVEKEYR (STM32L5_FLASH_REGS_ADDR + 0x14) +#define STM32L5_FLASH_NSSR (STM32L5_FLASH_REGS_ADDR + 0x20) +#define STM32L5_FLASH_SECSR (STM32L5_FLASH_REGS_ADDR + 0x24) +#define STM32L5_FLASH_NSCR (STM32L5_FLASH_REGS_ADDR + 0x28) +#define STM32L5_FLASH_SECCR (STM32L5_FLASH_REGS_ADDR + 0x2C) +#define STM32L5_FLASH_ECCR (STM32L5_FLASH_REGS_ADDR + 0x30) +#define STM32L5_FLASH_OPTR (STM32L5_FLASH_REGS_ADDR + 0x40) +#define STM32L5_FLASH_NSBOOTADDR0R (STM32L5_FLASH_REGS_ADDR + 0x44) +#define STM32L5_FLASH_NSBOOTADDR1R (STM32L5_FLASH_REGS_ADDR + 0x48) +#define STM32L5_FLASH_SECBOOTADDR0R (STM32L5_FLASH_REGS_ADDR + 0x4C) +#define STM32L5_FLASH_SECWM1R1 (STM32L5_FLASH_REGS_ADDR + 0x50) +#define STM32L5_FLASH_SECWM1R2 (STM32L5_FLASH_REGS_ADDR + 0x54) +#define STM32L5_FLASH_WRP1AR (STM32L5_FLASH_REGS_ADDR + 0x58) +#define STM32L5_FLASH_WRP1BR (STM32L5_FLASH_REGS_ADDR + 0x5C) +#define STM32L5_FLASH_SECWM2R1 (STM32L5_FLASH_REGS_ADDR + 0x60) +#define STM32L5_FLASH_SECWM2R2 (STM32L5_FLASH_REGS_ADDR + 0x64) +#define STM32L5_FLASH_WRP2AR (STM32L5_FLASH_REGS_ADDR + 0x68) +#define STM32L5_FLASH_WRP2BR (STM32L5_FLASH_REGS_ADDR + 0x6C) +#define STM32L5_FLASH_SECBB1Rx (STM32L5_FLASH_REGS_ADDR + 0x80) +#define STM32L5_FLASH_SECBB2Rx (STM32L5_FLASH_REGS_ADDR + 0xA0) +#define STM32L5_FLASH_SECHDPCR (STM32L5_FLASH_REGS_ADDR + 0xC0) +#define STM32L5_FLASH_PRIVCFGR (STM32L5_FLASH_REGS_ADDR + 0xC4) + +// L5 Flash control register. +#define STM32L5_FLASH_CR_MER1 (2) /* Mass erase */ +#define STM32L5_FLASH_CR_MER2 (15) /* Mass erase (2nd bank)*/ +#define STM32L5_FLASH_CR_STRT (16) /* FLASH_CR Start */ +#define STM32L5_FLASH_CR_OPTLOCK (30) /* FLASH_CR Option Lock */ +#define STM32L5_FLASH_CR_LOCK (31) /* FLASH_CR Lock */ +// L5 Flash status register. +#define STM32L5_FLASH_SR_BSY (16) /* FLASH_SR Busy */ +// L5 Flash option register +#define STM32L5_FLASH_OPTR_DBANK (22) /* FLASH_OPTR Dual Bank Mode */ + // 32L4 register base is at FLASH_REGS_ADDR (0x40022000) #define STM32L4_FLASH_KEYR (FLASH_REGS_ADDR + 0x08) #define STM32L4_FLASH_OPTKEYR (FLASH_REGS_ADDR + 0x0C) @@ -352,6 +393,8 @@ static inline uint32_t read_flash_cr(stlink_t *sl) { reg = STM32Gx_FLASH_CR; } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { reg = STM32WB_FLASH_CR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_L5) { + reg = STM32L5_FLASH_NSCR; } else { reg = FLASH_CR; } @@ -399,6 +442,9 @@ static inline unsigned int is_flash_locked(stlink_t *sl) { } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { cr_reg = STM32WB_FLASH_CR; cr_lock_shift = STM32WB_FLASH_CR_LOCK; + } else if (sl->flash_type == STLINK_FLASH_TYPE_L5) { + cr_reg = STM32L5_FLASH_NSCR; + cr_lock_shift = STM32L5_FLASH_CR_LOCK; } else { ELOG("unsupported flash method, abort\n"); return(-1); @@ -433,6 +479,8 @@ static void unlock_flash(stlink_t *sl) { key_reg = STM32Gx_FLASH_KEYR; } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { key_reg = STM32WB_FLASH_KEYR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_L5) { + key_reg = STM32L5_FLASH_NSKEYR; } else { ELOG("unsupported flash method, abort\n"); return; @@ -485,6 +533,9 @@ static void lock_flash(stlink_t *sl) { } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { cr_reg = STM32WB_FLASH_CR; cr_lock_shift = STM32WB_FLASH_CR_LOCK; + } else if (sl->flash_type == STLINK_FLASH_TYPE_L5) { + cr_reg = STM32L5_FLASH_NSCR; + cr_lock_shift = STM32L5_FLASH_CR_LOCK; } else { ELOG("unsupported flash method, abort\n"); return; @@ -533,6 +584,10 @@ static bool is_flash_option_locked(stlink_t *sl) { optcr_reg = STM32WB_FLASH_CR; optlock_shift = STM32WB_FLASH_CR_OPTLOCK; break; + case STLINK_FLASH_TYPE_L5: + optcr_reg = STM32L5_FLASH_NSCR; + optlock_shift = STM32L5_FLASH_CR_OPTLOCK; + break; default: ELOG("unsupported flash method, abort\n"); return(-1); @@ -580,6 +635,10 @@ static int lock_flash_option(stlink_t *sl) { optcr_reg = STM32WB_FLASH_CR; optlock_shift = STM32WB_FLASH_CR_OPTLOCK; break; + case STLINK_FLASH_TYPE_L5: + optcr_reg = STM32L5_FLASH_NSCR; + optlock_shift = STM32L5_FLASH_CR_OPTLOCK; + break; default: ELOG("unsupported flash method, abort\n"); return(-1); @@ -627,6 +686,9 @@ static int unlock_flash_option(stlink_t *sl) { case STLINK_FLASH_TYPE_WB: optkey_reg = STM32WB_FLASH_OPT_KEYR; break; + case STLINK_FLASH_TYPE_L5: + optkey_reg = STM32L5_FLASH_OPTKEYR; + break; default: ELOG("unsupported flash method, abort\n"); @@ -674,6 +736,9 @@ static void set_flash_cr_pg(stlink_t *sl) { } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { cr_reg = STM32WB_FLASH_CR; x |= (1 << FLASH_CR_PG); + } else if (sl->flash_type == STLINK_FLASH_TYPE_L5) { + cr_reg = STM32L5_FLASH_NSCR; + x |= (1 << FLASH_CR_PG); } else { cr_reg = FLASH_CR; x = (1 << FLASH_CR_PG); @@ -694,6 +759,8 @@ static void clear_flash_cr_pg(stlink_t *sl) { cr_reg = STM32Gx_FLASH_CR; } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { cr_reg = STM32WB_FLASH_CR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_L5) { + cr_reg = STM32L5_FLASH_NSCR; } else { cr_reg = FLASH_CR; } @@ -710,6 +777,8 @@ static void set_flash_cr_per(stlink_t *sl) { cr_reg = STM32Gx_FLASH_CR; } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { cr_reg = STM32WB_FLASH_CR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_L5) { + cr_reg = STM32L5_FLASH_NSCR; } else { cr_reg = FLASH_CR; } @@ -732,6 +801,8 @@ static void clear_flash_cr_per(stlink_t *sl) { cr_reg = STM32Gx_FLASH_CR; } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { cr_reg = STM32WB_FLASH_CR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_L5) { + cr_reg = STM32L5_FLASH_NSCR; } else { cr_reg = FLASH_CR; } @@ -765,6 +836,13 @@ static void set_flash_cr_mer(stlink_t *sl, bool v) { cr_reg = STM32WB_FLASH_CR; cr_mer = (1 << FLASH_CR_MER); cr_pg = (1 << FLASH_CR_PG); + } else if (sl->flash_type == STLINK_FLASH_TYPE_L5) { + cr_reg = STM32L5_FLASH_NSCR; + cr_mer = (1 << STM32L5_FLASH_CR_MER1); + if (sl->has_dual_bank) { + cr_mer |= (1 << STM32L5_FLASH_CR_MER2); + } + cr_pg = (1 << FLASH_CR_PG); } else { cr_reg = FLASH_CR; cr_mer = (1 << FLASH_CR_MER); @@ -840,6 +918,9 @@ static void set_flash_cr_strt(stlink_t *sl) { } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { cr_reg = STM32WB_FLASH_CR; cr_strt = (1 << STM32WB_FLASH_CR_STRT); + } else if (sl->flash_type == STLINK_FLASH_TYPE_L5) { + cr_reg = STM32L5_FLASH_NSCR; + cr_strt = (1 << STM32L5_FLASH_CR_STRT); } else { cr_reg = FLASH_CR; cr_strt = (1 << FLASH_CR_STRT); @@ -875,6 +956,8 @@ static inline uint32_t read_flash_sr(stlink_t *sl) { sr_reg = STM32Gx_FLASH_SR; } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { sr_reg = STM32WB_FLASH_SR; + } else if (sl->flash_type == STLINK_FLASH_TYPE_L5) { + sr_reg = STM32L5_FLASH_NSSR; } else { ELOG("unsupported flash method, abort"); return(-1); @@ -907,6 +990,8 @@ static inline unsigned int is_flash_busy(stlink_t *sl) { sr_busy_shift = STM32Gx_FLASH_SR_BSY; } else if (sl->flash_type == STLINK_FLASH_TYPE_WB) { sr_busy_shift = STM32WB_FLASH_SR_BSY; + } else if (sl->flash_type == STLINK_FLASH_TYPE_L5) { + sr_busy_shift = STM32L5_FLASH_SR_BSY; } else { ELOG("unsupported flash method, abort"); return(-1); @@ -1108,6 +1193,9 @@ int stlink_chip_id(stlink_t *sl, uint32_t *chip_id) { ret = stlink_read_debug32(sl, 0x40015800, chip_id); } + if (*chip_id == 0) + ret = stlink_read_debug32(sl, 0xE0044000, chip_id); //Try L5 DBGMCU_IDCODE + return(ret); } @@ -1224,6 +1312,14 @@ int stlink_load_device_params(stlink_t *sl) { if (!(flash_optr & (1 << STM32G4_FLASH_OPTR_DBANK))) { sl->flash_pgsz <<= 1; } } + if (sl->chip_id == STLINK_CHIPID_STM32_L5x2) { + uint32_t flash_optr; + stlink_read_debug32(sl, STM32L5_FLASH_OPTR, &flash_optr); + if (!(flash_optr & (1 << STM32L5_FLASH_OPTR_DBANK))) { + sl->flash_pgsz <<= 1; + } + } + #if 0 // Old code -- REW ILOG("Device connected is: %s, id %#x\n", params->description, chip_id); @@ -2259,6 +2355,7 @@ int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr) { val |= (1 << 0) | (1 << 1) | (1 << 2); stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val); } else if (sl->flash_type == STLINK_FLASH_TYPE_WB || + sl->flash_type == STLINK_FLASH_TYPE_L5 || sl->flash_type == STLINK_FLASH_TYPE_G0 || sl->flash_type == STLINK_FLASH_TYPE_G4) { uint32_t val; @@ -2276,6 +2373,13 @@ int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr) { val |= ((flash_page & 0xFF) << 3); stlink_write_debug32(sl, STM32WB_FLASH_CR, val); + } else if (sl->flash_type == STLINK_FLASH_TYPE_L5) { + uint32_t flash_page = ((flashaddr - STM32_FLASH_BASE) / (uint32_t)(sl->flash_pgsz)); + stlink_read_debug32(sl, STM32L5_FLASH_NSCR, &val); + // sec 6.9.9 - PNB[6:0] is offset by 3. PER is 0x2. + val &= ~(0x7F << 3); + val |= ((flash_page & 0x7F) << 3) | ( 1 << FLASH_CR_PER ); + stlink_write_debug32(sl, STM32L5_FLASH_NSCR, val); } else if (sl->flash_type == STLINK_FLASH_TYPE_G0) { uint32_t flash_page = ((flashaddr - STM32_FLASH_BASE) / (uint32_t)(sl->flash_pgsz)); stlink_read_debug32(sl, STM32Gx_FLASH_CR, &val); @@ -2615,6 +2719,7 @@ int stlink_write_flash( // STM32F4END } else if (sl->flash_type == STLINK_FLASH_TYPE_WB || + sl->flash_type == STLINK_FLASH_TYPE_L5 || sl->flash_type == STLINK_FLASH_TYPE_G0 || sl->flash_type == STLINK_FLASH_TYPE_G4) { fprintf(stdout, "Writing\r\n"); diff --git a/src/stlink-lib/chipid.c b/src/stlink-lib/chipid.c index bf0a56c96..fb9e5b70e 100644 --- a/src/stlink-lib/chipid.c +++ b/src/stlink-lib/chipid.c @@ -612,6 +612,20 @@ static const struct stlink_chipid_params devices[] = { .bootrom_base = 0x1fff0000, // see the memory map .bootrom_size = 0x7000 }, + { + // STM32L5x2 (from RM0438) + .chip_id = STLINK_CHIPID_STM32_L5x2, + .description = "L5x2", + .flash_type = STLINK_FLASH_TYPE_L5, + .has_dual_bank = true, + .flash_size_reg = 0x0BFA05E0, + .flash_pagesize = 0x800, // 2 banks of 128 x 2K pages + .sram_size = 0x40000, + .bootrom_base = 0x0BF90000, // See the memory map + .bootrom_size = 0x8000, + .option_base = STM32_L5_OPTION_BYTES_BASE, + .option_size = 4, + }, { // unknown .chip_id = STLINK_CHIPID_UNKNOWN, diff --git a/src/stlink-lib/chipid.h b/src/stlink-lib/chipid.h index b591f0012..71b7a2167 100644 --- a/src/stlink-lib/chipid.h +++ b/src/stlink-lib/chipid.h @@ -63,6 +63,7 @@ enum stlink_stm32_chipids { STLINK_CHIPID_STM32_G4_CAT2 = 0x468, /* See: RM 0440 s46.6.1 "MCU device ID code" */ STLINK_CHIPID_STM32_G4_CAT3 = 0x469, STLINK_CHIPID_STM32_L4RX = 0x470, /* ID found on the STM32L4R9I-DISCO board */ + STLINK_CHIPID_STM32_L5x2 = 0x472, STLINK_CHIPID_STM32_WB55 = 0x495 };