From f09ccc817b76683b42dc6ad410adddee16a351ed Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sat, 8 Jun 2024 11:33:35 +0200 Subject: [PATCH] flash/nor/nrf5: split chip and bank probes nrf5_auto_probe() always re-probed chip hardware to get flash geometry. Introduce nrf5_probe_chip() and move chip related probing to it. Save all flash parameters needed for bank setup to struct nrf5_info. Introduce nrf5_setup_bank() and move bank setup code to it. Call both chip probe and bank setup unconditionally from nrf5_probe(): in case of manual issuing 'flash probe' command, we should refresh actual values from the device. Call chip probe and bank setup only if not done before from nrf5_auto_probe(). Signed-off-by: Tomas Vanek Change-Id: Ib090a97fd7a41579b3d4f6e6634a5fdf93836c83 Reviewed-on: https://review.openocd.org/c/openocd/+/8322 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/flash/nor/nrf5.c | 104 ++++++++++++++++++++++++++++++------------- 1 file changed, 72 insertions(+), 32 deletions(-) diff --git a/src/flash/nor/nrf5.c b/src/flash/nor/nrf5.c index f07433e67..3ad6a9628 100644 --- a/src/flash/nor/nrf5.c +++ b/src/flash/nor/nrf5.c @@ -117,20 +117,24 @@ struct nrf5_map { 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; @@ -346,6 +350,16 @@ static bool nrf5_bank_is_probed(const struct flash_bank *bank) return nbank->probed; } +static bool nrf5_chip_is_probed(const struct flash_bank *bank) +{ + struct nrf5_bank *nbank = bank->driver_priv; + assert(nbank); + struct nrf5_info *chip = nbank->chip; + assert(chip); + + return chip->chip_probed; +} + static bool nrf5_bank_is_uicr(const struct nrf5_bank *nbank) { struct nrf5_info *chip = nbank->chip; @@ -709,8 +723,9 @@ static int nrf5_info(struct flash_bank *bank, struct command_invocation *cmd) 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; } @@ -838,7 +853,7 @@ static int nrf51_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 = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; @@ -968,9 +983,8 @@ static int nrf5_probe(struct flash_bank *bank) } /* The value stored in FICR CODEPAGESIZE is the number of bytes in one page of FLASH. */ - uint32_t flash_page_size; res = target_read_u32(chip->target, ficr_base + ficr_offsets->codepagesize, - &flash_page_size); + &chip->flash_page_size); if (res != ERROR_OK) { LOG_ERROR("Couldn't read code page size"); return res; @@ -978,69 +992,95 @@ static int nrf5_probe(struct flash_bank *bank) /* Note the register name is misleading, * 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, ficr_base + ficr_offsets->codesize, - &num_sectors); + &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 (nrf5_get_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); - free(bank->sectors); + chip->chip_probed = true; + return ERROR_OK; +} + +static int nrf5_setup_bank(struct flash_bank *bank) +{ + struct nrf5_bank *nbank = bank->driver_priv; + assert(nbank); + struct nrf5_info *chip = nbank->chip; + assert(chip); 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; + } + + return nrf5_setup_bank(bank); } @@ -1372,8 +1412,8 @@ FLASH_BANK_COMMAND_HANDLER(nrf5_flash_bank_command) 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);