Skip to content
Permalink
Browse files

drives/flash: use nrfx for nrf

Introduce nrfx_nvmc driver into nordic flash driver implementation.
Thanks to that nrf9160 SoC becomes supported by the driver.

nrfx helps dealing with differences with interface to the NVMC
in secure and non-secure execution modes.

This patch adds NRFX_NVMC Kconfig entry for enabling nrfx_nvmc and
select it along with nordic flash driver.

Disabled UICR operation on nRF9160 for non-secure build
as UICR is not available in this mode.

Signed-off-by: Andrzej Puzdrowski <andrzej.puzdrowski@nordicsemi.no>
  • Loading branch information...
nvlsianpu authored and carlescufi committed Apr 1, 2019
1 parent c430670 commit 560b458a21bbf898c7402c8561e5c3aa9193333a
@@ -14,6 +14,7 @@ config SOC_FLASH_NRF
depends on SOC_FAMILY_NRF
select FLASH_HAS_PAGE_LAYOUT
select FLASH_HAS_DRIVER_ENABLED
select NRFX_NVMC
default y
help
Enables Nordic Semiconductor nRF flash driver.
@@ -27,7 +28,7 @@ config SOC_FLASH_NRF_RADIO_SYNC

config SOC_FLASH_NRF_UICR
bool "Access to UICR"
depends on SOC_FLASH_NRF
depends on SOC_FLASH_NRF && !TRUSTED_EXECUTION_NONSECURE
help
Enable operations on UICR. Once enabled UICR are written or read as
ordinary flash memory. Erase is possible for whole UICR at once.
@@ -14,6 +14,7 @@
#include <soc.h>
#include <flash.h>
#include <string.h>
#include <nrfx_nvmc.h>

#if defined(CONFIG_SOC_FLASH_NRF_RADIO_SYNC)
#include <misc/__assert.h>
@@ -76,6 +77,7 @@ static struct k_sem sem_lock;
#define SYNC_LOCK()
#define SYNC_UNLOCK()
#endif
static bool write_protect;

static int write(off_t addr, const void *data, size_t len);
static int erase(u32_t addr, u32_t size);
@@ -122,7 +124,7 @@ static inline bool is_addr_valid(off_t addr, size_t len)

