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 <gluca86@gmail.com>
This commit is contained in:
AlmAck 2026-08-29 19:02:05 +02:00 committed by Alan C. Assis
parent b75b93fd32
commit 784c6519de
4 changed files with 135 additions and 0 deletions

View file

@ -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

View file

@ -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 */

View file

@ -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;
}

View file

@ -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