You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by je...@apache.org on 2020/10/22 06:24:36 UTC
[mynewt-core] branch master updated: 64KB block and chip erase for
Nordic nrf52 QSPI
This is an automated email from the ASF dual-hosted git repository.
jerzy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
The following commit(s) were added to refs/heads/master by this push:
new a285812 64KB block and chip erase for Nordic nrf52 QSPI
a285812 is described below
commit a2858122bdef03bf57f2208d9550fcd0de961985
Author: Mike Voytovich <mi...@rokkresearch.com>
AuthorDate: Sat Aug 29 18:37:54 2020 -0700
64KB block and chip erase for Nordic nrf52 QSPI
Without a hff_erase implementation for HAL flash functions,
the HAL flash layer will default to sector erase for all
erase functions, regardless of length.
This change implements hff_erase, and will issue a chip erase
or 64KB block erase where possible based on the address and
length of area to be erased.
On the nRF52840 DK (PCA10056) using the provided MX25R6435F QSPI
flash, I measured a 4K sector erase of about 84 mS. With this
patch, a 64KB block erase averages about 1164 mS. This saves
about 176 mS per 64K erase.
---
hw/mcu/nordic/nrf52xxx/src/hal_qspi.c | 103 +++++++++++++++++++++++++---------
1 file changed, 77 insertions(+), 26 deletions(-)
diff --git a/hw/mcu/nordic/nrf52xxx/src/hal_qspi.c b/hw/mcu/nordic/nrf52xxx/src/hal_qspi.c
index 57b32e2..88769e8 100644
--- a/hw/mcu/nordic/nrf52xxx/src/hal_qspi.c
+++ b/hw/mcu/nordic/nrf52xxx/src/hal_qspi.c
@@ -66,25 +66,29 @@
static int
nrf52k_qspi_read(const struct hal_flash *dev, uint32_t address,
- void *dst, uint32_t num_bytes);
+ void *dst, uint32_t num_bytes);
static int
nrf52k_qspi_write(const struct hal_flash *dev, uint32_t address,
- const void *src, uint32_t num_bytes);
+ const void *src, uint32_t num_bytes);
static int
nrf52k_qspi_erase_sector(const struct hal_flash *dev,
- uint32_t sector_address);
+ uint32_t sector_address);
static int
nrf52k_qspi_sector_info(const struct hal_flash *dev, int idx,
- uint32_t *address, uint32_t *sz);
+ uint32_t *address, uint32_t *sz);
static int
nrf52k_qspi_init(const struct hal_flash *dev);
+static int
+nrf52k_qspi_erase(const struct hal_flash *dev, uint32_t address,
+ uint32_t size);
static const struct hal_flash_funcs nrf52k_qspi_funcs = {
.hff_read = nrf52k_qspi_read,
.hff_write = nrf52k_qspi_write,
.hff_erase_sector = nrf52k_qspi_erase_sector,
.hff_sector_info = nrf52k_qspi_sector_info,
- .hff_init = nrf52k_qspi_init
+ .hff_init = nrf52k_qspi_init,
+ .hff_erase = nrf52k_qspi_erase
};
const struct hal_flash nrf52k_qspi_dev = {
@@ -98,7 +102,8 @@ const struct hal_flash nrf52k_qspi_dev = {
static int
nrf52k_qspi_read(const struct hal_flash *dev, uint32_t address,
- void *dst, uint32_t num_bytes) {
+ void *dst, uint32_t num_bytes)
+{
uint32_t ram_buffer[4];
uint8_t *ram_ptr = NULL;
uint32_t read_bytes;
@@ -149,7 +154,7 @@ nrf52k_qspi_read(const struct hal_flash *dev, uint32_t address,
static int
nrf52k_qspi_write(const struct hal_flash *dev, uint32_t address,
- const void *src, uint32_t num_bytes)
+ const void *src, uint32_t num_bytes)
{
uint32_t ram_buffer[4];
uint8_t *ram_ptr = NULL;
@@ -162,7 +167,7 @@ nrf52k_qspi_write(const struct hal_flash *dev, uint32_t address,
while (num_bytes != 0) {
page_limit = (address & ~(MYNEWT_VAL(QSPI_FLASH_PAGE_SIZE) - 1)) +
- MYNEWT_VAL(QSPI_FLASH_PAGE_SIZE);
+ MYNEWT_VAL(QSPI_FLASH_PAGE_SIZE);
/*
* Use RAM buffer if src or address is not 4 bytes aligned,
* or number of bytes to write is less then 4
@@ -218,30 +223,76 @@ nrf52k_qspi_write(const struct hal_flash *dev, uint32_t address,
return 0;
}
+static void
+erase_block(uint32_t starting_address,
+ nrf_qspi_erase_len_t block_size_type)
+{
+ while ((NRF_QSPI->STATUS & QSPI_STATUS_READY_Msk) == 0)
+ ;
+ NRF_QSPI->EVENTS_READY = 0;
+ NRF_QSPI->ERASE.PTR = starting_address;
+ NRF_QSPI->ERASE.LEN = block_size_type;
+ NRF_QSPI->TASKS_ERASESTART = 1;
+ while (NRF_QSPI->EVENTS_READY == 0)
+ ;
+
+}
+
static int
nrf52k_qspi_erase_sector(const struct hal_flash *dev,
- uint32_t sector_address)
+ uint32_t sector_address)
{
int8_t erases;
erases = MYNEWT_VAL(QSPI_FLASH_SECTOR_SIZE) / 4096;
while (erases-- > 0) {
- while ((NRF_QSPI->STATUS & QSPI_STATUS_READY_Msk) == 0)
- ;
- NRF_QSPI->EVENTS_READY = 0;
- NRF_QSPI->ERASE.PTR = sector_address;
- NRF_QSPI->ERASE.LEN = NRF_QSPI_ERASE_LEN_4KB;
- NRF_QSPI->TASKS_ERASESTART = 1;
- while (NRF_QSPI->EVENTS_READY == 0)
- ;
+ erase_block(sector_address, NRF_QSPI_ERASE_LEN_4KB);
sector_address += 4096;
}
+
+ return 0;
+}
+
+static int
+nrf52k_qspi_erase(const struct hal_flash *dev, uint32_t address,
+ uint32_t size)
+{
+
+ uint32_t end;
+
+ address &= ~0xFFFU;
+ end = address + size;
+
+ if (end == MYNEWT_VAL(QSPI_FLASH_SECTOR_COUNT) *
+ MYNEWT_VAL(QSPI_FLASH_SECTOR_SIZE)) {
+ erase_block(0, NRF_QSPI_ERASE_LEN_ALL);
+ return 0;
+ }
+
+ while (size) {
+ if ((address & 0xFFFFU) == 0 && (size >= 0x10000)) {
+ /* 64 KB erase if possible */
+ erase_block(address, NRF_QSPI_ERASE_LEN_64KB);
+ address += 0x10000;
+ size -= 0x10000;
+ continue;
+ }
+
+ erase_block(address, NRF_QSPI_ERASE_LEN_4KB);
+ address += 0x1000;
+ if (size > 0x1000) {
+ size -= 0x1000;
+ } else {
+ size = 0;
+ }
+ }
+
return 0;
}
static int
nrf52k_qspi_sector_info(const struct hal_flash *dev, int idx,
- uint32_t *address, uint32_t *sz)
+ uint32_t *address, uint32_t *sz)
{
*address = idx * MYNEWT_VAL(QSPI_FLASH_SECTOR_SIZE);
*sz = MYNEWT_VAL(QSPI_FLASH_SECTOR_SIZE);
@@ -253,16 +304,16 @@ static int
nrf52k_qspi_init(const struct hal_flash *dev)
{
const nrf_qspi_prot_conf_t config0 = {
- .readoc = MYNEWT_VAL(QSPI_READOC),
- .writeoc = MYNEWT_VAL(QSPI_WRITEOC),
- .addrmode = MYNEWT_VAL(QSPI_ADDRMODE),
- .dpmconfig = MYNEWT_VAL(QSPI_DPMCONFIG)
+ .readoc = MYNEWT_VAL(QSPI_READOC),
+ .writeoc = MYNEWT_VAL(QSPI_WRITEOC),
+ .addrmode = MYNEWT_VAL(QSPI_ADDRMODE),
+ .dpmconfig = MYNEWT_VAL(QSPI_DPMCONFIG)
};
const nrf_qspi_phy_conf_t config1 = {
- .sck_delay = MYNEWT_VAL(QSPI_SCK_DELAY),
- .dpmen = 0,
- .spi_mode = MYNEWT_VAL(QSPI_SPI_MODE),
- .sck_freq = MYNEWT_VAL(QSPI_SCK_FREQ),
+ .sck_delay = MYNEWT_VAL(QSPI_SCK_DELAY),
+ .dpmen = 0,
+ .spi_mode = MYNEWT_VAL(QSPI_SPI_MODE),
+ .sck_freq = MYNEWT_VAL(QSPI_SCK_FREQ),
};
/*
* Configure pins