aboutsummaryrefslogtreecommitdiff
path: root/src/flash
diff options
context:
space:
mode:
Diffstat (limited to 'src/flash')
-rw-r--r--src/flash/nor/ambiqmicro.c2
-rw-r--r--src/flash/nor/at91sam7.c4
-rw-r--r--src/flash/nor/atsame5.c30
-rw-r--r--src/flash/nor/core.h10
-rw-r--r--src/flash/nor/driver.h8
-rw-r--r--src/flash/nor/em357.c2
-rw-r--r--src/flash/nor/kinetis.c5
-rw-r--r--src/flash/nor/max32xxx.c2
-rw-r--r--src/flash/nor/msp432.c2
-rw-r--r--src/flash/nor/nrf5.c687
-rw-r--r--src/flash/nor/pic32mx.c2
-rw-r--r--src/flash/nor/psoc6.c7
-rw-r--r--src/flash/nor/sfdp.c3
-rw-r--r--src/flash/nor/sfdp.h4
-rw-r--r--src/flash/nor/stellaris.c2
-rw-r--r--src/flash/nor/stm32f2x.c2
-rw-r--r--src/flash/nor/stm32l4x.c58
-rw-r--r--src/flash/nor/stm32l4x.h2
-rw-r--r--src/flash/nor/stmqspi.c4
-rw-r--r--src/flash/nor/tcl.c1
-rw-r--r--src/flash/startup.tcl6
21 files changed, 594 insertions, 249 deletions
diff --git a/src/flash/nor/ambiqmicro.c b/src/flash/nor/ambiqmicro.c
index 2b458bc..bb89377 100644
--- a/src/flash/nor/ambiqmicro.c
+++ b/src/flash/nor/ambiqmicro.c
@@ -124,7 +124,7 @@ FLASH_BANK_COMMAND_HANDLER(ambiqmicro_flash_bank_command)
if (CMD_ARGC < 6)
return ERROR_COMMAND_SYNTAX_ERROR;
- ambiqmicro_info = calloc(sizeof(struct ambiqmicro_flash_bank), 1);
+ ambiqmicro_info = calloc(1, sizeof(struct ambiqmicro_flash_bank));
bank->driver_priv = ambiqmicro_info;
diff --git a/src/flash/nor/at91sam7.c b/src/flash/nor/at91sam7.c
index 6879a1b..86c8076 100644
--- a/src/flash/nor/at91sam7.c
+++ b/src/flash/nor/at91sam7.c
@@ -560,7 +560,7 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
if (bnk > 0) {
if (!t_bank->next) {
/* create a new flash bank element */
- struct flash_bank *fb = calloc(sizeof(struct flash_bank), 1);
+ struct flash_bank *fb = calloc(1, sizeof(struct flash_bank));
if (!fb) {
LOG_ERROR("No memory for flash bank");
return ERROR_FAIL;
@@ -748,7 +748,7 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command)
if (bnk > 0) {
if (!t_bank->next) {
/* create a new bank element */
- struct flash_bank *fb = calloc(sizeof(struct flash_bank), 1);
+ struct flash_bank *fb = calloc(1, sizeof(struct flash_bank));
if (!fb) {
LOG_ERROR("No memory for flash bank");
return ERROR_FAIL;
diff --git a/src/flash/nor/atsame5.c b/src/flash/nor/atsame5.c
index c590081..a6ac906 100644
--- a/src/flash/nor/atsame5.c
+++ b/src/flash/nor/atsame5.c
@@ -85,6 +85,9 @@
#define SAME_SERIES_51 0x01
#define SAME_SERIES_53 0x03
#define SAME_SERIES_54 0x04
+#define PIC32CXSG_SERIES_41 0x07
+#define PIC32CXSG_SERIES_60 0x00
+#define PIC32CXSG_SERIES_61 0x02
/* Device ID macros */
#define SAMD_GET_PROCESSOR(id) (id >> 28)
@@ -148,6 +151,27 @@ static const struct samd_part same54_parts[] = {
{ 0x03, "SAME54N19A", 512, 192 },
};
+/* See PIC32CX SG41/SG60/SG61 Family Silicon Errata and Datasheet Clarifications
+ * DS80000985G */
+/* Known PIC32CX-SG41 parts. */
+static const struct samd_part pic32cxsg41_parts[] = {
+ { 0x00, "PIC32CX1025SG41128", 1024, 256 },
+ { 0x01, "PIC32CX1025SG41100", 1024, 256 },
+ { 0x02, "PIC32CX1025SG41064", 1024, 256 },
+};
+
+/* Known PIC32CX-SG60 parts. */
+static const struct samd_part pic32cxsg60_parts[] = {
+ { 0x00, "PIC32CX1025SG60128", 1024, 256 },
+ { 0x01, "PIC32CX1025SG60100", 1024, 256 },
+};
+
+/* Known PIC32CX-SG61 parts. */
+static const struct samd_part pic32cxsg61_parts[] = {
+ { 0x00, "PIC32CX1025SG61128", 1024, 256 },
+ { 0x01, "PIC32CX1025SG61100", 1024, 256 },
+};
+
/* Each family of parts contains a parts table in the DEVSEL field of DID. The
* processor ID, family ID, and series ID are used to determine which exact
* family this is and then we can use the corresponding table. */
@@ -169,6 +193,12 @@ static const struct samd_family samd_families[] = {
same53_parts, ARRAY_SIZE(same53_parts) },
{ SAMD_PROCESSOR_M4, SAMD_FAMILY_E, SAME_SERIES_54,
same54_parts, ARRAY_SIZE(same54_parts) },
+ { SAMD_PROCESSOR_M4, SAMD_FAMILY_E, PIC32CXSG_SERIES_41,
+ pic32cxsg41_parts, ARRAY_SIZE(pic32cxsg41_parts) },
+ { SAMD_PROCESSOR_M4, SAMD_FAMILY_E, PIC32CXSG_SERIES_60,
+ pic32cxsg60_parts, ARRAY_SIZE(pic32cxsg60_parts) },
+ { SAMD_PROCESSOR_M4, SAMD_FAMILY_E, PIC32CXSG_SERIES_61,
+ pic32cxsg61_parts, ARRAY_SIZE(pic32cxsg61_parts) },
};
struct samd_info {
diff --git a/src/flash/nor/core.h b/src/flash/nor/core.h
index 80911f7..ff175a1 100644
--- a/src/flash/nor/core.h
+++ b/src/flash/nor/core.h
@@ -32,18 +32,18 @@ struct flash_sector {
uint32_t size;
/**
* Indication of erasure status: 0 = not erased, 1 = erased,
- * other = unknown. Set by @c flash_driver_s::erase_check only.
+ * other = unknown. Set by @c flash_driver::erase_check only.
*
* This information must be considered stale immediately.
- * Don't set it in flash_driver_s::erase or a device mass_erase
- * Don't clear it in flash_driver_s::write
+ * Don't set it in flash_driver::erase or a device mass_erase
+ * Don't clear it in flash_driver::write
* The flag is not used in a protection block
*/
int is_erased;
/**
* Indication of protection status: 0 = unprotected/unlocked,
* 1 = protected/locked, other = unknown. Set by
- * @c flash_driver_s::protect_check.
+ * @c flash_driver::protect_check.
*
* This information must be considered stale immediately.
* A million things could make it stale: power cycle,
@@ -67,7 +67,7 @@ struct flash_sector {
* a major interface.
*
* This structure will be passed as a parameter to the callbacks in the
- * flash_driver_s structure, some of which may modify the contents of
+ * flash_driver structure, some of which may modify the contents of
* this structure of the area of flash that it defines. Driver writers
* may use the @c driver_priv member to store additional data on a
* per-bank basis, if required.
diff --git a/src/flash/nor/driver.h b/src/flash/nor/driver.h
index 7d6f8c5..211661e 100644
--- a/src/flash/nor/driver.h
+++ b/src/flash/nor/driver.h
@@ -29,7 +29,7 @@ struct flash_bank;
* flash bank DRIVERNAME ...parameters...
* @endcode
*
- * OpenOCD will search for the driver with a @c flash_driver_s::name
+ * OpenOCD will search for the driver with a @c flash_driver::name
* that matches @c DRIVERNAME.
*
* The flash subsystem calls some of the other drivers routines a using
@@ -170,7 +170,7 @@ struct flash_driver {
/**
* Check the erasure status of a flash bank.
* When called, the driver routine must perform the required
- * checks and then set the @c flash_sector_s::is_erased field
+ * checks and then set the @c flash_sector::is_erased field
* for each of the flash banks's sectors.
*
* @param bank The bank to check
@@ -182,7 +182,7 @@ struct flash_driver {
* Determine if the specific bank is "protected" or not.
* When called, the driver routine must must perform the
* required protection check(s) and then set the @c
- * flash_sector_s::is_protected field for each of the flash
+ * flash_sector::is_protected field for each of the flash
* bank's sectors.
*
* If protection is not implemented, set method to NULL
@@ -204,7 +204,7 @@ struct flash_driver {
int (*info)(struct flash_bank *bank, struct command_invocation *cmd);
/**
- * A more gentle flavor of flash_driver_s::probe, performing
+ * A more gentle flavor of flash_driver::probe, performing
* setup with less noise. Generally, driver routines should test
* to see if the bank has already been probed; if it has, the
* driver probably should not perform its probe a second time.
diff --git a/src/flash/nor/em357.c b/src/flash/nor/em357.c
index 043494c..207346f 100644
--- a/src/flash/nor/em357.c
+++ b/src/flash/nor/em357.c
@@ -709,7 +709,7 @@ static int em357_probe(struct flash_bank *bank)
em357_info->ppage_size = 4;
- LOG_INFO("flash size = %d KiB", num_pages*page_size/1024);
+ LOG_INFO("flash size = %d KiB", num_pages * page_size / 1024);
free(bank->sectors);
diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c
index e8074e3..2d0a753 100644
--- a/src/flash/nor/kinetis.c
+++ b/src/flash/nor/kinetis.c
@@ -930,7 +930,7 @@ FLASH_BANK_COMMAND_HANDLER(kinetis_flash_bank_command)
k_chip = kinetis_get_chip(target);
if (!k_chip) {
- k_chip = calloc(sizeof(struct kinetis_chip), 1);
+ k_chip = calloc(1, sizeof(struct kinetis_chip));
if (!k_chip) {
LOG_ERROR("No memory");
return ERROR_FAIL;
@@ -1031,13 +1031,14 @@ static int kinetis_create_missing_banks(struct kinetis_chip *k_chip)
bank_idx - k_chip->num_pflash_blocks);
}
- bank = calloc(sizeof(struct flash_bank), 1);
+ bank = calloc(1, sizeof(struct flash_bank));
if (!bank)
return ERROR_FAIL;
bank->target = k_chip->target;
bank->driver = &kinetis_flash;
bank->default_padded_value = bank->erased_value = 0xff;
+ bank->minimal_write_gap = FLASH_WRITE_GAP_SECTOR;
snprintf(name, sizeof(name), "%s.%s%s",
base_name, class, num);
diff --git a/src/flash/nor/max32xxx.c b/src/flash/nor/max32xxx.c
index 51d6ae2..59a14af 100644
--- a/src/flash/nor/max32xxx.c
+++ b/src/flash/nor/max32xxx.c
@@ -87,7 +87,7 @@ FLASH_BANK_COMMAND_HANDLER(max32xxx_flash_bank_command)
return ERROR_FLASH_BANK_INVALID;
}
- info = calloc(sizeof(struct max32xxx_flash_bank), 1);
+ info = calloc(1, sizeof(struct max32xxx_flash_bank));
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], info->flash_size);
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[6], info->flc_base);
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[7], info->sector_size);
diff --git a/src/flash/nor/msp432.c b/src/flash/nor/msp432.c
index 5e2935d..b5e2b0b 100644
--- a/src/flash/nor/msp432.c
+++ b/src/flash/nor/msp432.c
@@ -937,7 +937,7 @@ static int msp432_probe(struct flash_bank *bank)
if (is_main && MSP432P4 == msp432_bank->family_type) {
/* Create the info flash bank needed by MSP432P4 variants */
- struct flash_bank *info = calloc(sizeof(struct flash_bank), 1);
+ struct flash_bank *info = calloc(1, sizeof(struct flash_bank));
if (!info)
return ERROR_FAIL;
diff --git a/src/flash/nor/nrf5.c b/src/flash/nor/nrf5.c
index bf8c9da..5cb552a 100644
--- a/src/flash/nor/nrf5.c
+++ b/src/flash/nor/nrf5.c
@@ -19,8 +19,7 @@
#include <helper/time_support.h>
#include <helper/bits.h>
-/* Both those values are constant across the current spectrum ofr nRF5 devices */
-#define WATCHDOG_REFRESH_REGISTER 0x40010600
+/* The refresh code is constant across the current spectrum of nRF5 devices */
#define WATCHDOG_REFRESH_VALUE 0x6e524635
enum {
@@ -28,12 +27,9 @@ enum {
};
enum nrf5_ficr_registers {
- NRF5_FICR_BASE = 0x10000000, /* Factory Information Configuration Registers */
+ NRF51_52_FICR_BASE = 0x10000000, /* Factory Information Configuration Registers */
-#define NRF5_FICR_REG(offset) (NRF5_FICR_BASE + offset)
-
- NRF5_FICR_CODEPAGESIZE = NRF5_FICR_REG(0x010),
- NRF5_FICR_CODESIZE = NRF5_FICR_REG(0x014),
+#define NRF5_FICR_REG(offset) (NRF51_52_FICR_BASE + (offset))
NRF51_FICR_CLENR0 = NRF5_FICR_REG(0x028),
NRF51_FICR_PPFC = NRF5_FICR_REG(0x02C),
@@ -42,39 +38,23 @@ enum nrf5_ficr_registers {
NRF51_FICR_SIZERAMBLOCK1 = NRF5_FICR_REG(0x03C),
NRF51_FICR_SIZERAMBLOCK2 = NRF5_FICR_REG(0x040),
NRF51_FICR_SIZERAMBLOCK3 = NRF5_FICR_REG(0x044),
-
- /* CONFIGID is documented on nRF51 series only.
- * On nRF52 is present but not documented */
- NRF5_FICR_CONFIGID = NRF5_FICR_REG(0x05C),
-
- /* Following registers are available on nRF52 and on nRF51 since rev 3 */
- NRF5_FICR_INFO_PART = NRF5_FICR_REG(0x100),
- NRF5_FICR_INFO_VARIANT = NRF5_FICR_REG(0x104),
- NRF5_FICR_INFO_PACKAGE = NRF5_FICR_REG(0x108),
- NRF5_FICR_INFO_RAM = NRF5_FICR_REG(0x10C),
- NRF5_FICR_INFO_FLASH = NRF5_FICR_REG(0x110),
};
enum nrf5_uicr_registers {
- NRF5_UICR_BASE = 0x10001000, /* User Information
+ NRF51_52_UICR_BASE = 0x10001000, /* User Information
* Configuration Registers */
-#define NRF5_UICR_REG(offset) (NRF5_UICR_BASE + offset)
+#define NRF5_UICR_REG(offset) (NRF51_52_UICR_BASE + (offset))
NRF51_UICR_CLENR0 = NRF5_UICR_REG(0x000),
};
enum nrf5_nvmc_registers {
- NRF5_NVMC_BASE = 0x4001E000, /* Non-Volatile Memory
- * Controller Registers */
-
-#define NRF5_NVMC_REG(offset) (NRF5_NVMC_BASE + offset)
-
- NRF5_NVMC_READY = NRF5_NVMC_REG(0x400),
- NRF5_NVMC_CONFIG = NRF5_NVMC_REG(0x504),
- NRF5_NVMC_ERASEPAGE = NRF5_NVMC_REG(0x508),
- NRF5_NVMC_ERASEALL = NRF5_NVMC_REG(0x50C),
- NRF5_NVMC_ERASEUICR = NRF5_NVMC_REG(0x514),
+ NRF5_NVMC_READY = 0x400,
+ NRF5_NVMC_CONFIG = 0x504,
+ NRF5_NVMC_ERASEPAGE = 0x508,
+ NRF5_NVMC_ERASEALL = 0x50C,
+ NRF5_NVMC_ERASEUICR = 0x514,
NRF5_BPROT_BASE = 0x40000000,
};
@@ -99,6 +79,9 @@ enum nrf5_features {
NRF5_FEATURE_SERIES_52 = BIT(1),
NRF5_FEATURE_BPROT = BIT(2),
NRF5_FEATURE_ACL_PROT = BIT(3),
+ NRF5_FEATURE_SERIES_53 = BIT(4),
+ NRF5_FEATURE_SERIES_91 = BIT(5),
+ NRF5_FEATURE_ERASE_BY_FLASH_WR = BIT(6),
};
struct nrf5_device_spec {
@@ -110,23 +93,52 @@ struct nrf5_device_spec {
enum nrf5_features features;
};
+/* FICR registers offsets */
+struct nrf5_ficr_map {
+ uint32_t codepagesize;
+ uint32_t codesize;
+ uint32_t configid;
+ uint32_t info_part;
+ uint32_t info_variant;
+ uint32_t info_package;
+ uint32_t info_ram;
+ uint32_t info_flash;
+};
+
+/* Map of device */
+struct nrf5_map {
+ uint32_t flash_base;
+ uint32_t ficr_base;
+ uint32_t uicr_base;
+ uint32_t nvmc_base;
+
+ uint32_t watchdog_refresh_addr;
+};
+
struct nrf5_info {
unsigned int refcount;
+ bool chip_probed;
struct nrf5_bank {
struct nrf5_info *chip;
bool probed;
} bank[2];
+
struct target *target;
- /* chip identification stored in nrf5_probe() for use in nrf5_info() */
+ /* chip identification stored in nrf5_probe_chip()
+ * for use in nrf5_info() and nrf5_setup_bank() */
bool ficr_info_valid;
struct nrf52_ficr_info ficr_info;
const struct nrf5_device_spec *spec;
uint16_t hwid;
enum nrf5_features features;
- unsigned int flash_size_kb;
+ uint32_t flash_page_size;
+ uint32_t flash_num_sectors;
unsigned int ram_size_kb;
+
+ const struct nrf5_map *map;
+ const struct nrf5_ficr_map *ficr_offsets;
};
#define NRF51_DEVICE_DEF(id, pt, var, bcode, fsize) \
@@ -238,16 +250,127 @@ static const struct nrf5_device_package nrf52_packages_table[] = {
{ 0x2009, "CF" },
};
+static const struct nrf5_ficr_map nrf51_52_ficr_offsets = {
+ .codepagesize = 0x10,
+ .codesize = 0x14,
+
+ /* CONFIGID is documented on nRF51 series only.
+ * On nRF52 is present but not documented */
+ .configid = 0x5c,
+
+ /* Following registers are available on nRF52 and on nRF51 since rev 3 */
+ .info_part = 0x100,
+ .info_variant = 0x104,
+ .info_package = 0x108,
+ .info_ram = 0x10c,
+ .info_flash = 0x110,
+};
+
+static const struct nrf5_map nrf51_52_map = {
+ .flash_base = NRF5_FLASH_BASE,
+ .ficr_base = NRF51_52_FICR_BASE,
+ .uicr_base = NRF51_52_UICR_BASE,
+ .nvmc_base = 0x4001E000,
+
+ .watchdog_refresh_addr = 0x40010600,
+};
+
+
+/* Third generation devices (nRF53, nRF91) */
+
+static const struct nrf5_ficr_map nrf53_91_ficr_offsets = {
+ .codepagesize = 0x220,
+ .codesize = 0x224,
+ .configid = 0x200,
+ .info_part = 0x20c,
+ .info_variant = 0x210,
+ .info_package = 0x214,
+ .info_ram = 0x218,
+ .info_flash = 0x21c,
+};
+
+/* Since nRF9160 Product Specification v2.1 there is
+ * a new UICR field SIPINFO, which should be preferred.
+ * The original INFO fields describe just a part of the chip
+ * (PARTNO=9120 at nRF9161)
+ */
+static const struct nrf5_ficr_map nrf91new_ficr_offsets = {
+ .codepagesize = 0x220,
+ .codesize = 0x224,
+ .configid = 0x200,
+ .info_part = 0x140, /* SIPINFO.PARTNO */
+ .info_variant = 0x148, /* SIPINFO.VARIANT */
+ .info_package = 0x214,
+ .info_ram = 0x218,
+ .info_flash = 0x21c,
+};
+
+enum {
+ NRF53APP_91_FICR_BASE = 0x00FF0000,
+ NRF53APP_91_UICR_BASE = 0x00FF8000,
+ NRF53NET_FLASH_BASE = 0x01000000,
+ NRF53NET_FICR_BASE = 0x01FF0000,
+ NRF53NET_UICR_BASE = 0x01FF8000,
+};
+
+static const struct nrf5_map nrf53app_91_map = {
+ .flash_base = NRF5_FLASH_BASE,
+ .ficr_base = NRF53APP_91_FICR_BASE,
+ .uicr_base = NRF53APP_91_UICR_BASE,
+ .nvmc_base = 0x50039000,
+
+ .watchdog_refresh_addr = 0x50018600,
+};
+
+/* nRF53 duality:
+ * SoC consists of two Cortex-M33 cores:
+ * - application core with security extensions
+ * - network core
+ * Each core has its own RAM, flash, FICR and UICR
+ * The flash driver probes and handles flash and UICR of one core
+ * independently of those dedicated to the other core.
+ */
+static const struct nrf5_map nrf53net_map = {
+ .flash_base = NRF53NET_FLASH_BASE,
+ .ficr_base = NRF53NET_FICR_BASE,
+ .uicr_base = NRF53NET_UICR_BASE,
+ .nvmc_base = 0x41080000,
+
+ .watchdog_refresh_addr = 0x41080000,
+};
+
+
const struct flash_driver nrf5_flash, nrf51_flash;
static bool nrf5_bank_is_probed(const struct flash_bank *bank)
{
struct nrf5_bank *nbank = bank->driver_priv;
- assert(nbank);
-
return nbank->probed;
}
+static bool nrf5_chip_is_probed(const struct flash_bank *bank)
+{
+ struct nrf5_bank *nbank = bank->driver_priv;
+ struct nrf5_info *chip = nbank->chip;
+ return chip->chip_probed;
+}
+
+static bool nrf5_bank_is_uicr(const struct nrf5_bank *nbank)
+{
+ struct nrf5_info *chip = nbank->chip;
+ return nbank == &chip->bank[1];
+}
+
+static int nrf5_nvmc_read_u32(struct nrf5_info *chip, uint32_t reg_offset, uint32_t *value)
+{
+ return target_read_u32(chip->target, chip->map->nvmc_base + reg_offset, value);
+}
+
+static int nrf5_nvmc_write_u32(struct nrf5_info *chip, uint32_t reg_offset, uint32_t value)
+{
+ return target_write_u32(chip->target, chip->map->nvmc_base + reg_offset, value);
+}
+
static int nrf5_wait_for_nvmc(struct nrf5_info *chip)
{
uint32_t ready;
@@ -256,7 +379,13 @@ static int nrf5_wait_for_nvmc(struct nrf5_info *chip)
int64_t ts_start = timeval_ms();
do {
- res = target_read_u32(chip->target, NRF5_NVMC_READY, &ready);
+ res = nrf5_nvmc_read_u32(chip, NRF5_NVMC_READY, &ready);
+ if (res == ERROR_WAIT) {
+ /* The adapter does not handle SWD WAIT properly,
+ * add some delay to reduce number of error messages */
+ alive_sleep(10);
+ continue;
+ }
if (res != ERROR_OK) {
LOG_ERROR("Error waiting NVMC_READY: generic flash write/erase error (check protection etc...)");
return res;
@@ -276,7 +405,7 @@ static int nrf5_wait_for_nvmc(struct nrf5_info *chip)
static int nrf5_nvmc_erase_enable(struct nrf5_info *chip)
{
int res;
- res = target_write_u32(chip->target,
+ res = nrf5_nvmc_write_u32(chip,
NRF5_NVMC_CONFIG,
NRF5_NVMC_CONFIG_EEN);
@@ -299,7 +428,7 @@ static int nrf5_nvmc_erase_enable(struct nrf5_info *chip)
static int nrf5_nvmc_write_enable(struct nrf5_info *chip)
{
int res;
- res = target_write_u32(chip->target,
+ res = nrf5_nvmc_write_u32(chip,
NRF5_NVMC_CONFIG,
NRF5_NVMC_CONFIG_WEN);
@@ -322,12 +451,12 @@ static int nrf5_nvmc_write_enable(struct nrf5_info *chip)
static int nrf5_nvmc_read_only(struct nrf5_info *chip)
{
int res;
- res = target_write_u32(chip->target,
+ res = nrf5_nvmc_write_u32(chip,
NRF5_NVMC_CONFIG,
NRF5_NVMC_CONFIG_REN);
if (res != ERROR_OK) {
- LOG_ERROR("Failed to enable read-only operation");
+ LOG_ERROR("Failed to disable write/erase operation");
return res;
}
/*
@@ -341,44 +470,14 @@ static int nrf5_nvmc_read_only(struct nrf5_info *chip)
return res;
}
-static int nrf5_nvmc_generic_erase(struct nrf5_info *chip,
- uint32_t erase_register, uint32_t erase_value)
-{
- int res;
-
- res = nrf5_nvmc_erase_enable(chip);
- if (res != ERROR_OK)
- goto error;
-
- res = target_write_u32(chip->target,
- erase_register,
- erase_value);
- if (res != ERROR_OK)
- goto set_read_only;
-
- res = nrf5_wait_for_nvmc(chip);
- if (res != ERROR_OK)
- goto set_read_only;
-
- return nrf5_nvmc_read_only(chip);
-
-set_read_only:
- nrf5_nvmc_read_only(chip);
-error:
- LOG_ERROR("Failed to erase reg: 0x%08"PRIx32" val: 0x%08"PRIx32,
- erase_register, erase_value);
- return ERROR_FAIL;
-}
-
-static int nrf5_protect_check_clenr0(struct flash_bank *bank)
+/* nRF51 series only */
+static int nrf51_protect_check_clenr0(struct flash_bank *bank)
{
int res;
uint32_t clenr0;
struct nrf5_bank *nbank = bank->driver_priv;
- assert(nbank);
struct nrf5_info *chip = nbank->chip;
- assert(chip);
res = target_read_u32(chip->target, NRF51_FICR_CLENR0,
&clenr0);
@@ -403,12 +502,11 @@ static int nrf5_protect_check_clenr0(struct flash_bank *bank)
return ERROR_OK;
}
-static int nrf5_protect_check_bprot(struct flash_bank *bank)
+/* nRF52 series only */
+static int nrf52_protect_check_bprot(struct flash_bank *bank)
{
struct nrf5_bank *nbank = bank->driver_priv;
- assert(nbank);
struct nrf5_info *chip = nbank->chip;
- assert(chip);
static uint32_t nrf5_bprot_offsets[4] = { 0x600, 0x604, 0x610, 0x614 };
uint32_t bprot_reg = 0;
@@ -432,35 +530,32 @@ static int nrf5_protect_check_bprot(struct flash_bank *bank)
static int nrf5_protect_check(struct flash_bank *bank)
{
- /* UICR cannot be write protected so just return early */
- if (bank->base == NRF5_UICR_BASE)
- return ERROR_OK;
-
struct nrf5_bank *nbank = bank->driver_priv;
- assert(nbank);
struct nrf5_info *chip = nbank->chip;
- assert(chip);
+
+ /* UICR cannot be write protected so just return early */
+ if (nrf5_bank_is_uicr(nbank))
+ return ERROR_OK;
if (chip->features & NRF5_FEATURE_BPROT)
- return nrf5_protect_check_bprot(bank);
+ return nrf52_protect_check_bprot(bank);
if (chip->features & NRF5_FEATURE_SERIES_51)
- return nrf5_protect_check_clenr0(bank);
+ return nrf51_protect_check_clenr0(bank);
LOG_WARNING("Flash protection of this nRF device is not supported");
return ERROR_FLASH_OPER_UNSUPPORTED;
}
-static int nrf5_protect_clenr0(struct flash_bank *bank, int set, unsigned int first,
+/* nRF51 series only */
+static int nrf51_protect_clenr0(struct flash_bank *bank, int set, unsigned int first,
unsigned int last)
{
int res;
uint32_t clenr0, ppfc;
struct nrf5_bank *nbank = bank->driver_priv;
- assert(nbank);
struct nrf5_info *chip = nbank->chip;
- assert(chip);
if (first != 0) {
LOG_ERROR("Code region 0 must start at the beginning of the bank");
@@ -517,8 +612,11 @@ error:
static int nrf5_protect(struct flash_bank *bank, int set, unsigned int first,
unsigned int last)
{
+ struct nrf5_bank *nbank = bank->driver_priv;
+ struct nrf5_info *chip = nbank->chip;
+
/* UICR cannot be write protected so just bail out early */
- if (bank->base == NRF5_UICR_BASE) {
+ if (nrf5_bank_is_uicr(nbank)) {
LOG_ERROR("UICR page does not support protection");
return ERROR_FLASH_OPER_UNSUPPORTED;
}
@@ -528,24 +626,24 @@ static int nrf5_protect(struct flash_bank *bank, int set, unsigned int first,
return ERROR_TARGET_NOT_HALTED;
}
- struct nrf5_bank *nbank = bank->driver_priv;
- assert(nbank);
- struct nrf5_info *chip = nbank->chip;
- assert(chip);
-
if (chip->features & NRF5_FEATURE_SERIES_51)
- return nrf5_protect_clenr0(bank, set, first, last);
+ return nrf51_protect_clenr0(bank, set, first, last);
LOG_ERROR("Flash protection setting is not supported on this nRF5 device");
return ERROR_FLASH_OPER_UNSUPPORTED;
}
-static bool nrf5_info_variant_to_str(uint32_t variant, char *bf)
+static bool nrf5_info_variant_to_str(uint32_t variant, char *bf, bool swap)
{
uint8_t b[4];
- h_u32_to_be(b, variant);
- if (isalnum(b[0]) && isalnum(b[1]) && isalnum(b[2]) && isalnum(b[3])) {
+ if (swap)
+ h_u32_to_le(b, variant);
+ else
+ h_u32_to_be(b, variant);
+
+ if (isalnum(b[0]) && isalnum(b[1]) && isalnum(b[2]) &&
+ (isalnum(b[3]) || b[3] == 0)) {
memcpy(bf, b, 4);
bf[4] = 0;
return true;
@@ -564,7 +662,7 @@ static const char *nrf5_decode_info_package(uint32_t package)
return "xx";
}
-static int get_nrf5_chip_type_str(const struct nrf5_info *chip, char *buf, unsigned int buf_size)
+static int nrf5_get_chip_type_str(const struct nrf5_info *chip, char *buf, unsigned int buf_size)
{
int res;
if (chip->spec) {
@@ -572,11 +670,19 @@ static int get_nrf5_chip_type_str(const struct nrf5_info *chip, char *buf, unsig
chip->spec->part, chip->spec->variant, chip->spec->build_code);
} else if (chip->ficr_info_valid) {
char variant[5];
- nrf5_info_variant_to_str(chip->ficr_info.variant, variant);
- res = snprintf(buf, buf_size, "nRF%" PRIx32 "-%s%.2s(build code: %s)",
- chip->ficr_info.part,
- nrf5_decode_info_package(chip->ficr_info.package),
- variant, &variant[2]);
+
+ nrf5_info_variant_to_str(chip->ficr_info.variant, variant,
+ chip->features & NRF5_FEATURE_SERIES_91);
+
+ if (chip->features & (NRF5_FEATURE_SERIES_53 | NRF5_FEATURE_SERIES_91)) {
+ res = snprintf(buf, buf_size, "nRF%" PRIx32 "-%s",
+ chip->ficr_info.part, variant);
+ } else {
+ res = snprintf(buf, buf_size, "nRF%" PRIx32 "-%s%.2s(build code: %s)",
+ chip->ficr_info.part,
+ nrf5_decode_info_package(chip->ficr_info.package),
+ variant, &variant[2]);
+ }
} else {
res = snprintf(buf, buf_size, "nRF51xxx (HWID 0x%04" PRIx16 ")", chip->hwid);
}
@@ -592,37 +698,39 @@ static int get_nrf5_chip_type_str(const struct nrf5_info *chip, char *buf, unsig
static int nrf5_info(struct flash_bank *bank, struct command_invocation *cmd)
{
struct nrf5_bank *nbank = bank->driver_priv;
- assert(nbank);
struct nrf5_info *chip = nbank->chip;
- assert(chip);
char chip_type_str[256];
- if (get_nrf5_chip_type_str(chip, chip_type_str, sizeof(chip_type_str)) != ERROR_OK)
+ if (nrf5_get_chip_type_str(chip, chip_type_str, sizeof(chip_type_str)) != ERROR_OK)
return ERROR_FAIL;
+ unsigned int flash_size_kb = chip->flash_num_sectors * chip->flash_page_size / 1024;
command_print_sameline(cmd, "%s %ukB Flash, %ukB RAM",
- chip_type_str, chip->flash_size_kb, chip->ram_size_kb);
+ chip_type_str, flash_size_kb, chip->ram_size_kb);
return ERROR_OK;
}
-static int nrf5_read_ficr_info(struct nrf5_info *chip)
+static int nrf5_read_ficr_info_part(struct nrf5_info *chip, const struct nrf5_map *map,
+ const struct nrf5_ficr_map *ficr_offsets)
{
- int res;
struct target *target = chip->target;
+ uint32_t ficr_base = map->ficr_base;
- chip->ficr_info_valid = false;
-
- res = target_read_u32(target, NRF5_FICR_INFO_PART, &chip->ficr_info.part);
- if (res != ERROR_OK) {
+ int res = target_read_u32(target, ficr_base + ficr_offsets->info_part, &chip->ficr_info.part);
+ if (res != ERROR_OK)
LOG_DEBUG("Couldn't read FICR INFO.PART register");
- return res;
- }
+
+ return res;
+}
+
+static int nrf51_52_partno_check(struct nrf5_info *chip)
+{
uint32_t series = chip->ficr_info.part & 0xfffff000;
switch (series) {
case 0x51000:
chip->features = NRF5_FEATURE_SERIES_51;
- break;
+ return ERROR_OK;
case 0x52000:
chip->features = NRF5_FEATURE_SERIES_52;
@@ -641,41 +749,59 @@ static int nrf5_read_ficr_info(struct nrf5_info *chip)
chip->features |= NRF5_FEATURE_ACL_PROT;
break;
}
- break;
+ return ERROR_OK;
default:
LOG_DEBUG("FICR INFO likely not implemented. Invalid PART value 0x%08"
- PRIx32, chip->ficr_info.part);
+ PRIx32, chip->ficr_info.part);
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
+}
- /* Now we know the device has FICR INFO filled by something relevant:
- * Although it is not documented, the tested nRF51 rev 3 devices
- * have FICR INFO.PART, RAM and FLASH of the same format as nRF52.
- * VARIANT and PACKAGE coding is unknown for a nRF51 device.
- * nRF52 devices have FICR INFO documented and always filled. */
+static int nrf53_91_partno_check(struct nrf5_info *chip)
+{
+ uint32_t series = chip->ficr_info.part & 0xffffff00;
+ switch (series) {
+ case 0x5300:
+ chip->features = NRF5_FEATURE_SERIES_53 | NRF5_FEATURE_ERASE_BY_FLASH_WR;
+ return ERROR_OK;
- res = target_read_u32(target, NRF5_FICR_INFO_VARIANT, &chip->ficr_info.variant);
- if (res != ERROR_OK)
- return res;
+ case 0x9100:
+ chip->features = NRF5_FEATURE_SERIES_91 | NRF5_FEATURE_ERASE_BY_FLASH_WR;
+ return ERROR_OK;
+
+ default:
+ LOG_DEBUG("Invalid FICR INFO PART value 0x%08"
+ PRIx32, chip->ficr_info.part);
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ }
+}
+
+static int nrf5_read_ficr_more_info(struct nrf5_info *chip)
+{
+ int res;
+ struct target *target = chip->target;
+ const struct nrf5_ficr_map *ficr_offsets = chip->ficr_offsets;
+ uint32_t ficr_base = chip->map->ficr_base;
- res = target_read_u32(target, NRF5_FICR_INFO_PACKAGE, &chip->ficr_info.package);
+ res = target_read_u32(target, ficr_base + ficr_offsets->info_variant, &chip->ficr_info.variant);
if (res != ERROR_OK)
return res;
- res = target_read_u32(target, NRF5_FICR_INFO_RAM, &chip->ficr_info.ram);
+ res = target_read_u32(target, ficr_base + ficr_offsets->info_package, &chip->ficr_info.package);
if (res != ERROR_OK)
return res;
- res = target_read_u32(target, NRF5_FICR_INFO_FLASH, &chip->ficr_info.flash);
+ res = target_read_u32(target, ficr_base + ficr_offsets->info_ram, &chip->ficr_info.ram);
if (res != ERROR_OK)
return res;
- chip->ficr_info_valid = true;
- return ERROR_OK;
+ res = target_read_u32(target, ficr_base + ficr_offsets->info_flash, &chip->ficr_info.flash);
+ return res;
}
-static int nrf5_get_ram_size(struct target *target, uint32_t *ram_size)
+/* nRF51 series only */
+static int nrf51_get_ram_size(struct target *target, uint32_t *ram_size)
{
int res;
@@ -708,34 +834,108 @@ static int nrf5_get_ram_size(struct target *target, uint32_t *ram_size)
return res;
}
-static int nrf5_probe(struct flash_bank *bank)
+static int nrf5_probe_chip(struct flash_bank *bank)
{
- int res;
+ int res = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
struct nrf5_bank *nbank = bank->driver_priv;
- assert(nbank);
struct nrf5_info *chip = nbank->chip;
- assert(chip);
struct target *target = chip->target;
- uint32_t configid;
- res = target_read_u32(target, NRF5_FICR_CONFIGID, &configid);
+ chip->spec = NULL;
+ chip->ficr_info_valid = false;
+
+ /* First try to detect nRF53/91 */
+ switch (bank->base) {
+ case NRF5_FLASH_BASE:
+ case NRF53APP_91_UICR_BASE:
+ res = nrf5_read_ficr_info_part(chip, &nrf53app_91_map, &nrf91new_ficr_offsets);
+ if (res == ERROR_OK) {
+ res = nrf53_91_partno_check(chip);
+ if (res == ERROR_OK) {
+ chip->map = &nrf53app_91_map;
+ chip->ficr_offsets = &nrf91new_ficr_offsets;
+ break;
+ }
+ }
+
+ res = nrf5_read_ficr_info_part(chip, &nrf53app_91_map, &nrf53_91_ficr_offsets);
+ if (res != ERROR_OK)
+ break;
+
+ res = nrf53_91_partno_check(chip);
+ if (res != ERROR_OK)
+ break;
+
+ chip->map = &nrf53app_91_map;
+ chip->ficr_offsets = &nrf53_91_ficr_offsets;
+ break;
+
+ case NRF53NET_FLASH_BASE:
+ case NRF53NET_UICR_BASE:
+ res = nrf5_read_ficr_info_part(chip, &nrf53net_map, &nrf53_91_ficr_offsets);
+ if (res != ERROR_OK)
+ break;
+
+ res = nrf53_91_partno_check(chip);
+ if (res != ERROR_OK)
+ break;
+
+ chip->map = &nrf53net_map;
+ chip->ficr_offsets = &nrf53_91_ficr_offsets;
+ break;
+
+ default:
+ break;
+ }
+
+ /* If nRF53/91 is not detected, try nRF51/52 */
if (res != ERROR_OK) {
- LOG_ERROR("Couldn't read CONFIGID register");
- return res;
+ /* Guess a nRF51 series if the device has no FICR INFO and we don't know HWID */
+ chip->features = NRF5_FEATURE_SERIES_51;
+ chip->map = &nrf51_52_map;
+ chip->ficr_offsets = &nrf51_52_ficr_offsets;
+
+ /* Don't bail out on error for the case that some old engineering
+ * sample has FICR INFO registers unreadable. We can proceed anyway. */
+ res = nrf5_read_ficr_info_part(chip, chip->map, chip->ficr_offsets);
+ if (res == ERROR_OK)
+ res = nrf51_52_partno_check(chip);
}
- /* HWID is stored in the lower two bytes of the CONFIGID register */
- chip->hwid = configid & 0xFFFF;
+ if (res == ERROR_OK) {
+ /* Now we know the device has FICR INFO filled by something relevant:
+ * Although it is not documented, the tested nRF51 rev 3 devices
+ * have FICR INFO.PART, RAM and FLASH of the same format as nRF52.
+ * VARIANT and PACKAGE coding is unknown for a nRF51 device.
+ * nRF52 devices have FICR INFO documented and always filled. */
+ res = nrf5_read_ficr_more_info(chip);
+ if (res == ERROR_OK) {
+ chip->ficr_info_valid = true;
+ } else if (chip->features & NRF5_FEATURE_SERIES_51) {
+ LOG_DEBUG("Couldn't read some of FICR INFO registers");
+ } else {
+ LOG_ERROR("Couldn't read some of FICR INFO registers");
+ return res;
+ }
+ }
+
+ const struct nrf5_ficr_map *ficr_offsets = chip->ficr_offsets;
+ uint32_t ficr_base = chip->map->ficr_base;
+ uint32_t configid = 0;
+ res = target_read_u32(target, ficr_base + ficr_offsets->configid, &configid);
+ if (res != ERROR_OK) {
+ if (chip->features & NRF5_FEATURE_SERIES_51) {
+ LOG_ERROR("Couldn't read FICR CONFIGID register");
+ return res;
+ }
- /* guess a nRF51 series if the device has no FICR INFO and we don't know HWID */
- chip->features = NRF5_FEATURE_SERIES_51;
+ LOG_DEBUG("Couldn't read FICR CONFIGID register, using FICR INFO");
+ }
- /* Don't bail out on error for the case that some old engineering
- * sample has FICR INFO registers unreadable. We can proceed anyway. */
- (void)nrf5_read_ficr_info(chip);
+ /* HWID is stored in the lower two bytes of the CONFIGID register */
+ chip->hwid = configid & 0xFFFF;
- chip->spec = NULL;
for (size_t i = 0; i < ARRAY_SIZE(nrf5_known_devices_table); i++) {
if (chip->hwid == nrf5_known_devices_table[i].hwid) {
chip->spec = &nrf5_known_devices_table[i];
@@ -753,94 +953,114 @@ static int nrf5_probe(struct flash_bank *bank)
if (chip->ficr_info_valid) {
chip->ram_size_kb = chip->ficr_info.ram;
- } else {
+ } else if (chip->features & NRF5_FEATURE_SERIES_51) {
uint32_t ram_size;
- nrf5_get_ram_size(target, &ram_size);
+ nrf51_get_ram_size(target, &ram_size);
chip->ram_size_kb = ram_size / 1024;
+ } else {
+ chip->ram_size_kb = 0;
}
- /* The value stored in NRF5_FICR_CODEPAGESIZE is the number of bytes in one page of FLASH. */
- uint32_t flash_page_size;
- res = target_read_u32(chip->target, NRF5_FICR_CODEPAGESIZE,
- &flash_page_size);
+ /* The value stored in FICR CODEPAGESIZE is the number of bytes in one page of FLASH. */
+ res = target_read_u32(chip->target, ficr_base + ficr_offsets->codepagesize,
+ &chip->flash_page_size);
if (res != ERROR_OK) {
LOG_ERROR("Couldn't read code page size");
return res;
}
/* Note the register name is misleading,
- * NRF5_FICR_CODESIZE is the number of pages in flash memory, not the number of bytes! */
- uint32_t num_sectors;
- res = target_read_u32(chip->target, NRF5_FICR_CODESIZE, &num_sectors);
+ * FICR CODESIZE is the number of pages in flash memory, not the number of bytes! */
+ res = target_read_u32(chip->target, ficr_base + ficr_offsets->codesize,
+ &chip->flash_num_sectors);
if (res != ERROR_OK) {
LOG_ERROR("Couldn't read code memory size");
return res;
}
- chip->flash_size_kb = num_sectors * flash_page_size / 1024;
+ char chip_type_str[256];
+ if (nrf5_get_chip_type_str(chip, chip_type_str, sizeof(chip_type_str)) != ERROR_OK)
+ return ERROR_FAIL;
- if (!chip->bank[0].probed && !chip->bank[1].probed) {
- char chip_type_str[256];
- if (get_nrf5_chip_type_str(chip, chip_type_str, sizeof(chip_type_str)) != ERROR_OK)
- return ERROR_FAIL;
- const bool device_is_unknown = (!chip->spec && !chip->ficr_info_valid);
- LOG_INFO("%s%s %ukB Flash, %ukB RAM",
- device_is_unknown ? "Unknown device: " : "",
- chip_type_str,
- chip->flash_size_kb,
- chip->ram_size_kb);
- }
+ unsigned int flash_size_kb = chip->flash_num_sectors * chip->flash_page_size / 1024;
+ const bool device_is_unknown = (!chip->spec && !chip->ficr_info_valid);
+ LOG_INFO("%s%s %ukB Flash, %ukB RAM",
+ device_is_unknown ? "Unknown device: " : "",
+ chip_type_str,
+ flash_size_kb,
+ chip->ram_size_kb);
+
+ chip->chip_probed = true;
+ return ERROR_OK;
+}
- free(bank->sectors);
+static int nrf5_setup_bank(struct flash_bank *bank)
+{
+ struct nrf5_bank *nbank = bank->driver_priv;
+ struct nrf5_info *chip = nbank->chip;
- if (bank->base == NRF5_FLASH_BASE) {
+ if (bank->base == chip->map->flash_base) {
+ unsigned int flash_size_kb = chip->flash_num_sectors * chip->flash_page_size / 1024;
/* Sanity check */
- if (chip->spec && chip->flash_size_kb != chip->spec->flash_size_kb)
+ if (chip->spec && flash_size_kb != chip->spec->flash_size_kb)
LOG_WARNING("Chip's reported Flash capacity does not match expected one");
- if (chip->ficr_info_valid && chip->flash_size_kb != chip->ficr_info.flash)
+ if (chip->ficr_info_valid && flash_size_kb != chip->ficr_info.flash)
LOG_WARNING("Chip's reported Flash capacity does not match FICR INFO.FLASH");
- bank->num_sectors = num_sectors;
- bank->size = num_sectors * flash_page_size;
+ bank->num_sectors = chip->flash_num_sectors;
+ bank->size = chip->flash_num_sectors * chip->flash_page_size;
- bank->sectors = alloc_block_array(0, flash_page_size, num_sectors);
+ bank->sectors = alloc_block_array(0, chip->flash_page_size, bank->num_sectors);
if (!bank->sectors)
return ERROR_FAIL;
chip->bank[0].probed = true;
- } else {
+ } else if (bank->base == chip->map->uicr_base) {
+ /* UICR bank */
bank->num_sectors = 1;
- bank->size = flash_page_size;
+ bank->size = chip->flash_page_size;
- bank->sectors = alloc_block_array(0, flash_page_size, num_sectors);
+ bank->sectors = alloc_block_array(0, chip->flash_page_size, bank->num_sectors);
if (!bank->sectors)
return ERROR_FAIL;
bank->sectors[0].is_protected = 0;
chip->bank[1].probed = true;
+ } else {
+ LOG_ERROR("Invalid nRF bank address " TARGET_ADDR_FMT, bank->base);
+ return ERROR_FLASH_BANK_INVALID;
}
return ERROR_OK;
}
+static int nrf5_probe(struct flash_bank *bank)
+{
+ /* probe always reads actual info from the device */
+ int res = nrf5_probe_chip(bank);
+ if (res != ERROR_OK)
+ return res;
+
+ return nrf5_setup_bank(bank);
+}
+
static int nrf5_auto_probe(struct flash_bank *bank)
{
if (nrf5_bank_is_probed(bank))
return ERROR_OK;
- return nrf5_probe(bank);
-}
+ if (!nrf5_chip_is_probed(bank)) {
+ int res = nrf5_probe_chip(bank);
+ if (res != ERROR_OK)
+ return res;
+ }
-static int nrf5_erase_all(struct nrf5_info *chip)
-{
- LOG_DEBUG("Erasing all non-volatile memory");
- return nrf5_nvmc_generic_erase(chip,
- NRF5_NVMC_ERASEALL,
- 0x00000001);
+ return nrf5_setup_bank(bank);
}
+
static int nrf5_erase_page(struct flash_bank *bank,
struct nrf5_info *chip,
struct flash_sector *sector)
@@ -849,7 +1069,7 @@ static int nrf5_erase_page(struct flash_bank *bank,
LOG_DEBUG("Erasing page at 0x%"PRIx32, sector->offset);
- if (bank->base == NRF5_UICR_BASE) {
+ if (bank->base == chip->map->uicr_base) {
if (chip->features & NRF5_FEATURE_SERIES_51) {
uint32_t ppfc;
res = target_read_u32(chip->target, NRF51_FICR_PPFC,
@@ -871,17 +1091,37 @@ static int nrf5_erase_page(struct flash_bank *bank,
}
}
- res = nrf5_nvmc_generic_erase(chip,
- NRF5_NVMC_ERASEUICR,
- 0x00000001);
-
+ res = nrf5_nvmc_write_u32(chip, NRF5_NVMC_ERASEUICR, 0x00000001);
+
+ } else if (chip->features & NRF5_FEATURE_ERASE_BY_FLASH_WR) {
+ res = target_write_u32(chip->target, bank->base + sector->offset, 0xffffffff);
+ /* nRF9160 errata [2] NVMC: CPU code execution from RAM halted during
+ * flash page erase operation
+ * https://infocenter.nordicsemi.com/index.jsp?topic=%2Ferrata_nRF9160_Rev1%2FERR%2FnRF9160%2FRev1%2Flatest%2Fanomaly_160_2.html
+ * affects also erasing by debugger MEM-AP write:
+ *
+ * Write to a flash address stalls the bus for 87 ms until
+ * page erase finishes! This makes problems if the adapter does not
+ * handle SWD WAIT properly or does not wait long enough.
+ * Using a target algo would not help, AP gets unresponsive too.
+ * Neither sending AP ABORT helps, the next AP access stalls again.
+ * Simply wait long enough before accessing AP again...
+ *
+ * The same errata was observed in nRF9161
+ */
+ if (chip->features & NRF5_FEATURE_SERIES_91)
+ alive_sleep(90);
} else {
- res = nrf5_nvmc_generic_erase(chip,
- NRF5_NVMC_ERASEPAGE,
- sector->offset);
+ res = nrf5_nvmc_write_u32(chip, NRF5_NVMC_ERASEPAGE, sector->offset);
+ }
+
+ if (res != ERROR_OK) {
+ /* caller logs the error */
+ return res;
}
+ res = nrf5_wait_for_nvmc(chip);
return res;
}
@@ -958,7 +1198,7 @@ static int nrf5_ll_flash_write(struct nrf5_info *chip, uint32_t address, const u
buf_set_u32(reg_params[2].value, 0, 32, source->address + source->size);
buf_set_u32(reg_params[3].value, 0, 32, address);
buf_set_u32(reg_params[4].value, 0, 32, WATCHDOG_REFRESH_VALUE);
- buf_set_u32(reg_params[5].value, 0, 32, WATCHDOG_REFRESH_REGISTER);
+ buf_set_u32(reg_params[5].value, 0, 32, chip->map->watchdog_refresh_addr);
retval = target_run_flash_async_algorithm(target, buffer, bytes/4, 4,
0, NULL,
@@ -991,9 +1231,7 @@ static int nrf5_write(struct flash_bank *bank, const uint8_t *buffer,
}
struct nrf5_bank *nbank = bank->driver_priv;
- assert(nbank);
struct nrf5_info *chip = nbank->chip;
- assert(chip);
assert(offset % 4 == 0);
assert(count % 4 == 0);
@@ -1008,7 +1246,7 @@ static int nrf5_write(struct flash_bank *bank, const uint8_t *buffer,
* is protected. */
if (chip->features & NRF5_FEATURE_SERIES_51) {
- res = nrf5_protect_check_clenr0(bank);
+ res = nrf51_protect_check_clenr0(bank);
if (res != ERROR_OK)
return res;
@@ -1053,9 +1291,7 @@ static int nrf5_erase(struct flash_bank *bank, unsigned int first,
}
struct nrf5_bank *nbank = bank->driver_priv;
- assert(nbank);
struct nrf5_info *chip = nbank->chip;
- assert(chip);
/* UICR CLENR0 based protection used on nRF51 prevents erase
* absolutely silently. NVMC has no flag to indicate the protection
@@ -1065,18 +1301,23 @@ static int nrf5_erase(struct flash_bank *bank, unsigned int first,
* is protected. */
if (chip->features & NRF5_FEATURE_SERIES_51) {
- res = nrf5_protect_check_clenr0(bank);
+ res = nrf51_protect_check_clenr0(bank);
if (res != ERROR_OK)
return res;
}
+ res = nrf5_nvmc_erase_enable(chip);
+ if (res != ERROR_OK)
+ goto error;
+
/* For each sector to be erased */
for (unsigned int s = first; s <= last; s++) {
if (chip->features & NRF5_FEATURE_SERIES_51
&& bank->sectors[s].is_protected == 1) {
LOG_ERROR("Flash sector %d is protected", s);
- return ERROR_FLASH_PROTECTED;
+ res = ERROR_FLASH_PROTECTED;
+ break;
}
res = nrf5_erase_page(bank, chip, &bank->sectors[s]);
@@ -1086,13 +1327,14 @@ static int nrf5_erase(struct flash_bank *bank, unsigned int first,
}
}
- return ERROR_OK;
+error:
+ nrf5_nvmc_read_only(chip);
+ return res;
}
static void nrf5_free_driver_priv(struct flash_bank *bank)
{
struct nrf5_bank *nbank = bank->driver_priv;
- assert(nbank);
struct nrf5_info *chip = nbank->chip;
if (!chip)
return;
@@ -1136,11 +1378,14 @@ FLASH_BANK_COMMAND_HANDLER(nrf5_flash_bank_command)
switch (bank->base) {
case NRF5_FLASH_BASE:
- case NRF5_UICR_BASE:
+ case NRF53NET_FLASH_BASE:
+ case NRF51_52_UICR_BASE:
+ case NRF53APP_91_UICR_BASE:
+ case NRF53NET_UICR_BASE:
break;
default:
- LOG_ERROR("Invalid bank address " TARGET_ADDR_FMT, bank->base);
- return ERROR_FAIL;
+ LOG_ERROR("Invalid nRF bank address " TARGET_ADDR_FMT, bank->base);
+ return ERROR_FLASH_BANK_INVALID;
}
chip = nrf5_get_chip(bank->target);
@@ -1155,9 +1400,12 @@ FLASH_BANK_COMMAND_HANDLER(nrf5_flash_bank_command)
switch (bank->base) {
case NRF5_FLASH_BASE:
+ case NRF53NET_FLASH_BASE:
nbank = &chip->bank[0];
break;
- case NRF5_UICR_BASE:
+ case NRF51_52_UICR_BASE:
+ case NRF53APP_91_UICR_BASE:
+ case NRF53NET_UICR_BASE:
nbank = &chip->bank[1];
break;
}
@@ -1182,17 +1430,13 @@ COMMAND_HANDLER(nrf5_handle_mass_erase_command)
if (res != ERROR_OK)
return res;
- assert(bank);
-
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
struct nrf5_bank *nbank = bank->driver_priv;
- assert(nbank);
struct nrf5_info *chip = nbank->chip;
- assert(chip);
if (chip->features & NRF5_FEATURE_SERIES_51) {
uint32_t ppfc;
@@ -1210,14 +1454,27 @@ COMMAND_HANDLER(nrf5_handle_mass_erase_command)
}
}
- res = nrf5_erase_all(chip);
+ res = nrf5_nvmc_erase_enable(chip);
+ if (res != ERROR_OK)
+ goto error;
+
+ res = nrf5_nvmc_write_u32(chip, NRF5_NVMC_ERASEALL, 0x00000001);
+ if (res != ERROR_OK) {
+ LOG_ERROR("Mass erase failed");
+ goto error;
+ }
+
+ res = nrf5_wait_for_nvmc(chip);
+ if (res != ERROR_OK)
+ LOG_ERROR("Mass erase did not complete");
+
+error:
+ nrf5_nvmc_read_only(chip);
+
if (res == ERROR_OK) {
LOG_INFO("Mass erase completed.");
if (chip->features & NRF5_FEATURE_SERIES_51)
LOG_INFO("A reset or power cycle is required if the flash was protected before.");
-
- } else {
- LOG_ERROR("Failed to erase the chip");
}
return res;
diff --git a/src/flash/nor/pic32mx.c b/src/flash/nor/pic32mx.c
index 0f3937c..982c961 100644
--- a/src/flash/nor/pic32mx.c
+++ b/src/flash/nor/pic32mx.c
@@ -92,7 +92,7 @@ struct pic32mx_flash_bank {
* DEVID values as per PIC32MX Flash Programming Specification Rev N
*/
-static const struct pic32mx_devs_s {
+static const struct pic32mx_devs {
uint32_t devid;
const char *name;
} pic32mx_devs[] = {
diff --git a/src/flash/nor/psoc6.c b/src/flash/nor/psoc6.c
index 859b3e9..47f3ac6 100644
--- a/src/flash/nor/psoc6.c
+++ b/src/flash/nor/psoc6.c
@@ -223,6 +223,8 @@ static int ipc_poll_lock_stat(struct target *target, uint32_t ipc_id, bool lock_
{
int hr;
uint32_t reg_val;
+ struct armv7m_common *armv7m = target_to_armv7m(target);
+ bool is_cm0 = (armv7m->arm.arch == ARM_ARCH_V6M);
struct timeout to;
timeout_init(&to, IPC_TIMEOUT_MS);
@@ -244,7 +246,7 @@ static int ipc_poll_lock_stat(struct target *target, uint32_t ipc_id, bool lock_
return ERROR_OK;
}
- if (target->coreid) {
+ if (!is_cm0) {
LOG_WARNING("SROM API calls via CM4 target are supported on single-core PSoC6 devices only. "
"Please perform all Flash-related operations via CM0+ target on dual-core devices.");
}
@@ -886,7 +888,8 @@ static int handle_reset_halt(struct target *target)
{
int hr;
uint32_t reset_addr;
- bool is_cm0 = (target->coreid == 0);
+ struct armv7m_common *armv7m = target_to_armv7m(target);
+ bool is_cm0 = (armv7m->arm.arch == ARM_ARCH_V6M);
/* Halt target device */
if (target->state != TARGET_HALTED) {
diff --git a/src/flash/nor/sfdp.c b/src/flash/nor/sfdp.c
index 5bfb541..917f162 100644
--- a/src/flash/nor/sfdp.c
+++ b/src/flash/nor/sfdp.c
@@ -12,7 +12,6 @@
#include "spi.h"
#include "sfdp.h"
-#define SFDP_MAGIC 0x50444653
#define SFDP_ACCESS_PROT 0xFF
#define SFDP_BASIC_FLASH 0xFF00
#define SFDP_4BYTE_ADDR 0xFF84
@@ -100,7 +99,7 @@ int spi_sfdp(struct flash_bank *bank, struct flash_device *dev,
goto err;
for (k = 0; k < nph; k++) {
- uint8_t words = (pheaders[k].revision >> 24) & 0xFF;
+ unsigned int words = (pheaders[k].revision >> 24) & 0xFF;
uint16_t id = (((pheaders[k].ptr) >> 16) & 0xFF00) | (pheaders[k].revision & 0xFF);
uint32_t ptr = pheaders[k].ptr & 0xFFFFFF;
diff --git a/src/flash/nor/sfdp.h b/src/flash/nor/sfdp.h
index 1c9af32..0d43519 100644
--- a/src/flash/nor/sfdp.h
+++ b/src/flash/nor/sfdp.h
@@ -7,6 +7,8 @@
#ifndef OPENOCD_FLASH_NOR_SFDP_H
#define OPENOCD_FLASH_NOR_SFDP_H
+#define SFDP_MAGIC 0x50444653
+
/* per JESD216D 'addr' is *byte* based but must be word aligned,
* 'buffer' is word based, word aligned and always little-endian encoded,
* in the flash, 'addr_len' is 3 or 4, 'dummy' ***usually*** 8
@@ -16,7 +18,7 @@
*
* buffer contents is supposed to be returned in ***host*** endianness */
typedef int (*read_sfdp_block_t)(struct flash_bank *bank, uint32_t addr,
- uint32_t words, uint32_t *buffer);
+ unsigned int words, uint32_t *buffer);
extern int spi_sfdp(struct flash_bank *bank, struct flash_device *dev,
read_sfdp_block_t read_sfdp_block);
diff --git a/src/flash/nor/stellaris.c b/src/flash/nor/stellaris.c
index 972686e..eab6244 100644
--- a/src/flash/nor/stellaris.c
+++ b/src/flash/nor/stellaris.c
@@ -453,7 +453,7 @@ FLASH_BANK_COMMAND_HANDLER(stellaris_flash_bank_command)
if (CMD_ARGC < 6)
return ERROR_COMMAND_SYNTAX_ERROR;
- stellaris_info = calloc(sizeof(struct stellaris_flash_bank), 1);
+ stellaris_info = calloc(1, sizeof(struct stellaris_flash_bank));
bank->base = 0x0;
bank->driver_priv = stellaris_info;
diff --git a/src/flash/nor/stm32f2x.c b/src/flash/nor/stm32f2x.c
index 4e0f731..3bafde5 100644
--- a/src/flash/nor/stm32f2x.c
+++ b/src/flash/nor/stm32f2x.c
@@ -1020,7 +1020,7 @@ static int stm32x_probe(struct flash_bank *bank)
assert(num_sectors > 0);
bank->num_sectors = num_sectors;
- bank->sectors = calloc(sizeof(struct flash_sector), num_sectors);
+ bank->sectors = calloc(num_sectors, sizeof(struct flash_sector));
if (stm32x_otp_is_f7(bank))
bank->size = STM32F7_OTP_SIZE;
diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c
index 0399385..9235dd7 100644
--- a/src/flash/nor/stm32l4x.c
+++ b/src/flash/nor/stm32l4x.c
@@ -120,6 +120,12 @@
* http://www.st.com/resource/en/reference_manual/dm00346336.pdf
*/
+/* STM32U5xxx series for reference.
+ *
+ * RM0456 (STM32U5xx)
+ * http://www.st.com/resource/en/reference_manual/dm00477635.pdf
+ */
+
/* Erase time can be as high as 25ms, 10x this and assume it's toast... */
#define FLASH_ERASE_TIMEOUT 250
@@ -344,9 +350,17 @@ static const struct stm32l4_rev stm32g49_g4axx_revs[] = {
{ 0x1000, "A" },
};
+static const struct stm32l4_rev stm32u53_u54xx_revs[] = {
+ { 0x1000, "A" }, { 0x1001, "Z" },
+};
+
static const struct stm32l4_rev stm32u57_u58xx_revs[] = {
{ 0x1000, "A" }, { 0x1001, "Z" }, { 0x1003, "Y" }, { 0x2000, "B" },
- { 0x2001, "X" }, { 0x3000, "C" },
+ { 0x2001, "X" }, { 0x3000, "C" }, { 0x3001, "W" },
+};
+
+static const struct stm32l4_rev stm32u59_u5axx_revs[] = {
+ { 0x3001, "X" },
};
static const struct stm32l4_rev stm32wba5x_revs[] = {
@@ -419,6 +433,18 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
.otp_size = 1024,
},
{
+ .id = DEVID_STM32U53_U54XX,
+ .revs = stm32u53_u54xx_revs,
+ .num_revs = ARRAY_SIZE(stm32u53_u54xx_revs),
+ .device_str = "STM32U535/U545",
+ .max_flash_size_kb = 512,
+ .flags = F_HAS_DUAL_BANK | F_QUAD_WORD_PROG | F_HAS_TZ | F_HAS_L5_FLASH_REGS,
+ .flash_regs_base = 0x40022000,
+ .fsize_addr = 0x0BFA07A0,
+ .otp_base = 0x0BFA0000,
+ .otp_size = 512,
+ },
+ {
.id = DEVID_STM32G05_G06XX,
.revs = stm32g05_g06xx_revs,
.num_revs = ARRAY_SIZE(stm32g05_g06xx_revs),
@@ -575,6 +601,18 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
.otp_size = 1024,
},
{
+ .id = DEVID_STM32U59_U5AXX,
+ .revs = stm32u59_u5axx_revs,
+ .num_revs = ARRAY_SIZE(stm32u59_u5axx_revs),
+ .device_str = "STM32U59/U5Axx",
+ .max_flash_size_kb = 4096,
+ .flags = F_HAS_DUAL_BANK | F_QUAD_WORD_PROG | F_HAS_TZ | F_HAS_L5_FLASH_REGS,
+ .flash_regs_base = 0x40022000,
+ .fsize_addr = 0x0BFA07A0,
+ .otp_base = 0x0BFA0000,
+ .otp_size = 512,
+ },
+ {
.id = DEVID_STM32U57_U58XX,
.revs = stm32u57_u58xx_revs,
.num_revs = ARRAY_SIZE(stm32u57_u58xx_revs),
@@ -2000,10 +2038,22 @@ static int stm32l4_probe(struct flash_bank *bank)
stm32l4_info->bank1_sectors = num_pages / 2;
}
break;
+ case DEVID_STM32U53_U54XX:
case DEVID_STM32U57_U58XX:
- /* if flash size is max (2M) the device is always dual bank
- * otherwise check DUALBANK
+ case DEVID_STM32U59_U5AXX:
+ /* according to RM0456 Rev 4, Chapter 7.3.1 and 7.9.13
+ * U53x/U54x have 512K max flash size:
+ * 512K variants are always in DUAL BANK mode
+ * 256K and 128K variants can be in DUAL BANK mode if FLASH_OPTR:DUALBANK is set
+ * U57x/U58x have 2M max flash size:
+ * 2M variants are always in DUAL BANK mode
+ * 1M variants can be in DUAL BANK mode if FLASH_OPTR:DUALBANK is set
+ * U59x/U5Ax have 4M max flash size:
+ * 4M variants are always in DUAL BANK mode
+ * 2M variants can be in DUAL BANK mode if FLASH_OPTR:DUALBANK is set
+ * Note: flash banks are always contiguous
*/
+
page_size_kb = 8;
num_pages = flash_size_kb / page_size_kb;
stm32l4_info->bank1_sectors = num_pages;
@@ -2572,7 +2622,7 @@ static const struct command_registration stm32l4_exec_command_handlers[] = {
.name = "option_write",
.handler = stm32l4_handle_option_write_command,
.mode = COMMAND_EXEC,
- .usage = "bank_id reg_offset value mask",
+ .usage = "bank_id reg_offset value [mask]",
.help = "Write device option bit fields with provided value.",
},
{
diff --git a/src/flash/nor/stm32l4x.h b/src/flash/nor/stm32l4x.h
index 3dc0909..5f3bc26 100644
--- a/src/flash/nor/stm32l4x.h
+++ b/src/flash/nor/stm32l4x.h
@@ -89,6 +89,7 @@
#define DEVID_STM32L43_L44XX 0x435
#define DEVID_STM32C01XX 0x443
#define DEVID_STM32C03XX 0x453
+#define DEVID_STM32U53_U54XX 0x455
#define DEVID_STM32G05_G06XX 0x456
#define DEVID_STM32G07_G08XX 0x460
#define DEVID_STM32L49_L4AXX 0x461
@@ -102,6 +103,7 @@
#define DEVID_STM32L4P_L4QXX 0x471
#define DEVID_STM32L55_L56XX 0x472
#define DEVID_STM32G49_G4AXX 0x479
+#define DEVID_STM32U59_U5AXX 0x481
#define DEVID_STM32U57_U58XX 0x482
#define DEVID_STM32WBA5X 0x492
#define DEVID_STM32WB1XX 0x494
diff --git a/src/flash/nor/stmqspi.c b/src/flash/nor/stmqspi.c
index a1e1d34..df58f6c 100644
--- a/src/flash/nor/stmqspi.c
+++ b/src/flash/nor/stmqspi.c
@@ -1807,7 +1807,7 @@ err:
/* Read SFDP parameter block */
static int read_sfdp_block(struct flash_bank *bank, uint32_t addr,
- uint32_t words, uint32_t *buffer)
+ unsigned int words, uint32_t *buffer)
{
struct target *target = bank->target;
struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv;
@@ -1848,7 +1848,7 @@ static int read_sfdp_block(struct flash_bank *bank, uint32_t addr,
}
}
- LOG_DEBUG("%s: addr=0x%08" PRIx32 " words=0x%08" PRIx32 " dummy=%u",
+ LOG_DEBUG("%s: addr=0x%08" PRIx32 " words=0x%08x dummy=%u",
__func__, addr, words, *dummy);
/* Abort any previous operation */
diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c
index 1c4e154..15edd1a 100644
--- a/src/flash/nor/tcl.c
+++ b/src/flash/nor/tcl.c
@@ -1299,6 +1299,7 @@ COMMAND_HANDLER(handle_flash_bank_command)
if (retval != ERROR_OK) {
LOG_ERROR("'%s' driver rejected flash bank at " TARGET_ADDR_FMT
"; usage: %s", driver_name, c->base, driver->usage);
+ free(c->name);
free(c);
return retval;
}
diff --git a/src/flash/startup.tcl b/src/flash/startup.tcl
index 654f201..0dd84ef 100644
--- a/src/flash/startup.tcl
+++ b/src/flash/startup.tcl
@@ -5,7 +5,7 @@
#
# program utility proc
# usage: program filename
-# optional args: verify, reset, exit and address
+# optional args: preverify, verify, reset, exit and address
#
lappend _telnet_autocomplete_skip program_error
@@ -101,8 +101,8 @@ proc program {filename args} {
return
}
-add_help_text program "write an image to flash, address is only required for binary images. verify, reset, exit are optional"
-add_usage_text program "<filename> \[address\] \[pre-verify\] \[verify\] \[reset\] \[exit\]"
+add_help_text program "write an image to flash, address is only required for binary images. preverify, verify, reset, exit are optional"
+add_usage_text program "<filename> \[address\] \[preverify\] \[verify\] \[reset\] \[exit\]"
# stm32[f0x|f3x] uses the same flash driver as the stm32f1x
proc stm32f0x args { eval stm32f1x $args }