This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 7cd511fed21 include/nuttx: Add link-time iterable sections 
infrastructure
7cd511fed21 is described below

commit 7cd511fed21998701c26efee4e805994b6b8a84f
Author: Jorge Guzman <[email protected]>
AuthorDate: Fri Aug 21 14:24:11 2026 -0300

    include/nuttx: Add link-time iterable sections infrastructure
    
    Add generic support for link-time registration of struct instances,
    modeled after the Zephyr STRUCT_SECTION_* mechanism:
    
    - include/nuttx/iterable_sections.h: STRUCT_SECTION_ITERABLE/DECLARE/
      FOREACH/GET/COUNT macros placing instances in name-sorted linker
      sections delimited by _<type>_list_start/_end symbols (attributes
      through the nuttx/compiler.h macros; FOREACH takes a caller-declared
      iterator, like list_for_every_entry).
    - include/nuttx/linker/iterable_sections.ld: ITERABLE_SECTION() macro
      emitting the KEEP + SORT_BY_NAME collection statements (linker
      scripts in ARCHSCRIPT are CPP-preprocessed).
    - include/nuttx/linker/common-rom.ld / common-ram.ld: central
      aggregators meant to be included by board linker scripts (inside
      .text and .data respectively); subsystems register their sections
      here guarded by their Kconfig options, so the fragments expand to
      nothing on configurations that do not use them.
    - CONFIG_ITERABLE_SECTIONS_LINKER_INSERT + include/nuttx/linker/
      common-insert.ld (added before the board script by tools/Config.mk and
      by the top-level CMakeLists.txt): optional zero-touch mode that
      supplements the board script through GNU ld INSERT AFTER, collecting
      the subsystems' ITERABLE_SECTION blocks in one output section; the
      common-rom.ld/common-ram.ld fragments expand to nothing in that mode.
      See the option help for the constraints.
    - Documentation/components/iterable_sections.rst.
    
    First user: the Zephyr zbus message bus port (apps/system/zbus in
    nuttx-apps); its board integration comes in a companion PR.
    
    Signed-off-by: Jorge Guzman <[email protected]>
---
 CMakeLists.txt                                 |   7 +
 Documentation/components/index.rst             |   1 +
 Documentation/components/iterable_sections.rst | 172 +++++++++++++++++++++++++
 Kconfig                                        |  24 ++++
 include/nuttx/iterable_sections.h              | 121 +++++++++++++++++
 include/nuttx/linker/common-insert.ld          |  59 +++++++++
 include/nuttx/linker/common-ram.ld             |  43 +++++++
 include/nuttx/linker/common-rom.ld             |  47 +++++++
 include/nuttx/linker/iterable_sections.ld      |  43 +++++++
 tools/Config.mk                                |  14 ++
 10 files changed, 531 insertions(+)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 820c5a4faa7..64d222f45ab 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -674,6 +674,13 @@ process_all_directory_romfs()
 # Get linker script to use
 get_property(ldscript GLOBAL PROPERTY LD_SCRIPT)
 
+# Iterable sections "zero-touch" mode: the central INSERT fragment must come
+# BEFORE the board script on the linker command line (GNU ld requirement for
+# INSERT AFTER), see include/nuttx/linker/common-insert.ld.
+if(CONFIG_ITERABLE_SECTIONS_LINKER_INSERT)
+  list(PREPEND ldscript ${NUTTX_DIR}/include/nuttx/linker/common-insert.ld)
+endif()
+
 # Pre-compile linker script(s)
 if(NOT CONFIG_ARCH_SIM)
   set(ldscript_tmp_list)
diff --git a/Documentation/components/index.rst 
b/Documentation/components/index.rst
index fe60af7b985..edd1415ede2 100644
--- a/Documentation/components/index.rst
+++ b/Documentation/components/index.rst
@@ -13,6 +13,7 @@ case, you can head to the :doc:`reference 
<../reference/index>`.
    
    binfmt.rst
    concurrency/index.rst
+   iterable_sections.rst
    drivers/index.rst
    nxflat.rst
    nxgraphics/index.rst
