Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions boards/arm/nrf52832_mdk/nrf52832_mdk.dts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@
storage_partition: partition@7a000 {
label = "storage";
reg = <0x0007a000 0x00006000>;
linker-region;
};
};
};
1 change: 1 addition & 0 deletions boards/arm/nrf52833dk_nrf52820/nrf52833dk_nrf52820.dts
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@
storage_partition: partition@3a000 {
label = "storage";
reg = <0x0003a000 0x00006000>;
linker-region;
};
};
};
Expand Down
1 change: 1 addition & 0 deletions boards/arm/nrf52833dk_nrf52833/nrf52833dk_nrf52833.dts
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ arduino_spi: &spi3 {
storage_partition: partition@7a000 {
label = "storage";
reg = <0x0007A000 0x00006000>;
linker-region;
};
};
};
Expand Down
1 change: 1 addition & 0 deletions boards/arm/nrf52840_blip/nrf52840_blip.dts
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@
storage_partition: partition@f8000 {
label = "storage";
reg = <0x000f8000 0x00008000>;
linker-region;
};
};
};
Expand Down
1 change: 1 addition & 0 deletions boards/arm/nrf52840_mdk/nrf52840_mdk.dts
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@
storage_partition: partition@f8000 {
label = "storage";
reg = <0x000f8000 0x00008000>;
linker-region;
};
};
};
Expand Down
1 change: 1 addition & 0 deletions boards/arm/nrf52840_papyr/nrf52840_papyr.dts
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@
storage_partition: partition@f8000 {
label = "storage";
reg = <0x000f8000 0x00008000>;
linker-region;
};
};
};
Expand Down
1 change: 1 addition & 0 deletions boards/arm/nrf52840dk_nrf52811/nrf52840dk_nrf52811.dts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@
storage_partition: partition@29000 {
label = "storage";
reg = <0x00029000 0x00007000>;
linker-region;
};
};
};
1 change: 1 addition & 0 deletions boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840.dts
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ arduino_spi: &spi3 {
storage_partition: partition@f8000 {
label = "storage";
reg = <0x000f8000 0x00008000>;
linker-region;
};
};
};
Expand Down
4 changes: 4 additions & 0 deletions dts/bindings/mtd/partition.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ child-binding:
type: boolean
required: false
description: if the partition is read-only or not
linker-region:
type: boolean
required: false
description: generate a MEMORY region for this partition in the linker
reg:
type: array
description: register space
Expand Down
6 changes: 5 additions & 1 deletion include/arch/arm/aarch32/cortex_a_r/scripts/linker.ld
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#include <autoconf.h>
#include <linker/sections.h>
#include <linker/devicetree_regions.h>
#include <devicetree.h>

#include <linker/linker-defs.h>
Expand Down Expand Up @@ -42,7 +43,8 @@
#if CONFIG_FLASH_LOAD_SIZE > 0
#define ROM_SIZE CONFIG_FLASH_LOAD_SIZE
#else
#define ROM_SIZE (CONFIG_FLASH_SIZE*1K - CONFIG_FLASH_LOAD_OFFSET)
#define ROM_USABLE_END DT_PARTITION_REGIONS_START(CONFIG_FLASH_SIZE*1K)
#define ROM_SIZE (ROM_USABLE_END - CONFIG_FLASH_LOAD_OFFSET)
#endif

#if defined(CONFIG_XIP)
Expand Down Expand Up @@ -84,6 +86,8 @@ MEMORY
SRAM (wx) : ORIGIN = RAM_ADDR, LENGTH = RAM_SIZE
/* Used by and documented in include/linker/intlist.ld */
IDT_LIST (wx) : ORIGIN = (RAM_ADDR + RAM_SIZE), LENGTH = 2K
/* Add custom memory regions requested from devicetree */
DT_PARTITION_REGIONS()
}

ENTRY(CONFIG_KERNEL_ENTRY)
Expand Down
6 changes: 5 additions & 1 deletion include/arch/arm/aarch32/cortex_m/scripts/linker.ld
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#include <autoconf.h>
#include <linker/sections.h>
#include <linker/devicetree_regions.h>
#include <devicetree.h>

#include <linker/linker-defs.h>
Expand Down Expand Up @@ -48,7 +49,8 @@
#if CONFIG_FLASH_LOAD_SIZE > 0
#define ROM_SIZE CONFIG_FLASH_LOAD_SIZE
#else
#define ROM_SIZE (CONFIG_FLASH_SIZE*1K - CONFIG_FLASH_LOAD_OFFSET)
#define ROM_USABLE_END DT_PARTITION_REGIONS_START(CONFIG_FLASH_SIZE*1K)
#define ROM_SIZE (ROM_USABLE_END - CONFIG_FLASH_LOAD_OFFSET)
#endif
#endif

Expand Down Expand Up @@ -116,6 +118,8 @@ MEMORY
#endif
/* Used by and documented in include/linker/intlist.ld */
IDT_LIST (wx) : ORIGIN = (RAM_ADDR + RAM_SIZE), LENGTH = 2K
/* Add custom memory regions requested from devicetree */
DT_PARTITION_REGIONS()
}

