diff --git a/src/target/stm32l4.c b/src/target/stm32l4.c index 8935382..2a6fda5 100644 --- a/src/target/stm32l4.c +++ b/src/target/stm32l4.c @@ -124,6 +124,108 @@ struct stm32l4_flash { uint32_t bank1_start; }; +enum ID_STM32L4 { + ID_STM32L41 = 0x464u, /* RM0394, Rev.4 */ + ID_STM32L43 = 0x435u, /* RM0394, Rev.4 */ + ID_STM32L45 = 0x462u, /* RM0394, Rev.4 */ + ID_STM32L47 = 0x415u, /* RM0351, Rev.5 */ + ID_STM32L49 = 0x461u, /* RM0351, Rev.5 */ + ID_STM32L4R = 0x470u, /* RM0432, Rev.5 */ + ID_STM32G07 = 0x460u, /* RM0444/454, Rev.1 */ +}; + +enum FAM_STM32L4 { + FAM_STM32L4xx = 1, + FAM_STM32L4Rx = 2, + FAM_STM32G0x = 3, + FAM_STM32WBxx = 4, +}; + +#define DUAL_BANK 0x80u +#define RAM_COUNT_MSK 0x07u + +struct stm32l4_info { + char designator[10]; + uint16_t sram1; + uint16_t sram2; + uint16_t sram3; + enum ID_STM32L4 idcode; + enum FAM_STM32L4 family; + uint8_t flags; +}; + +struct stm32l4_info const L4info[] = { + { + .idcode = ID_STM32L41, + .family = FAM_STM32L4xx, + .designator = "STM32L41x", + .sram1 = 32, + .sram2 = 8, + .flags = 2, + }, + { + .idcode = ID_STM32L43, + .family = FAM_STM32L4xx, + .designator = "STM32L43x", + .sram1 = 48, + .sram2 = 16, + .flags = 2, + }, + { + .idcode = ID_STM32L45, + .family = FAM_STM32L4xx, + .designator = "STM32L45x", + .sram1 = 128, + .sram2 = 32, + .flags = 2, + }, + { + .idcode = ID_STM32L47, + .family = FAM_STM32L4xx, + .designator = "STM32L47x", + .sram1 = 96, + .sram2 = 32, + .flags = 2 | DUAL_BANK, + }, + { + .idcode = ID_STM32L49, + .family = FAM_STM32L4xx, + .designator = "STM32L49x", + .sram1 = 256, + .sram2 = 64, + .flags = 2 | DUAL_BANK, + }, + { + .idcode = ID_STM32L4R, + .family = FAM_STM32L4Rx, + .designator = "STM32L4Rx", + .sram1 = 192, + .sram2 = 64, + .sram3 = 384, + .flags = 3 | DUAL_BANK, + }, + { + .idcode = ID_STM32G07, + .family = FAM_STM32G0x, + .designator = "STM32G07", + .sram1 = 36, + .flags = 1, + }, + { + /* Terminator */ + .idcode = 0, + }, +}; + + +/* Retrieve chip basic information, just add to the vector to extend */ +static struct stm32l4_info const * stm32l4_get_chip_info(uint32_t idcode) { + struct stm32l4_info const *p = L4info; + while (p->idcode && (p->idcode != idcode)) + p++; + return p; +} + static void stm32l4_add_flash(target *t, uint32_t addr, size_t length, size_t blocksize, uint32_t bank1_start) @@ -141,61 +243,61 @@ static void stm32l4_add_flash(target *t, target_add_flash(t, f); } -enum ID_STM32L4 { - ID_STM32L43 = 0x435, /* RM0394, Rev.4 */ - ID_STM32L45 = 0x462, /* RM0394, Rev.4 */ - ID_STM32L41 = 0x464, /* RM0394, Rev.4 */ - ID_STM32L47 = 0x415, /* RM0351, Rev.5 */ - ID_STM32G07 = 0x460, /* RM0444/454, Rev.1 */ - ID_STM32L49 = 0x461, /* RM0351, Rev.5 */ - ID_STM32L4R = 0x470, /* RM0432, Rev.5 */ -}; - static bool stm32l4_attach(target *t) { if (!cortexm_attach(t)) return false; - bool dual_bank = false; - uint32_t idcodereg = STM32L4_DBGMCU_IDCODE_PHYS; - uint32_t size = 0; + /* Retrive chip information, no need to check return */ + struct stm32l4_info const *chip = stm32l4_get_chip_info(t->idcode); + + + uint32_t idcodereg = (chip->family == FAM_STM32G0x) + ? STM32G0_DBGMCU_IDCODE_PHYS + : STM32L4_DBGMCU_IDCODE_PHYS; - switch(t->idcode) { - case ID_STM32L47: - case ID_STM32L49: - case ID_STM32L4R: - dual_bank = true; - break; - case ID_STM32G07: - idcodereg = STM32G0_DBGMCU_IDCODE_PHYS; - break; - } /* Save DBGMCU_CR to restore it when detaching*/ uint32_t dbgmcu_cr = target_mem_read32(t, DBGMCU_CR(idcodereg)); t->target_storage = dbgmcu_cr; + /* Enable debugging during all low power modes*/ target_mem_write32(t, DBGMCU_CR(idcodereg), DBGMCU_CR_DBG_SLEEP | DBGMCU_CR_DBG_STANDBY | DBGMCU_CR_DBG_STOP); - size = (target_mem_read32(t, FLASH_SIZE_REG) & 0xffff); - if (dual_bank) { - uint32_t options = target_mem_read32(t, FLASH_OPTR); - if (t->idcode == ID_STM32L4R) { - /* rm0432 Rev. 2 does not mention 1 MB devices or explain DB1M.*/ - if (options & OR_DBANK) { - stm32l4_add_flash(t, 0x08000000, 0x00100000, 0x1000, 0x08100000); - stm32l4_add_flash(t, 0x08100000, 0x00100000, 0x1000, 0x08100000); - } else - stm32l4_add_flash(t, 0x08000000, 0x00200000, 0x2000, -1); + + /* Free previously loaded memory map */ + target_mem_map_free(t); + + /* Add RAM to memory map */ + if (chip->family == FAM_STM32G0x) { + target_add_ram(t, 0x20000000, chip->sram1 << 10); + } else { + target_add_ram(t, 0x10000000, chip->sram2 << 10); + /* All L4 beside L47 alias SRAM2 after SRAM1.*/ + uint32_t ramsize = (t->idcode == ID_STM32L47)? + chip->sram1 : (chip->sram1 + chip->sram2 + chip->sram3); + target_add_ram(t, 0x20000000, ramsize << 10); + } + + /* Add the flash to memory map. */ + uint32_t size = target_mem_read16(t, FLASH_SIZE_REG); + uint32_t options = target_mem_read32(t, FLASH_OPTR); + + if (chip->family == FAM_STM32L4Rx) { + /* rm0432 Rev. 2 does not mention 1 MB devices or explain DB1M.*/ + if (options & OR_DBANK) { + stm32l4_add_flash(t, 0x08000000, 0x00100000, 0x1000, 0x08100000); + stm32l4_add_flash(t, 0x08100000, 0x00100000, 0x1000, 0x08100000); + } else + stm32l4_add_flash(t, 0x08000000, 0x00200000, 0x2000, -1); + } else if (chip->flags & DUAL_BANK) { + if (options & OR_DUALBANK) { + uint32_t banksize = size << 9; + stm32l4_add_flash(t, 0x08000000 , banksize, 0x0800, 0x08000000 + banksize); + stm32l4_add_flash(t, 0x08000000 + banksize, banksize, 0x0800, 0x08000000 + banksize); } else { - if (options & OR_DUALBANK) { - uint32_t banksize = size << 9; - stm32l4_add_flash(t, 0x08000000 , banksize, 0x0800, 0x08000000 + banksize); - stm32l4_add_flash(t, 0x08000000 + banksize, banksize, 0x0800, 0x08000000 + banksize); - } else { - uint32_t banksize = size << 10; - stm32l4_add_flash(t, 0x08000000 , banksize, 0x0800, -1); - } + uint32_t banksize = size << 10; + stm32l4_add_flash(t, 0x08000000 , banksize, 0x0800, -1); } } else stm32l4_add_flash(t, 0x08000000, size << 10, 0x800, -1); @@ -218,71 +320,22 @@ static void stm32l4_detach(target *t) bool stm32l4_probe(target *t) { - const char* designator = NULL; - bool is_stm32g0 = false; - uint16_t sram1_size = 0; - uint16_t sram2_size = 0; - uint16_t sram3_size = 0; - uint32_t idcode_reg = STM32L4_DBGMCU_IDCODE_PHYS; ADIv5_AP_t *ap = cortexm_ap(t); if (ap->dp->idcode == 0x0BC11477) idcode_reg = STM32G0_DBGMCU_IDCODE_PHYS; uint32_t idcode = target_mem_read32(t, idcode_reg) & 0xfff; - switch(idcode) { - case ID_STM32G07: - designator = "STM32G07"; - is_stm32g0 = true; - sram1_size = 36; - break; - case ID_STM32L41: - designator = "STM32L41x"; - sram1_size = 32; - sram2_size = 8; - break; - case ID_STM32L43: - designator = "STM32L43x"; - sram1_size = 48; - sram2_size = 16; - break; - case ID_STM32L45: - designator = "STM32L45x"; - sram1_size = 128; - sram2_size = 32; - break; - case ID_STM32L47: - designator = "STM32L47x"; - sram1_size = 96; - sram2_size = 32; - break; - case ID_STM32L49: - designator = "STM32L49x"; - sram1_size = 256; - sram2_size = 64; - break; - case ID_STM32L4R: - designator = "STM32L4Rx"; - sram1_size = 192; - sram2_size = 64; - sram3_size = 384; - break; - default: + + struct stm32l4_info const *chip = stm32l4_get_chip_info(idcode); + + if( !chip->idcode ) /* Not found */ return false; - } + t->idcode = idcode; - t->driver = designator; + t->driver = chip->designator; t->attach = stm32l4_attach; t->detach = stm32l4_detach; - if (is_stm32g0) { - target_add_ram(t, 0x20000000, sram1_size << 10); - } else { - target_add_ram(t, 0x10000000, sram2_size << 10); - /* All L4 beside L47 alias SRAM2 after SRAM1.*/ - uint32_t ramsize = (idcode == ID_STM32L47)? - sram1_size : (sram1_size + sram2_size + sram3_size); - target_add_ram(t, 0x20000000, ramsize << 10); - } - target_add_commands(t, stm32l4_cmd_list, designator); + target_add_commands(t, stm32l4_cmd_list, chip->designator); return true; } @@ -413,7 +466,7 @@ static const uint8_t g0_i2offset[7] = { static bool stm32l4_option_write( target *t,const uint32_t *values, int len, const uint8_t *i2offset) { - tc_printf(t, "Device will loose connection. Rescan!\n"); + tc_printf(t, "Device will lose connection. Rescan!\n"); stm32l4_flash_unlock(t); target_mem_write32(t, FLASH_OPTKEYR, OPTKEY1); target_mem_write32(t, FLASH_OPTKEYR, OPTKEY2); @@ -459,7 +512,7 @@ static bool stm32l4_cmd_option(target *t, int argc, char *argv[]) const uint8_t *i2offset = l4_i2offset; if (t->idcode == 0x435) {/* L43x */ len = 5; - } else if (t->idcode == 0x460) {/* G07x */ + } else if (t->idcode == ID_STM32G07) {/* G07x */ i2offset = g0_i2offset; len = 7; } else {