This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 784c6519def arch/arm/nrf53: enable the application core flash cache
784c6519def is described below

commit 784c6519defd4092963068e948207c061523b036
Author: AlmAck <[email protected]>
AuthorDate: Sat Aug 29 19:02:05 2026 +0200

    arch/arm/nrf53: enable the application core flash cache
    
    The nRF5340 application core comes out of reset with its flash cache
    disabled and nothing in the tree turns it on.  nrf53_start() does call
    nrf53_enable_icache(), but that drives NVMC ICACHECNF and is gated on
    NRF53_FLASH_PREFETCH, which depends on NRF53_NETCORE -- so it is not
    even compiled for an application core build.
    
    The nRF5340 places the application core cache in a separate CACHE
    peripheral at 0x50001000.  NRF53_CACHE_BASE is already defined in
    hardware/nrf53_memorymap_cpuapp.h, but there was no register header and
    no enable.  Add both, behind a new NRF53_CACHE option.
    
    The option defaults to n, matching ARMV7M_ICACHE and
    ARMV8M_ICACHE/DCACHE, so that upgrading does not silently change the
    behaviour of an existing configuration.
    
    Measured on nrf5340-dk at 64 MHz with apps/benchmarks/scbench:
    
      protected-build syscall round trip   64.1 us -> 29.6 us
      userspace sem wait + post pair       4.75 us -> 1.95 us
    
    Flat builds benefit equally; the gain is on any flash-resident code
    path.
    
    Per the nRF5340 Product Specification, 'CACHE - Instruction and data
    cache', 'both instruction and data accesses towards flash memory or XIP
    code regions are cached'.  The cache does not observe NVMC programming,
    so nrf53_flash.c has to account for it: both up_progmem_eraseblock() and
    up_progmem_write() read back what they just programmed to verify it, and
    up_progmem_ispageerased() reads a whole page, so lines covering the
    region being programmed are commonly resident.  Bypass the cache for the
    duration of an erase or a write and invalidate it before re-enabling, so
    the verify reads the array and later readers do too.  That file is built
    only when NRF53_PROGMEM is selected, which is not the default.
    
    Signed-off-by: AlmAck <[email protected]>
---
 arch/arm/src/nrf53/Kconfig                | 17 ++++++++
 arch/arm/src/nrf53/hardware/nrf53_cache.h | 66 +++++++++++++++++++++++++++++++
 arch/arm/src/nrf53/nrf53_flash.c          | 41 +++++++++++++++++++
 arch/arm/src/nrf53/nrf53_start.c          | 11 ++++++
 4 files changed, 135 insertions(+)

diff --git a/arch/arm/src/nrf53/Kconfig b/arch/arm/src/nrf53/Kconfig
index 501bb2d375f..b1b28e039bd 100644
--- a/arch/arm/src/nrf53/Kconfig
+++ b/arch/arm/src/nrf53/Kconfig
@@ -445,6 +445,23 @@ endif # NRF53_SYSTIMER_RTC
 
 endmenu # System Timer
 
+config NRF53_CACHE
+       bool "Application core flash cache"
+       depends on NRF53_APPCORE
+       default n
+       ---help---
+               Enable the application core CACHE peripheral, which caches both
+               instruction and data accesses towards flash and XIP code 
regions.
+               The application core runs uncached without this, so enabling it 
is
+               a substantial speedup on any flash-resident code path.
+
+               The cache does not observe writes to the memory it caches. The
+               in-tree progmem driver handles this, but code outside the kernel
+               that programs flash, or a board that maps QSPI into the XIP
+               window and writes it, must invalidate the cache itself. Left off
+               by default for that reason, matching ARMV7M_ICACHE and
+               ARMV8M_ICACHE/DCACHE.
+
 config NRF53_FLASH_PREFETCH
        bool "Enable FLASH Pre-fetch"
        depends on NRF53_NETCORE
diff --git a/arch/arm/src/nrf53/hardware/nrf53_cache.h 
b/arch/arm/src/nrf53/hardware/nrf53_cache.h
new file mode 100644
index 00000000000..fb2197dd475
--- /dev/null
+++ b/arch/arm/src/nrf53/hardware/nrf53_cache.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+ * arch/arm/src/nrf53/hardware/nrf53_cache.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_NRF53_HARDWARE_NRF53_CACHE_H
+#define __ARCH_ARM_SRC_NRF53_HARDWARE_NRF53_CACHE_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include "hardware/nrf53_memorymap.h"
+
+/* The application core CACHE peripheral (flash instruction/data cache).
+ * Distinct from the nRF52-era NVMC ICACHECNF register, which does not
+ * exist on this part.
+ */
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Register offsets *********************************************************/
+
+#define NRF53_CACHE_ENABLE_OFFSET          0x500  /* Enable the cache */
+#define NRF53_CACHE_INVALIDATE_OFFSET      0x504  /* Invalidate the cache */
+#define NRF53_CACHE_INFO_OFFSET            0x508  /* Cache info */
+#define NRF53_CACHE_PROFILINGENABLE_OFFSET 0x518  /* Profiling enable */
+#define NRF53_CACHE_MODE_OFFSET            0x51c  /* Cache mode */
+
+/* Register addresses *******************************************************/
+
+#define NRF53_CACHE_ENABLE         (NRF53_CACHE_BASE + 
NRF53_CACHE_ENABLE_OFFSET)
+#define NRF53_CACHE_INVALIDATE     (NRF53_CACHE_BASE + 
NRF53_CACHE_INVALIDATE_OFFSET)
+#define NRF53_CACHE_INFO           (NRF53_CACHE_BASE + NRF53_CACHE_INFO_OFFSET)
+#define NRF53_CACHE_PROFILINGENABLE (NRF53_CACHE_BASE + 
NRF53_CACHE_PROFILINGENABLE_OFFSET)
+#define NRF53_CACHE_MODE           (NRF53_CACHE_BASE + NRF53_CACHE_MODE_OFFSET)
+
+/* ENABLE Register **********************************************************/
+
+#define CACHE_ENABLE_ENABLE        (1 << 0)  /* Enable cache */
+
+/* INVALIDATE Register ******************************************************/
+
+#define CACHE_INVALIDATE_INVALIDATE (1 << 0) /* Invalidate cache */
+
+#endif /* __ARCH_ARM_SRC_NRF53_HARDWARE_NRF53_CACHE_H */
diff --git a/arch/arm/src/nrf53/nrf53_flash.c b/arch/arm/src/nrf53/nrf53_flash.c
index bf795c255be..f8efaa1bff8 100644
--- a/arch/arm/src/nrf53/nrf53_flash.c
+++ b/arch/arm/src/nrf53/nrf53_flash.c
@@ -36,6 +36,9 @@
 
 #include "hardware/nrf53_ficr.h"
 #include "hardware/nrf53_nvmc.h"
