target/stm: flash read write return bool
This commit is contained in:
parent
67c9f3f6e2
commit
085dcb7bc9
|
@ -46,8 +46,8 @@ const struct command_s stm32f1_cmd_list[] = {
|
|||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
static int stm32f1_flash_erase(target_flash_s *f, target_addr_t addr, size_t len);
|
||||
static int stm32f1_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len);
|
||||
static bool stm32f1_flash_erase(target_flash_s *f, target_addr_t addr, size_t len);
|
||||
static bool stm32f1_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len);
|
||||
static bool stm32f1_mass_erase(target *t);
|
||||
|
||||
/* Flash Program ad Erase Controller Register Map */
|
||||
|
@ -357,19 +357,33 @@ static int stm32f1_flash_unlock(target *t, uint32_t bank_offset)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int stm32f1_flash_erase(target_flash_s *f, target_addr_t addr, size_t len)
|
||||
static bool stm32f1_flash_busy_wait(target *t, uint32_t bank_offset)
|
||||
{
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
uint32_t sr;
|
||||
do {
|
||||
sr = target_mem_read32(t, FLASH_SR + bank_offset);
|
||||
if ((sr & SR_ERROR_MASK) || !(sr & SR_EOP) || target_check_error(t)) {
|
||||
DEBUG_WARN("stm32f1 flash error 0x%" PRIx32 "\n", sr);
|
||||
return false;
|
||||
}
|
||||
} while (sr & FLASH_SR_BSY);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool stm32f1_flash_erase(target_flash_s *f, target_addr_t addr, size_t len)
|
||||
{
|
||||
target *t = f->t;
|
||||
target_addr_t end = addr + len - 1;
|
||||
target_addr_t start = addr;
|
||||
|
||||
if (t->part_id == 0x430 && end >= FLASH_BANK_SPLIT)
|
||||
if (stm32f1_flash_unlock(t, FLASH_BANK2_OFFSET))
|
||||
return -1;
|
||||
return false;
|
||||
|
||||
if (addr < FLASH_BANK_SPLIT)
|
||||
if (stm32f1_flash_unlock(t, 0))
|
||||
return -1;
|
||||
return false;
|
||||
|
||||
while (len) {
|
||||
uint32_t bank_offset = 0;
|
||||
|
@ -383,13 +397,9 @@ static int stm32f1_flash_erase(target_flash_s *f, target_addr_t addr, size_t len
|
|||
/* Flash page erase start instruction */
|
||||
target_mem_write32(t, FLASH_CR + bank_offset, FLASH_CR_STRT | FLASH_CR_PER);
|
||||
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
while (target_mem_read32(t, FLASH_SR + bank_offset) & FLASH_SR_BSY) {
|
||||
if (target_check_error(t)) {
|
||||
DEBUG_WARN("stm32f1 flash erase: comm error\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/* Wait for completion or an error */
|
||||
if (!stm32f1_flash_busy_wait(t, bank_offset))
|
||||
return false;
|
||||
|
||||
if (len > f->blocksize)
|
||||
len -= f->blocksize;
|
||||
|
@ -399,29 +409,12 @@ static int stm32f1_flash_erase(target_flash_s *f, target_addr_t addr, size_t len
|
|||
addr += f->blocksize;
|
||||
}
|
||||
|
||||
/* Check for error */
|
||||
if (start < FLASH_BANK_SPLIT) {
|
||||
const uint32_t status = target_mem_read32(t, FLASH_SR);
|
||||
if ((status & SR_ERROR_MASK) || !(status & SR_EOP)) {
|
||||
DEBUG_INFO("stm32f1 flash erase error 0x%" PRIx32 "\n", status);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (t->part_id == 0x430 && end >= FLASH_BANK_SPLIT) {
|
||||
const uint32_t status = target_mem_read32(t, FLASH_SR + FLASH_BANK2_OFFSET);
|
||||
if ((status & SR_ERROR_MASK) || !(status & SR_EOP)) {
|
||||
DEBUG_INFO("stm32f1 bank 2 flash erase error 0x%" PRIx32 "\n", status);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int stm32f1_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len)
|
||||
static bool stm32f1_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len)
|
||||
{
|
||||
target *t = f->t;
|
||||
uint32_t sr;
|
||||
size_t length = 0;
|
||||
|
||||
if (dest < FLASH_BANK_SPLIT) {
|
||||
|
@ -433,20 +426,10 @@ static int stm32f1_flash_write(target_flash_s *f, target_addr_t dest, const void
|
|||
target_mem_write32(t, FLASH_CR, FLASH_CR_PG);
|
||||
cortexm_mem_write_sized(t, dest, src, length, ALIGN_HALFWORD);
|
||||
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
/* Wait for completion or an error */
|
||||
do {
|
||||
sr = target_mem_read32(t, FLASH_SR);
|
||||
if (target_check_error(t)) {
|
||||
DEBUG_WARN("stm32f1 flash write: comm error\n");
|
||||
return -1;
|
||||
}
|
||||
} while (sr & FLASH_SR_BSY);
|
||||
if (!stm32f1_flash_busy_wait(t, 0))
|
||||
return false;
|
||||
|
||||
if (sr & SR_ERROR_MASK) {
|
||||
DEBUG_WARN("stm32f1 flash write error 0x%" PRIx32 "\n", sr);
|
||||
return -1;
|
||||
}
|
||||
dest += length;
|
||||
src += length;
|
||||
}
|
||||
|
@ -455,23 +438,13 @@ static int stm32f1_flash_write(target_flash_s *f, target_addr_t dest, const void
|
|||
if (t->part_id == 0x430 && length) { /* Write on bank 2 */
|
||||
target_mem_write32(t, FLASH_CR + FLASH_BANK2_OFFSET, FLASH_CR_PG);
|
||||
cortexm_mem_write_sized(t, dest, src, length, ALIGN_HALFWORD);
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
/* Wait for completion or an error */
|
||||
do {
|
||||
sr = target_mem_read32(t, FLASH_SR + FLASH_BANK2_OFFSET);
|
||||
if (target_check_error(t)) {
|
||||
DEBUG_WARN("stm32f1 flash bank2 write: comm error\n");
|
||||
return -1;
|
||||
}
|
||||
} while (sr & FLASH_SR_BSY);
|
||||
|
||||
if (sr & SR_ERROR_MASK) {
|
||||
DEBUG_WARN("stm32f1 flash bank2 write error 0x%" PRIx32 "\n", sr);
|
||||
return -1;
|
||||
}
|
||||
/* Wait for completion or an error */
|
||||
if (!stm32f1_flash_busy_wait(t, FLASH_BANK2_OFFSET))
|
||||
return false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool stm32f1_mass_erase(target *t)
|
||||
|
@ -479,6 +452,7 @@ static bool stm32f1_mass_erase(target *t)
|
|||
if (stm32f1_flash_unlock(t, 0))
|
||||
return false;
|
||||
|
||||
uint32_t sr;
|
||||
platform_timeout timeout;
|
||||
platform_timeout_set(&timeout, 500);
|
||||
|
||||
|
@ -486,17 +460,15 @@ static bool stm32f1_mass_erase(target *t)
|
|||
target_mem_write32(t, FLASH_CR, FLASH_CR_MER);
|
||||
target_mem_write32(t, FLASH_CR, FLASH_CR_STRT | FLASH_CR_MER);
|
||||
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) {
|
||||
if (target_check_error(t))
|
||||
/* Wait for completion or an error */
|
||||
do {
|
||||
sr = target_mem_read32(t, FLASH_SR);
|
||||
if ((sr & SR_ERROR_MASK) || !(sr & SR_EOP) || target_check_error(t)) {
|
||||
DEBUG_WARN("stm32f1 flash error 0x%" PRIx32 "\n", sr);
|
||||
return false;
|
||||
}
|
||||
target_print_progress(&timeout);
|
||||
}
|
||||
|
||||
/* Check for error */
|
||||
uint16_t sr = target_mem_read32(t, FLASH_SR);
|
||||
if ((sr & SR_ERROR_MASK) || !(sr & SR_EOP))
|
||||
return false;
|
||||
} while (sr & FLASH_SR_BSY);
|
||||
|
||||
if (t->part_id == 0x430) {
|
||||
if (stm32f1_flash_unlock(t, FLASH_BANK2_OFFSET))
|
||||
|
@ -506,15 +478,15 @@ static bool stm32f1_mass_erase(target *t)
|
|||
target_mem_write32(t, FLASH_CR + FLASH_BANK2_OFFSET, FLASH_CR_MER);
|
||||
target_mem_write32(t, FLASH_CR + FLASH_BANK2_OFFSET, FLASH_CR_STRT | FLASH_CR_MER);
|
||||
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
while (target_mem_read32(t, FLASH_SR + FLASH_BANK2_OFFSET) & FLASH_SR_BSY)
|
||||
if (target_check_error(t))
|
||||
/* Wait for completion or an error */
|
||||
do {
|
||||
sr = target_mem_read32(t, FLASH_SR + FLASH_BANK2_OFFSET);
|
||||
if ((sr & SR_ERROR_MASK) || !(sr & SR_EOP) || target_check_error(t)) {
|
||||
DEBUG_WARN("stm32f1 flash error 0x%" PRIx32 "\n", sr);
|
||||
return false;
|
||||
|
||||
/* Check for error */
|
||||
sr = target_mem_read32(t, FLASH_SR + FLASH_BANK2_OFFSET);
|
||||
if ((sr & SR_ERROR_MASK) || !(sr & SR_EOP))
|
||||
return false;
|
||||
}
|
||||
target_print_progress(&timeout);
|
||||
} while (sr & FLASH_SR_BSY);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -526,12 +498,8 @@ static bool stm32f1_option_erase(target *t)
|
|||
target_mem_write32(t, FLASH_CR, FLASH_CR_OPTER | FLASH_CR_OPTWRE);
|
||||
target_mem_write32(t, FLASH_CR, FLASH_CR_STRT | FLASH_CR_OPTER | FLASH_CR_OPTWRE);
|
||||
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY)
|
||||
if (target_check_error(t))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
/* Wait for completion or an error */
|
||||
return stm32f1_flash_busy_wait(t, 0);
|
||||
}
|
||||
|
||||
static bool stm32f1_option_write_erased(target *t, uint32_t addr, uint16_t value, bool width_word)
|
||||
|
@ -547,12 +515,8 @@ static bool stm32f1_option_write_erased(target *t, uint32_t addr, uint16_t value
|
|||
else
|
||||
target_mem_write16(t, addr, value);
|
||||
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY)
|
||||
if (target_check_error(t))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
/* Wait for completion or an error */
|
||||
return stm32f1_flash_busy_wait(t, 0);
|
||||
}
|
||||
|
||||
static bool stm32f1_option_write(target *t, uint32_t addr, uint16_t value)
|
||||
|
|
|
@ -47,8 +47,8 @@ const struct command_s stm32f4_cmd_list[] = {
|
|||
};
|
||||
|
||||
static bool stm32f4_attach(target *t);
|
||||
static int stm32f4_flash_erase(target_flash_s *f, target_addr_t addr, size_t len);
|
||||
static int stm32f4_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len);
|
||||
static bool stm32f4_flash_erase(target_flash_s *f, target_addr_t addr, size_t len);
|
||||
static bool stm32f4_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len);
|
||||
static bool stm32f4_mass_erase(target *t);
|
||||
|
||||
/* Flash Program and Erase Controller Register Map */
|
||||
|
@ -390,11 +390,26 @@ static void stm32f4_flash_unlock(target *t)
|
|||
}
|
||||
}
|
||||
|
||||
static int stm32f4_flash_erase(target_flash_s *f, target_addr_t addr, size_t len)
|
||||
static bool stm32f4_flash_busy_wait(target *t)
|
||||
{
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
uint32_t sr;
|
||||
do {
|
||||
sr = target_mem_read32(t, FLASH_SR);
|
||||
if ((sr & SR_ERROR_MASK) || target_check_error(t)) {
|
||||
DEBUG_WARN("stm32f4 flash error 0x%" PRIx32 "\n", sr);
|
||||
return false;
|
||||
}
|
||||
} while (sr & FLASH_SR_BSY);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool stm32f4_flash_erase(target_flash_s *f, target_addr_t addr, size_t len)
|
||||
{
|
||||
target *t = f->t;
|
||||
struct stm32f4_flash *sf = (struct stm32f4_flash *)f;
|
||||
uint32_t sr;
|
||||
|
||||
/* No address translation is needed here, as we erase by sector number */
|
||||
uint8_t sector = sf->base_sector + (addr - f->start)/f->blocksize;
|
||||
stm32f4_flash_unlock(t);
|
||||
|
@ -413,12 +428,10 @@ static int stm32f4_flash_erase(target_flash_s *f, target_addr_t addr, size_t len
|
|||
/* write address to FMA */
|
||||
target_mem_write32(t, FLASH_CR, cr | FLASH_CR_STRT);
|
||||
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
while(target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY)
|
||||
if(target_check_error(t)) {
|
||||
DEBUG_WARN("stm32f4 flash erase: comm error\n");
|
||||
return -1;
|
||||
}
|
||||
/* Wait for completion or an error */
|
||||
if (!stm32f4_flash_busy_wait(t))
|
||||
return false;
|
||||
|
||||
if (len > f->blocksize)
|
||||
len -= f->blocksize;
|
||||
else
|
||||
|
@ -428,42 +441,23 @@ static int stm32f4_flash_erase(target_flash_s *f, target_addr_t addr, size_t len
|
|||
sector = 16;
|
||||
}
|
||||
|
||||
/* Check for error */
|
||||
sr = target_mem_read32(t, FLASH_SR);
|
||||
if(sr & SR_ERROR_MASK) {
|
||||
DEBUG_WARN("stm32f4 flash erase: sr error: 0x%" PRIx32 "\n", sr);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int stm32f4_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len)
|
||||
static bool stm32f4_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len)
|
||||
{
|
||||
/* Translate ITCM addresses to AXIM */
|
||||
if ((dest >= ITCM_BASE) && (dest < AXIM_BASE)) {
|
||||
dest = AXIM_BASE + (dest - ITCM_BASE);
|
||||
}
|
||||
target *t = f->t;
|
||||
uint32_t sr;
|
||||
enum align psize = ((struct stm32f4_flash *)f)->psize;
|
||||
target_mem_write32(t, FLASH_CR,
|
||||
(psize * FLASH_CR_PSIZE16) | FLASH_CR_PG);
|
||||
cortexm_mem_write_sized(t, dest, src, len, psize);
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
/* Wait for completion or an error */
|
||||
do {
|
||||
sr = target_mem_read32(t, FLASH_SR);
|
||||
if(target_check_error(t)) {
|
||||
DEBUG_WARN("stm32f4 flash write: comm error\n");
|
||||
return -1;
|
||||
}
|
||||
} while (sr & FLASH_SR_BSY);
|
||||
|
||||
if (sr & SR_ERROR_MASK) {
|
||||
DEBUG_WARN("stm32f4 flash write error 0x%" PRIx32 "\n", sr);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
enum align psize = ((struct stm32f4_flash *)f)->psize;
|
||||
target_mem_write32(t, FLASH_CR, (psize * FLASH_CR_PSIZE16) | FLASH_CR_PG);
|
||||
cortexm_mem_write_sized(t, dest, src, len, psize);
|
||||
|
||||
/* Wait for completion or an error */
|
||||
return stm32f4_flash_busy_wait(t);
|
||||
}
|
||||
|
||||
static bool stm32f4_mass_erase(target *t)
|
||||
|
@ -481,15 +475,15 @@ static bool stm32f4_mass_erase(target *t)
|
|||
platform_timeout timeout;
|
||||
platform_timeout_set(&timeout, 500);
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) {
|
||||
if (target_check_error(t))
|
||||
uint32_t sr;
|
||||
do {
|
||||
sr = target_mem_read32(t, FLASH_SR);
|
||||
if ((sr & SR_ERROR_MASK) || target_check_error(t))
|
||||
return false;
|
||||
target_print_progress(&timeout);
|
||||
}
|
||||
} while (sr & FLASH_SR_BSY);
|
||||
|
||||
/* Check for error */
|
||||
const uint32_t result = target_mem_read32(t, FLASH_SR);
|
||||
return !(result & SR_ERROR_MASK);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Dev | DOC |Rev|ID |OPTCR |OPTCR |OPTCR1 |OPTCR1 | OPTCR2
|
||||
|
@ -574,9 +568,9 @@ static bool stm32f4_option_write(target *t, uint32_t *val, int count)
|
|||
}
|
||||
target_mem_write32(t, FLASH_OPTKEYR, OPTKEY1);
|
||||
target_mem_write32(t, FLASH_OPTKEYR, OPTKEY2);
|
||||
while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY)
|
||||
if(target_check_error(t))
|
||||
return -1;
|
||||
|
||||
if (!stm32f4_flash_busy_wait(t))
|
||||
return false;
|
||||
|
||||
/* WRITE option bytes instruction */
|
||||
if (((t->part_id == ID_STM32F42X) || (t->part_id == ID_STM32F46X) ||
|
||||
|
@ -589,18 +583,22 @@ static bool stm32f4_option_write(target *t, uint32_t *val, int count)
|
|||
|
||||
target_mem_write32(t, FLASH_OPTCR, val[0]);
|
||||
target_mem_write32(t, FLASH_OPTCR, val[0] | FLASH_OPTCR_OPTSTRT);
|
||||
const char spinner[] = "|/-\\";
|
||||
int spinindex = 0;
|
||||
|
||||
tc_printf(t, "Erasing flash... This may take a few seconds. ");
|
||||
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
while(target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) {
|
||||
platform_delay(100);
|
||||
tc_printf(t, "\b%c", spinner[spinindex++ % 4]);
|
||||
if(target_check_error(t)) {
|
||||
platform_timeout timeout;
|
||||
platform_timeout_set(&timeout, 100);
|
||||
uint32_t sr;
|
||||
do {
|
||||
sr = target_mem_read32(t, FLASH_SR);
|
||||
if ((sr & SR_ERROR_MASK) || target_check_error(t)) {
|
||||
tc_printf(t, " failed\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
target_print_progress(&timeout);
|
||||
} while (sr & FLASH_SR_BSY);
|
||||
|
||||
tc_printf(t, "\n");
|
||||
target_mem_write32(t, FLASH_OPTCR, FLASH_OPTCR_OPTLOCK);
|
||||
/* Reset target to reload option bits.*/
|
||||
|
|
|
@ -160,8 +160,8 @@ typedef struct stm32g0_priv {
|
|||
|
||||
static bool stm32g0_attach(target *t);
|
||||
static void stm32g0_detach(target *t);
|
||||
static int stm32g0_flash_erase(target_flash_s *f, target_addr_t addr, size_t len);
|
||||
static int stm32g0_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len);
|
||||
static bool stm32g0_flash_erase(target_flash_s *f, target_addr_t addr, size_t len);
|
||||
static bool stm32g0_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len);
|
||||
static bool stm32g0_mass_erase(target *t);
|
||||
|
||||
/* Custom commands */
|
||||
|
@ -340,14 +340,14 @@ static void stm32g0_flash_op_finish(target *t)
|
|||
* Flash erasure function.
|
||||
* OTP case: this function clears any previous error and returns.
|
||||
*/
|
||||
static int stm32g0_flash_erase(target_flash_s *f, target_addr_t addr, size_t len)
|
||||
static bool stm32g0_flash_erase(target_flash_s *f, target_addr_t addr, size_t len)
|
||||
{
|
||||
target *const t = f->t;
|
||||
|
||||
/* Wait for Flash ready */
|
||||
if (!stm32g0_wait_busy(t)) {
|
||||
stm32g0_flash_op_finish(t);
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Clear any previous programming error */
|
||||
|
@ -355,7 +355,7 @@ static int stm32g0_flash_erase(target_flash_s *f, target_addr_t addr, size_t len
|
|||
|
||||
if (addr >= FLASH_OTP_START) {
|
||||
stm32g0_flash_op_finish(t);
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
const size_t pages_to_erase = ((len - 1U) / f->blocksize) + 1U;
|
||||
|
@ -382,7 +382,7 @@ static int stm32g0_flash_erase(target_flash_s *f, target_addr_t addr, size_t len
|
|||
|
||||
if (!stm32g0_wait_busy(t)) {
|
||||
stm32g0_flash_op_finish(t);
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -391,7 +391,7 @@ static int stm32g0_flash_erase(target_flash_s *f, target_addr_t addr, size_t len
|
|||
if (status & FLASH_SR_ERROR_MASK)
|
||||
DEBUG_WARN("stm32g0 flash erase error: sr 0x%" PRIx32 "\n", status);
|
||||
stm32g0_flash_op_finish(t);
|
||||
return (status & FLASH_SR_ERROR_MASK) ? -1 : 0;
|
||||
return !(status & FLASH_SR_ERROR_MASK);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -402,7 +402,7 @@ static int stm32g0_flash_erase(target_flash_s *f, target_addr_t addr, size_t len
|
|||
* OTP area is programmed as the "program" area. It can be programmed 8-bytes
|
||||
* by 8-bytes.
|
||||
*/
|
||||
static int stm32g0_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len)
|
||||
static bool stm32g0_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len)
|
||||
{
|
||||
target *const t = f->t;
|
||||
stm32g0_priv_s *ps = (stm32g0_priv_s *)t->target_storage;
|
||||
|
@ -410,7 +410,7 @@ static int stm32g0_flash_write(target_flash_s *f, target_addr_t dest, const void
|
|||
if (dest >= FLASH_OTP_START && !ps->irreversible_enabled) {
|
||||
tc_printf(t, "Irreversible operations disabled\n");
|
||||
stm32g0_flash_op_finish(t);
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
stm32g0_flash_unlock(t);
|
||||
|
@ -421,14 +421,14 @@ static int stm32g0_flash_write(target_flash_s *f, target_addr_t dest, const void
|
|||
if (!stm32g0_wait_busy(t)) {
|
||||
DEBUG_WARN("stm32g0 flash write: comm error\n");
|
||||
stm32g0_flash_op_finish(t);
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint32_t status = target_mem_read32(t, FLASH_SR);
|
||||
if (status & FLASH_SR_ERROR_MASK) {
|
||||
DEBUG_WARN("stm32g0 flash write error: sr 0x%" PRIx32 "\n", status);
|
||||
stm32g0_flash_op_finish(t);
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dest == FLASH_START && target_mem_read32(t, FLASH_START) != 0xFFFFFFFF) {
|
||||
|
@ -437,7 +437,7 @@ static int stm32g0_flash_write(target_flash_s *f, target_addr_t dest, const void
|
|||
}
|
||||
|
||||
stm32g0_flash_op_finish(t);
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool stm32g0_mass_erase(target *t)
|
||||
|
|
|
@ -52,8 +52,8 @@ const struct command_s stm32h7_cmd_list[] = {
|
|||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
static int stm32h7_flash_erase(target_flash_s *f, target_addr_t addr, size_t len);
|
||||
static int stm32h7_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len);
|
||||
static bool stm32h7_flash_erase(target_flash_s *f, target_addr_t addr, size_t len);
|
||||
static bool stm32h7_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len);
|
||||
static bool stm32h7_mass_erase(target *t);
|
||||
|
||||
static const char stm32h7_driver_str[] = "STM32H7";
|
||||
|
@ -243,22 +243,30 @@ bool stm32h7_probe(target *t)
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool stm32h7_flash_busy_wait(target *t, uint32_t regbase)
|
||||
{
|
||||
uint32_t sr;
|
||||
do {
|
||||
sr = target_mem_read32(t, regbase + FLASH_SR);
|
||||
if ((sr & FLASH_SR_ERROR_MASK) || target_check_error(t)) {
|
||||
DEBUG_WARN("stm32h7_flash_write: error sr %08" PRIx32 "\n", sr);
|
||||
target_mem_write32(t, regbase + FLASH_CCR, sr & FLASH_SR_ERROR_MASK);
|
||||
return false;
|
||||
}
|
||||
} while (sr & (FLASH_SR_BSY | FLASH_SR_QW));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool stm32h7_flash_unlock(target *t, const uint32_t addr)
|
||||
{
|
||||
uint32_t regbase = FPEC1_BASE;
|
||||
if (addr >= BANK2_START)
|
||||
regbase = FPEC2_BASE;
|
||||
|
||||
while (target_mem_read32(t, regbase + FLASH_SR) & FLASH_SR_BSY) {
|
||||
if (target_check_error(t))
|
||||
return false;
|
||||
}
|
||||
const uint32_t status = target_mem_read32(t, regbase + FLASH_SR) & FLASH_SR_ERROR_MASK;
|
||||
if (status) {
|
||||
DEBUG_WARN("%s error 0x%08" PRIx32, __func__, status);
|
||||
target_mem_write32(t, regbase + FLASH_CCR, status);
|
||||
if (!stm32h7_flash_busy_wait(t, regbase))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (target_mem_read32(t, regbase + FLASH_CR) & FLASH_CR_LOCK) {
|
||||
/* Enable FLASH controller access */
|
||||
target_mem_write32(t, regbase + FLASH_KEYR, KEY1);
|
||||
|
@ -267,12 +275,12 @@ static bool stm32h7_flash_unlock(target *t, const uint32_t addr)
|
|||
return !(target_mem_read32(t, regbase + FLASH_CR) & FLASH_CR_LOCK);
|
||||
}
|
||||
|
||||
static int stm32h7_flash_erase(target_flash_s *f, target_addr_t addr, size_t len)
|
||||
static bool stm32h7_flash_erase(target_flash_s *f, target_addr_t addr, size_t len)
|
||||
{
|
||||
target *t = f->t;
|
||||
struct stm32h7_flash *sf = (struct stm32h7_flash *)f;
|
||||
if (!stm32h7_flash_unlock(t, addr))
|
||||
return -1;
|
||||
return false;
|
||||
/* We come out of reset with HSI 64 MHz. Adapt FLASH_ACR.*/
|
||||
target_mem_write32(t, sf->regbase + FLASH_ACR, 0);
|
||||
addr &= (NUM_SECTOR_PER_BANK * FLASH_SECTOR_SIZE) - 1;
|
||||
|
@ -288,53 +296,37 @@ static int stm32h7_flash_erase(target_flash_s *f, target_addr_t addr, size_t len
|
|||
DEBUG_INFO(" started cr %08" PRIx32 " sr %08" PRIx32 "\n",
|
||||
target_mem_read32(t, sf->regbase + FLASH_CR),
|
||||
target_mem_read32(t, sf->regbase + FLASH_SR));
|
||||
uint32_t status = 0;
|
||||
do {
|
||||
status = target_mem_read32(t, sf->regbase + FLASH_SR);
|
||||
if (target_check_error(t)) {
|
||||
DEBUG_WARN("stm32h7_flash_erase: comm failed\n");
|
||||
return -1;
|
||||
}
|
||||
// target_mem_write32(t, H7_IWDG_BASE, 0x0000aaaa);
|
||||
} while (status & (FLASH_SR_QW | FLASH_SR_BSY));
|
||||
|
||||
if (status & FLASH_SR_ERROR_MASK) {
|
||||
DEBUG_WARN("stm32h7_flash_erase: error, sr: %08" PRIx32 "\n", status);
|
||||
return -1;
|
||||
}
|
||||
if (!stm32h7_flash_busy_wait(t, sf->regbase))
|
||||
return false;
|
||||
|
||||
++start_sector;
|
||||
}
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int stm32h7_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len)
|
||||
static bool stm32h7_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len)
|
||||
{
|
||||
target *t = f->t;
|
||||
struct stm32h7_flash *sf = (struct stm32h7_flash *)f;
|
||||
enum align psize = sf->psize;
|
||||
if (!stm32h7_flash_unlock(t, dest))
|
||||
return -1;
|
||||
return false;
|
||||
uint32_t cr = psize * FLASH_CR_PSIZE16;
|
||||
target_mem_write32(t, sf->regbase + FLASH_CR, cr);
|
||||
cr |= FLASH_CR_PG;
|
||||
target_mem_write32(t, sf->regbase + FLASH_CR, cr);
|
||||
/* does H7 stall?*/
|
||||
uint32_t status_reg = sf->regbase + FLASH_SR;
|
||||
uint32_t status = 0;
|
||||
|
||||
target_mem_write(t, dest, src, len);
|
||||
while ((status = target_mem_read32(t, status_reg)) & FLASH_SR_BSY) {
|
||||
if(target_check_error(t)) {
|
||||
DEBUG_WARN("stm32h7_flash_write: BSY comm failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (status & FLASH_SR_ERROR_MASK) {
|
||||
DEBUG_WARN("stm32h7_flash_write: error sr %08" PRIx32 "\n", status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!stm32h7_flash_busy_wait(t, sf->regbase))
|
||||
return false;
|
||||
|
||||
/* Close write windows.*/
|
||||
target_mem_write32(t, sf->regbase + FLASH_CR, 0);
|
||||
return 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool stm32h7_erase_bank(target *const t, const enum align psize,
|
||||
|
|
|
@ -143,11 +143,11 @@
|
|||
#define STM32L1_NVM_OPTR_BOR_LEV_M (0xf)
|
||||
#define STM32L1_NVM_OPTR_SPRMOD (1 << 8)
|
||||
|
||||
static int stm32lx_nvm_prog_erase(target_flash_s *f, target_addr_t addr, size_t len);
|
||||
static int stm32lx_nvm_prog_write(target_flash_s *f, target_addr_t destination, const void *src, size_t size);
|
||||
static bool stm32lx_nvm_prog_erase(target_flash_s *f, target_addr_t addr, size_t len);
|
||||
static bool stm32lx_nvm_prog_write(target_flash_s *f, target_addr_t destination, const void *src, size_t size);
|
||||
|
||||
static int stm32lx_nvm_data_erase(target_flash_s *f, target_addr_t addr, size_t len);
|
||||
static int stm32lx_nvm_data_write(target_flash_s *f, target_addr_t destination, const void *source, size_t size);
|
||||
static bool stm32lx_nvm_data_erase(target_flash_s *f, target_addr_t addr, size_t len);
|
||||
static bool stm32lx_nvm_data_write(target_flash_s *f, target_addr_t destination, const void *source, size_t size);
|
||||
|
||||
static bool stm32lx_cmd_option(target *t, int argc, char **argv);
|
||||
static bool stm32lx_cmd_eeprom(target *t, int argc, char **argv);
|
||||
|
@ -321,25 +321,37 @@ static bool stm32lx_nvm_opt_unlock(target *t, uint32_t nvm)
|
|||
return !(target_mem_read32(t, STM32Lx_NVM_PECR(nvm)) & STM32Lx_NVM_PECR_OPTLOCK);
|
||||
}
|
||||
|
||||
static bool stm32lx_nvm_busy_wait(target *t, uint32_t nvm)
|
||||
{
|
||||
uint32_t sr;
|
||||
do {
|
||||
sr = target_mem_read32(t, STM32Lx_NVM_SR(nvm));
|
||||
if ((sr & STM32Lx_NVM_SR_ERR_M) || !(sr & STM32Lx_NVM_SR_EOP) || target_check_error(t))
|
||||
return false;
|
||||
} while (sr & STM32Lx_NVM_SR_BSY);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Erase a region of program flash using operations through the debug
|
||||
interface. This is slower than stubbed versions(see NOTES). The
|
||||
flash array is erased for all pages from addr to addr+len
|
||||
inclusive. NVM register file address chosen from target. */
|
||||
static int stm32lx_nvm_prog_erase(target_flash_s *f, target_addr_t addr, size_t len)
|
||||
static bool stm32lx_nvm_prog_erase(target_flash_s *f, target_addr_t addr, size_t len)
|
||||
{
|
||||
target *t = f->t;
|
||||
const size_t page_size = f->blocksize;
|
||||
const uint32_t nvm = stm32lx_nvm_phys(t);
|
||||
|
||||
if (!stm32lx_nvm_prog_data_unlock(t, nvm))
|
||||
return -1;
|
||||
return false;
|
||||
|
||||
/* Flash page erase instruction */
|
||||
target_mem_write32(t, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_PROG);
|
||||
|
||||
uint32_t pecr = target_mem_read32(t, STM32Lx_NVM_PECR(nvm));
|
||||
const uint32_t pecr = target_mem_read32(t, STM32Lx_NVM_PECR(nvm));
|
||||
if ((pecr & (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE)) != (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE))
|
||||
return -1;
|
||||
return false;
|
||||
|
||||
/* Clear errors. Note that this only works when we wait for the NVM
|
||||
block to complete the last operation. */
|
||||
|
@ -359,32 +371,23 @@ static int stm32lx_nvm_prog_erase(target_flash_s *f, target_addr_t addr, size_t
|
|||
stm32lx_nvm_lock(t, nvm);
|
||||
|
||||
/* Wait for completion or an error */
|
||||
uint32_t sr;
|
||||
do {
|
||||
sr = target_mem_read32(t, STM32Lx_NVM_SR(nvm));
|
||||
} while (sr & STM32Lx_NVM_SR_BSY);
|
||||
|
||||
if ((sr & STM32Lx_NVM_SR_ERR_M) || !(sr & STM32Lx_NVM_SR_EOP) || target_check_error(t))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
return stm32lx_nvm_busy_wait(t, nvm);
|
||||
}
|
||||
|
||||
/** Write to program flash using operations through the debug
|
||||
interface. */
|
||||
static int stm32lx_nvm_prog_write(target_flash_s *f, target_addr_t dest, const void *src, size_t size)
|
||||
static bool stm32lx_nvm_prog_write(target_flash_s *f, target_addr_t dest, const void *src, size_t size)
|
||||
{
|
||||
target *t = f->t;
|
||||
const uint32_t nvm = stm32lx_nvm_phys(t);
|
||||
|
||||
if (!stm32lx_nvm_prog_data_unlock(t, nvm))
|
||||
return -1;
|
||||
return false;
|
||||
|
||||
/* Wait for BSY to clear because we cannot write the PECR until
|
||||
the previous operation completes on STM32Lxxx. */
|
||||
while (target_mem_read32(t, STM32Lx_NVM_SR(nvm)) & STM32Lx_NVM_SR_BSY)
|
||||
if (target_check_error(t))
|
||||
return -1;
|
||||
if (!stm32lx_nvm_busy_wait(t, nvm))
|
||||
return false;
|
||||
|
||||
target_mem_write32(t, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_FPRG);
|
||||
target_mem_write(t, dest, src, size);
|
||||
|
@ -393,22 +396,14 @@ static int stm32lx_nvm_prog_write(target_flash_s *f, target_addr_t dest, const v
|
|||
stm32lx_nvm_lock(t, nvm);
|
||||
|
||||
/* Wait for completion or an error */
|
||||
uint32_t sr;
|
||||
do {
|
||||
sr = target_mem_read32(t, STM32Lx_NVM_SR(nvm));
|
||||
} while (sr & STM32Lx_NVM_SR_BSY);
|
||||
|
||||
if ((sr & STM32Lx_NVM_SR_ERR_M) || !(sr & STM32Lx_NVM_SR_EOP) || target_check_error(t))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
return stm32lx_nvm_busy_wait(t, nvm);
|
||||
}
|
||||
|
||||
/** Erase a region of data flash using operations through the debug
|
||||
interface . The flash is erased for all pages from addr to
|
||||
addr+len, inclusive, on a word boundary. NVM register file
|
||||
address chosen from target. */
|
||||
static int stm32lx_nvm_data_erase(target_flash_s *f, target_addr_t addr, size_t len)
|
||||
static bool stm32lx_nvm_data_erase(target_flash_s *f, target_addr_t addr, size_t len)
|
||||
{
|
||||
target *t = f->t;
|
||||
const size_t page_size = f->blocksize;
|
||||
|
@ -419,14 +414,14 @@ static int stm32lx_nvm_data_erase(target_flash_s *f, target_addr_t addr, size_t
|
|||
addr &= ~3;
|
||||
|
||||
if (!stm32lx_nvm_prog_data_unlock(t, nvm))
|
||||
return -1;
|
||||
return false;
|
||||
|
||||
/* Flash data erase instruction */
|
||||
target_mem_write32(t, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_DATA);
|
||||
|
||||
uint32_t pecr = target_mem_read32(t, STM32Lx_NVM_PECR(nvm));
|
||||
if ((pecr & (STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_DATA)) != (STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_DATA))
|
||||
return -1;
|
||||
return false;
|
||||
|
||||
while (len > 0) {
|
||||
/* Write first word of page to 0 */
|
||||
|
@ -443,22 +438,14 @@ static int stm32lx_nvm_data_erase(target_flash_s *f, target_addr_t addr, size_t
|
|||
stm32lx_nvm_lock(t, nvm);
|
||||
|
||||
/* Wait for completion or an error */
|
||||
uint32_t sr;
|
||||
do {
|
||||
sr = target_mem_read32(t, STM32Lx_NVM_SR(nvm));
|
||||
} while (sr & STM32Lx_NVM_SR_BSY);
|
||||
|
||||
if ((sr & STM32Lx_NVM_SR_ERR_M) || !(sr & STM32Lx_NVM_SR_EOP) || target_check_error(t))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
return stm32lx_nvm_busy_wait(t, nvm);
|
||||
}
|
||||
|
||||
/** Write to data flash using operations through the debug interface.
|
||||
NVM register file address chosen from target. Unaligned
|
||||
destination writes are supported (though unaligned sources are
|
||||
not). */
|
||||
static int stm32lx_nvm_data_write(target_flash_s *f, target_addr_t destination, const void *src, size_t size)
|
||||
static bool stm32lx_nvm_data_write(target_flash_s *f, target_addr_t destination, const void *src, size_t size)
|
||||
{
|
||||
target *t = f->t;
|
||||
const uint32_t nvm = stm32lx_nvm_phys(t);
|
||||
|
@ -466,7 +453,7 @@ static int stm32lx_nvm_data_write(target_flash_s *f, target_addr_t destination,
|
|||
uint32_t *source = (uint32_t *)src;
|
||||
|
||||
if (!stm32lx_nvm_prog_data_unlock(t, nvm))
|
||||
return -1;
|
||||
return false;
|
||||
|
||||
target_mem_write32(t, STM32Lx_NVM_PECR(nvm), is_stm32l1 ? 0 : STM32Lx_NVM_PECR_DATA);
|
||||
|
||||
|
@ -477,22 +464,14 @@ static int stm32lx_nvm_data_write(target_flash_s *f, target_addr_t destination,
|
|||
destination += 4;
|
||||
|
||||
if (target_check_error(t))
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Disable further programming by locking PECR */
|
||||
stm32lx_nvm_lock(t, nvm);
|
||||
|
||||
/* Wait for completion or an error */
|
||||
uint32_t sr;
|
||||
do {
|
||||
sr = target_mem_read32(t, STM32Lx_NVM_SR(nvm));
|
||||
} while (sr & STM32Lx_NVM_SR_BSY);
|
||||
|
||||
if ((sr & STM32Lx_NVM_SR_ERR_M) || !(sr & STM32Lx_NVM_SR_EOP) || target_check_error(t))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
return stm32lx_nvm_busy_wait(t, nvm);
|
||||
}
|
||||
|
||||
/** Write one option word. The address is the physical address of the
|
||||
|
@ -509,12 +488,7 @@ static bool stm32lx_option_write(target *t, uint32_t address, uint32_t value)
|
|||
target_mem_write32(t, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_FIX);
|
||||
target_mem_write32(t, address, value);
|
||||
|
||||
uint32_t sr;
|
||||
do {
|
||||
sr = target_mem_read32(t, STM32Lx_NVM_SR(nvm));
|
||||
} while (sr & STM32Lx_NVM_SR_BSY);
|
||||
|
||||
return !(sr & STM32Lx_NVM_SR_ERR_M);
|
||||
return stm32lx_nvm_busy_wait(t, nvm);
|
||||
}
|
||||
|
||||
/** Write one eeprom value. This version is more flexible than that
|
||||
|
@ -543,12 +517,7 @@ static bool stm32lx_eeprom_write(target *t, uint32_t address, size_t cb, uint32_
|
|||
else
|
||||
return false;
|
||||
|
||||
uint32_t sr;
|
||||
do {
|
||||
sr = target_mem_read32(t, STM32Lx_NVM_SR(nvm));
|
||||
} while (sr & STM32Lx_NVM_SR_BSY);
|
||||
|
||||
return !(sr & STM32Lx_NVM_SR_ERR_M);
|
||||
return stm32lx_nvm_busy_wait(t, nvm);
|
||||
}
|
||||
|
||||
static bool stm32lx_cmd_option(target *t, int argc, char **argv)
|
||||
|
|
|
@ -53,8 +53,8 @@ const struct command_s stm32l4_cmd_list[] = {
|
|||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
static int stm32l4_flash_erase(target_flash_s *f, target_addr_t addr, size_t len);
|
||||
static int stm32l4_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len);
|
||||
static bool stm32l4_flash_erase(target_flash_s *f, target_addr_t addr, size_t len);
|
||||
static bool stm32l4_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len);
|
||||
static bool stm32l4_mass_erase(target *t);
|
||||
|
||||
/* Flash Program ad Erase Controller Register Map */
|
||||
|
@ -569,16 +569,28 @@ static void stm32l4_flash_unlock(target *t)
|
|||
}
|
||||
}
|
||||
|
||||
static int stm32l4_flash_erase(target_flash_s *f, target_addr_t addr, size_t len)
|
||||
static bool stm32l4_flash_busy_wait(target *t)
|
||||
{
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
uint32_t sr;
|
||||
do {
|
||||
sr = stm32l4_flash_read32(t, FLASH_SR);
|
||||
if ((sr & FLASH_SR_ERROR_MASK) || target_check_error(t)) {
|
||||
DEBUG_WARN("stm32l4 flash error: sr 0x%" PRIx32 "\n", sr);
|
||||
return false;
|
||||
}
|
||||
} while (sr & FLASH_SR_BSY);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool stm32l4_flash_erase(target_flash_s *f, target_addr_t addr, size_t len)
|
||||
{
|
||||
target *t = f->t;
|
||||
stm32l4_flash_unlock(t);
|
||||
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
while (stm32l4_flash_read32(t, FLASH_SR) & FLASH_SR_BSY) {
|
||||
if (target_check_error(t))
|
||||
return -1;
|
||||
}
|
||||
if (!stm32l4_flash_busy_wait(t))
|
||||
return false;
|
||||
|
||||
/* Fixme: OPTVER always set after reset! Wrong option defaults?*/
|
||||
stm32l4_flash_write32(t, FLASH_SR, stm32l4_flash_read32(t, FLASH_SR));
|
||||
|
@ -595,11 +607,9 @@ static int stm32l4_flash_erase(target_flash_s *f, target_addr_t addr, size_t len
|
|||
ctrl_reg |= FLASH_CR_STRT;
|
||||
stm32l4_flash_write32(t, FLASH_CR, ctrl_reg);
|
||||
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
while (stm32l4_flash_read32(t, FLASH_SR) & FLASH_SR_BSY) {
|
||||
if (target_check_error(t))
|
||||
return -1;
|
||||
}
|
||||
if (!stm32l4_flash_busy_wait(t))
|
||||
return false;
|
||||
|
||||
if (len > blocksize)
|
||||
len -= blocksize;
|
||||
else
|
||||
|
@ -608,32 +618,17 @@ static int stm32l4_flash_erase(target_flash_s *f, target_addr_t addr, size_t len
|
|||
page++;
|
||||
}
|
||||
|
||||
/* Check for error */
|
||||
if (stm32l4_flash_read32(t, FLASH_SR) & FLASH_SR_ERROR_MASK)
|
||||
return -1;
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int stm32l4_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len)
|
||||
static bool stm32l4_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len)
|
||||
{
|
||||
target *t = f->t;
|
||||
stm32l4_flash_write32(t, FLASH_CR, FLASH_CR_PG);
|
||||
target_mem_write(t, dest, src, len);
|
||||
/* Wait for completion or an error */
|
||||
uint32_t status;
|
||||
do {
|
||||
status = stm32l4_flash_read32(t, FLASH_SR);
|
||||
if (target_check_error(t)) {
|
||||
DEBUG_WARN("stm32l4 flash write: comm error\n");
|
||||
return -1;
|
||||
}
|
||||
} while (status & FLASH_SR_BSY);
|
||||
|
||||
if (status & FLASH_SR_ERROR_MASK) {
|
||||
DEBUG_WARN("stm32l4 flash write error: sr 0x%" PRIx32 "\n", status);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
/* Wait for completion or an error */
|
||||
return stm32l4_flash_busy_wait(t);
|
||||
}
|
||||
|
||||
static bool stm32l4_cmd_erase(target *const t, const uint32_t action)
|
||||
|
@ -644,17 +639,19 @@ static bool stm32l4_cmd_erase(target *const t, const uint32_t action)
|
|||
stm32l4_flash_write32(t, FLASH_CR, action);
|
||||
stm32l4_flash_write32(t, FLASH_CR, action | FLASH_CR_STRT);
|
||||
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
uint32_t sr;
|
||||
platform_timeout timeout;
|
||||
platform_timeout_set(&timeout, 500);
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
while (stm32l4_flash_read32(t, FLASH_SR) & FLASH_SR_BSY) {
|
||||
if(target_check_error(t))
|
||||
do {
|
||||
sr = stm32l4_flash_read32(t, FLASH_SR);
|
||||
if ((sr & FLASH_SR_ERROR_MASK) || target_check_error(t))
|
||||
return false;
|
||||
target_print_progress(&timeout);
|
||||
}
|
||||
} while (sr & FLASH_SR_BSY);
|
||||
|
||||
/* Check for error */
|
||||
return !(stm32l4_flash_read32(t, FLASH_SR) & FLASH_SR_ERROR_MASK);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool stm32l4_mass_erase(target *const t)
|
||||
|
@ -701,15 +698,13 @@ static bool stm32l4_option_write(
|
|||
stm32l4_flash_unlock(t);
|
||||
stm32l4_flash_write32(t, FLASH_OPTKEYR, OPTKEY1);
|
||||
stm32l4_flash_write32(t, FLASH_OPTKEYR, OPTKEY2);
|
||||
while (stm32l4_flash_read32(t, FLASH_SR) & FLASH_SR_BSY)
|
||||
if(target_check_error(t))
|
||||
return true;
|
||||
if (!stm32l4_flash_busy_wait(t))
|
||||
return true;
|
||||
for (int i = 0; i < len; i++)
|
||||
target_mem_write32(t, fpec_base + i2offset[i], values[i]);
|
||||
stm32l4_flash_write32(t, FLASH_CR, FLASH_CR_OPTSTRT);
|
||||
while (stm32l4_flash_read32(t, FLASH_SR) & FLASH_SR_BSY)
|
||||
if(target_check_error(t))
|
||||
return true;
|
||||
if (!stm32l4_flash_busy_wait(t))
|
||||
return false;
|
||||
stm32l4_flash_write32(t, FLASH_CR, FLASH_CR_OBL_LAUNCH);
|
||||
while (stm32l4_flash_read32(t, FLASH_CR) & FLASH_CR_OBL_LAUNCH)
|
||||
if(target_check_error(t))
|
||||
|
|
Loading…
Reference in New Issue