ENTRY(CONFIG_KERNEL_ENTRY)
Expand Down
47 changes: 47 additions & 0 deletions include/linker/devicetree_regions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2021, Commonwealth Scientific and Industrial Research
* Organisation (CSIRO) ABN 41 687 119 230.
*
* SPDX-License-Identifier: Apache-2.0
*
* Generate memory regions from devicetree partitions.
* Partitions are only considered if they exist under chosen/zephyr,flash.
*/

/* Partition under chosen/zephyr,flash */
#define _CHOSEN_PARTITIONS UTIL_CAT(DT_CHOSEN(zephyr_flash), _S_partitions)

/* Declare a memory region definition if `linker-region` is set */
#define _REGION_DECLARE(part) COND_CODE_1(DT_PROP(part, linker_region), \
(DT_LABEL(part) (rx) : \
ORIGIN = DT_REG_ADDR(part), \
LENGTH = DT_REG_SIZE(part)), \
())

/* Return a memory region origin if `linker-region` is set*/
#define _REGION_ADDR(part) COND_CODE_1(DT_PROP(part, linker_region), \
(DT_REG_ADDR(part),), \
())

/* Apply a macro to chosen partition, if it exists */
#define _REGION_APPLY(f) \
COND_CODE_1(IS_ENABLED(UTIL_CAT(_CHOSEN_PARTITIONS, _EXISTS)), \
(DT_FOREACH_CHILD(_CHOSEN_PARTITIONS, f)), ())

/**
* @brief Find the lowest start address of all devicetree linker regions
*
* The MIN symbol passed to `FOR_EACH_NESTED` does not resolve to the standard
* ternery operation macro. Instead it is pasted as a symbol into the final
* linker file, where MIN is a builtin function in ld.
* https://sourceware.org/binutils/docs/ld/Builtin-Functions.html
*
* @param def default return value if no custom partitions are present
*/
#define DT_PARTITION_REGIONS_START(def) \
FOR_EACH_NESTED(MIN, def, _REGION_APPLY(_REGION_ADDR))

/**
* @brief Generate region definitions for all devicetree linker regions
*/
#define DT_PARTITION_REGIONS() _REGION_APPLY(_REGION_DECLARE)
37 changes: 37 additions & 0 deletions include/sys/util_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,43 @@
#define Z_FOR_EACH_SWALLOW_INDEX_FIXED_ARG(F, fixed_arg, index, arg) F(arg)
#define Z_FOR_EACH_SWALLOW_INDEX(F, fixed_arg, index, arg) F(arg, fixed_arg)

/* Internal macros used by FOR_EACH_NESTED */
#define _Z_FEN_1(F, term, ...) F(GET_ARG_N(1, __VA_ARGS__), term)
#define _Z_FEN_2(F, term, ...) F(GET_ARG_N(2, __VA_ARGS__), \
_Z_FEN_1(F, term, __VA_ARGS__))
#define _Z_FEN_3(F, term, ...) F(GET_ARG_N(3, __VA_ARGS__), \
_Z_FEN_2(F, term, __VA_ARGS__))
#define _Z_FEN_4(F, term, ...) F(GET_ARG_N(4, __VA_ARGS__), \
_Z_FEN_3(F, term, __VA_ARGS__))
#define _Z_FEN_5(F, term, ...) F(GET_ARG_N(5, __VA_ARGS__), \
_Z_FEN_4(F, term, __VA_ARGS__))
#define _Z_FEN_6(F, term, ...) F(GET_ARG_N(6, __VA_ARGS__), \
_Z_FEN_5(F, term, __VA_ARGS__))
#define _Z_FEN_7(F, term, ...) F(GET_ARG_N(7, __VA_ARGS__), \
_Z_FEN_6(F, term, __VA_ARGS__))
#define _Z_FEN_8(F, term, ...) F(GET_ARG_N(8, __VA_ARGS__), \
_Z_FEN_7(F, term, __VA_ARGS__))
#define _Z_FEN_9(F, term, ...) F(GET_ARG_N(9, __VA_ARGS__), \
_Z_FEN_8(F, term, __VA_ARGS__))
#define _Z_FEN_10(F, term, ...) F(GET_ARG_N(10, __VA_ARGS__), \
_Z_FEN_9(F, term, __VA_ARGS__))
#define _Z_FEN_11(F, term, ...) F(GET_ARG_N(11, __VA_ARGS__), \
_Z_FEN_10(F, term, __VA_ARGS__))
#define _Z_FEN_12(F, term, ...) F(GET_ARG_N(12, __VA_ARGS__), \
_Z_FEN_11(F, term, __VA_ARGS__))
#define _Z_FEN_13(F, term, ...) F(GET_ARG_N(13, __VA_ARGS__), \
_Z_FEN_12(F, term, __VA_ARGS__))
#define _Z_FEN_14(F, term, ...) F(GET_ARG_N(14, __VA_ARGS__), \
_Z_FEN_13(F, term, __VA_ARGS__))
#define _Z_FEN_15(F, term, ...) F(GET_ARG_N(15, __VA_ARGS__), \
_Z_FEN_14(F, term, __VA_ARGS__))
#define _Z_FEN_16(F, term, ...) F(GET_ARG_N(16, __VA_ARGS__), \
_Z_FEN_15(F, term, __VA_ARGS__))