+#ifdef CONFIG_NRF53_CACHE
+#  include "hardware/nrf53_cache.h"
+#endif
 
 /****************************************************************************
  * Pre-processor Definitions
@@ -64,6 +67,35 @@ static inline uint32_t nrf53_get_pages_num(void)
   return getreg32(NRF53_FICR_INFO_CODESIZE);
 }
 
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/* The CACHE peripheral caches both instruction and data accesses towards
+ * flash, and does not observe NVMC programming.  A line held from before an
+ * erase or a write would otherwise satisfy the read-back that both paths use
+ * to verify what they just programmed -- up_progmem_ispageerased() reads a
+ * whole page, so the lines are commonly resident.
+ *
+ * Bypass the cache for the duration of the operation so the verify sees the
+ * array, then invalidate before re-enabling so later readers do too.
+ */
+
+static void nrf53_flash_cache_bypass(void)
+{
+#ifdef CONFIG_NRF53_CACHE
+  putreg32(0, NRF53_CACHE_ENABLE);
+#endif
+}
+
+static void nrf53_flash_cache_restore(void)
+{
+#ifdef CONFIG_NRF53_CACHE
+  putreg32(CACHE_INVALIDATE_INVALIDATE, NRF53_CACHE_INVALIDATE);
+  putreg32(CACHE_ENABLE_ENABLE, NRF53_CACHE_ENABLE);
+#endif
+}
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -212,6 +244,8 @@ ssize_t up_progmem_eraseblock(size_t block)
 
   page_address = up_progmem_getaddress(block);
 
+  nrf53_flash_cache_bypass();
+
   /* Enable erase mode */
 
   putreg32(NVMC_CONFIG_EEN, NRF53_NVMC_CONFIG);
@@ -244,10 +278,12 @@ ssize_t up_progmem_eraseblock(size_t block)
 
   if (up_progmem_ispageerased(block) == 0)
     {
+      nrf53_flash_cache_restore();
       return up_progmem_erasesize(block);
     }
   else
     {
+      nrf53_flash_cache_restore();
       return -EIO;
     }
 }
@@ -344,6 +380,8 @@ ssize_t up_progmem_write(size_t addr, const void *buf, 
size_t count)
 
   addr += NRF53_FLASH_BASE;
 
+  nrf53_flash_cache_bypass();
+
   /* Begin flashing */
 
   for (; count; count -= 4, pword++, addr += 4)
@@ -378,10 +416,13 @@ ssize_t up_progmem_write(size_t addr, const void *buf, 
size_t count)
 
       if (getreg32(addr) != *pword)
         {
+          nrf53_flash_cache_restore();
           return -EIO;
         }
     }
 
+  nrf53_flash_cache_restore();
+
   return written;
 }
 
diff --git a/arch/arm/src/nrf53/nrf53_start.c b/arch/arm/src/nrf53/nrf53_start.c
index 32a11e6334a..d8ccc8e2492 100644
--- a/arch/arm/src/nrf53/nrf53_start.c
+++ b/arch/arm/src/nrf53/nrf53_start.c
@@ -38,6 +38,7 @@
 #include "nvic.h"
 
 #include "nrf53_clockconfig.h"
+#include "hardware/nrf53_cache.h"
 #include "hardware/nrf53_nvmc.h"
 #include "hardware/nrf53_utils.h"
 #include "hardware/nrf53_uicr.h"
@@ -253,6 +254,16 @@ void __start(void)
   nrf53_enable_profile(true);
 #endif
 
+#ifdef CONFIG_NRF53_CACHE
+  /* Enable the application core CACHE peripheral.  The nrf53_enable_icache()
+   * path above drives NVMC ICACHECNF and is gated on NRF53_FLASH_PREFETCH,
+   * which depends on NRF53_NETCORE, so nothing else enables a cache on the
+   * application core.
+   */
+
+  putreg32(CACHE_ENABLE_ENABLE, NRF53_CACHE_ENABLE);
+#endif
+
 #ifdef CONFIG_ARCH_PERF_EVENTS
   up_perf_init((void *)BOARD_SYSTICK_CLOCK);
 #endif

Reply via email to