+// SPDX-License-Identifier: GPL-2.0-or-later
+
/***************************************************************************
* Copyright (C) 2005 by Dominic Rath *
* Dominic.Rath@gmx.de *
* *
* Copyright (C) 2011 Øyvind Harboe *
* oyvind.harboe@zylin.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "imp.h"
#include <helper/binarybuffer.h>
#include <target/algorithm.h>
-#include <target/armv7m.h>
+#include <target/cortex_m.h>
/* Regarding performance:
*
struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
if (!stm32x_info->otp_unlocked) {
- LOG_INFO("OTP memory bank #%u is is enabled for write commands.",
+ LOG_INFO("OTP memory bank #%u is enabled for write commands.",
bank->bank_number);
stm32x_info->otp_unlocked = true;
} else {
- LOG_WARNING("OTP memory bank #%u is is already enabled for write commands.",
+ LOG_WARNING("OTP memory bank #%u is already enabled for write commands.",
bank->bank_number);
}
return ERROR_OK;
for (unsigned int i = first; i <= last; i++) {
unsigned int snb;
- if (stm32x_info->has_large_mem && i >= 12)
- snb = (i - 12) | 0x10;
+ if (stm32x_info->has_large_mem && i >= (bank->num_sectors / 2))
+ snb = (i - (bank->num_sectors / 2)) | 0x10;
else
snb = i;
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);
}
if (stm32x_is_otp(bank)) {
- if (!set)
+ if (!set) {
+ LOG_ERROR("OTP protection can only be enabled");
return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
return stm32x_otp_protect(bank, first, last);
}
Wait for the BSY bit to be cleared
*/
while (words_remaining > 0) {
- uint16_t value;
- memcpy(&value, buffer + bytes_written, sizeof(uint16_t));
-
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR),
FLASH_PG | FLASH_PSIZE_16);
if (retval != ERROR_OK)
return retval;
- retval = target_write_u16(target, address, value);
+ retval = target_write_memory(target, address, 2, 1, buffer + bytes_written);
if (retval != ERROR_OK)
return retval;
* Only effects Rev A silicon */
struct target *target = bank->target;
- uint32_t cpuid;
/* read stm32 device id register */
int retval = target_read_u32(target, 0xE0042000, device_id);
if (retval != ERROR_OK)
return retval;
- if ((*device_id & 0xfff) == 0x411) {
- /* read CPUID reg to check core type */
- retval = target_read_u32(target, 0xE000ED00, &cpuid);
- if (retval != ERROR_OK)
- return retval;
-
- /* check for cortex_m4 */
- if (((cpuid >> 4) & 0xFFF) == 0xC24) {
- *device_id &= ~((0xFFFF << 16) | 0xfff);
- *device_id |= (0x1000 << 16) | 0x413;
- LOG_INFO("stm32f4x errata detected - fixing incorrect MCU_IDCODE");
- }
+ if ((*device_id & 0xfff) == 0x411
+ && cortex_m_get_impl_part(target) == CORTEX_M4_PARTNO) {
+ *device_id &= ~((0xFFFF << 16) | 0xfff);
+ *device_id |= (0x1000 << 16) | 0x413;
+ LOG_INFO("stm32f4x errata detected - fixing incorrect MCU_IDCODE");
}
return retval;
}
bank->num_prot_blocks = 0;
bank->prot_blocks = NULL;
+ if (!target_was_examined(target)) {
+ LOG_ERROR("Target not examined yet");
+ return ERROR_TARGET_NOT_EXAMINED;
+ }
+
/* if explicitly called out as OTP bank, short circuit probe */
if (stm32x_is_otp(bank)) {
if (stm32x_otp_is_f7(bank)) {
flash_size_in_kb = stm32x_info->user_bank_size / 1024;
}
- LOG_INFO("flash size = %" PRIu16 " kbytes", flash_size_in_kb);
+ LOG_INFO("flash size = %" PRIu16 " KiB", flash_size_in_kb);
/* did we assign flash size? */
assert(flash_size_in_kb != 0xffff);
return stm32x_probe(bank);
}
-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;
break;
default:
- snprintf(buf, buf_size, "Cannot identify target as a STM32F2/4/7\n");
+ command_print_sameline(cmd, "Cannot identify target as a STM32F2/4/7\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%04" PRIx16 ")", device_str, rev_id);
+ command_print_sameline(cmd, "%s - Rev: unknown (0x%04" PRIx16 ")", 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;
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;
COMMAND_HANDLER(stm32x_handle_mass_erase_command)
{
- if (CMD_ARGC < 1) {
- command_print(CMD, "stm32x mass_erase <bank>");
+ 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 (unsigned int i = 0; i < bank->num_sectors; i++)
- bank->sectors[i].is_erased = 1;
-
command_print(CMD, "stm32x mass erase complete");
} else {
command_print(CMD, "stm32x mass erase failed");
struct flash_bank *bank;
struct stm32x_flash_bank *stm32x_info = NULL;
- if (CMD_ARGC != 1) {
- command_print(CMD, "stm32f2x options_read <bank>");
+ if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &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;
stm32x_info = bank->driver_priv;
struct stm32x_flash_bank *stm32x_info = NULL;
uint16_t user_options, boot_addr0, boot_addr1, options_mask;
- if (CMD_ARGC < 1) {
- command_print(CMD, "stm32f2x options_write <bank> ...");
+ if (CMD_ARGC < 1)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &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;
stm32x_info = bank->driver_priv;
if (stm32x_info->has_boot_addr) {
- if (CMD_ARGC != 4) {
- command_print(CMD, "stm32f2x options_write <bank> <user_options>"
- " <boot_addr0> <boot_addr1>");
+ if (CMD_ARGC != 4)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
+
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[2], boot_addr0);
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[3], boot_addr1);
stm32x_info->option_bytes.boot_addr = boot_addr0 | (((uint32_t) boot_addr1) << 16);
- } else {
- if (CMD_ARGC != 2) {
- command_print(CMD, "stm32f2x options_write <bank> <user_options>");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
+ } else if (CMD_ARGC != 2) {
+ return ERROR_COMMAND_SYNTAX_ERROR;
}
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], user_options);
struct stm32x_flash_bank *stm32x_info = NULL;
uint32_t optcr2_pcrop;
- if (CMD_ARGC != 2) {
- command_print(CMD, "stm32f2x optcr2_write <bank> <optcr2_value>");
+ if (CMD_ARGC != 2)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
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;
" finally unlock it. Clears PCROP and mass erases flash.");
retval = stm32x_read_options(bank);
- if (ERROR_OK != retval)
+ if (retval != ERROR_OK)
return retval;
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], optcr2_pcrop);
COMMAND_HANDLER(stm32x_handle_otp_command)
{
- if (CMD_ARGC < 2) {
- command_print(CMD, "stm32x otp <bank> (enable|disable|show)");
+ 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;
if (stm32x_is_otp(bank)) {
if (strcmp(CMD_ARGV[1], "enable") == 0) {
return retval;
}
-static const struct command_registration stm32x_exec_command_handlers[] = {
+static const struct command_registration stm32f2x_exec_command_handlers[] = {
{
.name = "lock",
.handler = stm32x_handle_lock_command,
.name = "otp",
.handler = stm32x_handle_otp_command,
.mode = COMMAND_EXEC,
- .usage = "bank_id",
+ .usage = "bank_id (enable|disable|show)",
.help = "OTP (One Time Programmable) memory write enable/disable.",
},
COMMAND_REGISTRATION_DONE
};
-static const struct command_registration stm32x_command_handlers[] = {
+static const struct command_registration stm32f2x_command_handlers[] = {
{
.name = "stm32f2x",
.mode = COMMAND_ANY,
.help = "stm32f2x flash command group",
.usage = "",
- .chain = stm32x_exec_command_handlers,
+ .chain = stm32f2x_exec_command_handlers,
},
COMMAND_REGISTRATION_DONE
};
const struct flash_driver stm32f2x_flash = {
.name = "stm32f2x",
- .commands = stm32x_command_handlers,
+ .commands = stm32f2x_command_handlers,
.flash_bank_command = stm32x_flash_bank_command,
.erase = stm32x_erase,
.protect = stm32x_protect,