diff --git a/Documentation/components/iterable_sections.rst 
b/Documentation/components/iterable_sections.rst
new file mode 100644
index 00000000000..4e2063880fb
--- /dev/null
+++ b/Documentation/components/iterable_sections.rst
@@ -0,0 +1,172 @@
+=================
+Iterable Sections
+=================
+
+Iterable sections provide **link-time registration** of ``struct``
+instances: an instance defined with :c:macro:`STRUCT_SECTION_ITERABLE` in
+any compilation unit is placed in a dedicated linker input section.  The
+linker collects all instances into a contiguous, name-sorted array
+delimited by ``_<type>_list_start``/``_<type>_list_end`` symbols, which
+the code can then iterate like a plain C array -- no runtime registration
+calls, no central list to maintain.
+
+This is the same mechanism used by the Zephyr RTOS ``STRUCT_SECTION_*``
+macros.  The first user of this infrastructure is the zbus message bus
+port (``apps/system/zbus``, from nuttx-apps).
+
+C API
+=====
+
+The macros are provided by ``include/nuttx/iterable_sections.h``:
+
+.. code-block:: c
+
+   #include <nuttx/iterable_sections.h>
+
+   struct my_entry
+   {
+     const char *name;
+     int value;
+   };
+
+   /* In any .c file (const places the instance in ROM): */
+
+   const STRUCT_SECTION_ITERABLE(my_entry, entry_foo) =
+   {
+     .name = "foo",
+     .value = 42,
+   };
+
+   /* In the file that iterates: declare the section boundaries once, at
+    * file scope, then loop with a caller-declared pointer.
+    */
+
+   STRUCT_SECTION_DECLARE(my_entry);
+
+   void print_entries(void)
+   {
+     FAR struct my_entry *entry;
+
+     STRUCT_SECTION_FOREACH(my_entry, entry)
+       {
+         printf("%s = %d\n", entry->name, entry->value);
+       }
+   }
+
+Available macros:
+
+* ``STRUCT_SECTION_ITERABLE(type, varname)`` -- define an instance inside
+  the iterable section ``._<type>.static.<varname>``.  The variable name
+  is part of the input section name, so the linker's ``SORT_BY_NAME()``
+  defines the iteration order (instances may encode ordering in their
+  names).
+* ``STRUCT_SECTION_DECLARE(type)`` -- declare the boundary symbols (file
+  scope), required before iterating.
+* ``STRUCT_SECTION_FOREACH(type, iterator)`` -- for-loop over all
+  instances; ``iterator`` is a pointer declared by the caller, as with
+  ``list_for_every_entry()``.
+* ``STRUCT_SECTION_GET(type, i, dst)`` -- random access by index.
+* ``STRUCT_SECTION_COUNT(type, dst)`` -- number of instances.
+* ``STRUCT_SECTION_START/END/START_EXTERN/END_EXTERN`` -- direct access
+  to the boundary symbols.
+
+Linker integration
+==================
+
+The collection step needs linker script support.  Two mechanisms are
+available; both rely on the fact that the linker scripts listed in
+``ARCHSCRIPT`` are preprocessed with CPP (arm, arm64, risc-v, xtensa,
+x86_64 and tricore), so ``#include`` and ``#ifdef CONFIG_*`` work inside
+them.
+
+Board script include (first-class mechanism)
+--------------------------------------------
+
+The board linker script includes the central fragments, which expand to
+nothing unless a subsystem using iterable sections is enabled:
+
+.. code-block:: text
+
+   .text :
+   {
+       ...
+       *(.gnu.linkonce.r.*)
+   #include <nuttx/linker/common-rom.ld>
+       _etext = ABSOLUTE(.);
+   } > flash
+
+   .data :
+   {
+       _sdata = ABSOLUTE(.);
+       ...
+   #include <nuttx/linker/common-ram.ld>
+       . = ALIGN(4);
+       _edata = ABSOLUTE(.);
+   } > sram AT > flash
+
+* ``common-rom.ld`` collects the read-only (``const``) iterable sections
+  and must be included inside the read-only output section (typically
+  ``.text``, before ``_etext``).
+* ``common-ram.ld`` collects mutable *initialized* iterable sections and
+  must be included inside ``.data`` (between ``_sdata`` and ``_edata``)
+  so the startup FLASH-to-RAM copy initializes the entries.
+* Subsystems add their sections to these central files, guarded by their
+  Kconfig option (see ``include/nuttx/linker/common-rom.ld`` for the zbus
+  example).
+
+Supplementary INSERT script (zero-touch mode)
+---------------------------------------------
+
+With ``CONFIG_ITERABLE_SECTIONS_LINKER_INSERT`` the central script
+``include/nuttx/linker/common-insert.ld`` is added before the board
+script by the build system (``tools/Config.mk`` for Make, the top-level
+``CMakeLists.txt`` for CMake) and supplements it through the GNU ld
+``INSERT AFTER`` command, so **no board script modification is needed**.
+The file defines one output section, ``.iterable_sections``, inserted
+after ``.text``; subsystems add their ``ITERABLE_SECTION()`` blocks
+inside it, guarded by their Kconfig option, exactly as in
+``common-rom.ld`` (which expands to nothing in this mode).
+
+This mode has constraints, discovered the hard way and worth knowing
+before choosing it:
+
+* GNU ld only (``INSERT`` is not supported by the macOS ld64).
+* The INSERT script must come *before* the board script on the linker
+  command line.  Adding it via ``ARCHSCRIPT`` from ``tools/Config.mk``
+  guarantees that, because ``Config.mk`` is included by the board
+  ``Make.defs`` before it appends its own script.  (The reversed order
+  fails with ``.text not found for insert``.)
+* GNU ld assigns an INSERTed output section to a ``MEMORY`` region by
+  *attribute matching in declaration order*, not by inheriting the anchor
+  section's region.  The ROM/flash region must therefore be the first
+  region compatible with read-only sections.  Boards declaring a generic
+  ``rwx`` region at a lower address first (e.g. an ITCM at ``0x0``) are
+  incompatible with this mode and must use the board script include.
+* Giving the inserted section an explicit address is **not** a fix: a
+  section with an explicit address does not consume the memory region,
+  so the next region-allocated section overlaps it.
+
+Alignment rules
+===============
+
+Instances are aligned to the natural alignment of their type
+(``STRUCT_SECTION_ITERABLE`` adds ``__aligned__(__alignof__(type))``), and
+``sizeof`` is always a multiple of ``alignof``, so the collected section
+can be indexed as a plain array with no padding between entries from
+different compilation units.  The fragments additionally align the list
+boundaries to 4 bytes.
+
+Adding a new iterable type
+==========================
+
+1. Define the instances with ``STRUCT_SECTION_ITERABLE(mytype, name)``.
+2. Add ``ITERABLE_SECTION(mytype)`` to
+   ``include/nuttx/linker/common-rom.ld`` (const) or ``common-ram.ld``
+   (mutable initialized), guarded by the subsystem Kconfig option.
+3. Iterate with ``STRUCT_SECTION_FOREACH(mytype, it)`` after
+   ``STRUCT_SECTION_DECLARE(mytype);`` at file scope.
+
+Caveat on generated linker scripts: the preprocessed ``.ld.tmp`` files
+only depend on the board script and ``.config``; after editing the
+central fragments during development, remove the ``.tmp`` files (or run
+``make clean``) to force regeneration.
diff --git a/Kconfig b/Kconfig
index e0cfa1c37be..a38ef5dfeb5 100644
--- a/Kconfig
+++ b/Kconfig
@@ -2957,6 +2957,30 @@ config DEBUG_LINK_MAP
                and debugging magic section games, and for seeing which
                pieces of code get eliminated with DEBUG_OPT_UNUSED_SECTIONS.
 
