X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fflash%2Fnor%2Fstm32f2x.c;h=1fca3eba42251572eee9e3bbb5d399d2b64684c0;hb=e024bcc3d93b9b0a665a2d32b747733f90cbcfac;hp=c2f586a7a8983fe47bdbe5670c8ea37bbe583a2d;hpb=b066a7db2498eadcdeb55ea763d805c75fbbd00b;p=openocd.git diff --git a/src/flash/nor/stm32f2x.c b/src/flash/nor/stm32f2x.c index c2f586a7a8..1fca3eba42 100644 --- a/src/flash/nor/stm32f2x.c +++ b/src/flash/nor/stm32f2x.c @@ -165,8 +165,7 @@ FLASH_BANK_COMMAND_HANDLER(stm32x_flash_bank_command) if (CMD_ARGC < 6) { - LOG_WARNING("incomplete flash_bank stm32x configuration"); - return ERROR_FLASH_BANK_INVALID; + return ERROR_COMMAND_SYNTAX_ERROR; } stm32x_info = malloc(sizeof(struct stm32x_flash_bank)); @@ -233,6 +232,8 @@ static int stm32x_wait_status_busy(struct flash_bank *bank, int timeout) static int stm32x_unlock_reg(struct target *target) { + uint32_t ctrl; + /* unlock flash registers */ int retval = target_write_u32(target, STM32_FLASH_KEYR, KEY1); if (retval != ERROR_OK) @@ -241,6 +242,16 @@ static int stm32x_unlock_reg(struct target *target) retval = target_write_u32(target, STM32_FLASH_KEYR, KEY2); if (retval != ERROR_OK) return retval; + + retval = target_read_u32(target, STM32_FLASH_CR, &ctrl); + if (retval != ERROR_OK) + return retval; + + if (ctrl & FLASH_LOCK) { + LOG_ERROR("flash not unlocked STM32_FLASH_CR: %x", ctrl); + return ERROR_TARGET_FAILURE; + } + return ERROR_OK; } @@ -314,32 +325,31 @@ static int stm32x_write_block(struct flash_bank *bank, uint8_t *buffer, struct armv7m_algorithm armv7m_info; int retval = ERROR_OK; - /* see contib/loaders/flash/stm32x.s for src */ + /* see contrib/loaders/flash/stm32f2x.S for src */ static const uint16_t stm32x_flash_write_code_16[] = { -// 00000000 : - 0x4b07, // ldr r3, [pc, #28] (20 ) - 0x6123, // str r3, [r4, #16] - 0xf830, 0x3b02, //ldrh.w r3, [r0], #2 - 0xf821, 0x3b02, //strh.w r3, [r1], #2 - - //0000000c : - 0x68e3, //ldr r3, [r4, #12] -0xf413, 0x3f80, // tst.w r3, #65536 ; 0x10000 -0xd0fb, //beq.n c -0xf013, 0x0ff0, //tst.w r3, #240 ; 0xf0 -0xd101, //bne.n 1e -0x3a01, //subs r2, #1 -0xd1f0, //bne.n 0 - //0000001e : - 0xbe00, // bkpt 0x0000 - - //00000020 : - 0x0101, 0x0000, // .word 0x00000101 - + /* 00000000 : */ + 0x4b07, /* ldr r3, [pc, #28] (20 ) */ + 0x6123, /* str r3, [r4, #16] */ + 0xf830, 0x3b02, /* ldrh.w r3, [r0], #2 */ + 0xf821, 0x3b02, /* strh.w r3, [r1], #2 */ + + /* 0000000c : */ + 0x68e3, /* ldr r3, [r4, #12] */ + 0xf413, 0x3f80, /* tst.w r3, #65536 ; 0x10000 */ + 0xd0fb, /* beq.n c */ + 0xf013, 0x0ff0, /* tst.w r3, #240 ; 0xf0 */ + 0xd101, /* bne.n 1e */ + 0x3a01, /* subs r2, #1 */ + 0xd1f0, /* bne.n 0 */ + /* 0000001e : */ + 0xbe00, /* bkpt 0x0000 */ + + /* 00000020 : */ + 0x0101, 0x0000, /* .word 0x00000101 */ }; - // Flip endian + /* Flip endian */ uint8_t stm32x_flash_write_code[sizeof(stm32x_flash_write_code_16)*2]; for (unsigned i = 0; i < sizeof(stm32x_flash_write_code_16) / 2; i++) { @@ -565,7 +575,7 @@ static int stm32x_probe(struct flash_bank *bank) struct target *target = bank->target; struct stm32x_flash_bank *stm32x_info = bank->driver_priv; int i; - uint16_t num_pages; + uint16_t flash_size_in_kb; uint32_t device_id; uint32_t base_address = 0x08000000; @@ -577,22 +587,38 @@ static int stm32x_probe(struct flash_bank *bank) return retval; LOG_INFO("device id = 0x%08" PRIx32 "", device_id); - if ((device_id & 0x7ff) != 0x411) - { - LOG_WARNING("Cannot identify target as a STM32 family, try the other STM32 drivers."); + /* get flash size from target. */ + retval = target_read_u16(target, 0x1FFF7A10, &flash_size_in_kb); + if (retval != ERROR_OK) { + LOG_WARNING("failed reading flash size, default to max target family"); + /* failed reading flash size, default to max target family */ + flash_size_in_kb = 0xffff; + } + + if ((device_id & 0x7ff) == 0x411) { + /* check for early silicon */ + if (flash_size_in_kb == 0xffff) { + /* number of sectors may be incorrrect on early silicon */ + LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 512k flash"); + flash_size_in_kb = 512; + } + } else { + LOG_WARNING("Cannot identify target as a STM32 family."); return ERROR_FAIL; } - /* sectors sizes vary, handle this in a different code path - * than the rest. - */ - // Uhhh.... what to use here? + LOG_INFO("flash size = %dkbytes", flash_size_in_kb); - /* calculate numbers of pages*/ - num_pages = 4 + 1 + 7; + /* did we assign flash size? */ + assert(flash_size_in_kb != 0xffff); - if (bank->sectors) - { + /* calculate numbers of pages */ + int num_pages = (flash_size_in_kb / 128) + 4; + + /* check that calculation result makes sense */ + assert(num_pages > 0); + + if (bank->sectors) { free(bank->sectors); bank->sectors = NULL; } @@ -600,20 +626,20 @@ static int stm32x_probe(struct flash_bank *bank) bank->base = base_address; bank->num_sectors = num_pages; bank->sectors = malloc(sizeof(struct flash_sector) * num_pages); - bank->size = 0; + + /* fixed memory */ setup_sector(bank, 0, 4, 16 * 1024); setup_sector(bank, 4, 1, 64 * 1024); - setup_sector(bank, 4+1, 7, 128 * 1024); - for (i = 0; i < num_pages; i++) - { + /* dynamic memory */ + setup_sector(bank, 4 + 1, num_pages - 5, 128 * 1024); + + for (i = 0; i < num_pages; i++) { bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 0; } - LOG_INFO("flash size = %dkBytes", bank->size / 1024); - stm32x_info->probed = 1; return ERROR_OK; @@ -676,7 +702,76 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size) return ERROR_OK; } +static int stm32x_mass_erase(struct flash_bank *bank) +{ + int retval; + struct target *target = bank->target; + + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + retval = stm32x_unlock_reg(target); + if (retval != ERROR_OK) + return retval; + + /* mass erase flash memory */ + retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_MER); + if (retval != ERROR_OK) + return retval; + retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), + FLASH_MER | FLASH_STRT); + if (retval != ERROR_OK) + return retval; + + retval = stm32x_wait_status_busy(bank, 30000); + if (retval != ERROR_OK) + return retval; + + retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK); + if (retval != ERROR_OK) + return retval; + + return ERROR_OK; +} + +COMMAND_HANDLER(stm32x_handle_mass_erase_command) +{ + int i; + + if (CMD_ARGC < 1) { + command_print(CMD_CTX, "stm32x mass_erase "); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + struct flash_bank *bank; + int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); + if (ERROR_OK != retval) + return retval; + + retval = stm32x_mass_erase(bank); + if (retval == ERROR_OK) { + /* set all sectors as erased */ + for (i = 0; i < bank->num_sectors; i++) + bank->sectors[i].is_erased = 1; + + command_print(CMD_CTX, "stm32x mass erase complete"); + } else { + command_print(CMD_CTX, "stm32x mass erase failed"); + } + + return retval; +} + static const struct command_registration stm32x_exec_command_handlers[] = { + { + .name = "mass_erase", + .handler = stm32x_handle_mass_erase_command, + .mode = COMMAND_EXEC, + .usage = "bank_id", + .help = "Erase entire flash device.", + }, COMMAND_REGISTRATION_DONE };