stm32f4: Fix option byte handling (#654)
Option bytes are not accessible with level 1 protection, so Use FLASH_OPTCR(x) Fix crash with "mon opt write xxxx" Handle option manipulation better when HW Watchdog fuse is set Allow abbreviated "mon option x<yyy>" commands
This commit is contained in:
parent
923949d5dd
commit
9b939f4a3a
|
@ -83,9 +83,14 @@ static int stm32f4_flash_write(struct target_flash *f,
|
|||
|
||||
#define FLASH_OPTCR_OPTLOCK (1 << 0)
|
||||
#define FLASH_OPTCR_OPTSTRT (1 << 1)
|
||||
#define FLASH_OPTCR_WDG_SW (1 << 5)
|
||||
#define FLASH_OPTCR_nDBANK (1 << 29)
|
||||
#define FLASH_OPTCR_DB1M (1 << 30)
|
||||
|
||||
#define FLASH_OPTCR_PROT_MASK 0xff00
|
||||
#define FLASH_OPTCR_PROT_L0 0xaa00
|
||||
#define FLASH_OPTCR_PROT_L1 0xbb00
|
||||
|
||||
#define KEY1 0x45670123
|
||||
#define KEY2 0xCDEF89AB
|
||||
|
||||
|
@ -561,6 +566,19 @@ static bool optcr_mask(target *t, uint32_t *val)
|
|||
|
||||
static bool stm32f4_option_write(target *t, uint32_t *val, int count)
|
||||
{
|
||||
val[0] &= ~(FLASH_OPTCR_OPTSTRT | FLASH_OPTCR_OPTLOCK);
|
||||
uint32_t optcr = target_mem_read32(t, FLASH_OPTCR);
|
||||
/* Check if watchdog and read protection is active.
|
||||
* When both are active, watchdog will trigger when erasing
|
||||
* to get back to level 0 protection and operation aborts!
|
||||
*/
|
||||
if (!(optcr & FLASH_OPTCR_WDG_SW) &&
|
||||
((optcr & FLASH_OPTCR_PROT_MASK) != FLASH_OPTCR_PROT_L0) &&
|
||||
((val[0] & FLASH_OPTCR_PROT_MASK) != FLASH_OPTCR_PROT_L1)) {
|
||||
val[0] &= ~FLASH_OPTCR_PROT_MASK;
|
||||
val[0] |= FLASH_OPTCR_PROT_L1;
|
||||
tc_printf(t, "Keeping L1 protection while HW Watchdog fuse is set!\n");
|
||||
}
|
||||
target_mem_write32(t, FLASH_OPTKEYR, OPTKEY1);
|
||||
target_mem_write32(t, FLASH_OPTKEYR, OPTKEY2);
|
||||
while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY)
|
||||
|
@ -578,11 +596,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)
|
||||
if(target_check_error(t))
|
||||
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)) {
|
||||
tc_printf(t, " failed\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
tc_printf(t, "\n");
|
||||
target_mem_write32(t, FLASH_OPTCR, FLASH_OPTCR_OPTLOCK);
|
||||
/* Reset target to reload option bits.*/
|
||||
target_reset(t);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -619,7 +648,7 @@ static bool stm32f4_option_write_default(target *t)
|
|||
|
||||
static bool stm32f4_cmd_option(target *t, int argc, char *argv[])
|
||||
{
|
||||
uint32_t start = 0x1FFFC000, val[3];
|
||||
uint32_t val[3];
|
||||
int count = 0, readcount = 1;
|
||||
|
||||
switch (t->idcode) {
|
||||
|
@ -628,8 +657,6 @@ static bool stm32f4_cmd_option(target *t, int argc, char *argv[])
|
|||
/* fall through.*/
|
||||
case ID_STM32F74X:
|
||||
case ID_STM32F76X:
|
||||
/* F7 Devices have option bytes at 0x1FFF0000. */
|
||||
start = 0x1FFF0000;
|
||||
readcount++;
|
||||
break;
|
||||
case ID_STM32F42X:
|
||||
|
@ -637,17 +664,17 @@ static bool stm32f4_cmd_option(target *t, int argc, char *argv[])
|
|||
readcount++;
|
||||
}
|
||||
|
||||
if ((argc == 2) && !strcmp(argv[1], "erase")) {
|
||||
if ((argc == 2) && !strncasecmp(argv[1], "erase", 1)) {
|
||||
stm32f4_option_write_default(t);
|
||||
}
|
||||
else if ((argc > 1) && !strcmp(argv[1], "write")) {
|
||||
else if ((argc > 2) && !strncasecmp(argv[1], "write", 1)) {
|
||||
val[0] = strtoul(argv[2], NULL, 0);
|
||||
count++;
|
||||
if (argc > 2) {
|
||||
if (argc > 3) {
|
||||
val[1] = strtoul(argv[3], NULL, 0);
|
||||
count ++;
|
||||
}
|
||||
if (argc > 3) {
|
||||
if (argc > 4) {
|
||||
val[2] = strtoul(argv[4], NULL, 0);
|
||||
count ++;
|
||||
}
|
||||
|
@ -665,22 +692,11 @@ static bool stm32f4_cmd_option(target *t, int argc, char *argv[])
|
|||
tc_printf(t, "\n");
|
||||
}
|
||||
|
||||
val[0] = (target_mem_read32(t, start + 8) & 0xffff) << 16;
|
||||
val[0] |= (target_mem_read32(t, start ) & 0xffff);
|
||||
if (readcount > 1) {
|
||||
if (start == 0x1FFFC000) /* F4 */ {
|
||||
val[1] = target_mem_read32(t, 0x1ffec008);
|
||||
val[1] &= 0xffff;
|
||||
val[1] <<= 16;
|
||||
} else {
|
||||
val[1] = (target_mem_read32(t, start + 0x18) & 0xffff) << 16;
|
||||
val[1] |= (target_mem_read32(t, start + 0x10) & 0xffff);
|
||||
}
|
||||
}
|
||||
if (readcount > 2) {
|
||||
val[2] = (target_mem_read32(t, start + 0x28) & 0xffff) << 16;
|
||||
val[2] |= (target_mem_read32(t, start + 0x20) & 0xffff);
|
||||
}
|
||||
val[0] = target_mem_read32(t, FLASH_OPTCR);
|
||||
if (readcount > 1)
|
||||
val[1] = target_mem_read32(t, FLASH_OPTCR + 4);
|
||||
if (readcount > 2)
|
||||
val[2] = target_mem_read32(t, FLASH_OPTCR + 8);
|
||||
optcr_mask(t, val);
|
||||
tc_printf(t, "OPTCR: 0x%08X ", val[0]);
|
||||
if (readcount > 1)
|
||||
|
|
Loading…
Reference in New Issue