Skip to content

Commit 34f4aa3

Browse files
committed
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>
1 parent f9bf75a commit 34f4aa3

4 files changed

Lines changed: 135 additions & 0 deletions

File tree

arch/arm/src/nrf53/Kconfig

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,23 @@ endif # NRF53_SYSTIMER_RTC
445445

446446
endmenu # System Timer
447447

448+
config NRF53_CACHE
449+
bool "Application core flash cache"
450+
depends on NRF53_APPCORE
451+
default n
452+
---help---
453+
Enable the application core CACHE peripheral, which caches both
454+
instruction and data accesses towards flash and XIP code regions.
455+
The application core runs uncached without this, so enabling it is
456+
a substantial speedup on any flash-resident code path.
457+
458+
The cache does not observe writes to the memory it caches. The
459+
in-tree progmem driver handles this, but code outside the kernel
460+
that programs flash, or a board that maps QSPI into the XIP
461+
window and writes it, must invalidate the cache itself. Left off
462+
by default for that reason, matching ARMV7M_ICACHE and
463+
ARMV8M_ICACHE/DCACHE.
464+
448465
config NRF53_FLASH_PREFETCH
449466
bool "Enable FLASH Pre-fetch"
450467
depends on NRF53_NETCORE
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/****************************************************************************
2+
* arch/arm/src/nrf53/hardware/nrf53_cache.h
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Licensed to the Apache Software Foundation (ASF) under one or more
7+
* contributor license agreements. See the NOTICE file distributed with
8+
* this work for additional information regarding copyright ownership. The
9+
* ASF licenses this file to you under the Apache License, Version 2.0 (the
10+
* "License"); you may not use this file except in compliance with the
11+
* License. You may obtain a copy of the License at
12+
*
13+
* http://www.apache.org/licenses/LICENSE-2.0
14+
*
15+
* Unless required by applicable law or agreed to in writing, software
16+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
18+
* License for the specific language governing permissions and limitations
19+
* under the License.
20+
*
21+
****************************************************************************/
22+
23+
#ifndef __ARCH_ARM_SRC_NRF53_HARDWARE_NRF53_CACHE_H
24+
#define __ARCH_ARM_SRC_NRF53_HARDWARE_NRF53_CACHE_H
25+
26+
/****************************************************************************
27+
* Included Files
28+
****************************************************************************/
29+
30+
#include <nuttx/config.h>
31+
#include "hardware/nrf53_memorymap.h"
32+
33+
/* The application core CACHE peripheral (flash instruction/data cache).
34+
* Distinct from the nRF52-era NVMC ICACHECNF register, which does not
35+
* exist on this part.
36+
*/
37+
38+
/****************************************************************************
39+
* Pre-processor Definitions
40+
****************************************************************************/
41+
42+
/* Register offsets *********************************************************/
43+
44+
#define NRF53_CACHE_ENABLE_OFFSET 0x500 /* Enable the cache */
45+
#define NRF53_CACHE_INVALIDATE_OFFSET 0x504 /* Invalidate the cache */
46+
#define NRF53_CACHE_INFO_OFFSET 0x508 /* Cache info */
47+
#define NRF53_CACHE_PROFILINGENABLE_OFFSET 0x518 /* Profiling enable */
48+
#define NRF53_CACHE_MODE_OFFSET 0x51c /* Cache mode */
49+
50+
/* Register addresses *******************************************************/
51+
52+
#define NRF53_CACHE_ENABLE (NRF53_CACHE_BASE + NRF53_CACHE_ENABLE_OFFSET)
53+
#define NRF53_CACHE_INVALIDATE (NRF53_CACHE_BASE + NRF53_CACHE_INVALIDATE_OFFSET)
54+
#define NRF53_CACHE_INFO (NRF53_CACHE_BASE + NRF53_CACHE_INFO_OFFSET)
55+
#define NRF53_CACHE_PROFILINGENABLE (NRF53_CACHE_BASE + NRF53_CACHE_PROFILINGENABLE_OFFSET)
56+
#define NRF53_CACHE_MODE (NRF53_CACHE_BASE + NRF53_CACHE_MODE_OFFSET)
57+
58+
/* ENABLE Register **********************************************************/
59+
60+
#define CACHE_ENABLE_ENABLE (1 << 0) /* Enable cache */
61+
62+
/* INVALIDATE Register ******************************************************/
63+
64+
#define CACHE_INVALIDATE_INVALIDATE (1 << 0) /* Invalidate cache */
65+
66+
#endif /* __ARCH_ARM_SRC_NRF53_HARDWARE_NRF53_CACHE_H */

