From 0498621a46e1d2638d4a4c1771fbc84cdb9b4cdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Mellstr=C3=B6m?= Date: Sun, 14 May 2017 12:42:14 +0200 Subject: [PATCH] Added support for flashing second bank on STM32F10x_XL (#592) --- include/stlink.h | 3 +- src/chipid.c | 2 +- src/common.c | 88 ++++++++++++++++++++++++++++++++++++++++++---- src/flash_loader.c | 12 +++++-- 4 files changed, 95 insertions(+), 10 deletions(-) diff --git a/include/stlink.h b/include/stlink.h index 813086e15..ac0bfe190 100644 --- a/include/stlink.h +++ b/include/stlink.h @@ -83,7 +83,8 @@ extern "C" { STLINK_FLASH_TYPE_F0, STLINK_FLASH_TYPE_L0, STLINK_FLASH_TYPE_F4, - STLINK_FLASH_TYPE_L4 + STLINK_FLASH_TYPE_L4, + STLINK_FLASH_TYPE_F1_XL, }; struct stlink_reg { diff --git a/src/chipid.c b/src/chipid.c index 15b2f563a..808a23c52 100644 --- a/src/chipid.c +++ b/src/chipid.c @@ -255,7 +255,7 @@ static const struct stlink_chipid_params devices[] = { { .chip_id = STLINK_CHIPID_STM32_F1_XL, .description = "F1 XL-density device", - .flash_type = STLINK_FLASH_TYPE_F0, + .flash_type = STLINK_FLASH_TYPE_F1_XL, .flash_size_reg = 0x1ffff7e0, .flash_pagesize = 0x800, .sram_size = 0x18000, diff --git a/src/common.c b/src/common.c index 74b96f5da..b2a5db55f 100644 --- a/src/common.c +++ b/src/common.c @@ -35,6 +35,13 @@ #define FLASH_OBR (FLASH_REGS_ADDR + 0x1c) #define FLASH_WRPR (FLASH_REGS_ADDR + 0x20) +// STM32F10x_XL has two flash memory banks with separate registers to control the second bank. +#define FLASH_KEYR2 (FLASH_REGS_ADDR + 0x44) +#define FLASH_SR2 (FLASH_REGS_ADDR + 0x4c) +#define FLASH_CR2 (FLASH_REGS_ADDR + 0x50) +#define FLASH_AR2 (FLASH_REGS_ADDR + 0x54) +#define FLASH_BANK2_START_ADDR 0x08080000 + // For STM32F05x, the RDPTR_KEY may be wrong, but as it is not used anywhere... #define FLASH_RDPTR_KEY 0x00a5 #define FLASH_KEY1 0x45670123 @@ -189,6 +196,15 @@ static inline uint32_t read_flash_cr(stlink_t *sl) { return res; } +static inline uint32_t read_flash_cr2(stlink_t *sl) { + uint32_t res; + stlink_read_debug32(sl, FLASH_CR2, &res); +#if DEBUG_FLASH + fprintf(stdout, "CR2:0x%x\n", res); +#endif + return res; +} + static inline unsigned int is_flash_locked(stlink_t *sl) { /* return non zero for true */ uint32_t cr_lock_shift, cr = read_flash_cr(sl); @@ -219,6 +235,11 @@ static void unlock_flash(stlink_t *sl) { stlink_write_debug32(sl, key_reg, FLASH_KEY1); stlink_write_debug32(sl, key_reg, FLASH_KEY2); + + if (sl->flash_type == STLINK_FLASH_TYPE_F1_XL) { + stlink_write_debug32(sl, FLASH_KEYR2, FLASH_KEY1); + stlink_write_debug32(sl, FLASH_KEYR2, FLASH_KEY2); + } } static int unlock_flash_if(stlink_t *sl) { @@ -251,6 +272,11 @@ static void lock_flash(stlink_t *sl) { n = read_flash_cr(sl) | (1 << cr_lock_shift); stlink_write_debug32(sl, cr_reg, n); + + if (sl->flash_type == STLINK_FLASH_TYPE_F1_XL) { + n = read_flash_cr2(sl) | (1 << cr_lock_shift); + stlink_write_debug32(sl, FLASH_CR2, n); + } } @@ -293,6 +319,11 @@ static void set_flash_cr_per(stlink_t *sl) { stlink_write_debug32(sl, FLASH_CR, n); } +static void set_flash_cr2_per(stlink_t *sl) { + const uint32_t n = 1 << FLASH_CR_PER; + stlink_write_debug32(sl, FLASH_CR2, n); +} + static void __attribute__((unused)) clear_flash_cr_per(stlink_t *sl) { const uint32_t n = read_flash_cr(sl) & ~(1 << FLASH_CR_PER); stlink_write_debug32(sl, FLASH_CR, n); @@ -367,6 +398,14 @@ static void set_flash_cr_strt(stlink_t *sl) { stlink_write_debug32(sl, cr_reg, val); } +static void set_flash_cr2_strt(stlink_t *sl) { + uint32_t val; + + stlink_read_debug32(sl, FLASH_CR2, &val); + val |= 1 << FLASH_CR_STRT; + stlink_write_debug32(sl, FLASH_CR2, val); +} + static inline uint32_t read_flash_sr(stlink_t *sl) { uint32_t res, sr_reg; @@ -382,8 +421,15 @@ static inline uint32_t read_flash_sr(stlink_t *sl) { return res; } +static inline uint32_t read_flash_sr2(stlink_t *sl) { + uint32_t res; + stlink_read_debug32(sl, FLASH_SR2, &res); + return res; +} + static inline unsigned int is_flash_busy(stlink_t *sl) { uint32_t sr_busy_shift; + unsigned int res; if (sl->flash_type == STLINK_FLASH_TYPE_F4) sr_busy_shift = FLASH_F4_SR_BSY; @@ -392,7 +438,13 @@ static inline unsigned int is_flash_busy(stlink_t *sl) { else sr_busy_shift = FLASH_SR_BSY; - return read_flash_sr(sl) & (1 << sr_busy_shift); + res = read_flash_sr(sl) & (1 << sr_busy_shift); + + if (sl->flash_type == STLINK_FLASH_TYPE_F1_XL) { + res |= read_flash_sr2(sl) & (1 << sr_busy_shift); + } + + return res; } static void wait_flash_busy(stlink_t *sl) { @@ -435,6 +487,10 @@ static inline void write_flash_ar(stlink_t *sl, uint32_t n) { stlink_write_debug32(sl, FLASH_AR, n); } +static inline void write_flash_ar2(stlink_t *sl, uint32_t n) { + stlink_write_debug32(sl, FLASH_AR2, n); +} + static inline void write_flash_cr_psiz(stlink_t *sl, uint32_t n) { uint32_t x = read_flash_cr(sl); x &= ~(0x03 << 8); @@ -1531,7 +1587,7 @@ int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr) stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); 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_F0) { + } else if ((sl->flash_type == STLINK_FLASH_TYPE_F0) || ((sl->flash_type == STLINK_FLASH_TYPE_F1_XL) && (flashaddr < FLASH_BANK2_START_ADDR))) { /* wait for ongoing op to finish */ wait_flash_busy(sl); @@ -1550,6 +1606,27 @@ int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr) /* wait for completion */ wait_flash_busy(sl); + /* relock the flash */ + lock_flash(sl); + } else if ((sl->flash_type == STLINK_FLASH_TYPE_F1_XL) && (flashaddr >= FLASH_BANK2_START_ADDR)) { + /* wait for ongoing op to finish */ + wait_flash_busy(sl); + + /* unlock if locked */ + unlock_flash_if(sl); + + /* set the page erase bit */ + set_flash_cr2_per(sl); + + /* select the page to erase */ + write_flash_ar2(sl, flashaddr); + + /* start erase operation, reset by hw with bsy bit */ + set_flash_cr2_strt(sl); + + /* wait for completion */ + wait_flash_busy(sl); + /* relock the flash */ lock_flash(sl); } else { @@ -1908,8 +1985,8 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val); 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_F0) { - ILOG("Starting Flash write for VL/F0/F3 core id\n"); + } else if ((sl->flash_type == STLINK_FLASH_TYPE_F0) || (sl->flash_type == STLINK_FLASH_TYPE_F1_XL)) { + ILOG("Starting Flash write for VL/F0/F3/F1_XL core id\n"); /* flash loader initialization */ if (stlink_flash_loader_init(sl, &fl) == -1) { ELOG("stlink_flash_loader_init() == -1\n"); @@ -1924,8 +2001,7 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t /* unlock and set programming mode */ unlock_flash_if(sl); - set_flash_cr_pg(sl); - DLOG("Finished setting flash cr pg, running loader!\n"); + DLOG("Finished unlocking flash, running loader!\n"); if (stlink_flash_loader_run(sl, &fl, addr + (uint32_t) off, base + off, size) == -1) { ELOG("stlink_flash_loader_run(%#zx) failed! == -1\n", addr + off); return -1; diff --git a/src/flash_loader.c b/src/flash_loader.c index ed53a0c6b..96084ab27 100644 --- a/src/flash_loader.c +++ b/src/flash_loader.c @@ -4,6 +4,9 @@ #include #include +#define FLASH_REGS_BANK2_OFS 0x40 +#define FLASH_BANK2_START_ADDR 0x08080000 + /* from openocd, contrib/loaders/flash/stm32.s */ static const uint8_t loader_code_stm32vl[] = { 0x08, 0x4c, /* ldr r4, STM32_FLASH_BASE */ @@ -325,6 +328,7 @@ int stlink_flash_loader_run(stlink_t *sl, flash_loader_t* fl, stm32_addr_t targe struct stlink_reg rr; int i = 0; size_t count = 0; + uint32_t flash_base = 0; DLOG("Running flash loader, write address:%#x, size: %u\n", target, (unsigned int)size); // FIXME This can never return -1 @@ -334,7 +338,7 @@ int stlink_flash_loader_run(stlink_t *sl, flash_loader_t* fl, stm32_addr_t targe return -1; } - if (sl->flash_type == STLINK_FLASH_TYPE_F0) { + if ((sl->flash_type == STLINK_FLASH_TYPE_F0) || (sl->flash_type == STLINK_FLASH_TYPE_F1_XL)) { count = size / sizeof(uint16_t); if (size % sizeof(uint16_t)) ++count; @@ -348,11 +352,15 @@ int stlink_flash_loader_run(stlink_t *sl, flash_loader_t* fl, stm32_addr_t targe ++count; } + if ((sl->flash_type == STLINK_FLASH_TYPE_F1_XL) && (target >= FLASH_BANK2_START_ADDR)) { + flash_base = FLASH_REGS_BANK2_OFS; + } + /* setup core */ stlink_write_reg(sl, fl->buf_addr, 0); /* source */ stlink_write_reg(sl, target, 1); /* target */ stlink_write_reg(sl, (uint32_t) count, 2); /* count */ - stlink_write_reg(sl, 0, 3); /* flash bank 0 (input), only used on F0, but armless fopr others */ + stlink_write_reg(sl, flash_base, 3); /* flash register base, only used on VL/F1_XL, but harmless for others */ stlink_write_reg(sl, fl->loader_addr, 15); /* pc register */ /* run loader */