diff --git a/cmake/linker_script/arm/linker.cmake b/cmake/linker_script/arm/linker.cmake index c557dfb57fb..231c9df8a76 100644 --- a/cmake/linker_script/arm/linker.cmake +++ b/cmake/linker_script/arm/linker.cmake @@ -195,3 +195,8 @@ zephyr_linker_section_configure(SECTION .data ANY FLAGS "+RW") zephyr_linker_section_configure(SECTION .bss ANY FLAGS "+ZI") include(${COMMON_ZEPHYR_LINKER_DIR}/debug-sections.cmake) + +dt_comp_path(paths COMPATIBLE "zephyr,memory-region") +foreach(path IN LISTS paths) + zephyr_linker_dts_section(PATH ${path}) +endforeach() diff --git a/cmake/modules/extensions.cmake b/cmake/modules/extensions.cmake index 0b1ee6bb765..efcbb988181 100644 --- a/cmake/modules/extensions.cmake +++ b/cmake/modules/extensions.cmake @@ -3333,6 +3333,53 @@ macro(zephyr_linker_memory_ifdef feature_toggle) endif() endmacro() +# Usage: +# zephyr_linker_dts_section(PATH ) +# +# Zephyr linker devicetree memory section from path. +# +# This function specifies an output section for the platform in use based on its +# devicetree configuration. +# +# The section will only be defined if the devicetree exists and has status okay. +# +# PATH : Devicetree node path. +# +function(zephyr_linker_dts_section) + set(single_args "PATH") + cmake_parse_arguments(DTS_SECTION "" "${single_args}" "" ${ARGN}) + + if(DTS_SECTION_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "zephyr_linker_dts_section(${ARGV0} ...) given unknown " + "arguments: ${DTS_SECTION_UNPARSED_ARGUMENTS}" + ) + endif() + + if(NOT DEFINED DTS_SECTION_PATH) + message(FATAL_ERROR "zephyr_linker_dts_section(${ARGV0} ...) missing " + "required argument: PATH" + ) + endif() + + dt_node_exists(exists PATH ${DTS_SECTION_PATH}) + if(NOT ${exists}) + return() + endif() + + dt_prop(name PATH ${DTS_SECTION_PATH} PROPERTY "zephyr,memory-region") + if(NOT DEFINED name) + message(FATAL_ERROR "zephyr_linker_dts_section(${ARGV0} ...) missing " + "\"zephyr,memory-region\" property" + ) + endif() + zephyr_string(SANITIZE name ${name}) + + dt_reg_addr(addr PATH ${DTS_SECTION_PATH}) + + zephyr_linker_section(NAME ${name} ADDRESS ${addr} VMA ${name} TYPE NOLOAD) + +endfunction() + # Usage: # zephyr_linker_dts_memory(PATH FLAGS ) # zephyr_linker_dts_memory(NODELABEL FLAGS ) diff --git a/include/arch/arm/aarch32/cortex_a_r/scripts/linker.ld b/include/arch/arm/aarch32/cortex_a_r/scripts/linker.ld index e231b6dc5ac..5c9ab3f5ed8 100644 --- a/include/arch/arm/aarch32/cortex_a_r/scripts/linker.ld +++ b/include/arch/arm/aarch32/cortex_a_r/scripts/linker.ld @@ -383,6 +383,9 @@ GROUP_END(OCM) KEEP(*(.gnu.attributes)) } + /* Sections generated from 'zephyr,memory-region' nodes */ + LINKER_DT_SECTIONS() + /* Must be last in romable region */ SECTION_PROLOGUE(.last_section,(NOLOAD),) { diff --git a/include/arch/arm/aarch32/cortex_m/scripts/linker.ld b/include/arch/arm/aarch32/cortex_m/scripts/linker.ld index 3681ccbc29b..82d46ef9e33 100644 --- a/include/arch/arm/aarch32/cortex_m/scripts/linker.ld +++ b/include/arch/arm/aarch32/cortex_m/scripts/linker.ld @@ -437,6 +437,9 @@ GROUP_END(DTCM) KEEP(*(.gnu.attributes)) } + /* Sections generated from 'zephyr,memory-region' nodes */ + LINKER_DT_SECTIONS() + /* Must be last in romable region */ SECTION_PROLOGUE(.last_section,(NOLOAD),) { diff --git a/include/linker/devicetree_regions.h b/include/linker/devicetree_regions.h index 5307c34dbf6..638e9d19951 100644 --- a/include/linker/devicetree_regions.h +++ b/include/linker/devicetree_regions.h @@ -39,6 +39,13 @@ #define _DT_COMPATIBLE zephyr_memory_region +#define _DT_SECTION_NAME(node_id) DT_STRING_TOKEN(node_id, zephyr_memory_region) +#define _DT_SECTION_PREFIX(node_id) UTIL_CAT(__, _DT_SECTION_NAME(node_id)) +#define _DT_SECTION_START(node_id) UTIL_CAT(_DT_SECTION_PREFIX(node_id), _start) +#define _DT_SECTION_END(node_id) UTIL_CAT(_DT_SECTION_PREFIX(node_id), _end) +#define _DT_SECTION_SIZE(node_id) UTIL_CAT(_DT_SECTION_PREFIX(node_id), _size) +#define _DT_SECTION_LOAD(node_id) UTIL_CAT(_DT_SECTION_PREFIX(node_id), _load_start) + /** * @brief Declare a memory region * @@ -50,6 +57,23 @@ ORIGIN = DT_REG_ADDR(node_id), \ LENGTH = DT_REG_SIZE(node_id) +/** + * @brief Declare a memory section from the device tree nodes with + * compatible 'zephyr,memory-region' + * + * @param node_id devicetree node identifier + */ +#define _SECTION_DECLARE(node_id) \ + _DT_SECTION_NAME(node_id) DT_REG_ADDR(node_id) (NOLOAD) : \ + { \ + _DT_SECTION_START(node_id) = .; \ + KEEP(*(_DT_SECTION_NAME(node_id))) \ + KEEP(*(_DT_SECTION_NAME(node_id).*)) \ + _DT_SECTION_END(node_id) = .; \ + } > _DT_SECTION_NAME(node_id) \ + _DT_SECTION_SIZE(node_id) = _DT_SECTION_END(node_id) - _DT_SECTION_START(node_id); \ + _DT_SECTION_LOAD(node_id) = LOADADDR(_DT_SECTION_NAME(node_id)); + /** @endcond */ /** @@ -62,3 +86,10 @@ */ #define LINKER_DT_REGIONS() \ DT_FOREACH_STATUS_OKAY(_DT_COMPATIBLE, _REGION_DECLARE) + +/** + * @brief Generate linker memory sections from the device tree nodes with + * compatible 'zephyr,memory-region' + */ +#define LINKER_DT_SECTIONS() \ + DT_FOREACH_STATUS_OKAY(_DT_COMPATIBLE, _SECTION_DECLARE) diff --git a/scripts/dts/gen_dts_cmake.py b/scripts/dts/gen_dts_cmake.py index f3be6a0fa1d..8dc0f2e4516 100755 --- a/scripts/dts/gen_dts_cmake.py +++ b/scripts/dts/gen_dts_cmake.py @@ -148,6 +148,9 @@ def main(): for path in compatible2paths[comp]: cmake_path = f'{cmake_path}{path};' + # Remove the last ';' + cmake_path = cmake_path[:-1] + cmake_comp = f'DT_COMP|{comp}' cmake_props.append(f'"{cmake_comp}" "{cmake_path}"')