linker: add ITERABLE_SECTION_RA|OM_NUMERIC

In some cases, like devices, it is necessary to sort numerically, that
is, sort 10 before 2. Add a new helper function to do that, up to 2
numeric digits.

Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
This commit is contained in:
Gerard Marull-Paretas 2023-04-26 15:18:13 +02:00 committed by Carles Cufí
parent f0db892d7b
commit b8efac92e0
5 changed files with 73 additions and 0 deletions

View file

@ -48,6 +48,12 @@
KEEP(*(SORT_BY_NAME(._##struct_type.static.*))); \ KEEP(*(SORT_BY_NAME(._##struct_type.static.*))); \
_CONCAT(_##struct_type, _list_end) = . _CONCAT(_##struct_type, _list_end) = .
#define Z_LINK_ITERABLE_NUMERIC(struct_type) \
_CONCAT(_##struct_type, _list_start) = .; \
KEEP(*(SORT(._##struct_type.static.*_?_*))); \
KEEP(*(SORT(._##struct_type.static.*_??_*))); \
_CONCAT(_##struct_type, _list_end) = .
#define Z_LINK_ITERABLE_ALIGNED(struct_type, align) \ #define Z_LINK_ITERABLE_ALIGNED(struct_type, align) \
. = ALIGN(align); \ . = ALIGN(align); \
Z_LINK_ITERABLE(struct_type); Z_LINK_ITERABLE(struct_type);
@ -77,6 +83,21 @@
Z_LINK_ITERABLE(struct_type); \ Z_LINK_ITERABLE(struct_type); \
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) } GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
/**
* @brief Define a read-only iterable section output, sorted numerically.
*
* This version of ITERABLE_SECTION_ROM() sorts the entries numerically, that
* is, `SECNAME_10` will come after `SECNAME_2`. `_` separator is required, and
* up to 2 numeric digits are handled (0-99).
*
* @see ITERABLE_SECTION_ROM()
*/
#define ITERABLE_SECTION_ROM_NUMERIC(struct_type, subalign) \
SECTION_PROLOGUE(struct_type##_area, EMPTY, SUBALIGN(subalign)) \
{ \
Z_LINK_ITERABLE_NUMERIC(struct_type); \
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
/** /**
* @brief Define a garbage collectable read-only iterable section output. * @brief Define a garbage collectable read-only iterable section output.
* *
@ -115,6 +136,21 @@
Z_LINK_ITERABLE(struct_type); \ Z_LINK_ITERABLE(struct_type); \
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
/**
* @brief Define a read-write iterable section output, sorted numerically.
*
* This version of ITERABLE_SECTION_RAM() sorts the entries numerically, that
* is, `SECNAME10` will come after `SECNAME2`. Up to 2 numeric digits are
* handled (0-99).
*
* @see ITERABLE_SECTION_RAM()
*/
#define ITERABLE_SECTION_RAM_NUMERIC(struct_type, subalign) \
SECTION_PROLOGUE(struct_type##_area, EMPTY, SUBALIGN(subalign)) \
{ \
Z_LINK_ITERABLE_NUMERIC(struct_type); \
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
/** /**
* @brief Define a garbage collectable read-write iterable section output. * @brief Define a garbage collectable read-write iterable section output.
* *

View file

@ -11,8 +11,10 @@ zephyr_linker_sources(DATA_SECTIONS sections-ram.ld)
zephyr_iterable_section(NAME test_ram GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) zephyr_iterable_section(NAME test_ram GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4)
zephyr_iterable_section(NAME test_ram2 GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) zephyr_iterable_section(NAME test_ram2 GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4)
zephyr_iterable_section(NAME test_ram_named GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) zephyr_iterable_section(NAME test_ram_named GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4)
zephyr_iterable_section(NAME test_ram_numeric NUMERIC GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4)
zephyr_linker_sources(SECTIONS sections-rom.ld) zephyr_linker_sources(SECTIONS sections-rom.ld)
zephyr_iterable_section(NAME test_rom KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) zephyr_iterable_section(NAME test_rom KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4)
zephyr_iterable_section(NAME test_rom2 KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) zephyr_iterable_section(NAME test_rom2 KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4)
zephyr_iterable_section(NAME test_rom_named KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) zephyr_iterable_section(NAME test_rom_named KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4)
zephyr_iterable_section(NAME test_rom_numeric NUMERIC KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4)

View file

@ -1,3 +1,4 @@
ITERABLE_SECTION_RAM(test_ram, 4) ITERABLE_SECTION_RAM(test_ram, 4)
ITERABLE_SECTION_RAM(test_ram2, 4) ITERABLE_SECTION_RAM(test_ram2, 4)
ITERABLE_SECTION_RAM(test_ram_named, 4) ITERABLE_SECTION_RAM(test_ram_named, 4)
ITERABLE_SECTION_RAM_NUMERIC(test_ram_numeric, 4)

View file

@ -1,3 +1,4 @@
ITERABLE_SECTION_ROM(test_rom, 4) ITERABLE_SECTION_ROM(test_rom, 4)
ITERABLE_SECTION_ROM(test_rom2, 4) ITERABLE_SECTION_ROM(test_rom2, 4)
ITERABLE_SECTION_ROM(test_rom_named, 4) ITERABLE_SECTION_ROM(test_rom_named, 4)
ITERABLE_SECTION_ROM_NUMERIC(test_rom_numeric, 4)

View file

@ -14,6 +14,10 @@ struct test_ram_named {
int i; int i;
}; };
struct test_ram_numeric {
int i;
};
#define CHECK_BIT 0x80 #define CHECK_BIT 0x80
/* declare in random order to check that the linker is sorting by name */ /* declare in random order to check that the linker is sorting by name */
@ -33,6 +37,12 @@ const STRUCT_SECTION_ITERABLE_NAMED(test_ram_named, C, ram7) = {0x03};
const STRUCT_SECTION_ITERABLE_NAMED(test_ram_named, D, ram8) = {0x04}; const STRUCT_SECTION_ITERABLE_NAMED(test_ram_named, D, ram8) = {0x04};
const STRUCT_SECTION_ITERABLE_NAMED(test_ram_named, B, ram9) = {0x02}; const STRUCT_SECTION_ITERABLE_NAMED(test_ram_named, B, ram9) = {0x02};
/* declare in random order to check that the linker is sorting numerically */
const STRUCT_SECTION_ITERABLE(test_ram_numeric, ramn_1) = {0x01};
const STRUCT_SECTION_ITERABLE(test_ram_numeric, ramn_10) = {0x03};
const STRUCT_SECTION_ITERABLE(test_ram_numeric, ramn_11) = {0x04};
const STRUCT_SECTION_ITERABLE(test_ram_numeric, ramn_3) = {0x02};
/** /**
* *
* @brief Test iterable in read write section. * @brief Test iterable in read write section.
@ -71,6 +81,13 @@ ZTEST(iterable_sections, test_ram)
} }
zassert_equal(out, RAM_EXPECT, "Check value incorrect (got: 0x%x)", out); zassert_equal(out, RAM_EXPECT, "Check value incorrect (got: 0x%x)", out);
out = 0;
STRUCT_SECTION_FOREACH(test_ram_numeric, t) {
out = (out << 8) | t->i;
}
zassert_equal(out, RAM_EXPECT, "Check value incorrect (got: 0x%x)", out);
} }
struct test_rom { struct test_rom {
@ -81,6 +98,10 @@ struct test_rom_named {
int i; int i;
}; };
struct test_rom_numeric {
int i;
};
/* declare in random order to check that the linker is sorting by name */ /* declare in random order to check that the linker is sorting by name */
const STRUCT_SECTION_ITERABLE(test_rom, rom1) = {0x10}; const STRUCT_SECTION_ITERABLE(test_rom, rom1) = {0x10};
const STRUCT_SECTION_ITERABLE(test_rom, rom3) = {0x30}; const STRUCT_SECTION_ITERABLE(test_rom, rom3) = {0x30};
@ -98,6 +119,12 @@ const STRUCT_SECTION_ITERABLE_NAMED(test_rom_named, C, rom7) = {0x30};
const STRUCT_SECTION_ITERABLE_NAMED(test_rom_named, D, rom8) = {0x40}; const STRUCT_SECTION_ITERABLE_NAMED(test_rom_named, D, rom8) = {0x40};
const STRUCT_SECTION_ITERABLE_NAMED(test_rom_named, B, rom9) = {0x20}; const STRUCT_SECTION_ITERABLE_NAMED(test_rom_named, B, rom9) = {0x20};
/* declare in random order to check that the linker is sorting numerically */
const STRUCT_SECTION_ITERABLE(test_rom_numeric, romn_1) = {0x10};
const STRUCT_SECTION_ITERABLE(test_rom_numeric, romn_10) = {0x30};
const STRUCT_SECTION_ITERABLE(test_rom_numeric, romn_11) = {0x40};
const STRUCT_SECTION_ITERABLE(test_rom_numeric, romn_3) = {0x20};
/** /**
* *
* @brief Test iterable in read only section. * @brief Test iterable in read only section.
@ -127,6 +154,12 @@ ZTEST(iterable_sections, test_rom)
zassert_equal(out, ROM_EXPECT, "Check value incorrect (got: 0x%x)", out); zassert_equal(out, ROM_EXPECT, "Check value incorrect (got: 0x%x)", out);
out = 0;
STRUCT_SECTION_FOREACH(test_rom_numeric, t) {
out = (out << 8) | t->i;
}
zassert_equal(out, ROM_EXPECT, "Check value incorrect (got: 0x%x)", out);
} }
ZTEST_SUITE(iterable_sections, NULL, NULL, NULL, NULL, NULL); ZTEST_SUITE(iterable_sections, NULL, NULL, NULL, NULL, NULL);