arch/arm/src/nrf53/nrf53_flash.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@
3636

3737
#include "hardware/nrf53_ficr.h"
3838
#include "hardware/nrf53_nvmc.h"
39+
#ifdef CONFIG_NRF53_CACHE
40+
# include "hardware/nrf53_cache.h"
41+
#endif
3942

4043
/****************************************************************************
4144
* Pre-processor Definitions
@@ -64,6 +67,35 @@ static inline uint32_t nrf53_get_pages_num(void)
6467
return getreg32(NRF53_FICR_INFO_CODESIZE);
6568
}
6669

70+
/****************************************************************************
71+
* Private Functions
72+
****************************************************************************/
73+
74+
/* The CACHE peripheral caches both instruction and data accesses towards
75+
* flash, and does not observe NVMC programming. A line held from before an
76+
* erase or a write would otherwise satisfy the read-back that both paths use
77+
* to verify what they just programmed -- up_progmem_ispageerased() reads a
78+
* whole page, so the lines are commonly resident.
79+
*
80+
* Bypass the cache for the duration of the operation so the verify sees the
81+
* array, then invalidate before re-enabling so later readers do too.
82+
*/
83+
84+
static void nrf53_flash_cache_bypass(void)
85+
{
86+
#ifdef CONFIG_NRF53_CACHE
87+
putreg32(0, NRF53_CACHE_ENABLE);
88+
#endif
89+
}
90+
91+
static void nrf53_flash_cache_restore(void)
92+
{
93+
#ifdef CONFIG_NRF53_CACHE
94+
putreg32(CACHE_INVALIDATE_INVALIDATE, NRF53_CACHE_INVALIDATE);
95+
putreg32(CACHE_ENABLE_ENABLE, NRF53_CACHE_ENABLE);
96+
#endif
97+
}
98+
6799
/****************************************************************************
68100
* Public Functions
69101
****************************************************************************/
@@ -212,6 +244,8 @@ ssize_t up_progmem_eraseblock(size_t block)
212244

213245
page_address = up_progmem_getaddress(block);
214246

247+
nrf53_flash_cache_bypass();
248+
215249
/* Enable erase mode */
216250

217251
putreg32(NVMC_CONFIG_EEN, NRF53_NVMC_CONFIG);
@@ -244,10 +278,12 @@ ssize_t up_progmem_eraseblock(size_t block)
244278

245279
if (up_progmem_ispageerased(block) == 0)
246280
{
281+
nrf53_flash_cache_restore();
247282
return up_progmem_erasesize(block);
248283
}
249284
else
250285
{
286+
nrf53_flash_cache_restore();
251287
return -EIO;
252288
}
253289
}
@@ -344,6 +380,8 @@ ssize_t up_progmem_write(size_t addr, const void *buf, size_t count)
344380

345381
addr += NRF53_FLASH_BASE;
346382

383+
nrf53_flash_cache_bypass();
384+
347385
/* Begin flashing */
348386

349387
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)
378416

379417
if (getreg32(addr) != *pword)
380418
{
419+
nrf53_flash_cache_restore();
381420
return -EIO;
382421
}
383422
}
384423

424+
nrf53_flash_cache_restore();
425+
385426
return written;
386427
}
387428

arch/arm/src/nrf53/nrf53_start.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "nvic.h"
3939

4040
#include "nrf53_clockconfig.h"
41+
#include "hardware/nrf53_cache.h"
4142
#include "hardware/nrf53_nvmc.h"
4243
#include "hardware/nrf53_utils.h"
4344
#include "hardware/nrf53_uicr.h"
@@ -253,6 +254,16 @@ void __start(void)
253254
nrf53_enable_profile(true);
254255
#endif
255256

257+
#ifdef CONFIG_NRF53_CACHE
258+
/* Enable the application core CACHE peripheral. The nrf53_enable_icache()
259+
* path above drives NVMC ICACHECNF and is gated on NRF53_FLASH_PREFETCH,
260+
* which depends on NRF53_NETCORE, so nothing else enables a cache on the
261+
* application core.
262+
*/
263+
264+
putreg32(CACHE_ENABLE_ENABLE, NRF53_CACHE_ENABLE);
265+
#endif
266+
256267
#ifdef CONFIG_ARCH_PERF_EVENTS
257268
up_perf_init((void *)BOARD_SYSTICK_CLOCK);
258269
#endif

0 commit comments

Comments
 (0)