+config ITERABLE_SECTIONS_LINKER_INSERT
+       bool "Collect iterable sections through a supplementary INSERT linker 
script"
+       default n
+       depends on ARCH_TOOLCHAIN_GNU
+       ---help---
+               Zero-touch mode for link-time iterable sections
+               (include/nuttx/iterable_sections.h): instead of the board linker
+               script including <nuttx/linker/common-rom.ld>, the supplementary
+               script <nuttx/linker/common-insert.ld> is added before the board
+               script (Make and CMake builds) and supplements it with GNU ld
+               "INSERT AFTER .text"; subsystems add their ITERABLE_SECTION 
blocks
+               to that central file.
+
+               Leave disabled for boards whose linker script already includes
+               the common fragments.
+
+               Constraints: requires GNU ld, a board script with an output
+               section named ".text", and a MEMORY layout where the ROM/flash
+               region is the first region compatible with read-only sections
+               (GNU ld assigns INSERTed sections to a region by attribute
+               matching, in declaration order).  Boards declaring a generic
+               rwx region at a lower address first (e.g. ITCM at 0x0) must use
+               the common-rom.ld include instead.
+
 config CCACHE
        bool "Use ccache"
        default n
diff --git a/include/nuttx/iterable_sections.h 
b/include/nuttx/iterable_sections.h
new file mode 100644
index 00000000000..a997d936cc9
--- /dev/null
+++ b/include/nuttx/iterable_sections.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+ * include/nuttx/iterable_sections.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/* Iterable sections: link-time registration of struct instances.
+ *
+ * A struct instance defined with STRUCT_SECTION_ITERABLE() in any
+ * compilation unit is placed in a dedicated input section named
+ * "._<struct_type>.static.<varname>".  The board linker script collects
+ * these input sections (sorted by name) into a contiguous array delimited
+ * by the _<struct_type>_list_start/_<struct_type>_list_end symbols by
+ * including <nuttx/linker/common-rom.ld> (const data, inside the .text or
+ * .rodata output section) and <nuttx/linker/common-ram.ld> (mutable
+ * initialized data, inside the .data output section, so that the startup
+ * FLASH-to-RAM copy initializes it).
+ *
+ * The collection is only available on architectures whose linker scripts
+ * are preprocessed with CPP (arm, arm64, risc-v, xtensa, x86_64, tricore)
+ * and on boards whose scripts include the common-*.ld fragments.
+ */
+
+#ifndef __INCLUDE_NUTTX_ITERABLE_SECTIONS_H
+#define __INCLUDE_NUTTX_ITERABLE_SECTIONS_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/compiler.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Define a struct instance inside an iterable section.  A "const"
+ * qualifier may be prepended at the point of use to place the instance in
+ * ROM.  Each instance is aligned to the natural alignment of its type so
+ * that the collected section can be indexed as a plain C array.  The
+ * variable name is part of the input section name so that the linker's
+ * SORT_BY_NAME() defines the iteration order (instances may encode
+ * ordering in their names).
+ */
+
+#define STRUCT_SECTION_ITERABLE(struct_type, varname) \
+  struct struct_type varname \
+  used_data \
+  aligned_data(__alignof__(struct struct_type)) \
+  locate_data("._" #struct_type ".static." #varname)
+
+/* Start/end symbols provided by the linker script fragments */
+
+#define STRUCT_SECTION_START(struct_type) _##struct_type##_list_start
+#define STRUCT_SECTION_END(struct_type)   _##struct_type##_list_end
+
+#define STRUCT_SECTION_START_EXTERN(struct_type) \
+  extern struct struct_type STRUCT_SECTION_START(struct_type)[]
+#define STRUCT_SECTION_END_EXTERN(struct_type) \
+  extern struct struct_type STRUCT_SECTION_END(struct_type)[]
+
+/* Declare both boundary symbols of an iterable section.  Place it at file
+ * scope (followed by a semicolon) in every file that iterates with
+ * STRUCT_SECTION_FOREACH.
+ */
+
+#define STRUCT_SECTION_DECLARE(struct_type) \
+  STRUCT_SECTION_START_EXTERN(struct_type); \
+  STRUCT_SECTION_END_EXTERN(struct_type)
+
+/* Iterate over every instance of an iterable section.  "iterator" is a
+ * pointer variable (FAR struct struct_type *) declared by the caller, as
+ * with list_for_every_entry(); the boundary symbols must be in scope
+ * (STRUCT_SECTION_DECLARE).
+ */
+
+#define STRUCT_SECTION_FOREACH(struct_type, iterator) \
+  for ((iterator) = STRUCT_SECTION_START(struct_type); \
+       (iterator) < STRUCT_SECTION_END(struct_type); \
+       (iterator)++)
+
+/* Get the i-th element of an iterable section (no bounds checking) */
+
+#define STRUCT_SECTION_GET(struct_type, i, dst) \
+  do \
+    { \
+      STRUCT_SECTION_START_EXTERN(struct_type); \
+      *(dst) = &STRUCT_SECTION_START(struct_type)[i]; \
+    } \
+  while (0)
+
+/* Number of elements in an iterable section */
+
+#define STRUCT_SECTION_COUNT(struct_type, dst) \
+  do \
+    { \
+      STRUCT_SECTION_START_EXTERN(struct_type); \
+      STRUCT_SECTION_END_EXTERN(struct_type); \
+      *(dst) = STRUCT_SECTION_END(struct_type) - \
+               STRUCT_SECTION_START(struct_type); \
+    } \
+  while (0)
+
+#endif /* __INCLUDE_NUTTX_ITERABLE_SECTIONS_H */
diff --git a/include/nuttx/linker/common-insert.ld 
b/include/nuttx/linker/common-insert.ld
new file mode 100644
index 00000000000..44a11e06c2a
--- /dev/null
+++ b/include/nuttx/linker/common-insert.ld
@@ -0,0 +1,59 @@
+/****************************************************************************
+ * include/nuttx/linker/common-insert.ld
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/* Supplementary linker script for the iterable sections "zero-touch" mode
+ * (CONFIG_ITERABLE_SECTIONS_LINKER_INSERT): added before the board linker
+ * script by the build system, it supplements -- does not replace -- that
+ * script through the GNU ld INSERT command, so boards need no edit.  The
+ * read-only iterable sections are collected in one output section placed
+ * right after .text.
+ *
+ * Subsystem blocks are added inside the output section below, each
+ * guarded by its Kconfig option (same layout as common-rom.ld):
+ *
+ *   #ifdef CONFIG_MYSUBSYS
+ *   ITERABLE_SECTION(mysubsys_entry)
+ *   #endif
+ *
+ * Constraints of this mode:
+ *  - GNU ld only (INSERT is not supported by the macOS ld64), and this
+ *    script must come BEFORE the board script on the command line (the
+ *    build system guarantees that ordering).
+ *  - The board script must define an output section named ".text".
+ *  - The ROM/flash region must be the first MEMORY region compatible
+ *    with read-only sections: GNU ld assigns the INSERTed section to a
+ *    region by attribute matching in declaration order, so a board that
+ *    declares a generic rwx region at a lower address first (e.g. ITCM
+ *    at 0x0) would pull these sections into the wrong region.  Such
+ *    boards must use the <nuttx/linker/common-rom.ld> include instead.
+ */
+
+#include <nuttx/config.h>
+#include <nuttx/linker/iterable_sections.ld>
+
+SECTIONS
+{
+    .iterable_sections : SUBALIGN(4)
+    {
+    }
+}
+INSERT AFTER .text;
diff --git a/include/nuttx/linker/common-ram.ld 
b/include/nuttx/linker/common-ram.ld
new file mode 100644
index 00000000000..30b56edae83
--- /dev/null
+++ b/include/nuttx/linker/common-ram.ld
@@ -0,0 +1,43 @@
+/****************************************************************************
+ * include/nuttx/linker/common-ram.ld
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/* Mutable (initialized) iterable sections.  Boards opt in by adding,
+ * INSIDE their .data output section (between _sdata and _edata, so the
+ * startup FLASH-to-RAM copy initializes the entries):
+ *
+ *   #include <nuttx/linker/common-ram.ld>
+ *
+ * Every block below is guarded by its subsystem's Kconfig option, so this
+ * file expands to nothing on configurations that do not use iterable
+ * sections (zero binary impact).
+ */
+
+#include <nuttx/config.h>
+#include <nuttx/linker/iterable_sections.ld>
+
+#ifndef CONFIG_ITERABLE_SECTIONS_LINKER_INSERT
+
+/* Extension point for subsystems that need initialized RAM iterable
+ * sections; blocks are added below, each guarded by its Kconfig option.
+ */
+
+#endif /* !CONFIG_ITERABLE_SECTIONS_LINKER_INSERT */
diff --git a/include/nuttx/linker/common-rom.ld 
b/include/nuttx/linker/common-rom.ld
new file mode 100644
index 00000000000..7c0467c25e8
--- /dev/null
+++ b/include/nuttx/linker/common-rom.ld
@@ -0,0 +1,47 @@
+/****************************************************************************
+ * include/nuttx/linker/common-rom.ld
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/* Read-only iterable sections.  Boards opt in by adding, INSIDE their
+ * read-only output section (typically .text, before _etext):
+ *
+ *   #include <nuttx/linker/common-rom.ld>
+ *
+ * Every block below is guarded by its subsystem's Kconfig option, so this
+ * file expands to nothing on configurations that do not use iterable
+ * sections (zero binary impact).  In the INSERT mode
+ * (CONFIG_ITERABLE_SECTIONS_LINKER_INSERT) the sections are collected by
+ * common-insert.ld instead, so this file expands to nothing as well.
+ */
+
+#include <nuttx/config.h>
+#include <nuttx/linker/iterable_sections.ld>
+
+#ifndef CONFIG_ITERABLE_SECTIONS_LINKER_INSERT
+
+/* Subsystem blocks are added below, each guarded by its Kconfig option:
+ *
+ *   #ifdef CONFIG_MYSUBSYS
+ *   ITERABLE_SECTION(mysubsys_entry)
+ *   #endif
+ */
+
+#endif /* !CONFIG_ITERABLE_SECTIONS_LINKER_INSERT */
diff --git a/include/nuttx/linker/iterable_sections.ld 
b/include/nuttx/linker/iterable_sections.ld
new file mode 100644
index 00000000000..433e68e19b9
--- /dev/null
+++ b/include/nuttx/linker/iterable_sections.ld
@@ -0,0 +1,43 @@
+/****************************************************************************
+ * include/nuttx/linker/iterable_sections.ld
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/* CPP macro emitting the linker statements that collect one iterable
+ * section (see include/nuttx/iterable_sections.h).  This file is meant to
+ * be included from linker scripts that are preprocessed with CPP (the
+ * ARCHSCRIPT .tmp rule).
+ *
+ * The macro must be expanded INSIDE an output section (e.g. .text or
+ * .data).  KEEP() protects the entries from --gc-sections and
+ * SORT_BY_NAME() defines the iteration order.
+ */
+
+#ifndef __INCLUDE_NUTTX_LINKER_ITERABLE_SECTIONS_LD
+#define __INCLUDE_NUTTX_LINKER_ITERABLE_SECTIONS_LD
+
+#define ITERABLE_SECTION(name) \
+  . = ALIGN(4); \
+  _##name##_list_start = .; \
+  KEEP(*(SORT_BY_NAME(._##name.static.*))); \
+  _##name##_list_end = .; \
+  . = ALIGN(4);
+
+#endif /* __INCLUDE_NUTTX_LINKER_ITERABLE_SECTIONS_LD */
diff --git a/tools/Config.mk b/tools/Config.mk
index bc5d2ffd542..e767c148269 100644
--- a/tools/Config.mk
+++ b/tools/Config.mk
@@ -861,3 +861,17 @@ LOWERMAP = A a B b C c D d E e F f G g H h I i J j K k L l 
M m N n O o P p Q q R
 
 UPPER_CASE = $(call ULMAP,$(UPPERMAP),$(1))
 LOWER_CASE = $(call ULMAP,$(LOWERMAP),$(1))
+
+# Iterable sections "zero-touch" mode: supplement the board linker script
+# with the central INSERT fragment (include/nuttx/linker/common-insert.ld,
+# which collects the per-subsystem iterable sections) instead of requiring
+# the board script to include common-rom.ld.
+#
+# The fragment is added through ARCHSCRIPT (not EXTRALINKCMDS) because GNU
+# ld requires the INSERT script to come BEFORE the script that defines the
+# target section on the command line; this file is included by the board
+# Make.defs before it appends its own script, so the fragment lands first.
+
+ifeq ($(CONFIG_ITERABLE_SECTIONS_LINKER_INSERT),y)
+  ARCHSCRIPT += 
$(TOPDIR)$(DELIM)include$(DELIM)nuttx$(DELIM)linker$(DELIM)common-insert.ld
+endif

Reply via email to