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:
parent
d3203dc70d
commit
ac6060f966
8 changed files with 173 additions and 2 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
CONFIG_NRFX_QSPI=y
|
||||
CONFIG_GPIO=y
|
||||
CONFIG_NRF_ENABLE_CACHE=n
|
|
@ -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);
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue