#include "imp.h"
#include <helper/binarybuffer.h>
#include <target/algorithm.h>
-#include <target/armv7m.h>
+#include <target/cortex_m.h>
/* stm32x register locations */
struct stm32x_flash_bank {
struct stm32x_options option_bytes;
int ppage_size;
- int probed;
+ bool probed;
bool has_dual_banks;
/* used to access dual flash bank stm32xl */
static int stm32x_mass_erase(struct flash_bank *bank);
static int stm32x_get_device_id(struct flash_bank *bank, uint32_t *device_id);
static int stm32x_write_block(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count);
+ uint32_t address, uint32_t count);
/* flash bank stm32x <base> <size> 0 0 <target#>
*/
stm32x_info = malloc(sizeof(struct stm32x_flash_bank));
bank->driver_priv = stm32x_info;
- stm32x_info->probed = 0;
+ stm32x_info->probed = false;
stm32x_info->has_dual_banks = false;
stm32x_info->can_load_options = false;
stm32x_info->register_base = FLASH_REG_BASE_B0;
/* if we have a dual flash bank device then
* we need to perform option byte stuff on bank0 only */
if (stm32x_info->register_base != FLASH_REG_BASE_B0) {
- LOG_ERROR("Option Byte Operation's must use bank0");
+ LOG_ERROR("Option byte operations must use bank 0");
return ERROR_FLASH_OPERATION_FAILED;
}
uint32_t option_bytes;
int retval;
- /* read user and read protection option bytes */
- retval = target_read_u32(target, STM32_OB_RDP, &option_bytes);
+ /* read user and read protection option bytes, user data option bytes */
+ retval = target_read_u32(target, STM32_FLASH_OBR_B0, &option_bytes);
if (retval != ERROR_OK)
return retval;
- stm32x_info->option_bytes.rdp = option_bytes & 0xFF;
- stm32x_info->option_bytes.user = (option_bytes >> 16) & 0xFF;
-
- /* read user data option bytes */
- retval = target_read_u32(target, STM32_OB_DATA0, &option_bytes);
- if (retval != ERROR_OK)
- return retval;
-
- stm32x_info->option_bytes.data = ((option_bytes >> 8) & 0xFF00) | (option_bytes & 0xFF);
+ stm32x_info->option_bytes.rdp = (option_bytes & (1 << OPT_READOUT)) ? 0 : stm32x_info->default_rdp;
+ stm32x_info->option_bytes.user = (option_bytes >> stm32x_info->option_offset >> 2) & 0xff;
+ stm32x_info->option_bytes.data = (option_bytes >> stm32x_info->user_data_offset) & 0xffff;
/* read write protection option bytes */
- retval = target_read_u32(target, STM32_OB_WRP0, &option_bytes);
- if (retval != ERROR_OK)
- return retval;
-
- stm32x_info->option_bytes.protection = ((option_bytes >> 8) & 0xFF00) | (option_bytes & 0xFF);
-
- retval = target_read_u32(target, STM32_OB_WRP2, &option_bytes);
+ retval = target_read_u32(target, STM32_FLASH_WRPR_B0, &stm32x_info->option_bytes.protection);
if (retval != ERROR_OK)
return retval;
- stm32x_info->option_bytes.protection |= (((option_bytes >> 8) & 0xFF00) | (option_bytes & 0xFF)) << 16;
-
return ERROR_OK;
}
target_buffer_set_u16(target, opt_bytes + 12, (stm32x_info->option_bytes.protection >> 16) & 0xff);
target_buffer_set_u16(target, opt_bytes + 14, (stm32x_info->option_bytes.protection >> 24) & 0xff);
- uint32_t offset = STM32_OB_RDP - bank->base;
- retval = stm32x_write_block(bank, opt_bytes, offset, sizeof(opt_bytes) / 2);
+ retval = stm32x_write_block(bank, opt_bytes, STM32_OB_RDP, sizeof(opt_bytes) / 2);
if (retval != ERROR_OK) {
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
LOG_ERROR("working area required to erase options bytes");
uint32_t protection;
int retval = stm32x_check_operation_supported(bank);
- if (ERROR_OK != retval)
+ if (retval != ERROR_OK)
return retval;
/* medium density - each bit refers to a 4 sector protection block
if (retval != ERROR_OK)
return retval;
- for (int i = 0; i < bank->num_prot_blocks; i++)
+ for (unsigned int i = 0; i < bank->num_prot_blocks; i++)
bank->prot_blocks[i].is_protected = (protection & (1 << i)) ? 0 : 1;
return ERROR_OK;
}
-static int stm32x_erase(struct flash_bank *bank, int first, int last)
+static int stm32x_erase(struct flash_bank *bank, unsigned int first,
+ unsigned int last)
{
struct target *target = bank->target;
- int i;
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
if (retval != ERROR_OK)
return retval;
- for (i = first; i <= last; i++) {
+ for (unsigned int i = first; i <= last; i++) {
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_PER);
if (retval != ERROR_OK)
return retval;
retval = stm32x_wait_status_busy(bank, FLASH_ERASE_TIMEOUT);
if (retval != ERROR_OK)
return retval;
-
- bank->sectors[i].is_erased = 1;
}
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK);
return ERROR_OK;
}
-static int stm32x_protect(struct flash_bank *bank, int set, int first, int last)
+static int stm32x_protect(struct flash_bank *bank, int set, unsigned int first,
+ unsigned int last)
{
struct target *target = bank->target;
struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
return retval;
retval = stm32x_erase_options(bank);
- if (retval != ERROR_OK)
+ if (retval != ERROR_OK) {
+ LOG_ERROR("stm32x failed to erase options");
return retval;
+ }
- for (int i = first; i <= last; i++) {
+ for (unsigned int i = first; i <= last; i++) {
if (set)
stm32x_info->option_bytes.protection &= ~(1 << i);
else
}
static int stm32x_write_block(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
+ uint32_t address, uint32_t count)
{
struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
struct target *target = bank->target;
uint32_t buffer_size = 16384;
struct working_area *write_algorithm;
struct working_area *source;
- uint32_t address = bank->base + offset;
struct reg_param reg_params[5];
struct armv7m_algorithm armv7m_info;
int retval = ERROR_OK;
* discrete accesses. */
if (count & 1) {
new_buffer = malloc(count + 1);
- if (new_buffer == NULL) {
+ if (!new_buffer) {
LOG_ERROR("odd number of bytes to write and no memory for padding buffer");
return ERROR_FAIL;
}
goto cleanup;
/* try using a block write */
- retval = stm32x_write_block(bank, buffer, offset, words_remaining);
+ retval = stm32x_write_block(bank, buffer, bank->base + offset, words_remaining);
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
/* if block write failed (no sufficient working area),
LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
while (words_remaining > 0) {
- uint16_t value;
- memcpy(&value, buffer, sizeof(uint16_t));
-
- retval = target_write_u16(target, bank->base + offset, value);
+ retval = target_write_memory(target, bank->base + offset, 2, 1, buffer);
if (retval != ERROR_OK)
goto reset_pg_and_lock;
retval = retval2;
cleanup:
- if (new_buffer)
- free(new_buffer);
-
+ free(new_buffer);
return retval;
}
static int stm32x_get_device_id(struct flash_bank *bank, uint32_t *device_id)
{
- /* This check the device CPUID core register to detect
- * the M0 from the M3 devices. */
-
struct target *target = bank->target;
- uint32_t cpuid, device_id_register = 0;
+ uint32_t device_id_register = 0;
- /* Get the CPUID from the ARM Core
- * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0432c/DDI0432C_cortex_m0_r0p0_trm.pdf 4.2.1 */
- int retval = target_read_u32(target, 0xE000ED00, &cpuid);
- if (retval != ERROR_OK)
- return retval;
+ if (!target_was_examined(target)) {
+ LOG_ERROR("Target not examined yet");
+ return ERROR_TARGET_NOT_EXAMINED;
+ }
- if (((cpuid >> 4) & 0xFFF) == 0xC20) {
- /* 0xC20 is M0 devices */
+ switch (cortex_m_get_partno_safe(target)) {
+ case CORTEX_M0_PARTNO: /* STM32F0x devices */
device_id_register = 0x40015800;
- } else if (((cpuid >> 4) & 0xFFF) == 0xC23) {
- /* 0xC23 is M3 devices */
+ break;
+ case CORTEX_M3_PARTNO: /* STM32F1x devices */
device_id_register = 0xE0042000;
- } else if (((cpuid >> 4) & 0xFFF) == 0xC24) {
- /* 0xC24 is M4 devices */
+ break;
+ case CORTEX_M4_PARTNO: /* STM32F3x devices */
device_id_register = 0xE0042000;
- } else {
+ break;
+ case CORTEX_M23_PARTNO: /* GD32E23x devices */
+ device_id_register = 0x40015800;
+ break;
+ default:
LOG_ERROR("Cannot identify target as a stm32x");
return ERROR_FAIL;
}
/* read stm32 device id register */
- retval = target_read_u32(target, device_id_register, device_id);
+ int retval = target_read_u32(target, device_id_register, device_id);
if (retval != ERROR_OK)
return retval;
static int stm32x_get_flash_size(struct flash_bank *bank, uint16_t *flash_size_in_kb)
{
struct target *target = bank->target;
- uint32_t cpuid, flash_size_reg;
+ uint32_t flash_size_reg;
- int retval = target_read_u32(target, 0xE000ED00, &cpuid);
- if (retval != ERROR_OK)
- return retval;
+ if (!target_was_examined(target)) {
+ LOG_ERROR("Target not examined yet");
+ return ERROR_TARGET_NOT_EXAMINED;
+ }
- if (((cpuid >> 4) & 0xFFF) == 0xC20) {
- /* 0xC20 is M0 devices */
+ switch (cortex_m_get_partno_safe(target)) {
+ case CORTEX_M0_PARTNO: /* STM32F0x devices */
flash_size_reg = 0x1FFFF7CC;
- } else if (((cpuid >> 4) & 0xFFF) == 0xC23) {
- /* 0xC23 is M3 devices */
+ break;
+ case CORTEX_M3_PARTNO: /* STM32F1x devices */
flash_size_reg = 0x1FFFF7E0;
- } else if (((cpuid >> 4) & 0xFFF) == 0xC24) {
- /* 0xC24 is M4 devices */
+ break;
+ case CORTEX_M4_PARTNO: /* STM32F3x devices */
flash_size_reg = 0x1FFFF7CC;
- } else {
+ break;
+ case CORTEX_M23_PARTNO: /* GD32E23x devices */
+ flash_size_reg = 0x1FFFF7E0;
+ break;
+ default:
LOG_ERROR("Cannot identify target as a stm32x");
return ERROR_FAIL;
}
- retval = target_read_u16(target, flash_size_reg, flash_size_in_kb);
+ int retval = target_read_u16(target, flash_size_reg, flash_size_in_kb);
if (retval != ERROR_OK)
return retval;
struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
uint16_t flash_size_in_kb;
uint16_t max_flash_size_in_kb;
- uint32_t device_id;
+ uint32_t dbgmcu_idcode;
int page_size;
uint32_t base_address = 0x08000000;
- stm32x_info->probed = 0;
+ stm32x_info->probed = false;
stm32x_info->register_base = FLASH_REG_BASE_B0;
stm32x_info->user_data_offset = 10;
stm32x_info->option_offset = 0;
stm32x_info->default_rdp = 0xA5;
/* read stm32 device id register */
- int retval = stm32x_get_device_id(bank, &device_id);
+ int retval = stm32x_get_device_id(bank, &dbgmcu_idcode);
if (retval != ERROR_OK)
return retval;
- LOG_INFO("device id = 0x%08" PRIx32 "", device_id);
+ LOG_INFO("device id = 0x%08" PRIx32 "", dbgmcu_idcode);
+
+ uint16_t device_id = dbgmcu_idcode & 0xfff;
+ uint16_t rev_id = dbgmcu_idcode >> 16;
/* set page size, protection granularity and max flash size depending on family */
- switch (device_id & 0xfff) {
- case 0x410: /* medium density */
+ switch (device_id) {
+ case 0x440: /* stm32f05x */
page_size = 1024;
stm32x_info->ppage_size = 4;
+ max_flash_size_in_kb = 64;
+ stm32x_info->user_data_offset = 16;
+ stm32x_info->option_offset = 6;
+ stm32x_info->default_rdp = 0xAA;
+ stm32x_info->can_load_options = true;
+ break;
+ case 0x444: /* stm32f03x */
+ case 0x445: /* stm32f04x */
+ page_size = 1024;
+ stm32x_info->ppage_size = 4;
+ max_flash_size_in_kb = 32;
+ stm32x_info->user_data_offset = 16;
+ stm32x_info->option_offset = 6;
+ stm32x_info->default_rdp = 0xAA;
+ stm32x_info->can_load_options = true;
+ break;
+ case 0x448: /* stm32f07x */
+ page_size = 2048;
+ stm32x_info->ppage_size = 4;
max_flash_size_in_kb = 128;
+ stm32x_info->user_data_offset = 16;
+ stm32x_info->option_offset = 6;
+ stm32x_info->default_rdp = 0xAA;
+ stm32x_info->can_load_options = true;
+ break;
+ case 0x442: /* stm32f09x */
+ page_size = 2048;
+ stm32x_info->ppage_size = 4;
+ max_flash_size_in_kb = 256;
+ stm32x_info->user_data_offset = 16;
+ stm32x_info->option_offset = 6;
+ stm32x_info->default_rdp = 0xAA;
+ stm32x_info->can_load_options = true;
break;
- case 0x412: /* low density */
+ case 0x410: /* stm32f1x medium-density */
+ page_size = 1024;
+ stm32x_info->ppage_size = 4;
+ max_flash_size_in_kb = 128;
+ /* GigaDevice GD32F1x0 & GD32F3x0 & GD32E23x series devices
+ share DEV_ID with STM32F101/2/3 medium-density line,
+ however they use a REV_ID different from any STM32 device.
+ The main difference is another offset of user option bits
+ (like WDG_SW, nRST_STOP, nRST_STDBY) in option byte register
+ (FLASH_OBR/FMC_OBSTAT 0x4002201C).
+ This caused problems e.g. during flash block programming
+ because of unexpected active hardware watchog. */
+ switch (rev_id) {
+ case 0x1303: /* gd32f1x0 */
+ stm32x_info->user_data_offset = 16;
+ stm32x_info->option_offset = 6;
+ max_flash_size_in_kb = 64;
+ break;
+ case 0x1704: /* gd32f3x0 */
+ stm32x_info->user_data_offset = 16;
+ stm32x_info->option_offset = 6;
+ break;
+ case 0x1909: /* gd32e23x */
+ stm32x_info->user_data_offset = 16;
+ stm32x_info->option_offset = 6;
+ max_flash_size_in_kb = 64;
+ break;
+ }
+ break;
+ case 0x412: /* stm32f1x low-density */
page_size = 1024;
stm32x_info->ppage_size = 4;
max_flash_size_in_kb = 32;
break;
- case 0x414: /* high density */
+ case 0x414: /* stm32f1x high-density */
page_size = 2048;
stm32x_info->ppage_size = 2;
max_flash_size_in_kb = 512;
break;
- case 0x418: /* connectivity line density */
+ case 0x418: /* stm32f1x connectivity */
page_size = 2048;
stm32x_info->ppage_size = 2;
max_flash_size_in_kb = 256;
break;
- case 0x420: /* value line density */
+ case 0x430: /* stm32f1 XL-density (dual flash banks) */
+ page_size = 2048;
+ stm32x_info->ppage_size = 2;
+ max_flash_size_in_kb = 1024;
+ stm32x_info->has_dual_banks = true;
+ break;
+ case 0x420: /* stm32f100xx low- and medium-density value line */
page_size = 1024;
stm32x_info->ppage_size = 4;
max_flash_size_in_kb = 128;
break;
+ case 0x428: /* stm32f100xx high-density value line */
+ page_size = 2048;
+ stm32x_info->ppage_size = 4;
+ max_flash_size_in_kb = 512;
+ break;
case 0x422: /* stm32f302/3xb/c */
page_size = 2048;
stm32x_info->ppage_size = 2;
stm32x_info->default_rdp = 0xAA;
stm32x_info->can_load_options = true;
break;
- case 0x428: /* value line High density */
- page_size = 2048;
- stm32x_info->ppage_size = 4;
- max_flash_size_in_kb = 128;
- break;
- case 0x430: /* xl line density (dual flash banks) */
- page_size = 2048;
- stm32x_info->ppage_size = 2;
- max_flash_size_in_kb = 1024;
- stm32x_info->has_dual_banks = true;
- break;
case 0x432: /* stm32f37x */
page_size = 2048;
stm32x_info->ppage_size = 2;
stm32x_info->default_rdp = 0xAA;
stm32x_info->can_load_options = true;
break;
- case 0x440: /* stm32f05x */
- case 0x444: /* stm32f03x */
- case 0x445: /* stm32f04x */
- page_size = 1024;
- stm32x_info->ppage_size = 4;
- max_flash_size_in_kb = 64;
- stm32x_info->user_data_offset = 16;
- stm32x_info->option_offset = 6;
- stm32x_info->default_rdp = 0xAA;
- stm32x_info->can_load_options = true;
- break;
- case 0x448: /* stm32f07x */
- case 0x442: /* stm32f09x */
- page_size = 2048;
- stm32x_info->ppage_size = 4;
- max_flash_size_in_kb = 256;
- stm32x_info->user_data_offset = 16;
- stm32x_info->option_offset = 6;
- stm32x_info->default_rdp = 0xAA;
- stm32x_info->can_load_options = true;
- break;
default:
LOG_WARNING("Cannot identify target as a STM32 family.");
return ERROR_FAIL;
/* check that calculation result makes sense */
assert(num_pages > 0);
- if (bank->sectors) {
- free(bank->sectors);
- bank->sectors = NULL;
- }
+ free(bank->sectors);
+ bank->sectors = NULL;
- if (bank->prot_blocks) {
- free(bank->prot_blocks);
- bank->prot_blocks = NULL;
- }
+ free(bank->prot_blocks);
+ bank->prot_blocks = NULL;
bank->base = base_address;
bank->size = (num_pages * page_size);
if (num_prot_blocks == 32)
bank->prot_blocks[31].size = (num_pages - (31 * stm32x_info->ppage_size)) * page_size;
- stm32x_info->probed = 1;
+ stm32x_info->probed = true;
return ERROR_OK;
}
return rev_str;
}
-static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
+static int get_stm32x_info(struct flash_bank *bank, struct command_invocation *cmd)
{
uint32_t dbgmcu_idcode;
- /* read stm32 device id register */
+ /* read stm32 device id register */
int retval = stm32x_get_device_id(bank, &dbgmcu_idcode);
if (retval != ERROR_OK)
return retval;
rev_str = "A";
break;
+ case 0x1303: /* gd32f1x0 */
+ device_str = "GD32F1x0";
+ break;
+
+ case 0x1704: /* gd32f3x0 */
+ device_str = "GD32F3x0";
+ break;
+
+ case 0x1909: /* gd32e23x */
+ device_str = "GD32E23x";
+ break;
+
case 0x2000:
rev_str = "B";
break;
break;
default:
- snprintf(buf, buf_size, "Cannot identify target as a STM32F0/1/3\n");
+ command_print_sameline(cmd, "Cannot identify target as a STM32F0/1/3\n");
return ERROR_FAIL;
}
- if (rev_str != NULL)
- snprintf(buf, buf_size, "%s - Rev: %s", device_str, rev_str);
+ if (rev_str)
+ command_print_sameline(cmd, "%s - Rev: %s", device_str, rev_str);
else
- snprintf(buf, buf_size, "%s - Rev: unknown (0x%04x)", device_str, rev_id);
+ command_print_sameline(cmd, "%s - Rev: unknown (0x%04x)", device_str, rev_id);
return ERROR_OK;
}
struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
+ if (retval != ERROR_OK)
return retval;
stm32x_info = bank->driver_priv;
}
retval = stm32x_check_operation_supported(bank);
- if (ERROR_OK != retval)
+ if (retval != ERROR_OK)
return retval;
if (stm32x_erase_options(bank) != ERROR_OK) {
- command_print(CMD_CTX, "stm32x failed to erase options");
+ command_print(CMD, "stm32x failed to erase options");
return ERROR_OK;
}
stm32x_info->option_bytes.rdp = 0;
if (stm32x_write_options(bank) != ERROR_OK) {
- command_print(CMD_CTX, "stm32x failed to lock device");
+ command_print(CMD, "stm32x failed to lock device");
return ERROR_OK;
}
- command_print(CMD_CTX, "stm32x locked");
+ command_print(CMD, "stm32x locked");
return ERROR_OK;
}
struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
+ if (retval != ERROR_OK)
return retval;
target = bank->target;
}
retval = stm32x_check_operation_supported(bank);
- if (ERROR_OK != retval)
+ if (retval != ERROR_OK)
return retval;
if (stm32x_erase_options(bank) != ERROR_OK) {
- command_print(CMD_CTX, "stm32x failed to unlock device");
+ command_print(CMD, "stm32x failed to erase options");
return ERROR_OK;
}
if (stm32x_write_options(bank) != ERROR_OK) {
- command_print(CMD_CTX, "stm32x failed to lock device");
+ command_print(CMD, "stm32x failed to unlock device");
return ERROR_OK;
}
- command_print(CMD_CTX, "stm32x unlocked.\n"
+ command_print(CMD, "stm32x unlocked.\n"
"INFO: a reset or power cycle is required "
"for the new settings to take effect.");
struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
+ if (retval != ERROR_OK)
return retval;
stm32x_info = bank->driver_priv;
}
retval = stm32x_check_operation_supported(bank);
- if (ERROR_OK != retval)
+ if (retval != ERROR_OK)
return retval;
retval = target_read_u32(target, STM32_FLASH_OBR_B0, &optionbyte);
return retval;
if (optionbyte & (1 << OPT_ERROR))
- command_print(CMD_CTX, "option byte complement error");
+ command_print(CMD, "option byte complement error");
- command_print(CMD_CTX, "option byte register = 0x%" PRIx32 "", optionbyte);
- command_print(CMD_CTX, "write protection register = 0x%" PRIx32 "", protection);
+ command_print(CMD, "option byte register = 0x%" PRIx32 "", optionbyte);
+ command_print(CMD, "write protection register = 0x%" PRIx32 "", protection);
- command_print(CMD_CTX, "read protection: %s",
+ command_print(CMD, "read protection: %s",
(optionbyte & (1 << OPT_READOUT)) ? "on" : "off");
/* user option bytes are offset depending on variant */
optionbyte >>= stm32x_info->option_offset;
- command_print(CMD_CTX, "watchdog: %sware",
+ command_print(CMD, "watchdog: %sware",
(optionbyte & (1 << OPT_RDWDGSW)) ? "soft" : "hard");
- command_print(CMD_CTX, "stop mode: %sreset generated upon entry",
+ command_print(CMD, "stop mode: %sreset generated upon entry",
(optionbyte & (1 << OPT_RDRSTSTOP)) ? "no " : "");
- command_print(CMD_CTX, "standby mode: %sreset generated upon entry",
+ command_print(CMD, "standby mode: %sreset generated upon entry",
(optionbyte & (1 << OPT_RDRSTSTDBY)) ? "no " : "");
if (stm32x_info->has_dual_banks)
- command_print(CMD_CTX, "boot: bank %d", (optionbyte & (1 << OPT_BFB2)) ? 0 : 1);
+ command_print(CMD, "boot: bank %d", (optionbyte & (1 << OPT_BFB2)) ? 0 : 1);
- command_print(CMD_CTX, "user data = 0x%02" PRIx16 "", user_data);
+ command_print(CMD, "user data = 0x%02" PRIx16 "", user_data);
return ERROR_OK;
}
{
struct target *target = NULL;
struct stm32x_flash_bank *stm32x_info = NULL;
- uint16_t optionbyte;
+ uint8_t optionbyte;
+ uint16_t useropt;
if (CMD_ARGC < 2)
return ERROR_COMMAND_SYNTAX_ERROR;
struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
+ if (retval != ERROR_OK)
return retval;
stm32x_info = bank->driver_priv;
}
retval = stm32x_check_operation_supported(bank);
- if (ERROR_OK != retval)
+ if (retval != ERROR_OK)
return retval;
retval = stm32x_read_options(bank);
- if (ERROR_OK != retval)
+ if (retval != ERROR_OK)
return retval;
/* start with current options */
optionbyte = stm32x_info->option_bytes.user;
+ useropt = stm32x_info->option_bytes.data;
/* skip over flash bank */
CMD_ARGC--;
optionbyte |= (1 << 2);
else if (strcmp("RSTSTNDBY", CMD_ARGV[0]) == 0)
optionbyte &= ~(1 << 2);
- else if (stm32x_info->has_dual_banks) {
+ else if (strcmp("USEROPT", CMD_ARGV[0]) == 0) {
+ if (CMD_ARGC < 2)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], useropt);
+ CMD_ARGC--;
+ CMD_ARGV++;
+ } else if (stm32x_info->has_dual_banks) {
if (strcmp("BOOT0", CMD_ARGV[0]) == 0)
optionbyte |= (1 << 3);
else if (strcmp("BOOT1", CMD_ARGV[0]) == 0)
}
if (stm32x_erase_options(bank) != ERROR_OK) {
- command_print(CMD_CTX, "stm32x failed to erase options");
+ command_print(CMD, "stm32x failed to erase options");
return ERROR_OK;
}
stm32x_info->option_bytes.user = optionbyte;
+ stm32x_info->option_bytes.data = useropt;
if (stm32x_write_options(bank) != ERROR_OK) {
- command_print(CMD_CTX, "stm32x failed to write options");
+ command_print(CMD, "stm32x failed to write options");
return ERROR_OK;
}
- command_print(CMD_CTX, "stm32x write options complete.\n"
+ command_print(CMD, "stm32x write options complete.\n"
"INFO: %spower cycle is required "
"for the new settings to take effect.",
stm32x_info->can_load_options
struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
+ if (retval != ERROR_OK)
return retval;
struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
}
retval = stm32x_check_operation_supported(bank);
- if (ERROR_OK != retval)
+ if (retval != ERROR_OK)
return retval;
/* unlock option flash registers */
COMMAND_HANDLER(stm32x_handle_mass_erase_command)
{
- int i;
-
if (CMD_ARGC < 1)
return ERROR_COMMAND_SYNTAX_ERROR;
struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
+ if (retval != ERROR_OK)
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");
+ if (retval == ERROR_OK)
+ command_print(CMD, "stm32x mass erase complete");
+ else
+ command_print(CMD, "stm32x mass erase failed");
return retval;
}
-static const struct command_registration stm32x_exec_command_handlers[] = {
+static const struct command_registration stm32f1x_exec_command_handlers[] = {
{
.name = "lock",
.handler = stm32x_handle_lock_command,
.mode = COMMAND_EXEC,
.usage = "bank_id ('SWWDG'|'HWWDG') "
"('RSTSTNDBY'|'NORSTSTNDBY') "
- "('RSTSTOP'|'NORSTSTOP')",
+ "('RSTSTOP'|'NORSTSTOP') ('USEROPT' user_data)",
.help = "Replace bits in device option bytes.",
},
{
COMMAND_REGISTRATION_DONE
};
-static const struct command_registration stm32x_command_handlers[] = {
+static const struct command_registration stm32f1x_command_handlers[] = {
{
.name = "stm32f1x",
.mode = COMMAND_ANY,
.help = "stm32f1x flash command group",
.usage = "",
- .chain = stm32x_exec_command_handlers,
+ .chain = stm32f1x_exec_command_handlers,
},
COMMAND_REGISTRATION_DONE
};
-struct flash_driver stm32f1x_flash = {
+const struct flash_driver stm32f1x_flash = {
.name = "stm32f1x",
- .commands = stm32x_command_handlers,
+ .commands = stm32f1x_command_handlers,
.flash_bank_command = stm32x_flash_bank_command,
.erase = stm32x_erase,
.protect = stm32x_protect,