Skip to content

Commit

Permalink
Added support for flashing second bank on STM32F10x_XL (#592)
Browse files Browse the repository at this point in the history
  • Loading branch information
bmellstrom authored and xor-gate committed May 14, 2017
1 parent 5c10d4b commit 0498621
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 10 deletions.
3 changes: 2 additions & 1 deletion include/stlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion src/chipid.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
88 changes: 82 additions & 6 deletions src/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
}
}


Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;

Expand All @@ -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;
Expand All @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);

Expand All @@ -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 {
Expand Down Expand Up @@ -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");
Expand All @@ -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;
Expand Down
12 changes: 10 additions & 2 deletions src/flash_loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
#include <string.h>
#include <unistd.h>

#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 */
Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand All @@ -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 */
Expand Down

0 comments on commit 0498621

Please sign in to comment.