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 <vanekt@fbl.cz>
Change-Id: Ib090a97fd7a41579b3d4f6e6634a5fdf93836c83
Reviewed-on: https://review.openocd.org/c/openocd/+/8322
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
This commit is contained in:
Tomas Vanek 2024-06-08 11:33:35 +02:00 committed by Antonio Borneo
parent c322060fbd
commit f09ccc817b
1 changed files with 72 additions and 32 deletions

View File

@ -117,20 +117,24 @@ struct nrf5_map {
struct nrf5_info { struct nrf5_info {
unsigned int refcount; unsigned int refcount;
bool chip_probed;
struct nrf5_bank { struct nrf5_bank {
struct nrf5_info *chip; struct nrf5_info *chip;
bool probed; bool probed;
} bank[2]; } bank[2];
struct target *target; 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; bool ficr_info_valid;
struct nrf52_ficr_info ficr_info; struct nrf52_ficr_info ficr_info;
const struct nrf5_device_spec *spec; const struct nrf5_device_spec *spec;
uint16_t hwid; uint16_t hwid;
enum nrf5_features features; enum nrf5_features features;
unsigned int flash_size_kb; uint32_t flash_page_size;
uint32_t flash_num_sectors;
unsigned int ram_size_kb; unsigned int ram_size_kb;
const struct nrf5_map *map; const struct nrf5_map *map;
@ -346,6 +350,16 @@ static bool nrf5_bank_is_probed(const struct flash_bank *bank)
return nbank->probed; 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) static bool nrf5_bank_is_uicr(const struct nrf5_bank *nbank)
{ {
struct nrf5_info *chip = nbank->chip; 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) if (nrf5_get_chip_type_str(chip, chip_type_str, sizeof(chip_type_str)) != ERROR_OK)
return ERROR_FAIL; 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", 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; return ERROR_OK;
} }
@ -838,7 +853,7 @@ static int nrf51_get_ram_size(struct target *target, uint32_t *ram_size)
return res; 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; 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. */ /* 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, res = target_read_u32(chip->target, ficr_base + ficr_offsets->codepagesize,
&flash_page_size); &chip->flash_page_size);
if (res != ERROR_OK) { if (res != ERROR_OK) {
LOG_ERROR("Couldn't read code page size"); LOG_ERROR("Couldn't read code page size");
return res; return res;
@ -978,69 +992,95 @@ static int nrf5_probe(struct flash_bank *bank)
/* Note the register name is misleading, /* Note the register name is misleading,
* FICR CODESIZE is the number of pages in flash memory, not the number of bytes! */ * 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, res = target_read_u32(chip->target, ficr_base + ficr_offsets->codesize,
&num_sectors); &chip->flash_num_sectors);
if (res != ERROR_OK) { if (res != ERROR_OK) {
LOG_ERROR("Couldn't read code memory size"); LOG_ERROR("Couldn't read code memory size");
return res; return res;
} }
chip->flash_size_kb = num_sectors * flash_page_size / 1024;
if (!chip->bank[0].probed && !chip->bank[1].probed) {
char chip_type_str[256]; char chip_type_str[256];
if (nrf5_get_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; return ERROR_FAIL;
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); const bool device_is_unknown = (!chip->spec && !chip->ficr_info_valid);
LOG_INFO("%s%s %ukB Flash, %ukB RAM", LOG_INFO("%s%s %ukB Flash, %ukB RAM",
device_is_unknown ? "Unknown device: " : "", device_is_unknown ? "Unknown device: " : "",
chip_type_str, chip_type_str,
chip->flash_size_kb, flash_size_kb,
chip->ram_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;
assert(nbank);
struct nrf5_info *chip = nbank->chip;
assert(chip);
if (bank->base == chip->map->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 */ /* 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"); 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"); LOG_WARNING("Chip's reported Flash capacity does not match FICR INFO.FLASH");
bank->num_sectors = num_sectors; bank->num_sectors = chip->flash_num_sectors;
bank->size = num_sectors * flash_page_size; 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) if (!bank->sectors)
return ERROR_FAIL; return ERROR_FAIL;
chip->bank[0].probed = true; chip->bank[0].probed = true;
} else { } else if (bank->base == chip->map->uicr_base) {
/* UICR bank */ /* UICR bank */
bank->num_sectors = 1; 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) if (!bank->sectors)
return ERROR_FAIL; return ERROR_FAIL;
bank->sectors[0].is_protected = 0; bank->sectors[0].is_protected = 0;
chip->bank[1].probed = true; 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; 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) static int nrf5_auto_probe(struct flash_bank *bank)
{ {
if (nrf5_bank_is_probed(bank)) if (nrf5_bank_is_probed(bank))
return ERROR_OK; 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: case NRF53NET_UICR_BASE:
break; break;
default: default:
LOG_ERROR("Invalid bank address " TARGET_ADDR_FMT, bank->base); LOG_ERROR("Invalid nRF bank address " TARGET_ADDR_FMT, bank->base);
return ERROR_FAIL; return ERROR_FLASH_BANK_INVALID;
} }
chip = nrf5_get_chip(bank->target); chip = nrf5_get_chip(bank->target);