NRF51_UICR_BASE = 0x10001000, /* User Information
* Configuration Regsters */
- NRF51_UICR_SIZE = 252,
+ NRF51_UICR_SIZE = 0x100,
#define NRF51_UICR_REG(offset) (NRF51_UICR_BASE + offset)
0x00000001);
}
-static int nrf51_erase_page(struct nrf51_info *chip, struct flash_sector *sector)
+static int nrf51_erase_page(struct flash_bank *bank,
+ struct nrf51_info *chip,
+ struct flash_sector *sector)
{
int res;
if (sector->is_protected)
return ERROR_FAIL;
- if (sector->offset == NRF51_UICR_BASE) {
+ if (bank->base == NRF51_UICR_BASE) {
uint32_t ppfc;
res = target_read_u32(chip->target, NRF51_FICR_PPFC,
&ppfc);
}
if ((ppfc & 0xFF) == 0xFF) {
+ /* We can't erase the UICR. Double-check to
+ see if it's already erased before complaining. */
+ default_flash_blank_check(bank);
+ if (sector->is_erased == 1)
+ return ERROR_OK;
+
LOG_ERROR("The chip was not pre-programmed with SoftDevice stack and UICR cannot be erased separately. Please issue mass erase before trying to write to this region");
return ERROR_FAIL;
};
return res;
}
+static int nrf51_ll_flash_write(struct nrf51_info *chip, uint32_t offset, const uint8_t *buffer, uint32_t buffer_size)
+{
+ int res;
+ assert(buffer_size % 4 == 0);
+
+ for (; buffer_size > 0; buffer_size -= 4) {
+ res = target_write_memory(chip->target, offset, 4, 1, buffer);
+ if (res != ERROR_OK)
+ return res;
+
+ res = nrf51_wait_for_nvmc(chip);
+ if (res != ERROR_OK)
+ return res;
+
+ offset += 4;
+ buffer += 4;
+ }
+
+ return ERROR_OK;
+}
+
static int nrf51_write_page(struct flash_bank *bank, uint32_t offset, const uint8_t *buffer)
{
assert(offset % 4 == 0);
-
int res = ERROR_FAIL;
struct nrf51_info *chip = bank->driver_priv;
struct flash_sector *sector = nrf51_find_sector_by_address(bank, offset);
if (!sector)
- goto error;
+ return ERROR_FLASH_SECTOR_INVALID;
if (sector->is_protected)
goto error;
- if (!sector->is_erased) {
- res = nrf51_erase_page(chip, sector);
+ if (sector->is_erased != 1) {
+ res = nrf51_erase_page(bank, chip, sector);
if (res != ERROR_OK) {
LOG_ERROR("Failed to erase sector @ 0x%08"PRIx32, sector->offset);
goto error;
goto error;
sector->is_erased = 0;
- res = target_write_memory(bank->target, offset, 4,
- chip->code_page_size / 4, buffer);
+
+ res = nrf51_ll_flash_write(chip, offset, buffer, chip->code_page_size);
if (res != ERROR_OK)
goto set_read_only;
/* For each sector to be erased */
for (int s = first; s <= last && res == ERROR_OK; s++)
- res = nrf51_erase_page(chip, &bank->sectors[s]);
+ res = nrf51_erase_page(bank, chip, &bank->sectors[s]);
return res;
}
if (res != ERROR_OK)
return res;
- if (!sector->is_erased) {
- res = nrf51_erase_page(chip, sector);
+ if (sector->is_erased != 1) {
+ res = nrf51_erase_page(bank, chip, sector);
if (res != ERROR_OK)
return res;
}
memcpy(&uicr[offset], buffer, count);
- res = target_write_memory(bank->target,
- NRF51_UICR_BASE,
- 4,
- NRF51_UICR_SIZE / 4,
- uicr);
+ res = nrf51_ll_flash_write(chip, NRF51_UICR_BASE, uicr, NRF51_UICR_SIZE);
if (res != ERROR_OK) {
nrf51_nvmc_read_only(chip);
return res;
if (res != ERROR_OK)
return res;
- struct {
- uint32_t address, value;
+ static struct {
+ const uint32_t address;
+ uint32_t value;
} ficr[] = {
{ .address = NRF51_FICR_CODEPAGESIZE },
{ .address = NRF51_FICR_CODESIZE },