linker: Create sections from zephyr,memory-region nodes
Currently when a node has a 'zephyr,memory-region' compatible and a
'zephyr,memory-region' string property, a new memory region is created
in the linker script.
Having a memory region without a section to place variables in could be
not that useful. With this patch we extend the memory-region mechanism
to also create sections.
The user can then place variables in the sections as usual by using for
example the GCC attributes.
Signed-off-by: Carlo Caione <ccaione@baylibre.com>
diff --git a/cmake/linker_script/arm/linker.cmake b/cmake/linker_script/arm/linker.cmake
index c557dfb..231c9df 100644
--- a/cmake/linker_script/arm/linker.cmake
+++ b/cmake/linker_script/arm/linker.cmake
@@ -195,3 +195,8 @@
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 0b1ee6b..efcbb98 100644
--- a/cmake/modules/extensions.cmake
+++ b/cmake/modules/extensions.cmake
@@ -3334,6 +3334,53 @@
endmacro()
# Usage:
+# zephyr_linker_dts_section(PATH <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 <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 <path> FLAGS <flags>)
# zephyr_linker_dts_memory(NODELABEL <nodelabel> FLAGS <flags>)
# zephyr_linker_dts_memory(CHOSEN <prop> FLAGS <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 e231b6d..5c9ab3f 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 @@
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 3681ccb..82d46ef 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 @@
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 5307c34..638e9d1 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 f3be6a0..8dc0f2e4 100755
--- a/scripts/dts/gen_dts_cmake.py
+++ b/scripts/dts/gen_dts_cmake.py
@@ -148,6 +148,9 @@
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}"')