diff options
Diffstat (limited to 'src/flash/nor')
-rw-r--r-- | src/flash/nor/ambiqmicro.c | 2 | ||||
-rw-r--r-- | src/flash/nor/at91sam7.c | 4 | ||||
-rw-r--r-- | src/flash/nor/atsame5.c | 30 | ||||
-rw-r--r-- | src/flash/nor/core.h | 10 | ||||
-rw-r--r-- | src/flash/nor/driver.h | 8 | ||||
-rw-r--r-- | src/flash/nor/em357.c | 2 | ||||
-rw-r--r-- | src/flash/nor/kinetis.c | 5 | ||||
-rw-r--r-- | src/flash/nor/max32xxx.c | 2 | ||||
-rw-r--r-- | src/flash/nor/msp432.c | 2 | ||||
-rw-r--r-- | src/flash/nor/nrf5.c | 687 | ||||
-rw-r--r-- | src/flash/nor/pic32mx.c | 2 | ||||
-rw-r--r-- | src/flash/nor/psoc6.c | 7 | ||||
-rw-r--r-- | src/flash/nor/sfdp.c | 3 | ||||
-rw-r--r-- | src/flash/nor/sfdp.h | 4 | ||||
-rw-r--r-- | src/flash/nor/stellaris.c | 2 | ||||
-rw-r--r-- | src/flash/nor/stm32f2x.c | 2 | ||||
-rw-r--r-- | src/flash/nor/stm32l4x.c | 58 | ||||
-rw-r--r-- | src/flash/nor/stm32l4x.h | 2 | ||||
-rw-r--r-- | src/flash/nor/stmqspi.c | 4 | ||||
-rw-r--r-- | src/flash/nor/tcl.c | 1 |
20 files changed, 591 insertions, 246 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; } |