#define _Z_FOR_EACH_NESTED(F, term, ...) \
UTIL_CAT(_Z_FEN_, NUM_VA_ARGS_LESS_1(__VA_ARGS__, _)) \
(F, term, __VA_ARGS__)

/* This is a workaround to enable mixing GET_ARG_N with FOR_EACH macros. If
* same UTIL_EVAL macro is used then macro is incorrectly resolved.
*/
Expand Down
29 changes: 29 additions & 0 deletions include/sys/util_macro.h
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,35 @@ extern "C" {
0, Z_FOR_EACH_SWALLOW_NOTHING, sep, \
F, fixed_arg, __VA_ARGS__)

/**
* @brief Call a macro @p F on each provided argument in a nested fashion
*
* For each argument provided evaluates a two input macro where the second
* parameter is the result of the evaluation on the previous argument.
*
* Example:
*
* // Find the smallest number in a list
* FOR_EACH_NESTED(MIN, INT_MAX, 4, 5, 6);
*
* This expands to:
*
* MIN(6, MIN(5, MIN(4, INT_MAX)))
*
* @param F Macro to invoke.
* @param term Final argument provided to the last invocation of @p F.
* @param ... Variable argument list.
* @return Result of macro invocation, or @p term if argument list is empty.
*/
#define FOR_EACH_NESTED(F, term, ...) \
COND_CODE_0( \
/* are there zero non-empty arguments ? */ \
NUM_VA_ARGS_LESS_1(LIST_DROP_EMPTY(__VA_ARGS__, _)), \
/* if so, expand to term */ \
(term), \
/* otherwise, expand to: */ \
(_Z_FOR_EACH_NESTED(F, term, LIST_DROP_EMPTY(__VA_ARGS__))))

/**
* @brief Number of arguments in the variable arguments list minus one.
*
Expand Down
11 changes: 11 additions & 0 deletions samples/application_development/linker_regions/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.13.1)

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(linker_regions)

zephyr_linker_sources(SECTIONS partition_first.ld)
zephyr_linker_sources_ifdef(SECOND_REGION SECTIONS partition_second.ld)

target_sources(app PRIVATE src/main.c)
23 changes: 23 additions & 0 deletions samples/application_development/linker_regions/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
.. _linker_regions:

Linker Regions
##############

Overview
********

A sample that demonstrates using devicetree to define linker
memory regions. These memory regions allow constants to be
placed at desired memory addresses in a portable manner.

Building and Running
********************

This application can be built and executed on QEMU as follows:

.. zephyr-app-commands::
:zephyr-app: samples/application_development/linker_regions
:host-os: unix
:board: qemu_cortex_m3
:goals: run
:compact:
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright (c) 2021, Commonwealth Scientific and Industrial Research
* Organisation (CSIRO) ABN 41 687 119 230.
*
* SPDX-License-Identifier: Apache-2.0
*/

&flash0 {
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;

first_partition: partition@38000 {
label = "first_region";
reg = <0x00038000 0x00008000>;
linker-region;
};
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright (c) 2021, Commonwealth Scientific and Industrial Research
* Organisation (CSIRO) ABN 41 687 119 230.
*
* SPDX-License-Identifier: Apache-2.0
*/

&flash0 {
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;

/* Regions are unordered to show the correct selection of
* ROM bounds.
*/
first_partition: partition@3c000 {
label = "first_region";
reg = <0x0003c000 0x00004000>;
linker-region;
};

second_partition: partition@38000 {
label = "second_region";
reg = <0x00038000 0x00004000>;
linker-region;
};
};
};
17 changes: 17 additions & 0 deletions samples/application_development/linker_regions/partition_first.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright (c) 2021, Commonwealth Scientific and Industrial Research
* Organisation (CSIRO) ABN 41 687 119 230.
*
* SPDX-License-Identifier: Apache-2.0
*/

/* Link ".first_section" into the first partition */
GROUP_START(first_region)

SECTION_DATA_PROLOGUE(first_section,,)
{
KEEP(*(".first_section"));
KEEP(*(".first_section.*"));
} GROUP_LINK_IN(first_region)

GROUP_END(first_region)
17 changes: 17 additions & 0 deletions samples/application_development/linker_regions/partition_second.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright (c) 2021, Commonwealth Scientific and Industrial Research
* Organisation (CSIRO) ABN 41 687 119 230.
*
* SPDX-License-Identifier: Apache-2.0
*/

/* Link ".second_section" into the second partition */
GROUP_START(second_region)

SECTION_DATA_PROLOGUE(second_section,,)
{
KEEP(*(".second_section"));
KEEP(*(".second_section.*"));
} GROUP_LINK_IN(second_region)

GROUP_END(second_region)
1 change: 1 addition & 0 deletions samples/application_development/linker_regions/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# nothing here
Loading