diff --git a/arch/Kconfig b/arch/Kconfig index de365d9a26fe9..7d2623cb170b5 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -361,6 +361,14 @@ config NOCACHE_MEMORY transfers when cache coherence issues are not optimal or can not be solved using cache maintenance operations. +DT_CHOSEN_Z_NOCACHE_SRAM := zephyr,sram-no-cache + +config NOCACHE_SRAM_MEMORY_DEV_NAME + string "non-cacheable SRAM region" + default "$(dt_chosen_label,$(DT_CHOSEN_Z_NOCACHE_SRAM))" if HAS_DTS + help + Memory region used as non-cacheable memory pool. + menu "Interrupt Configuration" config DYNAMIC_INTERRUPTS diff --git a/dts/bindings/sram/mmio-sram.yaml b/dts/bindings/sram/mmio-sram.yaml index e9919806ea1c8..30a839d6206c4 100644 --- a/dts/bindings/sram/mmio-sram.yaml +++ b/dts/bindings/sram/mmio-sram.yaml @@ -13,3 +13,7 @@ properties: label: required: false + + mpu-attr: + required: false + type: int diff --git a/include/linker/devicetree_sram.h b/include/linker/devicetree_sram.h new file mode 100644 index 0000000000000..39d066330bae0 --- /dev/null +++ b/include/linker/devicetree_sram.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021, Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT mmio_sram + +#define _DT_SRAM_INST_NAME(inst) DT_STRING_TOKEN(DT_DRV_INST(inst), label) + +#define DT_INST_SRAM_PREFIX(inst) UTIL_CAT(__, _DT_SRAM_INST_NAME(inst)) +#define DT_INST_SRAM_START(inst) UTIL_CAT(DT_INST_SRAM_PREFIX(inst), _start) +#define DT_INST_SRAM_END(inst) UTIL_CAT(DT_INST_SRAM_PREFIX(inst), _end) + +#define _DEFINE_SRAM_REGION(inst, ...) \ + _DT_SRAM_INST_NAME(inst) : \ + ORIGIN = DT_INST_REG_ADDR(inst), \ + LENGTH = DT_INST_REG_SIZE(inst) + +#define _DEFINE_SRAM_SECTION(inst, ...) \ + SECTION_DATA_PROLOGUE(_DT_SRAM_INST_NAME(inst), (NOLOAD),) \ + { \ + DT_INST_SRAM_START(inst) = .; \ + KEEP(*(_DT_SRAM_INST_NAME(inst))) \ + KEEP(*(_DT_SRAM_INST_NAME(inst).*)) \ + DT_INST_SRAM_END(inst) = \ + DT_INST_SRAM_START(inst) + DT_INST_REG_SIZE(inst); \ + } GROUP_DATA_LINK_IN(_DT_SRAM_INST_NAME(inst), _DT_SRAM_INST_NAME(inst)) + +#define _CHECK_ATTR_FN(inst, FN, ...) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, mpu_attr), \ + (FN(inst, __VA_ARGS__)), \ + ()) + +#define _EXPAND_MPU_FN(inst, FN, ...) \ + FN(DT_INST_PROP(inst, label), \ + DT_INST_REG_ADDR(inst), \ + DT_INST_REG_SIZE(inst), \ + DT_INST_PROP(inst, mpu_attr)) + +#define _CHECK_APPLY_FN(FN, ...) \ + DT_INST_FOREACH_STATUS_OKAY_VARGS(_CHECK_ATTR_FN, FN, __VA_ARGS__) + + +/* Add the SRAM sections to the linker script */ +#define LINKER_DT_SRAM_SECTIONS() _CHECK_APPLY_FN(_DEFINE_SRAM_SECTION) + +/* Add the SRAM regions to the linker script */ +#define LINKER_DT_SRAM_REGIONS() _CHECK_APPLY_FN(_DEFINE_SRAM_REGION) + +/* + * Helper macro to apply an MPU_FN macro to all the SRAM regions declared with + * an 'mpu-attr' property. + * + * MPU_FN must take the form: + * + * #define MPU_FN(name, base, size, attr) ... + */ +#define DT_SRAM_INST_FOREACH(MPU_FN) _CHECK_APPLY_FN(_EXPAND_MPU_FN, MPU_FN) diff --git a/include/linker/section_tags.h b/include/linker/section_tags.h index 12b1378f8729c..dae9aa2311cab 100644 --- a/include/linker/section_tags.h +++ b/include/linker/section_tags.h @@ -45,6 +45,13 @@ #define __nocache #endif /* CONFIG_NOCACHE_MEMORY */ +#if defined(CONFIG_NOCACHE_SRAM_MEMORY_DEV_NAME) +/* Do not use Z_GENERIC_SECTION */ +#define __nocache_sram __attribute((__section__(CONFIG_NOCACHE_SRAM_MEMORY_DEV_NAME))) +#else +#define __nocache_sram +#endif /* CONFIG_NOCACHE_SRAM_MEMORY_DEV_NAME */ + #if defined(CONFIG_KERNEL_COHERENCE) #define __incoherent __in_section_unique(cached) #define __stackmem __incoherent diff --git a/include/linker/sections.h b/include/linker/sections.h index 0bab1b8a5956c..dd4e0f8583f92 100644 --- a/include/linker/sections.h +++ b/include/linker/sections.h @@ -72,6 +72,10 @@ #define _NOCACHE_SECTION_NAME nocache #endif +#ifdef CONFIG_NOCACHE_SRAM_MEMORY_DEV_NAME +#define _NOCACHE_SRAM_SECTION_NAME CONFIG_NOCACHE_SRAM_MEMORY_DEV_NAME +#endif + #if defined(CONFIG_LINKER_USE_BOOT_SECTION) #define BOOT_TEXT_SECTION_NAME boot_text #define BOOT_BSS_SECTION_NAME boot_bss diff --git a/samples/memory/sram_regions/CMakeLists.txt b/samples/memory/sram_regions/CMakeLists.txt new file mode 100644 index 0000000000000..776b0f23ece19 --- /dev/null +++ b/samples/memory/sram_regions/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(sram_mpu) + +target_sources(app PRIVATE src/main.c src/arm_mpu_regions.c) diff --git a/samples/memory/sram_regions/boards/dt_mpu_attr.h b/samples/memory/sram_regions/boards/dt_mpu_attr.h new file mode 100644 index 0000000000000..7ebaa5a38d67c --- /dev/null +++ b/samples/memory/sram_regions/boards/dt_mpu_attr.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021 Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifdef __DTS__ + +#define DT_256B (0x07U) +#define DT_512B (0x08U) +#define DT_1KB (0x09U) +#define DT_2KB (0x0aU) +#define DT_4KB (0x0bU) +#define DT_8KB (0x0cU) +#define DT_16KB (0x0dU) +#define DT_32KB (0x0eU) +#define DT_64KB (0x0fU) +#define DT_128KB (0x10U) +#define DT_256KB (0x11U) +#define DT_512KB (0x12U) +#define DT_1MB (0x13U) +#define DT_2MB (0x14U) +#define DT_4MB (0x15U) +#define DT_8MB (0x16U) +#define DT_16MB (0x17U) +#define DT_32MB (0x18U) +#define DT_64MB (0x19U) +#define DT_128MB (0x1aU) +#define DT_256MB (0x1bU) +#define DT_512MB (0x1cU) +#define DT_1GB (0x1dU) +#define DT_2GB (0x1eU) +#define DT_4GB (0x1fU) + +/* + * NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_SHAREABLE | + * MPU_RASR_XN_Msk | P_RW_U_NA_Msk + */ +#define DT_SRAM_ATTR(size) (0x110b0000 | size) + +/* + * NORMAL_OUTER_INNER_NON_CACHEABLE_NON_SHAREABLE | + * MPU_RASR_XN_Msk | P_RW_U_NA_Msk + */ +#define DT_SRAM_NOCACHE_ATTR(size) (0x11080000 | size) + +#endif /* __DTS__ */ diff --git a/samples/memory/sram_regions/boards/mps2_an385.overlay b/samples/memory/sram_regions/boards/mps2_an385.overlay new file mode 100644 index 0000000000000..5ea853d017ade --- /dev/null +++ b/samples/memory/sram_regions/boards/mps2_an385.overlay @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021 Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "dt_mpu_attr.h" + +/ { + /delete-node/ memory@20000000; + + chosen { + zephyr,sram-no-cache = &sram_no_cache; + }; + + sram0: memory@20000000 { + compatible = "mmio-sram"; + reg = <0x20000000 0x200000>; + }; + + sram_attr_0: memory@20200000 { + compatible = "mmio-sram"; + reg = <0x20200000 0x100000>; + mpu-attr = ; + label = "region0"; + }; + + sram_no_cache: memory@20300000 { + compatible = "mmio-sram"; + reg = <0x20300000 0x100000>; + mpu-attr = ; + label = "region1"; + }; +}; diff --git a/samples/memory/sram_regions/linker_sram_regions.ld b/samples/memory/sram_regions/linker_sram_regions.ld new file mode 100644 index 0000000000000..af6fa6a0850d0 --- /dev/null +++ b/samples/memory/sram_regions/linker_sram_regions.ld @@ -0,0 +1,26 @@ +/* + * Copyright (c) Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +#include + +#include + +MEMORY +{ + LINKER_DT_SRAM_REGIONS() +} + +SECTIONS +{ + LINKER_DT_SRAM_SECTIONS() +} + +#include diff --git a/samples/memory/sram_regions/prj.conf b/samples/memory/sram_regions/prj.conf new file mode 100644 index 0000000000000..cb46455553825 --- /dev/null +++ b/samples/memory/sram_regions/prj.conf @@ -0,0 +1,3 @@ +CONFIG_CPU_HAS_CUSTOM_FIXED_SOC_MPU_REGIONS=y +CONFIG_HAVE_CUSTOM_LINKER_SCRIPT=y +CONFIG_CUSTOM_LINKER_SCRIPT="linker_sram_regions.ld" diff --git a/samples/memory/sram_regions/sample.yaml b/samples/memory/sram_regions/sample.yaml new file mode 100644 index 0000000000000..358e14aee1069 --- /dev/null +++ b/samples/memory/sram_regions/sample.yaml @@ -0,0 +1,8 @@ +sample: + description: SRAM MPU sample application + name: sram_mpu +tests: + sample.memory.sram_regions: + platform_allow: mps2_an385 + tags: sample board sram mpu + build_only: true diff --git a/samples/memory/sram_regions/src/arm_mpu_regions.c b/samples/memory/sram_regions/src/arm_mpu_regions.c new file mode 100644 index 0000000000000..bd74b552a33e7 --- /dev/null +++ b/samples/memory/sram_regions/src/arm_mpu_regions.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#define BUILD_MPU_REGION(p_name, p_base, p_size, p_attr) \ + { .name = p_name, \ + .base = p_base, \ + .attr.rasr = p_attr, \ + }, + +static const struct arm_mpu_region mpu_regions[] = { + /* FLASH */ + MPU_REGION_ENTRY("FLASH_0", + CONFIG_FLASH_BASE_ADDRESS, + REGION_FLASH_ATTR(REGION_4M)), + + /* SRAM0 */ + MPU_REGION_ENTRY("SRAM_0", + CONFIG_SRAM_BASE_ADDRESS, + REGION_RAM_ATTR(REGION_2M)), + + /* Generated SRAM regions */ + DT_SRAM_INST_FOREACH(BUILD_MPU_REGION) +}; + +const struct arm_mpu_config mpu_config = { + .num_regions = ARRAY_SIZE(mpu_regions), + .mpu_regions = mpu_regions, +}; diff --git a/samples/memory/sram_regions/src/main.c b/samples/memory/sram_regions/src/main.c new file mode 100644 index 0000000000000..83a2caf7adb96 --- /dev/null +++ b/samples/memory/sram_regions/src/main.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2021 Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +uint32_t var_in_region0 __attribute((__section__("region0"))) = 0xaabbccdd; +uint32_t var_in_region1 __attribute((__section__("region1"))) = 0xddccbbaa; + +uint32_t buf_in_nocache[0xA] __nocache_sram; + +void main(void) +{ + printk("Address of var_in_region0: %p\n", &var_in_region0); + printk("Address of var_in_region1: %p\n", &var_in_region1); + + printk("Address of buf_in_nocache: %p\n", buf_in_nocache); +}