diff --git a/drivers/flash/Kconfig.nrf b/drivers/flash/Kconfig.nrf index 6aaa0178002..57ac4abf522 100644 --- a/drivers/flash/Kconfig.nrf +++ b/drivers/flash/Kconfig.nrf @@ -27,6 +27,29 @@ config SOC_FLASH_NRF_RADIO_SYNC help Enable synchronization between flash memory driver and radio. +config SOC_FLASH_NRF_PARTIAL_ERASE + bool "Nordic nRFx flash driver partial erase" + depends on HAS_HW_NRF_NVMC_PE + help + Enable partial erase feature. Partial erase is performed in time + slices instead of blocking MCU, for the time it is needed to + complete operation over given area. + This allows interrupting flash erase between operations + to perform other task by MCU. + This feature may also be used for better syncing flash erase + operations, when compiled with SOC_FLASH_NRF_RADIO_SYNC, + with Bluetooth. + +config SOC_FLASH_NRF_PARTIAL_ERASE_MS + int "Partial erase timeout in MS" + depends on SOC_FLASH_NRF_PARTIAL_ERASE + default 3 + help + This is maximum time, in ms, that NVMC will use to erase part + of Flash, before stopping to let CPU resume operation. + Minimal timeout is 2ms maximum should not exceed half of + FLASH_PAGE_ERASE_MAX_TIME_US im ms. + config SOC_FLASH_NRF_UICR bool "Access to UICR" depends on !TRUSTED_EXECUTION_NONSECURE diff --git a/drivers/flash/soc_flash_nrf.c b/drivers/flash/soc_flash_nrf.c index 7b62897ed75..04c6e7c09e8 100644 --- a/drivers/flash/soc_flash_nrf.c +++ b/drivers/flash/soc_flash_nrf.c @@ -26,18 +26,33 @@ #define FLASH_RADIO_ABORT_DELAY_US 1500 #define FLASH_RADIO_WORK_DELAY_US 200 -#define FLASH_SLOT_ERASE FLASH_PAGE_ERASE_MAX_TIME_US + #define FLASH_INTERVAL_ERASE (FLASH_RADIO_ABORT_DELAY_US + \ FLASH_RADIO_WORK_DELAY_US + \ FLASH_SLOT_ERASE) -#define FLASH_INTERVAL_WRITE 7500 #define FLASH_SLOT_WRITE (FLASH_INTERVAL_WRITE - \ FLASH_RADIO_ABORT_DELAY_US - \ FLASH_RADIO_WORK_DELAY_US) +#define FLASH_INTERVAL_WRITE 7500 + +#if defined(CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE) + +/* The timeout is multiplied by 1.5 because switching tasks may take + * significant portion of time. + */ +#define FLASH_TIMEOUT_MS ((FLASH_PAGE_ERASE_MAX_TIME_US) * \ + (FLASH_PAGE_MAX_CNT) / 1000 * 15 / 10) +#define FLASH_SLOT_ERASE (MAX(CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE_MS * 1000, \ + 7500)) +#else + +#define FLASH_TIMEOUT_MS ((FLASH_PAGE_ERASE_MAX_TIME_US) * \ + (FLASH_PAGE_MAX_CNT) / 1000) +#define FLASH_SLOT_ERASE FLASH_PAGE_ERASE_MAX_TIME_US + +#endif /* CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE */ -#define FLASH_TIMEOUT_MS ((FLASH_PAGE_ERASE_MAX_TIME_US)\ - * (FLASH_PAGE_MAX_CNT) / 1000) #endif /* CONFIG_SOC_FLASH_NRF_RADIO_SYNC */ #define FLASH_OP_DONE (0) /* 0 for compliance with the driver API. */ @@ -52,6 +67,9 @@ struct flash_context { u32_t interval; /* timeslot interval. */ u32_t slot; /* timeslot length. */ #endif /* CONFIG_SOC_FLASH_NRF_RADIO_SYNC */ +#if defined(CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE) + u32_t flash_addr_next; +#endif /* CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE */ }; /*< Context type for f. @ref write_op @ref erase_op */ #if defined(CONFIG_SOC_FLASH_NRF_RADIO_SYNC) @@ -426,7 +444,10 @@ static int erase_in_timeslice(u32_t addr, u32_t size) .len = size, .enable_time_limit = 1, /* enable time limit */ .interval = FLASH_INTERVAL_ERASE, - .slot = FLASH_SLOT_ERASE + .slot = FLASH_SLOT_ERASE, +#if defined(CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE) + .flash_addr_next = addr +#endif }; struct flash_op_desc flash_op_desc = { @@ -481,10 +502,23 @@ static int erase_op(void *context) #endif do { - (void)nrfx_nvmc_page_erase(e_ctx->flash_addr); +#if defined(CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE) + if (e_ctx->flash_addr == e_ctx->flash_addr_next) { + nrfx_nvmc_page_partial_erase_init(e_ctx->flash_addr, + CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE_MS); + e_ctx->flash_addr_next += pg_size; + } + + if (nrfx_nvmc_page_partial_erase_continue()) { + e_ctx->len -= pg_size; + e_ctx->flash_addr += pg_size; + } +#else + (void)nrfx_nvmc_page_erase(e_ctx->flash_addr); e_ctx->len -= pg_size; e_ctx->flash_addr += pg_size; +#endif /* CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE */ #if defined(CONFIG_SOC_FLASH_NRF_RADIO_SYNC) i++; @@ -597,8 +631,11 @@ static int erase(u32_t addr, u32_t size) .flash_addr = addr, .len = size, #if defined(CONFIG_SOC_FLASH_NRF_RADIO_SYNC) - .enable_time_limit = 0 /* disable time limit */ + .enable_time_limit = 0, /* disable time limit */ #endif /* CONFIG_SOC_FLASH_NRF_RADIO_SYNC */ +#if defined(CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE) + .flash_addr_next = addr +#endif }; return erase_op(&context); diff --git a/soc/arm/nordic_nrf/Kconfig.peripherals b/soc/arm/nordic_nrf/Kconfig.peripherals index bc5606c0b1e..b29bd097fdd 100644 --- a/soc/arm/nordic_nrf/Kconfig.peripherals +++ b/soc/arm/nordic_nrf/Kconfig.peripherals @@ -78,6 +78,10 @@ config HAS_HW_NRF_MWU config HAS_HW_NRF_NFCT bool +# NVMC supports partial erase +config HAS_HW_NRF_NVMC_PE + bool + config HAS_HW_NRF_PDM bool diff --git a/soc/arm/nordic_nrf/nrf52/Kconfig.soc b/soc/arm/nordic_nrf/nrf52/Kconfig.soc index ce9c3abda1e..c3ab1d6cb56 100644 --- a/soc/arm/nordic_nrf/nrf52/Kconfig.soc +++ b/soc/arm/nordic_nrf/nrf52/Kconfig.soc @@ -15,6 +15,7 @@ config SOC_NRF52810 select HAS_HW_NRF_EGU1 select HAS_HW_NRF_GPIO0 select HAS_HW_NRF_GPIOTE + select HAS_HW_NRF_NVMC_PE select HAS_HW_NRF_PDM select HAS_HW_NRF_POWER select HAS_HW_NRF_PPI @@ -56,6 +57,7 @@ config SOC_NRF52811 select HAS_HW_NRF_EGU1 select HAS_HW_NRF_GPIO0 select HAS_HW_NRF_GPIOTE + select HAS_HW_NRF_NVMC_PE select HAS_HW_NRF_PDM select HAS_HW_NRF_POWER select HAS_HW_NRF_PPI @@ -179,6 +181,7 @@ config SOC_NRF52833 select HAS_HW_NRF_LPCOMP select HAS_HW_NRF_MWU select HAS_HW_NRF_NFCT + select HAS_HW_NRF_NVMC_PE select HAS_HW_NRF_PDM select HAS_HW_NRF_POWER select HAS_HW_NRF_PPI @@ -252,6 +255,7 @@ config SOC_NRF52840 select HAS_HW_NRF_LPCOMP select HAS_HW_NRF_MWU select HAS_HW_NRF_NFCT + select HAS_HW_NRF_NVMC_PE select HAS_HW_NRF_PDM select HAS_HW_NRF_POWER select HAS_HW_NRF_PPI diff --git a/soc/arm/nordic_nrf/nrf53/Kconfig.soc b/soc/arm/nordic_nrf/nrf53/Kconfig.soc index e3bc3498fd4..6817d17b7a6 100644 --- a/soc/arm/nordic_nrf/nrf53/Kconfig.soc +++ b/soc/arm/nordic_nrf/nrf53/Kconfig.soc @@ -25,6 +25,7 @@ config SOC_NRF5340_CPUAPP select HAS_HW_NRF_I2S select HAS_HW_NRF_IPC select HAS_HW_NRF_NFCT + select HAS_HW_NRF_NVMC_PE select HAS_HW_NRF_PDM select HAS_HW_NRF_POWER select HAS_HW_NRF_PWM0 @@ -75,6 +76,7 @@ config SOC_NRF5340_CPUNET select HAS_HW_NRF_GPIO1 select HAS_HW_NRF_GPIOTE select HAS_HW_NRF_IPC + select HAS_HW_NRF_NVMC_PE select HAS_HW_NRF_POWER select HAS_HW_NRF_RADIO_BLE_CODED select HAS_HW_NRF_RADIO_IEEE802154 diff --git a/soc/arm/nordic_nrf/nrf91/Kconfig.soc b/soc/arm/nordic_nrf/nrf91/Kconfig.soc index ab954bbff7c..333d1f92b51 100644 --- a/soc/arm/nordic_nrf/nrf91/Kconfig.soc +++ b/soc/arm/nordic_nrf/nrf91/Kconfig.soc @@ -19,6 +19,7 @@ config SOC_NRF9160 select HAS_HW_NRF_GPIOTE select HAS_HW_NRF_I2S select HAS_HW_NRF_IPC + select HAS_HW_NRF_NVMC_PE select HAS_HW_NRF_PDM select HAS_HW_NRF_POWER select HAS_HW_NRF_PWM0