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>
This commit is contained in:
Carlo Caione 2022-03-09 17:19:03 +01:00 committed by Anas Nashif
commit bc72fb67b1
6 changed files with 92 additions and 0 deletions

View file

@ -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()

View file

@ -3333,6 +3333,53 @@ macro(zephyr_linker_memory_ifdef feature_toggle)
endif()
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>)

View file

@ -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),)
{

View file

@ -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),)
{

View file

@ -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)

View file

@ -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}"')