drivers/flash/nrfx: Enable partial erase of flash
When enabled, instead of erasing entire flash page at once, page will be erased in defined time slices. Erasing single page stalls CPU for significant time share (~80ms) and partial erase divides the operation in to the shorter time periods, resuming CPU operation in meantime and enabling better scheduling of time sensitive operations. Signed-off-by: Dominik Ermel <dominik.ermel@nordicsemi.no>
This commit is contained in:
parent
6aaad93e6f
commit
143f9bfd4e
6 changed files with 78 additions and 7 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue