code_relocation: Extend the nocopy sample to nRF5340dk

The nRF5340dk is shipping an external QSPI flash that can be used to do
XIP from. Extend the code_relocation nocopy sample to support this
platform so that part of the functions are executed from internal flash
and others from external flash.

Signed-off-by: Carlo Caione <ccaione@baylibre.com>
This commit is contained in:
Carlo Caione 2022-02-17 13:04:00 +01:00 committed by Anas Nashif
commit ac6060f966
8 changed files with 173 additions and 2 deletions

View file

@ -7,6 +7,7 @@ project(code_relocation_nocopy)
FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})
target_sources_ifdef(CONFIG_NRFX_QSPI app PRIVATE boards/nrf5340dk_nrf5340_cpuapp/ext_mem_init.c)
# Run ext_code from the external flash (XIP). No need to copy.
zephyr_code_relocate(src/ext_code.c EXTFLASH_TEXT NOCOPY)

View file

@ -11,3 +11,36 @@ using a custom linker script.
Differently from the code relocation sample, this sample is relocating the
content of the ext_code.c file to a different FLASH section and the code is XIP
directly from there without the need to copy / relocate the code.
nRF5340dk platform instructions
*******************************
The nRF5340 PDK has a 64 Mb external flash memory supporting Quad SPI. It is
possible to do XIP from the external flash memory.
The external flash memory is mapped to 0x10000000.
In this sample we relocate some of the code to the external flash memory with
the remaining Zephyr kernel in the internal flash.
Compile the code:
$ west build -b nrf5340dk_nrf5340_cpuapp samples/application_development/code_relocation_nocopy --pristine
Get the HEX file from the ELF:
$ arm-linux-gnueabihf-objcopy -O ihex build/zephyr/zephyr.elf zephyr.hex
Erase the external FLASH (just to be sure):
$ nrfjprog --qspicustominit --qspieraseall
Write the HEX to internal and external FLASH:
$ nrfjprog --coprocessor CP_APPLICATION --sectorerase --qspisectorerase --program zephyr.hex
Execution output:
*** Booting Zephyr OS build v3.0.0-rc3-25-g0df32cec1ff2 ***
Address of main function 0x4f9
Address of function_in_ext_flash 0x10000001
Address of var_ext_sram_data 0x200000a0 (10)
Address of function_in_sram 0x20000001
Address of var_sram_data 0x200000a4 (10)
Hello World! nrf5340dk_nrf5340_cpuapp

View file

@ -0,0 +1,3 @@
CONFIG_NRFX_QSPI=y
CONFIG_GPIO=y
CONFIG_NRF_ENABLE_CACHE=n

View file

@ -0,0 +1,112 @@
/*
* Copyright (c) 2022 Nordic Semiconductor ASA.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <errno.h>
#include <init.h>
#include <zephyr.h>
#include <device.h>
#include <nrfx_qspi.h>
#include <hal/nrf_clock.h>
#define QSPI_STD_CMD_WRSR 0x01
#define QSPI_STD_CMD_WRDI 0x04
#define QSPI_STD_CMD_RSTEN 0x66
#define QSPI_STD_CMD_RST 0x99
#define QSPI_NODE DT_NODELABEL(qspi)
#define QSPI_PROP_AT(prop, idx) DT_PROP_BY_IDX(QSPI_NODE, prop, idx)
static inline int qspi_get_zephyr_ret_code(nrfx_err_t res)
{
switch (res) {
case NRFX_SUCCESS:
return 0;
case NRFX_ERROR_INVALID_PARAM:
case NRFX_ERROR_INVALID_ADDR:
return -EINVAL;
case NRFX_ERROR_INVALID_STATE:
return -ECANCELED;
case NRFX_ERROR_BUSY:
case NRFX_ERROR_TIMEOUT:
default:
return -EBUSY;
}
}
static int qspi_ext_mem_init(const struct device *dev)
{
ARG_UNUSED(dev);
int ret;
nrf_clock_hfclk192m_div_set(NRF_CLOCK, NRF_CLOCK_HFCLK_DIV_1);
static nrfx_qspi_config_t qspi_config = {
.pins = {
.sck_pin = DT_PROP(QSPI_NODE, sck_pin),
.csn_pin = QSPI_PROP_AT(csn_pins, 0),
.io0_pin = QSPI_PROP_AT(io_pins, 0),
.io1_pin = QSPI_PROP_AT(io_pins, 1),
.io2_pin = QSPI_PROP_AT(io_pins, 2),
.io3_pin = QSPI_PROP_AT(io_pins, 3),
},
.irq_priority = NRFX_QSPI_DEFAULT_CONFIG_IRQ_PRIORITY,
.prot_if = {
.readoc = NRF_QSPI_READOC_READ4IO,
.writeoc = NRF_QSPI_WRITEOC_PP4IO,
.addrmode = NRF_QSPI_ADDRMODE_24BIT,
.dpmconfig = false
},
.phy_if = {
.sck_freq = 1,
.sck_delay = 0x05,
.spi_mode = NRF_QSPI_MODE_0,
.dpmen = false
}
};
nrfx_err_t res = nrfx_qspi_init(&qspi_config, NULL, NULL);
ret = qspi_get_zephyr_ret_code(res);
if (ret < 0) {
return ret;
}
/* Enable XiP */
nrf_qspi_xip_set(NRF_QSPI, true);
uint8_t temporary = 0x40;
nrf_qspi_cinstr_conf_t cinstr_cfg = {
.opcode = QSPI_STD_CMD_RSTEN,
.length = NRF_QSPI_CINSTR_LEN_1B,
.io2_level = true,
.io3_level = true,
.wipwait = true,
.wren = true
};
/* Send reset enable */
nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL);
/* Send reset command */
cinstr_cfg.opcode = QSPI_STD_CMD_RST;
nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL);
/* Switch to qspi mode and high performance */
cinstr_cfg.opcode = QSPI_STD_CMD_WRSR;
cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_2B;
nrfx_qspi_cinstr_xfer(&cinstr_cfg, &temporary, NULL);
/* Send write disable command */
cinstr_cfg.opcode = QSPI_STD_CMD_WRDI;
cinstr_cfg.wren = false;
cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_1B;
nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL);
return 0;
}
SYS_INIT(qspi_ext_mem_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS);

View file

@ -18,6 +18,19 @@
#include <linker/linker-defs.h>
#include <linker/linker-tool.h>
#if CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP
/*
* nRF5340dk is shipping a QSPI external flash mapped at 0x1000_0000 that can
* be used for XIP
*/
MEMORY
{
EXTFLASH (wx) : ORIGIN = 0x10000000, LENGTH = 0x800000
}
#else
/*
* Add another fake portion of FLASH to simulate a secondary or external FLASH
* that we can do XIP from.
@ -30,4 +43,6 @@ MEMORY
EXTFLASH (wx) : ORIGIN = 0x5000, LENGTH = EXTFLASH_SIZE
}
#endif /* CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP */
#include <arch/arm/aarch32/cortex_m/scripts/linker.ld>

View file

@ -3,3 +3,4 @@ CONFIG_HAVE_CUSTOM_LINKER_SCRIPT=y
CONFIG_CUSTOM_LINKER_SCRIPT="linker_arm_nocopy.ld"
CONFIG_COVERAGE=n
CONFIG_XIP=y
CONFIG_LOG=y

View file

@ -3,7 +3,7 @@ sample:
name: code relocation nocopy
tests:
sample.application_development.code_relocation_nocopy:
platform_allow: qemu_cortex_m3
platform_allow: qemu_cortex_m3 nrf5340dk_nrf5340_cpuapp
tags: linker
harness: console
harness_config:

View file

@ -27,12 +27,18 @@ void disable_mpu_rasr_xn(void)
*/
for (index = 0U; index < 8; index++) {
MPU->RNR = index;
#if defined(CONFIG_ARMV8_M_BASELINE) || defined(CONFIG_ARMV8_M_MAINLINE)
if (MPU->RBAR & MPU_RBAR_XN_Msk) {
MPU->RBAR ^= MPU_RBAR_XN_Msk;
}
#else
if (MPU->RASR & MPU_RASR_XN_Msk) {
MPU->RASR ^= MPU_RASR_XN_Msk;
}
#endif /* CONFIG_ARMV8_M_BASELINE || CONFIG_ARMV8_M_MAINLINE */
}
}
#endif /* CONFIG_ARM_MPU */
#endif /* CONFIG_ARM_MPU */
extern void function_in_ext_flash(void);
extern void function_in_sram(void);