Skip to content

zephyr_code_relocate() now supports the NOCOPY_DATA flag to inhibit data relocation #86628

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
11 changes: 9 additions & 2 deletions cmake/modules/extensions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -1446,13 +1446,15 @@ endmacro()
# zephyr_code_relocate(LIBRARY my_lib SRAM)
#
# The following optional arguments are supported:
# - NOCOPY: this flag indicates that the file data does not need to be copied
# - NOCOPY: this flag indicates that the file's text section does not need to be copied
# at boot time (For example, for flash XIP).
# - NOCOPY_DATA: this flag indicates that the file's data section (read-write data)
# does not need to be copied at boot time (For example, if it is directly loaded into SRAM).
# - NOKEEP: suppress the generation of KEEP() statements in the linker script,
# to allow any unused code in the given files/library to be discarded.
# - PHDR [program_header]: add program header. Used on Xtensa platforms.
function(zephyr_code_relocate)
set(options NOCOPY NOKEEP)
set(options NOCOPY NOCOPY_DATA NOKEEP)
set(single_args LIBRARY LOCATION PHDR FILTER)
set(multi_args FILES)
cmake_parse_arguments(CODE_REL "${options}" "${single_args}"
Expand Down Expand Up @@ -1516,6 +1518,11 @@ function(zephyr_code_relocate)
else()
set(flag_list NOCOPY)
endif()
if(NOT CODE_REL_NOCOPY_DATA)
list(APPEND flag_list COPYDATA)
else()
list(APPEND flag_list NOCOPYDATA)
endif()
if(CODE_REL_NOKEEP)
list(APPEND flag_list NOKEEP)
endif()
Expand Down
17 changes: 14 additions & 3 deletions doc/kernel/code-relocation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@ you can pass ``NOKEEP`` to your ``zephyr_code_relocate()`` call.
The example above will help ensure that any unused code found in the .text
sections of ``file1.c`` will not stick to SRAM2.

NOCOPY flag
===========
NOCOPY and NOCOPY_DATA flags
============================

When a ``NOCOPY`` option is passed to the ``zephyr_code_relocate()`` function,
the relocation code is not generated in ``code_relocation.c``. This flag can be
Expand All @@ -149,13 +149,24 @@ XIP area.

This example will place the .text section of the ``xip_external_flash.c`` file
to the ``EXTFLASH`` memory region where it will be executed from (XIP). The
.data will be relocated as usual into SRAM.
.data will be relocated as usual into SRAM, since flash in XIP mode does not
allow random write access and variables do not have to persist.

.. code-block:: none

zephyr_code_relocate(FILES src/xip_external_flash.c LOCATION EXTFLASH_TEXT NOCOPY)
zephyr_code_relocate(FILES src/xip_external_flash.c LOCATION SRAM_DATA)

You can additionally specify ``NOCOPY_DATA`` if you do not want .data to be copied into SRAM.
This can be useful if it is already loaded into SRAM, e.g. by the Linux kernel
using the `remoteproc framework <https://docs.kernel.org/staging/remoteproc.html>`_.
The following example demonstrates how to place an entire file into the SRAM section without
copying.

.. code-block:: none

zephyr_code_relocate(FILES src/file1.c LOCATION SRAM NOCOPY NOCOPY_DATA)

Relocating libraries
====================

Expand Down
24 changes: 13 additions & 11 deletions scripts/build/gen_relocate_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@
- If the memory type is appended with _DATA / _TEXT/ _RODATA/ _BSS only the
selected memory is placed in the required memory region. Others are
ignored.
- COPY/NOCOPY defines whether the script should generate the relocation code in
code_relocation.c or not
- COPY/NOCOPY defines whether the script should generate the relocation code for text segment
symbols in code_relocation.c or not
- COPYDATA/NOCOPYDATA defines whether the script should generate the relocation code for data segment
symbols in code_relocation.c or not
- NOKEEP will suppress the default behavior of marking every relocated symbol
with KEEP() in the generated linker script.
Expand Down Expand Up @@ -389,9 +391,10 @@ def generate_linker_script(linker_file, sram_data_linker_file, sram_bss_linker_f

for memory_type, full_list_of_sections in \
sorted(complete_list_of_sections.items()):

is_copy = bool("|COPY" in memory_type)
memory_type = memory_type.split("|", 1)[0]
memory_type = memory_type.split("|")
is_copy = bool("COPY" in memory_type)
is_copy_data = bool("COPYDATA" in memory_type)
memory_type = memory_type[0]

if region_is_default_ram(memory_type) and is_copy:
gen_string += MPU_RO_REGION_START.format(memory_type.lower(), memory_type.upper())
Expand All @@ -404,10 +407,10 @@ def generate_linker_script(linker_file, sram_data_linker_file, sram_bss_linker_f
gen_string += MPU_RO_REGION_END.format(memory_type.lower())

if region_is_default_ram(memory_type):
gen_string_sram_data += string_create_helper(SectionKind.DATA, memory_type, full_list_of_sections, 1, 1, phdrs)
gen_string_sram_data += string_create_helper(SectionKind.DATA, memory_type, full_list_of_sections, 1, is_copy_data, phdrs)
gen_string_sram_bss += string_create_helper(SectionKind.BSS, memory_type, full_list_of_sections, 0, 1, phdrs)
else:
gen_string += string_create_helper(SectionKind.DATA, memory_type, full_list_of_sections, 1, 1, phdrs)
gen_string += string_create_helper(SectionKind.DATA, memory_type, full_list_of_sections, 1, is_copy_data, phdrs)
gen_string += string_create_helper(SectionKind.BSS, memory_type, full_list_of_sections, 0, 1, phdrs)

# finally writing to the linker file
Expand Down Expand Up @@ -623,10 +626,9 @@ def main():

code_generation = {"copy_code": '', "zero_code": '', "extern": ''}
for mem_type, list_of_sections in sorted(complete_list_of_sections.items()):

if "|COPY" in mem_type:
mem_type = mem_type.split("|", 1)[0]
code_generation = generate_memcpy_code(mem_type,
mem_type = mem_type.split("|")
if "COPY" in mem_type:
code_generation = generate_memcpy_code(mem_type[0],
list_of_sections, code_generation)

dump_header_file(args.output_code, code_generation)
Expand Down
Loading