This is an automated email from Gerrit. Claudio Lanconelli ([email protected]) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/3519
-- gerrit commit c4ee985c56a400d5b4de01bbc5ffe0862baa44f9 Author: Claudio Lanconelli <[email protected]> Date: Fri Jun 17 15:40:58 2016 +0200 Flash commands 'stm32f2x options_read and options_read' fixed for STM32F7. There are two additional halfwords for adjusting boot adresses, and another byte for user options. Before this patch on STM32F7 the option bits IWDG_STOP IWDG_STDBY and WWDG_SW were corrupted. Change-Id: I75c740db09157e40c6b77c70eb19420349a790ea Signed-off-by: Claudio Lanconelli <[email protected]> diff --git a/src/flash/nor/stm32f2x.c b/src/flash/nor/stm32f2x.c index 4269c44..84af8fd 100644 --- a/src/flash/nor/stm32f2x.c +++ b/src/flash/nor/stm32f2x.c @@ -164,13 +164,16 @@ struct stm32x_options { uint8_t RDP; uint8_t user_options; + uint8_t user_options_high; uint32_t protection; + uint16_t boot_addr[2]; }; struct stm32x_flash_bank { struct stm32x_options option_bytes; int probed; bool has_large_mem; /* stm32f42x/stm32f43x family */ + bool has_boot_addr; /* stm32f7xxx */ uint32_t user_bank_size; }; @@ -321,16 +324,32 @@ static int stm32x_read_options(struct flash_bank *bank) if (retval != ERROR_OK) return retval; - stm32x_info->option_bytes.user_options = optiondata & 0xec; + LOG_DEBUG("FLASH_OPTCR: %" PRIx32, optiondata); + + /* caution: f2 implements 5 bits (WDG_SW only) + * whereas f7 6 bits (IWDG_SW and WWDG_SW) in user_options */ + stm32x_info->option_bytes.user_options = optiondata & 0xfc; + /* f7 has IWDG_STOP and IWDG_STDBY in bit 31 and 30 */ + stm32x_info->option_bytes.user_options_high = (optiondata >> 24) & 0xc0; stm32x_info->option_bytes.RDP = (optiondata >> 8) & 0xff; - stm32x_info->option_bytes.protection = (optiondata >> 16) & 0xfff; + stm32x_info->option_bytes.protection = (optiondata >> 16) & 0xff; - if (stm32x_info->has_large_mem) { + if (stm32x_info->has_boot_addr) { + retval = target_read_u32(target, STM32_FLASH_OPTCR1, &optiondata); + if (retval != ERROR_OK) + return retval; + LOG_DEBUG("FLASH_OPTCR1: %" PRIx32, optiondata); + + stm32x_info->option_bytes.boot_addr[0] = optiondata & 0xffff; + stm32x_info->option_bytes.boot_addr[1] = (optiondata >> 16) & 0xffff; + } else if (stm32x_info->has_large_mem) { retval = target_read_u32(target, STM32_FLASH_OPTCR1, &optiondata); if (retval != ERROR_OK) return retval; + LOG_DEBUG("FLASH_OPTCR1: %" PRIx32, optiondata); + /* append protection bits */ stm32x_info->option_bytes.protection |= (optiondata >> 4) & 0x00fff000; } @@ -355,18 +374,25 @@ static int stm32x_write_options(struct flash_bank *bank) /* rebuild option data */ optiondata = stm32x_info->option_bytes.user_options; - optiondata |= stm32x_info->option_bytes.RDP << 8; + optiondata |= (uint32_t)stm32x_info->option_bytes.RDP << 8; optiondata |= (stm32x_info->option_bytes.protection & 0x0fff) << 16; + optiondata |= (uint32_t)stm32x_info->option_bytes.user_options_high << 24; /* program options */ retval = target_write_u32(target, STM32_FLASH_OPTCR, optiondata); if (retval != ERROR_OK) return retval; - if (stm32x_info->has_large_mem) { - - uint32_t optiondata2 = 0; - optiondata2 |= (stm32x_info->option_bytes.protection & 0x00fff000) << 4; + if (stm32x_info->has_boot_addr) { + uint32_t optiondata2; + optiondata2 = stm32x_info->option_bytes.boot_addr[0] | + (uint32_t)stm32x_info->option_bytes.boot_addr[1] << 16; + retval = target_write_u32(target, STM32_FLASH_OPTCR1, optiondata2); + if (retval != ERROR_OK) + return retval; + } else if (stm32x_info->has_large_mem) { + uint32_t optiondata2; + optiondata2 = (stm32x_info->option_bytes.protection & 0x00fff000) << 4; retval = target_write_u32(target, STM32_FLASH_OPTCR1, optiondata2); if (retval != ERROR_OK) return retval; @@ -774,6 +800,7 @@ static int stm32x_probe(struct flash_bank *bank) stm32x_info->probed = 0; stm32x_info->has_large_mem = false; + stm32x_info->has_boot_addr = false; /* read stm32 device id register */ int retval = stm32x_get_device_id(bank, &device_id); @@ -807,6 +834,7 @@ static int stm32x_probe(struct flash_bank *bank) max_flash_size_in_kb = 1024; max_sector_size_in_kb = 256; flash_size_reg = 0x1FF0F442; + stm32x_info->has_boot_addr = true; break; default: LOG_WARNING("Cannot identify target as a STM32 family."); @@ -1193,6 +1221,93 @@ COMMAND_HANDLER(stm32x_handle_mass_erase_command) return retval; } +COMMAND_HANDLER(stm32f2x_handle_options_read_command) +{ + int retval; + struct flash_bank *bank; + struct stm32x_flash_bank *stm32x_info = NULL; + uint16_t user_options; + + if (CMD_ARGC != 1) { + command_print(CMD_CTX, "stm32f2x options_read <bank>"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); + if (ERROR_OK != retval) + return retval; + + retval = stm32x_read_options(bank); + if (ERROR_OK != retval) + return retval; + + stm32x_info = bank->driver_priv; + user_options = stm32x_info->option_bytes.user_options | + (uint16_t)stm32x_info->option_bytes.user_options_high << 8; + if (stm32x_info->has_boot_addr) { + command_print(CMD_CTX, "stm32f2x user_options 0x%02X, " + "boot_add0 0x%04X, boot_add1 0x%04X", + user_options, + stm32x_info->option_bytes.boot_addr[0], + stm32x_info->option_bytes.boot_addr[1]); + } else { + command_print(CMD_CTX, "stm32f2x user_options 0x%02X", + user_options); + } + + return retval; +} + +COMMAND_HANDLER(stm32f2x_handle_options_write_command) +{ + int retval; + struct flash_bank *bank; + struct stm32x_flash_bank *stm32x_info = NULL; + uint16_t user_options; + + if (CMD_ARGC < 1) { + command_print(CMD_CTX, "stm32f2x options_write <bank> ..."); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); + if (ERROR_OK != retval) + return retval; + + retval = stm32x_read_options(bank); + if (ERROR_OK != retval) + return retval; + + stm32x_info = bank->driver_priv; + if (!stm32x_info->has_boot_addr) { + if (CMD_ARGC != 2) { + command_print(CMD_CTX, "stm32f2x options_write <bank> <user_options>"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + } else { + if (CMD_ARGC != 4) { + command_print(CMD_CTX, "stm32f2x options_write <bank> <user_options> <boot_addr0> <boot_addr1>"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + COMMAND_PARSE_NUMBER(u16, CMD_ARGV[2], stm32x_info->option_bytes.boot_addr[0]); + COMMAND_PARSE_NUMBER(u16, CMD_ARGV[3], stm32x_info->option_bytes.boot_addr[1]); + } + + COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], user_options); + stm32x_info->option_bytes.user_options = user_options & 0xff; + stm32x_info->option_bytes.user_options_high = (user_options >> 8) & 0xff; + + if (stm32x_write_options(bank) != ERROR_OK) { + command_print(CMD_CTX, "stm32f2x failed to write options"); + return ERROR_OK; + } + + command_print(CMD_CTX, "stm32f2x write options complete.\n" + "INFO: a reset or power cycle is required " + "for the new settings to take effect."); + return retval; +} + static const struct command_registration stm32x_exec_command_handlers[] = { { .name = "lock", @@ -1215,6 +1330,20 @@ static const struct command_registration stm32x_exec_command_handlers[] = { .usage = "bank_id", .help = "Erase entire flash device.", }, + { + .name = "options_read", + .handler = stm32f2x_handle_options_read_command, + .mode = COMMAND_EXEC, + .usage = "bank_id", + .help = "Read and display device option bytes.", + }, + { + .name = "options_write", + .handler = stm32f2x_handle_options_write_command, + .mode = COMMAND_EXEC, + .usage = "bank_id option_byte [ boot_add0 boot_add1]", + .help = "Write option bytes", + }, COMMAND_REGISTRATION_DONE }; -- ------------------------------------------------------------------------------ What NetFlow Analyzer can do for you? Monitors network bandwidth and traffic patterns at an interface-level. Reveals which users, apps, and protocols are consuming the most bandwidth. Provides multi-vendor support for NetFlow, J-Flow, sFlow and other flows. Make informed decisions using capacity planning reports. http://sdm.link/zohomanageengine _______________________________________________ OpenOCD-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/openocd-devel