static void nvmc_wait_ready(void)
{
while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {
while (!nrfx_nvmc_write_done_check()) {
;
}
}
@@ -148,6 +150,10 @@ static int flash_nrf_write(struct device *dev, off_t addr,
{
int ret;

if (write_protect) {
return -EACCES;
}

if (!is_addr_valid(addr, len)) {
return -EINVAL;
}
@@ -178,6 +184,10 @@ static int flash_nrf_erase(struct device *dev, off_t addr, size_t size)
u32_t n_pages = size / pg_size;
int ret;

if (write_protect) {
return -EACCES;
}

if (is_regular_addr_valid(addr, size)) {
/* Erase can only be done per page */
if (((addr % pg_size) != 0) || ((size % pg_size) != 0)) {
@@ -215,16 +225,8 @@ static int flash_nrf_erase(struct device *dev, off_t addr, size_t size)

static int flash_nrf_write_protection(struct device *dev, bool enable)
{
SYNC_LOCK();

if (enable) {
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;
} else {
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;
}
nvmc_wait_ready();

SYNC_UNLOCK();
/* virtual write-erase protection */
write_protect = enable;

return 0;
}
@@ -264,6 +266,7 @@ static int nrf_flash_init(struct device *dev)
dev_layout.pages_count = NRF_FICR->CODESIZE;
dev_layout.pages_size = NRF_FICR->CODEPAGESIZE;
#endif
write_protect = true;

return 0;
}
@@ -432,7 +435,6 @@ static int write_in_timeslice(off_t addr, const void *data, size_t len)

static int erase_op(void *context)
{
u32_t prev_nvmc_cfg = NRF_NVMC->CONFIG;
u32_t pg_size = NRF_FICR->CODEPAGESIZE;
struct flash_context *e_ctx = context;

@@ -446,23 +448,15 @@ static int erase_op(void *context)
}
#endif /* CONFIG_SOC_FLASH_NRF_RADIO_SYNC */

/* Erase uses a specific configuration register */
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een << NVMC_CONFIG_WEN_Pos;
nvmc_wait_ready();

#ifdef CONFIG_SOC_FLASH_NRF_UICR
if (e_ctx->flash_addr == (off_t)NRF_UICR) {
NRF_NVMC->ERASEUICR = 1;
nvmc_wait_ready();
NRF_NVMC->CONFIG = prev_nvmc_cfg;
nvmc_wait_ready();
(void)nrfx_nvmc_uicr_erase();
return FLASH_OP_DONE;
}
#endif

do {
NRF_NVMC->ERASEPAGE = e_ctx->flash_addr;
nvmc_wait_ready();
(void)nrfx_nvmc_page_erase(e_ctx->flash_addr);

e_ctx->len -= pg_size;
e_ctx->flash_addr += pg_size;
@@ -483,9 +477,6 @@ static int erase_op(void *context)

} while (e_ctx->len > 0);

NRF_NVMC->CONFIG = prev_nvmc_cfg;
nvmc_wait_ready();

return (e_ctx->len > 0) ? FLASH_OP_ONGOING : FLASH_OP_DONE;
}

@@ -499,8 +490,6 @@ static void shift_write_context(u32_t shift, struct flash_context *w_ctx)
static int write_op(void *context)
{
struct flash_context *w_ctx = context;
u32_t addr_word;
u32_t tmp_word;
u32_t count;

#if defined(CONFIG_SOC_FLASH_NRF_RADIO_SYNC)
@@ -513,23 +502,16 @@ static int write_op(void *context)
}
#endif /* CONFIG_SOC_FLASH_NRF_RADIO_SYNC */

/* Start with a word-aligned address and handle the offset */
addr_word = (u32_t)w_ctx->flash_addr & ~0x3;

/* If not aligned, read first word, update and write it back */
/* If not aligned, write unaligned beginning */
if (!is_aligned_32(w_ctx->flash_addr)) {
tmp_word = *(u32_t *)(addr_word);

count = sizeof(u32_t) - (w_ctx->flash_addr & 0x3);
if (count > w_ctx->len) {
count = w_ctx->len;
}

memcpy((u8_t *)&tmp_word + (w_ctx->flash_addr & 0x3),
(void *)w_ctx->data_addr,
count);
nvmc_wait_ready();
*(u32_t *)addr_word = tmp_word;
nrfx_nvmc_bytes_write(w_ctx->flash_addr,
(const void *)w_ctx->data_addr,
count);

shift_write_context(count, w_ctx);

@@ -549,9 +531,8 @@ static int write_op(void *context)

/* Write all the 4-byte aligned data */
while (w_ctx->len >= sizeof(u32_t)) {
nvmc_wait_ready();
*(u32_t *)w_ctx->flash_addr =
UNALIGNED_GET((u32_t *)w_ctx->data_addr);
nrfx_nvmc_word_write(w_ctx->flash_addr,
UNALIGNED_GET((u32_t *)w_ctx->data_addr));

shift_write_context(sizeof(u32_t), w_ctx);

@@ -571,12 +552,11 @@ static int write_op(void *context)
#endif /* CONFIG_SOC_FLASH_NRF_RADIO_SYNC */
}

/* Write remaining data */
/* Write remaining unaligned data */
if (w_ctx->len) {
tmp_word = *(u32_t *)(w_ctx->flash_addr);
memcpy((u8_t *)&tmp_word, (void *)w_ctx->data_addr, w_ctx->len);
nvmc_wait_ready();
*(u32_t *)w_ctx->flash_addr = tmp_word;
nrfx_nvmc_bytes_write(w_ctx->flash_addr,
(const void *)w_ctx->data_addr,
w_ctx->len);

shift_write_context(w_ctx->len, w_ctx);
}
@@ -34,6 +34,7 @@ if(CONFIG_HAS_NRFX)
zephyr_sources_ifdef(CONFIG_NRFX_DPPI nrfx/drivers/src/nrfx_dppi.c)
zephyr_sources_ifdef(CONFIG_NRFX_GPIOTE nrfx/drivers/src/nrfx_gpiote.c)
zephyr_sources_ifdef(CONFIG_NRFX_NFCT nrfx/drivers/src/nrfx_nfct.c)
zephyr_sources_ifdef(CONFIG_NRFX_NVMC nrfx/drivers/src/nrfx_nvmc.c)
zephyr_sources_ifdef(CONFIG_NRFX_PPI nrfx/drivers/src/nrfx_ppi.c)
zephyr_sources_ifdef(CONFIG_NRFX_PWM nrfx/drivers/src/nrfx_pwm.c)
zephyr_sources_ifdef(CONFIG_NRFX_QDEC nrfx/drivers/src/nrfx_qdec.c)
@@ -29,6 +29,9 @@ config NRFX_NFCT
bool
select NRFX_TIMER4

config NRFX_NVMC
bool

config NRFX_PPI
bool

@@ -391,8 +391,8 @@

// <e> NRFX_NVMC_ENABLED - nrfx_nvmc - NVMC peripheral driver
//==========================================================
#ifndef NRFX_NVMC_ENABLED
#define NRFX_NVMC_ENABLED 0
#ifdef CONFIG_NRFX_NVMC
#define NRFX_NVMC_ENABLED 1
#endif

// </e>
@@ -346,8 +346,8 @@

// <e> NRFX_NVMC_ENABLED - nrfx_nvmc - NVMC peripheral driver
//==========================================================
#ifndef NRFX_NVMC_ENABLED
#define NRFX_NVMC_ENABLED 0
#ifdef CONFIG_NRFX_NVMC
#define NRFX_NVMC_ENABLED 1
#endif

// </e>
@@ -743,8 +743,8 @@

// <e> NRFX_NVMC_ENABLED - nrfx_nvmc - NVMC peripheral driver
//==========================================================
#ifndef NRFX_NVMC_ENABLED
#define NRFX_NVMC_ENABLED 0
#ifdef CONFIG_NRFX_NVMC
#define NRFX_NVMC_ENABLED 1
#endif

// </e>
@@ -743,8 +743,8 @@

// <e> NRFX_NVMC_ENABLED - nrfx_nvmc - NVMC peripheral driver
//==========================================================
#ifndef NRFX_NVMC_ENABLED
#define NRFX_NVMC_ENABLED 0
#ifdef CONFIG_NRFX_NVMC
#define NRFX_NVMC_ENABLED 1
#endif

// </e>
@@ -615,8 +615,8 @@

// <e> NRFX_NVMC_ENABLED - nrfx_nvmc - NVMC peripheral driver
//==========================================================
#ifndef NRFX_NVMC_ENABLED
#define NRFX_NVMC_ENABLED 0
#ifdef CONFIG_NRFX_NVMC
#define NRFX_NVMC_ENABLED 1
#endif

// </e>

0 comments on commit 560b458

Please sign in to comment.
You can’t perform that action at this time.