stm32l4: Switched to the unified mass erase command and added progress dots to stop GDB timing out
This commit is contained in:
parent
787d66fe95
commit
90b7362162
|
@ -40,14 +40,13 @@
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
#include "target_internal.h"
|
#include "target_internal.h"
|
||||||
#include "cortexm.h"
|
#include "cortexm.h"
|
||||||
|
#include "gdb_packet.h"
|
||||||
|
|
||||||
static bool stm32l4_cmd_erase_mass(target *t, int argc, const char **argv);
|
|
||||||
static bool stm32l4_cmd_erase_bank1(target *t, int argc, const char **argv);
|
static bool stm32l4_cmd_erase_bank1(target *t, int argc, const char **argv);
|
||||||
static bool stm32l4_cmd_erase_bank2(target *t, int argc, const char **argv);
|
static bool stm32l4_cmd_erase_bank2(target *t, int argc, const char **argv);
|
||||||
static bool stm32l4_cmd_option(target *t, int argc, char *argv[]);
|
static bool stm32l4_cmd_option(target *t, int argc, char *argv[]);
|
||||||
|
|
||||||
const struct command_s stm32l4_cmd_list[] = {
|
const struct command_s stm32l4_cmd_list[] = {
|
||||||
{"erase_mass", (cmd_handler)stm32l4_cmd_erase_mass, "Erase entire flash memory"},
|
|
||||||
{"erase_bank1", (cmd_handler)stm32l4_cmd_erase_bank1, "Erase entire bank1 flash memory"},
|
{"erase_bank1", (cmd_handler)stm32l4_cmd_erase_bank1, "Erase entire bank1 flash memory"},
|
||||||
{"erase_bank2", (cmd_handler)stm32l4_cmd_erase_bank2, "Erase entire bank2 flash memory"},
|
{"erase_bank2", (cmd_handler)stm32l4_cmd_erase_bank2, "Erase entire bank2 flash memory"},
|
||||||
{"option", (cmd_handler)stm32l4_cmd_option, "Manipulate option bytes"},
|
{"option", (cmd_handler)stm32l4_cmd_option, "Manipulate option bytes"},
|
||||||
|
@ -55,8 +54,8 @@ const struct command_s stm32l4_cmd_list[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static int stm32l4_flash_erase(struct target_flash *f, target_addr addr, size_t len);
|
static int stm32l4_flash_erase(struct target_flash *f, target_addr addr, size_t len);
|
||||||
static int stm32l4_flash_write(struct target_flash *f,
|
static int stm32l4_flash_write(struct target_flash *f, target_addr dest, const void *src, size_t len);
|
||||||
target_addr dest, const void *src, size_t len);
|
static bool stm32l4_mass_erase(target *t);
|
||||||
|
|
||||||
/* Flash Program ad Erase Controller Register Map */
|
/* Flash Program ad Erase Controller Register Map */
|
||||||
#define L4_FPEC_BASE 0x40022000
|
#define L4_FPEC_BASE 0x40022000
|
||||||
|
@ -336,7 +335,6 @@ static struct stm32l4_info const L4info[] = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Retrieve chip basic information, just add to the vector to extend */
|
/* Retrieve chip basic information, just add to the vector to extend */
|
||||||
static struct stm32l4_info const * stm32l4_get_chip_info(uint32_t idcode) {
|
static struct stm32l4_info const * stm32l4_get_chip_info(uint32_t idcode) {
|
||||||
struct stm32l4_info const *p = L4info;
|
struct stm32l4_info const *p = L4info;
|
||||||
|
@ -366,19 +364,15 @@ static void stm32l4_flash_write32(target *t, enum stm32l4_flash_regs reg, uint32
|
||||||
target_mem_write32(t, addr, value);
|
target_mem_write32(t, addr, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stm32l4_add_flash(target *t,
|
static void stm32l4_add_flash(target *t, uint32_t addr, size_t length, size_t blocksize, uint32_t bank1_start)
|
||||||
uint32_t addr, size_t length, size_t blocksize,
|
|
||||||
uint32_t bank1_start)
|
|
||||||
{
|
{
|
||||||
struct stm32l4_flash *sf = calloc(1, sizeof(*sf));
|
struct stm32l4_flash *sf = calloc(1, sizeof(*sf));
|
||||||
struct target_flash *f;
|
|
||||||
|
|
||||||
if (!sf) { /* calloc failed: heap exhaustion */
|
if (!sf) { /* calloc failed: heap exhaustion */
|
||||||
DEBUG_WARN("calloc: failed in %s\n", __func__);
|
DEBUG_WARN("calloc: failed in %s\n", __func__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
f = &sf->f;
|
struct target_flash *f = &sf->f;
|
||||||
f->start = addr;
|
f->start = addr;
|
||||||
f->length = length;
|
f->length = length;
|
||||||
f->blocksize = blocksize;
|
f->blocksize = blocksize;
|
||||||
|
@ -389,10 +383,12 @@ static void stm32l4_add_flash(target *t,
|
||||||
sf->bank1_start = bank1_start;
|
sf->bank1_start = bank1_start;
|
||||||
target_add_flash(t, f);
|
target_add_flash(t, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define L5_RCC_APB1ENR1 0x50021058
|
#define L5_RCC_APB1ENR1 0x50021058
|
||||||
#define L5_RCC_APB1ENR1_PWREN (1 << 28)
|
#define L5_RCC_APB1ENR1_PWREN (1 << 28)
|
||||||
#define L5_PWR_CR1 0x50007000
|
#define L5_PWR_CR1 0x50007000
|
||||||
#define L5_PWR_CR1_VOS (3 << 9)
|
#define L5_PWR_CR1_VOS (3 << 9)
|
||||||
|
|
||||||
/* For flash programming, L5 needs to be in VOS 0 or 1 while reset set 2 (or even 3?) */
|
/* For flash programming, L5 needs to be in VOS 0 or 1 while reset set 2 (or even 3?) */
|
||||||
static void stm32l5_flash_enable(target *t)
|
static void stm32l5_flash_enable(target *t)
|
||||||
{
|
{
|
||||||
|
@ -409,7 +405,6 @@ static bool stm32l4_attach(target *t)
|
||||||
/* Retrive chip information, no need to check return */
|
/* Retrive chip information, no need to check return */
|
||||||
struct stm32l4_info const *chip = stm32l4_get_chip_info(t->idcode);
|
struct stm32l4_info const *chip = stm32l4_get_chip_info(t->idcode);
|
||||||
|
|
||||||
|
|
||||||
uint32_t idcodereg;
|
uint32_t idcodereg;
|
||||||
switch(chip->family) {
|
switch(chip->family) {
|
||||||
case FAM_STM32L55x:
|
case FAM_STM32L55x:
|
||||||
|
@ -556,6 +551,7 @@ bool stm32l4_probe(target *t)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
t->mass_erase = stm32l4_mass_erase;
|
||||||
t->attach = stm32l4_attach;
|
t->attach = stm32l4_attach;
|
||||||
t->detach = stm32l4_detach;
|
t->detach = stm32l4_detach;
|
||||||
target_add_commands(t, stm32l4_cmd_list, chip->designator);
|
target_add_commands(t, stm32l4_cmd_list, chip->designator);
|
||||||
|
@ -574,36 +570,34 @@ static void stm32l4_flash_unlock(target *t)
|
||||||
static int stm32l4_flash_erase(struct target_flash *f, target_addr addr, size_t len)
|
static int stm32l4_flash_erase(struct target_flash *f, target_addr addr, size_t len)
|
||||||
{
|
{
|
||||||
target *t = f->t;
|
target *t = f->t;
|
||||||
uint16_t sr;
|
|
||||||
uint32_t bank1_start = ((struct stm32l4_flash *)f)->bank1_start;
|
|
||||||
uint32_t page;
|
|
||||||
uint32_t blocksize = f->blocksize;
|
|
||||||
|
|
||||||
stm32l4_flash_unlock(t);
|
stm32l4_flash_unlock(t);
|
||||||
|
|
||||||
/* Read FLASH_SR to poll for BSY bit */
|
/* Read FLASH_SR to poll for BSY bit */
|
||||||
while(stm32l4_flash_read32(t, FLASH_SR) & FLASH_SR_BSY)
|
while (stm32l4_flash_read32(t, FLASH_SR) & FLASH_SR_BSY) {
|
||||||
if(target_check_error(t))
|
if (target_check_error(t))
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Fixme: OPTVER always set after reset! Wrong option defaults?*/
|
/* Fixme: OPTVER always set after reset! Wrong option defaults?*/
|
||||||
stm32l4_flash_write32(t, FLASH_SR, stm32l4_flash_read32(t, FLASH_SR));
|
stm32l4_flash_write32(t, FLASH_SR, stm32l4_flash_read32(t, FLASH_SR));
|
||||||
page = (addr - 0x08000000) / blocksize;
|
const uint32_t blocksize = f->blocksize;
|
||||||
while(len) {
|
uint32_t page = (addr - 0x08000000) / blocksize;
|
||||||
uint32_t cr;
|
const uint32_t bank1_start = ((struct stm32l4_flash *)f)->bank1_start;
|
||||||
|
while (len) {
|
||||||
cr = FLASH_CR_PER | (page << FLASH_CR_PAGE_SHIFT );
|
uint32_t ctrl_reg = FLASH_CR_PER | (page << FLASH_CR_PAGE_SHIFT);
|
||||||
if (addr >= bank1_start)
|
if (addr >= bank1_start)
|
||||||
cr |= FLASH_CR_BKER;
|
ctrl_reg |= FLASH_CR_BKER;
|
||||||
/* Flash page erase instruction */
|
/* Flash page erase instruction */
|
||||||
stm32l4_flash_write32(t, FLASH_CR, cr);
|
stm32l4_flash_write32(t, FLASH_CR, ctrl_reg);
|
||||||
/* write address to FMA */
|
/* write address to FMA */
|
||||||
cr |= FLASH_CR_STRT;
|
ctrl_reg |= FLASH_CR_STRT;
|
||||||
stm32l4_flash_write32(t, FLASH_CR, cr);
|
stm32l4_flash_write32(t, FLASH_CR, ctrl_reg);
|
||||||
|
|
||||||
/* Read FLASH_SR to poll for BSY bit */
|
/* Read FLASH_SR to poll for BSY bit */
|
||||||
while(stm32l4_flash_read32(t, FLASH_SR) & FLASH_SR_BSY)
|
while (stm32l4_flash_read32(t, FLASH_SR) & FLASH_SR_BSY) {
|
||||||
if(target_check_error(t))
|
if (target_check_error(t))
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
if (len > blocksize)
|
if (len > blocksize)
|
||||||
len -= blocksize;
|
len -= blocksize;
|
||||||
else
|
else
|
||||||
|
@ -613,77 +607,77 @@ static int stm32l4_flash_erase(struct target_flash *f, target_addr addr, size_t
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for error */
|
/* Check for error */
|
||||||
sr = stm32l4_flash_read32(t, FLASH_SR);
|
if (stm32l4_flash_read32(t, FLASH_SR) & FLASH_SR_ERROR_MASK)
|
||||||
if(sr & FLASH_SR_ERROR_MASK)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stm32l4_flash_write(struct target_flash *f,
|
static int stm32l4_flash_write(struct target_flash *f, target_addr dest, const void *src, size_t len)
|
||||||
target_addr dest, const void *src, size_t len)
|
|
||||||
{
|
{
|
||||||
target *t = f->t;
|
target *t = f->t;
|
||||||
stm32l4_flash_write32(t, FLASH_CR, FLASH_CR_PG);
|
stm32l4_flash_write32(t, FLASH_CR, FLASH_CR_PG);
|
||||||
target_mem_write(t, dest, src, len);
|
target_mem_write(t, dest, src, len);
|
||||||
/* Wait for completion or an error */
|
/* Wait for completion or an error */
|
||||||
uint32_t sr;
|
uint32_t status;
|
||||||
do {
|
do {
|
||||||
sr = stm32l4_flash_read32(t, FLASH_SR);
|
status = stm32l4_flash_read32(t, FLASH_SR);
|
||||||
if (target_check_error(t)) {
|
if (target_check_error(t)) {
|
||||||
DEBUG_WARN("stm32l4 flash write: comm error\n");
|
DEBUG_WARN("stm32l4 flash write: comm error\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} while (sr & FLASH_SR_BSY);
|
} while (status & FLASH_SR_BSY);
|
||||||
|
|
||||||
if(sr & FLASH_SR_ERROR_MASK) {
|
if (status & FLASH_SR_ERROR_MASK) {
|
||||||
DEBUG_WARN("stm32l4 flash write error: sr 0x%" PRIx32 "\n", sr);
|
DEBUG_WARN("stm32l4 flash write error: sr 0x%" PRIx32 "\n", status);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool stm32l4_cmd_erase(target *t, uint32_t action)
|
static bool stm32l4_cmd_erase(target *const t, const uint32_t action)
|
||||||
{
|
{
|
||||||
stm32l4_flash_unlock(t);
|
stm32l4_flash_unlock(t);
|
||||||
/* Erase time is 25 ms. No need for a spinner.*/
|
/* Erase time is 25 ms. Timeout logic shouldn't get fired.*/
|
||||||
/* Flash erase action start instruction */
|
/* Flash erase action start instruction */
|
||||||
stm32l4_flash_write32(t, FLASH_CR, action);
|
stm32l4_flash_write32(t, FLASH_CR, action);
|
||||||
stm32l4_flash_write32(t, FLASH_CR, action | FLASH_CR_STRT);
|
stm32l4_flash_write32(t, FLASH_CR, action | FLASH_CR_STRT);
|
||||||
|
|
||||||
|
platform_timeout timeout;
|
||||||
|
platform_timeout_set(&timeout, 500);
|
||||||
/* Read FLASH_SR to poll for BSY bit */
|
/* Read FLASH_SR to poll for BSY bit */
|
||||||
while (stm32l4_flash_read32(t, FLASH_SR) & FLASH_SR_BSY) {
|
while (stm32l4_flash_read32(t, FLASH_SR) & FLASH_SR_BSY) {
|
||||||
if(target_check_error(t)) {
|
if(target_check_error(t))
|
||||||
return false;
|
return false;
|
||||||
}
|
target_print_progress(&timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for error */
|
/* Check for error */
|
||||||
uint16_t sr = stm32l4_flash_read32(t, FLASH_SR);
|
return !(stm32l4_flash_read32(t, FLASH_SR) & FLASH_SR_ERROR_MASK);
|
||||||
if (sr & FLASH_SR_ERROR_MASK)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool stm32l4_cmd_erase_mass(target *t, int argc, const char **argv)
|
static bool stm32l4_mass_erase(target *const t)
|
||||||
{
|
{
|
||||||
(void)argc;
|
|
||||||
(void)argv;
|
|
||||||
return stm32l4_cmd_erase(t, FLASH_CR_MER1 | FLASH_CR_MER2);
|
return stm32l4_cmd_erase(t, FLASH_CR_MER1 | FLASH_CR_MER2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool stm32l4_cmd_erase_bank1(target *t, int argc, const char **argv)
|
static bool stm32l4_cmd_erase_bank1(target *const t, const int argc, const char **const argv)
|
||||||
{
|
{
|
||||||
(void)argc;
|
(void)argc;
|
||||||
(void)argv;
|
(void)argv;
|
||||||
return stm32l4_cmd_erase(t, FLASH_CR_MER1);
|
gdb_out("Erasing bank 1: ");
|
||||||
|
const bool result = stm32l4_cmd_erase(t, FLASH_CR_MER1);
|
||||||
|
gdb_out("done\n");
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool stm32l4_cmd_erase_bank2(target *t, int argc, const char **argv)
|
static bool stm32l4_cmd_erase_bank2(target *const t, const int argc, const char **const argv)
|
||||||
{
|
{
|
||||||
(void)argc;
|
(void)argc;
|
||||||
(void)argv;
|
(void)argv;
|
||||||
return stm32l4_cmd_erase(t, FLASH_CR_MER2);
|
gdb_out("Erasing bank 2: ");
|
||||||
|
const bool result = stm32l4_cmd_erase(t, FLASH_CR_MER2);
|
||||||
|
gdb_out("done\n");
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint8_t l4_i2offset[9] = {
|
static const uint8_t l4_i2offset[9] = {
|
||||||
|
|
Loading…
Reference in New Issue