flash/nor/nrf5: fix protection setting on nRF51

Protection setting has not ever worked. UICR CLENR0 register cannot
be simply written but has to programmed because it resides in UICR
page of the flash.

Enable flash programming before writing CLENR0 and set back to r/o
afterwards.

Inform the user that reset might be required.

Change-Id: Ib0f96c74ba3583ac33f4394ddb57d8c8895adf53
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-on: http://openocd.zylin.com/5586
Tested-by: jenkins
This commit is contained in:
Tomas Vanek 2020-04-12 10:15:00 +02:00
parent 895d4a5995
commit c97ccc8971
1 changed files with 50 additions and 26 deletions

View File

@ -512,25 +512,13 @@ static int nrf5_protect_check(struct flash_bank *bank)
return ERROR_OK;
}
static int nrf5_protect(struct flash_bank *bank, int set, unsigned int first,
static int nrf5_protect_clenr0(struct flash_bank *bank, int set, unsigned int first,
unsigned int last)
{
int res;
uint32_t clenr0, ppfc;
struct nrf5_info *chip;
/* UICR cannot be write protected so just bail out early */
if (bank->base == NRF5_UICR_BASE)
return ERROR_FAIL;
res = nrf5_get_probed_chip_if_halted(bank, &chip);
if (res != ERROR_OK)
return res;
if (!(chip->features & NRF5_FEATURE_SERIES_51)) {
LOG_ERROR("Flash protection setting of this nRF device is not supported");
return ERROR_FLASH_OPER_UNSUPPORTED;
}
struct nrf5_bank *nbank = bank->driver_priv;
struct nrf5_info *chip = nbank->chip;
if (first != 0) {
LOG_ERROR("Code region 0 must start at the beginning of the bank");
@ -552,25 +540,61 @@ static int nrf5_protect(struct flash_bank *bank, int set, unsigned int first,
res = target_read_u32(chip->target, NRF51_UICR_CLENR0,
&clenr0);
if (res != ERROR_OK) {
LOG_ERROR("Couldn't read code region 0 size[UICR]");
LOG_ERROR("Couldn't read code region 0 size from UICR");
return res;
}
if (clenr0 == 0xFFFFFFFF) {
res = target_write_u32(chip->target, NRF51_UICR_CLENR0,
clenr0);
if (res != ERROR_OK) {
LOG_ERROR("Couldn't write code region 0 size[UICR]");
return res;
}
} else {
if (!set || clenr0 != 0xFFFFFFFF) {
LOG_ERROR("You need to perform chip erase before changing the protection settings");
return ERROR_FAIL;
}
res = nrf5_nvmc_write_enable(chip);
if (res != ERROR_OK)
goto error;
clenr0 = bank->sectors[last].offset + bank->sectors[last].size;
res = target_write_u32(chip->target, NRF51_UICR_CLENR0, clenr0);
int res2 = nrf5_wait_for_nvmc(chip);
if (res == ERROR_OK)
res = res2;
if (res == ERROR_OK)
LOG_INFO("A reset or power cycle is required for the new protection settings to take effect.");
else
LOG_ERROR("Couldn't write code region 0 size to UICR");
error:
nrf5_nvmc_read_only(chip);
nrf5_protect_check(bank);
return ERROR_OK;
return res;
}
static int nrf5_protect(struct flash_bank *bank, int set, unsigned int first,
unsigned int last)
{
int res;
struct nrf5_info *chip;
/* UICR cannot be write protected so just bail out early */
if (bank->base == NRF5_UICR_BASE) {
LOG_ERROR("UICR page does not support protection");
return ERROR_FLASH_OPER_UNSUPPORTED;
}
res = nrf5_get_probed_chip_if_halted(bank, &chip);
if (res != ERROR_OK)
return res;
if (chip->features & NRF5_FEATURE_SERIES_51)
return nrf5_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)