From b1cbfc92fb3f9831425ada9eb2242b15f669ba49 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Fri, 27 Jun 2025 13:05:40 +0800 Subject: [PATCH 1/8] manifest: use latest zephyr branch Switch to 4.2.0-rc3 + outstanding PRs. --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 16a78b2f..8e94fe61 100644 --- a/west.yml +++ b/west.yml @@ -21,7 +21,7 @@ manifest: projects: - name: zephyr remote: arduino - revision: zephyr-arduino-20250529 + revision: zephyr-arduino-20250714 import: name-allowlist: - cmsis From ca3ea3aa737369930f2ad9efc96cd25a9ad061eb Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Fri, 27 Jun 2025 13:14:25 +0800 Subject: [PATCH 2/8] package_core: accept licenses --- .github/workflows/package_core.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/package_core.yml b/.github/workflows/package_core.yml index 2fbdbf6e..62be1487 100644 --- a/.github/workflows/package_core.yml +++ b/.github/workflows/package_core.yml @@ -29,7 +29,7 @@ jobs: - name: Initialize Zephyr environment run: | - ./extra/bootstrap.sh -o=--filter=tree:0 + yes | ./extra/bootstrap.sh -o=--filter=tree:0 echo "CORE_TAG=$(git describe --always)" >> "$GITHUB_ENV" echo "CORE_ARTIFACT=ArduinoCore-zephyr-$(git describe --always)" >> "$GITHUB_ENV" echo "BOARD_VARIANTS=$(extra/get_board_details.sh | jq -cr 'sort_by(.variant)')" >> "$GITHUB_ENV" From b12eb1c241535b25c7f0cc3473197034c7327118 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Tue, 8 Jul 2025 15:50:02 +0200 Subject: [PATCH 3/8] giga: fix wrong remote-endpoint DTS definition --- .../arduino_giga_r1_stm32h747xx_m7.overlay | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/variants/arduino_giga_r1_stm32h747xx_m7/arduino_giga_r1_stm32h747xx_m7.overlay b/variants/arduino_giga_r1_stm32h747xx_m7/arduino_giga_r1_stm32h747xx_m7.overlay index f397b784..1bce0bdf 100644 --- a/variants/arduino_giga_r1_stm32h747xx_m7/arduino_giga_r1_stm32h747xx_m7.overlay +++ b/variants/arduino_giga_r1_stm32h747xx_m7/arduino_giga_r1_stm32h747xx_m7.overlay @@ -37,7 +37,7 @@ port { gc2145_ep_out: endpoint { - remote-endpoint = <&dcmi_ep_in>; + remote-endpoint-label = "dcmi_ep_in"; }; }; }; From 6c82ffd09302f3d50044af2184a77bb76b657805 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Fri, 11 Jul 2025 17:20:32 +0200 Subject: [PATCH 4/8] build: replace gdb/readelf with extra/gen_provides.py Add a new Python script `extra/gen_provides.py` to generate the provides.ld file for linked builds, replacing the previous approach that used 'readelf' and 'gdb'. Signed-off-by: Luca Burelli --- extra/build.sh | 28 ++--- extra/gen_provides.py | 247 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 257 insertions(+), 18 deletions(-) create mode 100755 extra/gen_provides.py diff --git a/extra/build.sh b/extra/build.sh index 90321ee5..adb5adef 100755 --- a/extra/build.sh +++ b/extra/build.sh @@ -90,23 +90,15 @@ for ext in elf bin hex; do done # Generate the provides.ld file for linked builds -echo "Exporting provides.ld" -READELF=${ZEPHYR_SDK_INSTALL_DIR}/arm-zephyr-eabi/bin/arm-zephyr-eabi-readelf -GDB=${ZEPHYR_SDK_INSTALL_DIR}/arm-zephyr-eabi/bin/arm-zephyr-eabi-gdb -$READELF --wide -s ${BUILD_DIR}/zephyr/zephyr.elf | grep FUNC | awk -F' ' '{print "PROVIDE("$8" = 0x"$2");"}' > ${VARIANT_DIR}/provides.ld -$READELF --wide -s ${BUILD_DIR}/zephyr/zephyr.elf | grep kheap_llext_heap | awk -F' ' '{print "PROVIDE("$8" = 0x"$2");"}' >> ${VARIANT_DIR}/provides.ld -$READELF --wide -s ${BUILD_DIR}/zephyr/zephyr.elf | grep kheap_llext_heap | awk -F' ' '{print "PROVIDE(kheap_llext_heap_size = "$3");"}' >> ${VARIANT_DIR}/provides.ld -$READELF --wide -s ${BUILD_DIR}/zephyr/zephyr.elf | grep kheap__system_heap | awk -F' ' '{print "PROVIDE("$8" = 0x"$2");"}' >> ${VARIANT_DIR}/provides.ld -$READELF --wide -s ${BUILD_DIR}/zephyr/zephyr.elf | grep kheap__system_heap | awk -F' ' '{print "PROVIDE(kheap__system_heap_size = "$3");"}' >> ${VARIANT_DIR}/provides.ld -cat ${BUILD_DIR}/zephyr/zephyr.map | grep __device_dts_ord | grep -v rodata | grep -v llext_const_symbol | awk -F' ' '{print "PROVIDE("$2" = "$1");"}' >> ${VARIANT_DIR}/provides.ld -#TEXT_START=`cat variants/$variant/$variant.overlay | grep user_sketch: | cut -f2 -d"@" | cut -f1 -d"{"` -TEXT_START=`$GDB --quiet -ex "p/x sketch_base_addr" ${BUILD_DIR}/zephyr/zephyr.elf -ex "exit" | grep "= 0x" | cut -f 2 -d"="` -echo "PROVIDE(_sketch_start = $TEXT_START);" >> ${VARIANT_DIR}/provides.ld - -sed -i 's/PROVIDE(malloc =/PROVIDE(__wrap_malloc =/g' ${VARIANT_DIR}/provides.ld -sed -i 's/PROVIDE(free =/PROVIDE(__wrap_free =/g' ${VARIANT_DIR}/provides.ld -sed -i 's/PROVIDE(realloc =/PROVIDE(__wrap_realloc =/g' ${VARIANT_DIR}/provides.ld -sed -i 's/PROVIDE(calloc =/PROVIDE(__wrap_calloc =/g' ${VARIANT_DIR}/provides.ld -sed -i 's/PROVIDE(random =/PROVIDE(__wrap_random =/g' ${VARIANT_DIR}/provides.ld +echo "Generating exported symbol scripts" +extra/gen_provides.py "${BUILD_DIR}/zephyr/zephyr.elf" -LF \ + "+kheap_llext_heap" \ + "+kheap__system_heap" \ + "*sketch_base_addr=_sketch_start" \ + "malloc=__wrap_malloc" \ + "free=__wrap_free" \ + "realloc=__wrap_realloc" \ + "calloc=__wrap_calloc" \ + "random=__wrap_random" > ${VARIANT_DIR}/provides.ld cmake -P extra/gen_arduino_files.cmake $variant diff --git a/extra/gen_provides.py b/extra/gen_provides.py new file mode 100755 index 00000000..09db69c7 --- /dev/null +++ b/extra/gen_provides.py @@ -0,0 +1,247 @@ +#!/usr/bin/env python +import argparse +import hashlib +import itertools +import os +import re +import struct +import sys +import textwrap +import traceback + +from elftools.construct.macros import UNInt32, UNInt64 +from elftools.common.exceptions import ELFError +from elftools.common.utils import parse_cstring_from_stream, struct_parse +from elftools.elf.elffile import ELFFile +from elftools.elf.sections import SymbolTableSection + + +NativePtr = None + +def get_str_at(elf, addr): + for section in elf.iter_sections(): + if section['sh_type'] == 'SHT_NOBITS' or addr < section['sh_addr'] or addr >= section['sh_addr'] + section['sh_size']: + continue + + file_offset = section['sh_offset'] + addr - section['sh_addr'] + return parse_cstring_from_stream(elf.stream, file_offset).decode('utf-8', errors='replace') + + return None + +def get_ptr_at(elf, addr): + for section in elf.iter_sections(): + if section['sh_type'] == 'SHT_NOBITS' or addr < section['sh_addr'] or addr >= section['sh_addr'] + section['sh_size']: + continue + + file_offset = section['sh_offset'] + addr - section['sh_addr'] + return struct_parse(NativePtr, elf.stream, file_offset) + + return None + +def get_all_syms(elf): + syms = {} + for section in elf.iter_sections(): + if not isinstance(section, SymbolTableSection): + continue + for symbol in section.iter_symbols(): + syms[symbol.name] = symbol + + return syms + +def get_llext_syms(elf): + syms = {} + for section in elf.iter_sections(): + if not isinstance(section, SymbolTableSection): + continue + for symbol in section.iter_symbols(): + if symbol.name.startswith("__llext_sym_"): + llext_sym_addr = symbol['st_value'] + sym_name = get_str_at(elf, get_ptr_at(elf, llext_sym_addr)) + sym_value = get_ptr_at(elf, llext_sym_addr + NativePtr.length) + if sym_value: + syms[sym_name] = sym_value + + return syms + +def main(): + global NativePtr + + # parse the command-line arguments and invoke ReadElf + argparser = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description="Extract symbols from ELF files", + epilog=textwrap.dedent(f'''\ + SYMBOL DEFINITION + ----------------- + Each describes symbol names to extract. This can be an exact symbol + name, a regular expression, or a rename expression. Also, the symbol can be + dereferenced, so that the pointer value stored at the symbol address is + exported, or the size of the symbol can be exported as well. + The exact rules are as follows: + + - if starts with a slash ('/'), the rest is treated as a regexp. All + symbols matching the regexp will be extracted. Can be combined with + dereferencing, but not renames. + - if does not start with a slash, but contains an equals sign ('='), + it is treated as a rename expression, where the part before the equals + is the symbol name to extract, and the part after the equals is + the new name to use in the output. + - if the first char of is an asterisk ('*'), the symbol is + dereferenced, i.e. the pointer value stored at the symbol address is + exported instead of the symbol address itself. + - if the first char of is a plus ('+'), in addition to itself, a + second symbol called '_size' is defined with the size of the + current symbol. + + For example, the symbol definition: + + *sketch_base_addr=__sketch_start + + will export the value stored at the address of the 'sketch_base_addr' symbol + as '__sketch_start', while + + /__device_dts_ord_.* + + will export all symbols starting with '__device_dts_ord_' as-is. Also, + + +kheap_llext_heap + + will export the value of the 'kheap_llext_heap' symbol and its size in a + separate 'kheap_llext_heap_size' symbol. + ''')) + argparser.add_argument('-v', '--verbose', + action='store_true', + help='Write the source of the symbol definition as a comment') + argparser.add_argument('-L', '--llext', + action='store_true', + help='Extract symbols from the __llext_sym_* symbols') + argparser.add_argument('-F', '--funcs', + action='store_true', + help='Extract all public functions') + argparser.add_argument('file', + help='ELF file to parse') + argparser.add_argument('syms', nargs='*', + help='Symbols to export') + + args = argparser.parse_intermixed_args() + + exact_syms = set() + regex_syms = set() + deref_syms = set() + sized_syms = set() + rename_map = {} + for sym in args.syms: + sym_class = None + if sym[0] == '/': + # Regexp + sym = f"^{sym[1:]}$" + sym_class = "regexp" + elif '=' in sym: + # Rename expression + sym, new_sym = sym.split('=') + sym_class = "rename" + else: + # Exact symbol + sym_class = "exact" + + if sym[0] == '*': + # Dereference symbol + sym = sym[1:] + deref_syms.add(sym) + elif sym[0] == '+': + # Store size as well + sym = sym[1:] + sized_syms.add(sym) + + if sym_class == "regexp": + regex_syms.add(sym) + else: + exact_syms.add(sym) + if sym_class == "rename": + rename_map[sym] = new_sym + + with open(args.file, 'rb') as file: + try: + elf_sha = hashlib.sha256(file.read()).hexdigest() + elf = ELFFile(file) + except ELFError as ex: + sys.stdout.flush() + sys.stderr.write('ELF error: %s\n' % ex) + traceback.print_exc() + sys.exit(1) + + if elf.elfclass == 32: + NativePtr = UNInt32("ptr") + elif elf.elfclass == 64: + NativePtr = UNInt64("ptr") + + all_syms = get_all_syms(elf) + out_syms = {} + fail = False + + for name, sym in all_syms.items(): + value = None + comment = [] + if name in exact_syms or any(re.match(r, name) for r in regex_syms): + comment = "cmd_line" + value = sym['st_value'] + elif args.funcs and (sym['st_info']['type'] == 'STT_FUNC' + and sym['st_info']['bind'] == 'STB_GLOBAL'): + comment = "public_fn" + value = sym['st_value'] + elif args.llext and name.startswith("__llext_sym_"): + comment = "llext_sym" + llext_sym_addr = sym['st_value'] + name = get_str_at(elf, get_ptr_at(elf, llext_sym_addr)) + value = get_ptr_at(elf, llext_sym_addr + NativePtr.length) + + if name in deref_syms: + value = get_ptr_at(elf, value) + if name in rename_map: + name = rename_map[name] + + if value is None: + continue + + if name in out_syms: + if out_syms[name][0] != value: + sys.stderr.write( + f"Warning: duplicate symbol {name} with different values: " + f"{out_syms[name][0]:#010x} vs {value:#010x}\n") + fail = True + out_syms[name][1].append(comment) + else: + out_syms[name] = (value, [comment]) + + if name in sized_syms: + out_syms[name + "_size"] = (sym['st_size'], [f"size of {name}"]) + + if not out_syms: + sys.stderr.write("No symbols found matching the criteria.\n") + fail = True + + if fail: + sys.exit(1) + + print(f""" +/* + * Automatically generated by {os.path.basename(sys.argv[0])}, do not edit! + * + * Source: {args.file} + * SHA256: {elf_sha} + */ +""") + sym_comment = nul_comment = "" + for name, (value, comments) in sorted(out_syms.items(), key=lambda x: x[0]): + if args.verbose: + comment = ', '.join(sorted(comments)) + sym_comment = f"/* {comment} */" + nul_comment = f" ({comment})" + if value: + print(f"PROVIDE({name} = {value:#010x});{sym_comment}") + else: + print(f"/* NULL {name}{nul_comment} */") + +#------------------------------------------------------------------------------- +if __name__ == '__main__': + main() From 8f1af8bdce2ae98ba3e4328ab2a20a9bef9d121d Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Fri, 11 Jul 2025 15:20:32 +0200 Subject: [PATCH 5/8] linked: enforce maximum size of sketch in linker script Stop the build when a sketch exceeds the maximum size defined by the 'user_sketch' node in the device tree. Signed-off-by: Luca Burelli --- extra/build.sh | 1 + loader/main.c | 1 + variants/_linked/linker_script.ld | 7 +++---- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/extra/build.sh b/extra/build.sh index adb5adef..c606f545 100755 --- a/extra/build.sh +++ b/extra/build.sh @@ -95,6 +95,7 @@ extra/gen_provides.py "${BUILD_DIR}/zephyr/zephyr.elf" -LF \ "+kheap_llext_heap" \ "+kheap__system_heap" \ "*sketch_base_addr=_sketch_start" \ + "*sketch_max_size=_sketch_max_size" \ "malloc=__wrap_malloc" \ "free=__wrap_free" \ "realloc=__wrap_realloc" \ diff --git a/loader/main.c b/loader/main.c index f348f1da..643da9d7 100644 --- a/loader/main.c +++ b/loader/main.c @@ -66,6 +66,7 @@ void llext_entry(void *arg0, void *arg1, void *arg2) __attribute__((retain)) const uintptr_t sketch_base_addr = DT_REG_ADDR(DT_GPARENT(DT_NODELABEL(user_sketch))) + DT_REG_ADDR(DT_NODELABEL(user_sketch)); +__attribute__((retain)) const uintptr_t sketch_max_size = DT_REG_SIZE(DT_NODELABEL(user_sketch)); static int loader(const struct shell *sh) { diff --git a/variants/_linked/linker_script.ld b/variants/_linked/linker_script.ld index 18a5ee6f..64c3e86d 100644 --- a/variants/_linked/linker_script.ld +++ b/variants/_linked/linker_script.ld @@ -1,10 +1,9 @@ INCLUDE "provides.ld" -PROVIDE(TEXT_LENGTH = 0x100000); - MEMORY { - FLASH (rx) : ORIGIN = _sketch_start + 16, LENGTH = TEXT_LENGTH + /* 16 below compensates for the zsk header that is added before the .bin */ + FLASH (rx) : ORIGIN = _sketch_start + 16, LENGTH = _sketch_max_size - 16 RAM (rwx) : ORIGIN = kheap_llext_heap, LENGTH = kheap_llext_heap_size } @@ -117,4 +116,4 @@ SECTIONS { .got : { KEEP(*(.got .got.* .got.plt .got.plt*)) } -} \ No newline at end of file +} From af931dd852a4bf4c5ab648a4d743fdfab1c20275 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Tue, 15 Jul 2025 15:02:49 +0200 Subject: [PATCH 6/8] platform: remove useless vars - compiler.zephyr.arch.define is always included in generated cflags/cxxflags - compiler.zephyr is always empty - build.extra_extra_ldflags is not used anywhere --- boards.txt | 23 ----------------------- platform.txt | 9 +++------ 2 files changed, 3 insertions(+), 29 deletions(-) diff --git a/boards.txt b/boards.txt index b36a45f8..01b4dc17 100644 --- a/boards.txt +++ b/boards.txt @@ -19,14 +19,12 @@ giga.build.variant=arduino_giga_r1_stm32h747xx_m7 giga.build.mcu=cortex-m7 giga.build.fpu=-mfpu=fpv5-d16 giga.build.architecture=cortex-m7 -giga.compiler.zephyr.arch.define=-DCORE_CM7 giga.build.float-abi=-mfloat-abi=softfp giga.build.extra_flags= giga.build.postbuild.cmd="{tools.imgtool.path}/{tools.imgtool.cmd}" exit giga.build.architecture=cortex-m7 giga.build.board=ARDUINO_GIGA -giga.compiler.zephyr= giga.vid.0=0x2341 giga.pid.0=0x0066 giga.upload_port.0.vid=0x2341 @@ -85,14 +83,12 @@ nano33ble.build.variant=arduino_nano_33_ble_nrf52840_sense nano33ble.build.mcu=cortex-m4 nano33ble.build.fpu=-mfpu=fpv4-sp-d16 nano33ble.build.architecture=cortex-m4 -nano33ble.compiler.zephyr.arch.define= nano33ble.build.float-abi=-mfloat-abi=hard nano33ble.build.extra_flags= nano33ble.build.postbuild.cmd="{tools.imgtool.path}/{tools.imgtool.cmd}" exit nano33ble.build.architecture=cortex-m4 nano33ble.build.board=ARDUINO_NANO33BLE -nano33ble.compiler.zephyr= nano33ble.vid.0=0x2341 nano33ble.pid.0=0x035a nano33ble.upload_port.0.vid=0x2341 @@ -149,19 +145,16 @@ ek_ra8d1.build.variant=ek_ra8d1_r7fa8d1bhecbd ek_ra8d1.build.mcu=cortex-m85+nomve ek_ra8d1.build.fpu=-mfpu=fpv5-d16 ek_ra8d1.build.architecture=cortex-m85+nomve -ek_ra8d1.compiler.zephyr.arch.define= ek_ra8d1.build.float-abi=-mfloat-abi=hard ek_ra8d1.build.extra_flags= ek_ra8d1.build.postbuild.cmd="{tools.imgtool.path}/{tools.imgtool.cmd}" exit ek_ra8d1.build.architecture=cortex-m85+nomve ek_ra8d1.build.board=EK_RA8D1 -ek_ra8d1.compiler.zephyr.arch.define= #ek_ra8d1.recipe.hooks.objcopy.postobjcopy.4.pattern=cp {build.variant.path}/flasher.jlink "{build.path}/flasher.jlink" #ek_ra8d1.recipe.hooks.objcopy.postobjcopy.5.pattern=sed -i 's|SKETCH|"{build.path}/{build.project_name}.llext.dfu.bin"|g' "{build.path}/flasher.jlink" -ek_ra8d1.compiler.zephyr= ek_ra8d1.vid.0=0x2341 ek_ra8d1.pid.0=0x0077 ek_ra8d1.upload_port.0.vid=0x2341 @@ -208,14 +201,11 @@ frdm_mcxn947.build.variant=frdm_mcxn947_mcxn947_cpu0 frdm_mcxn947.build.mcu=cortex-m33 frdm_mcxn947.build.fpu=-mfpu=fpv5-sp-d16 frdm_mcxn947.build.architecture=cortex-m33 -frdm_mcxn947.compiler.zephyr.arch.define= frdm_mcxn947.build.float-abi=-mfloat-abi=hard frdm_mcxn947.build.extra_flags= frdm_mcxn947.build.postbuild.cmd="{tools.imgtool.path}/{tools.imgtool.cmd}" exit frdm_mcxn947.build.board=FRDM_MCXN947 -frdm_mcxn947.compiler.zephyr.arch.define= -frdm_mcxn947.compiler.zephyr= frdm_mcxn947.vid.0=0x1fc9 frdm_mcxn947.pid.0=0x0143 frdm_mcxn947.upload_port.0.vid=0x1fc9 @@ -262,14 +252,12 @@ portentah7.build.variant=arduino_portenta_h7_stm32h747xx_m7 portentah7.build.mcu=cortex-m7 portentah7.build.fpu=-mfpu=fpv5-d16 portentah7.build.architecture=cortex-m7 -portentah7.compiler.zephyr.arch.define=-DCORE_CM7 portentah7.build.float-abi=-mfloat-abi=softfp portentah7.build.extra_flags= portentah7.build.postbuild.cmd="{tools.imgtool.path}/{tools.imgtool.cmd}" exit portentah7.build.architecture=cortex-m7 portentah7.build.board=ARDUINO_PORTENTA_H7 -portentah7.compiler.zephyr= portentah7.vid.0=0x2341 portentah7.pid.0=0x005b portentah7.upload_port.0.vid=0x2341 @@ -328,14 +316,11 @@ frdm_rw612.build.variant=frdm_rw612_rw612 frdm_rw612.build.mcu=cortex-m33+nodsp frdm_rw612.build.fpu=-mfpu=fpv5-sp-d16 frdm_rw612.build.architecture=cortex-m33+nodsp -frdm_rw612.compiler.zephyr.arch.define= frdm_rw612.build.float-abi=-mfloat-abi=hard frdm_rw612.build.extra_flags= frdm_rw612.build.postbuild.cmd="{tools.imgtool.path}/{tools.imgtool.cmd}" exit frdm_rw612.build.board=FRDM_RW612 -frdm_rw612.compiler.zephyr.arch.define= -frdm_rw612.compiler.zephyr= frdm_rw612.vid.0=0x1fc9 frdm_rw612.pid.0=0x0143 frdm_rw612.upload_port.0.vid=0x1fc9 @@ -381,14 +366,12 @@ niclasense.build.variant=arduino_nicla_sense_me_nrf52832 niclasense.build.mcu=cortex-m4 niclasense.build.fpu=-mfpu=fpv4-sp-d16 niclasense.build.architecture=cortex-m4 -niclasense.compiler.zephyr.arch.define= niclasense.build.float-abi=-mfloat-abi=hard niclasense.build.extra_flags= niclasense.build.postbuild.cmd="{tools.imgtool.path}/{tools.imgtool.cmd}" exit niclasense.build.architecture=cortex-m4 niclasense.build.board=ARDUINO_NICLA_SENSE_ME -niclasense.compiler.zephyr= niclasense.vid.0=0x2341 niclasense.pid.0=0x0360 niclasense.upload_port.0.vid=0x2341 @@ -449,7 +432,6 @@ portentac33.menu.mode.linked=linked portentac33.menu.mode.linked.build.extra_ldflags=-lc -lm -lgcc -L{build.variant.path} -Wl,--wrap=random -Wl,--wrap=calloc -Wl,--wrap=free -Wl,--wrap=malloc -Wl,--wrap=realloc portentac33.menu.mode.linked.build.llext_link_flags= -portentac33.menu.mode.linked.build.suffix=_linked portentac33.menu.mode.linked.build.ldscript={runtime.platform.path}/variants/_linked/linker_script.ld portentac33.menu.mode.linked.upload.extension=bin-zsk.bin portentac33.menu.mode.linked.postbuild_mode=-prelinked @@ -461,14 +443,11 @@ portentac33.build.variant=arduino_portenta_c33_r7fa6m5bh3cfc portentac33.build.mcu=cortex-m33 portentac33.build.fpu=-mfpu=fpv5-sp-d16 portentac33.build.architecture=cortex-m33 -portentac33.compiler.zephyr.arch.define= portentac33.build.float-abi=-mfloat-abi=hard portentac33.build.extra_flags= portentac33.build.postbuild.cmd="{tools.imgtool.path}/{tools.imgtool.cmd}" exit portentac33.build.board=ARDUINO_PORTENTA_C33 -portentac33.compiler.zephyr.arch.define= -portentac33.compiler.zephyr= portentac33.vid.0=0x2341 portentac33.pid.0=0x0068 portentac33.upload_port.0.vid=0x2341 @@ -517,14 +496,12 @@ opta.build.variant=arduino_opta_stm32h747xx_m7 opta.build.mcu=cortex-m7 opta.build.fpu=-mfpu=fpv5-d16 opta.build.architecture=cortex-m7 -opta.compiler.zephyr.arch.define=-DCORE_CM7 opta.build.float-abi=-mfloat-abi=softfp opta.build.extra_flags= opta.build.postbuild.cmd="{tools.imgtool.path}/{tools.imgtool.cmd}" exit opta.build.architecture=cortex-m7 opta.build.board=ARDUINO_OPTA -opta.compiler.zephyr= opta.vid.0=0x2341 opta.pid.0=0x0064 opta.upload_port.0.vid=0x2341 diff --git a/platform.txt b/platform.txt index a85a76de..c3598d30 100644 --- a/platform.txt +++ b/platform.txt @@ -17,13 +17,13 @@ compiler.warning_flags.all=-Wall -Wextra compiler.path={build.compiler_path} compiler.c.cmd={build.crossprefix}gcc -compiler.c.flags=-g -c {compiler.warning_flags} {compiler.zephyr.macros} "@{compiler.zephyr.cflags_file}" {compiler.zephyr.arch.define} -MMD -mcpu={build.mcu} {build.float-abi} {build.fpu} +compiler.c.flags=-g -c {compiler.warning_flags} {compiler.zephyr.macros} "@{compiler.zephyr.cflags_file}" -MMD -mcpu={build.mcu} {build.float-abi} {build.fpu} compiler.c.elf.cmd={build.crossprefix}g++ compiler.c.elf.flags={build.llext_link_flags} -Wl,--gc-sections -mcpu={build.mcu} {build.float-abi} {build.fpu} -std=gnu++17 compiler.S.cmd={build.crossprefix}g++ compiler.S.flags=-c -x assembler-with-cpp -mcpu={build.mcu} {build.fpu} compiler.cpp.cmd={build.crossprefix}g++ -compiler.cpp.flags=-g -Os -std=gnu++17 -c {compiler.warning_flags} {compiler.zephyr.macros} "@{compiler.zephyr.cxxflags_file}" {compiler.zephyr.common_ldflags} {compiler.zephyr.extra_ldflags} {compiler.zephyr.common_cxxflags} {compiler.zephyr.extra_cxxflags} {compiler.zephyr.arch.define} -MMD -mcpu={build.mcu} {build.float-abi} {build.fpu} +compiler.cpp.flags=-g -Os -std=gnu++17 -c {compiler.warning_flags} {compiler.zephyr.macros} "@{compiler.zephyr.cxxflags_file}" {compiler.zephyr.common_ldflags} {compiler.zephyr.extra_ldflags} {compiler.zephyr.common_cxxflags} {compiler.zephyr.extra_cxxflags} -MMD -mcpu={build.mcu} {build.float-abi} {build.fpu} compiler.ar.cmd={build.crossprefix}ar compiler.ar.flags=rcs compiler.objcopy.cmd= @@ -49,12 +49,9 @@ compiler.zephyr.extra_ldflags=-lstdc++ -lsupc++ # this can be overriden in boards.txt build.extra_flags= build.extra_ldflags= -compiler.zephyr= build.ldscript={runtime.platform.path}/variants/_llext/linker_script.ld build.llext_link_flags=-r -e main -build.extra_extra_ldflags= -build.suffix= upload.extension=elf-zsk.bin postbuild_debug= postbuild_mode= @@ -99,7 +96,7 @@ recipe.S.o.pattern="{compiler.path}{compiler.S.cmd}" {compiler.S.flags} -DARDUIN recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" ## Combine gc-sections, archives, and objects -recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" "-L{build.path}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} {build.extra_flags} {build.extra_ldflags} {compiler.zephyr.common_ldflags} "-T{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" --specs=picolibc.specs --specs=nosys.specs {compiler.ldflags} -o "{build.path}/{build.project_name}_debug.elf" {object_files} -Wl,--start-group "{build.path}/{archive_file}" {compiler.zephyr} {compiler.zephyr.extra_ldflags} {compiler.libraries.ldflags} -Wl,--end-group +recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" "-L{build.path}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} {build.extra_flags} {build.extra_ldflags} {compiler.zephyr.common_ldflags} "-T{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" --specs=picolibc.specs --specs=nosys.specs {compiler.ldflags} -o "{build.path}/{build.project_name}_debug.elf" {object_files} -Wl,--start-group "{build.path}/{archive_file}" {compiler.zephyr.extra_ldflags} {compiler.libraries.ldflags} -Wl,--end-group recipe.hooks.linking.postlink.1.pattern="{compiler.path}{build.crossprefix}strip" --strip-debug "{build.path}/{build.project_name}_debug.elf" -o "{build.path}/{build.project_name}.elf" ## Create eeprom From 289280df8b9b568d770c57ceda612b8eba528002 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Tue, 15 Jul 2025 16:15:13 +0200 Subject: [PATCH 7/8] platform: generic 'static' and 'dynamic' builds Refactor C33 'linked' mode into a common 'static' build, and the usual LLEXT mode as 'dynamic' build. --- boards.txt | 20 +++++------ extra/package_core.inc | 3 +- platform.txt | 33 +++++++++++++------ .../dynamic.ld} | 0 .../linker_script.ld => _ldscripts/static.ld} | 0 5 files changed, 32 insertions(+), 24 deletions(-) rename variants/{_llext/linker_script.ld => _ldscripts/dynamic.ld} (100%) rename variants/{_linked/linker_script.ld => _ldscripts/static.ld} (100%) diff --git a/boards.txt b/boards.txt index 01b4dc17..ff52cb7e 100644 --- a/boards.txt +++ b/boards.txt @@ -1,5 +1,7 @@ menu.debug=Debug -menu.mode=Mode +menu.link_mode=Link mode + +########################################################################################## giga.name=Arduino Giga R1 giga.build.core=arduino @@ -423,18 +425,12 @@ portentac33.build.compiler_path={runtime.tools.arm-zephyr-eabi-0.16.8.path}/bin/ portentac33.menu.debug.false=Standard portentac33.menu.debug.true=Debug +portentac33.menu.debug.true.build.zsk_args.debug=-debug -portentac33.menu.debug.false.postbuild_debug= -portentac33.menu.debug.true.postbuild_debug=-debug - -portentac33.menu.mode.llext=llext -portentac33.menu.mode.linked=linked - -portentac33.menu.mode.linked.build.extra_ldflags=-lc -lm -lgcc -L{build.variant.path} -Wl,--wrap=random -Wl,--wrap=calloc -Wl,--wrap=free -Wl,--wrap=malloc -Wl,--wrap=realloc -portentac33.menu.mode.linked.build.llext_link_flags= -portentac33.menu.mode.linked.build.ldscript={runtime.platform.path}/variants/_linked/linker_script.ld -portentac33.menu.mode.linked.upload.extension=bin-zsk.bin -portentac33.menu.mode.linked.postbuild_mode=-prelinked +portentac33.menu.link_mode.dynamic=Dynamic +portentac33.menu.link_mode.static=Static +portentac33.menu.link_mode.static.build.link_mode=static +portentac33.menu.link_mode.static.upload.extension=bin-zsk.bin portentac33.build.zephyr_target=arduino_portenta_c33 portentac33.build.zephyr_args= diff --git a/extra/package_core.inc b/extra/package_core.inc index 61218d07..60a7d284 100644 --- a/extra/package_core.inc +++ b/extra/package_core.inc @@ -13,5 +13,4 @@ README.md doc/ cores/ libraries/ -variants/_llext/ -variants/_linked/ +variants/_ldscripts/ diff --git a/platform.txt b/platform.txt index c3598d30..26d671d9 100644 --- a/platform.txt +++ b/platform.txt @@ -19,7 +19,7 @@ compiler.path={build.compiler_path} compiler.c.cmd={build.crossprefix}gcc compiler.c.flags=-g -c {compiler.warning_flags} {compiler.zephyr.macros} "@{compiler.zephyr.cflags_file}" -MMD -mcpu={build.mcu} {build.float-abi} {build.fpu} compiler.c.elf.cmd={build.crossprefix}g++ -compiler.c.elf.flags={build.llext_link_flags} -Wl,--gc-sections -mcpu={build.mcu} {build.float-abi} {build.fpu} -std=gnu++17 +compiler.c.elf.flags=-Wl,--gc-sections -mcpu={build.mcu} {build.float-abi} {build.fpu} -std=gnu++17 compiler.S.cmd={build.crossprefix}g++ compiler.S.flags=-c -x assembler-with-cpp -mcpu={build.mcu} {build.fpu} compiler.cpp.cmd={build.crossprefix}g++ @@ -46,15 +46,28 @@ compiler.zephyr.common_ldflags=-fno-exceptions -fno-rtti -fno-threadsafe-statics compiler.zephyr.extra_cxxflags= compiler.zephyr.extra_ldflags=-lstdc++ -lsupc++ -# this can be overriden in boards.txt +# these can be overriden in boards.txt build.extra_flags= build.extra_ldflags= - -build.ldscript={runtime.platform.path}/variants/_llext/linker_script.ld -build.llext_link_flags=-r -e main +build.link_mode=dynamic upload.extension=elf-zsk.bin -postbuild_debug= -postbuild_mode= + +build.ldscript.path={runtime.platform.path}/variants/_ldscripts +build.link_command="{compiler.path}{compiler.c.elf.cmd}" "-L{build.path}" "-L{build.variant.path}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} {build.extra_flags} {build.extra_ldflags} {compiler.zephyr.common_ldflags} --specs=picolibc.specs --specs=nosys.specs {compiler.ldflags} {object_files} -Wl,--start-group "{build.path}/{archive_file}" {compiler.zephyr.extra_ldflags} {compiler.libraries.ldflags} -Wl,--end-group {build.link_args.{build.link_mode}} + +# link_args.* are included by any link_command depending on the link_mode +build.link_args.dynamic=-e main +build.link_args.static=-lc -lm -lgcc -Wl,--wrap=random -Wl,--wrap=calloc -Wl,--wrap=free -Wl,--wrap=malloc -Wl,--wrap=realloc + +# link_args.build-* are used to create the final binary. -common are added to both static and dynamic. +build.link_args.build-dynamic="-T{build.ldscript.path}/dynamic.ld" -r +build.link_args.build-static="-T{build.variant.path}/provides.ld" "-T{build.ldscript.path}/static.ld" +build.link_args.build-common="-Wl,-Map,{build.path}/{build.project_name}.map" -o "{build.path}/{build.project_name}_debug.elf" + +# zsk_args are used to create the final binary with zephyr-sketch-tool +build.zsk_args.debug= +build.zsk_args.mode-dynamic= +build.zsk_args.mode-static=-prelinked # These can be overridden in platform.local.txt compiler.c.extra_flags= @@ -96,7 +109,7 @@ recipe.S.o.pattern="{compiler.path}{compiler.S.cmd}" {compiler.S.flags} -DARDUIN recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" ## Combine gc-sections, archives, and objects -recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" "-L{build.path}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} {build.extra_flags} {build.extra_ldflags} {compiler.zephyr.common_ldflags} "-T{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" --specs=picolibc.specs --specs=nosys.specs {compiler.ldflags} -o "{build.path}/{build.project_name}_debug.elf" {object_files} -Wl,--start-group "{build.path}/{archive_file}" {compiler.zephyr.extra_ldflags} {compiler.libraries.ldflags} -Wl,--end-group +recipe.c.combine.pattern={build.link_command} {build.link_args.build-{build.link_mode}} {build.link_args.build-common} recipe.hooks.linking.postlink.1.pattern="{compiler.path}{build.crossprefix}strip" --strip-debug "{build.path}/{build.project_name}_debug.elf" -o "{build.path}/{build.project_name}.elf" ## Create eeprom @@ -109,8 +122,8 @@ recipe.objcopy.bin.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex" ## Mangle the file -recipe.hooks.objcopy.postobjcopy.1.pattern="{runtime.tools.zephyr-sketch-tool.path}/zephyr-sketch-tool" {postbuild_debug} {postbuild_mode} "{build.path}/{build.project_name}.elf" -recipe.hooks.objcopy.postobjcopy.2.pattern="{runtime.tools.zephyr-sketch-tool.path}/zephyr-sketch-tool" {postbuild_debug} {postbuild_mode} "{build.path}/{build.project_name}.bin" +recipe.hooks.objcopy.postobjcopy.1.pattern="{runtime.tools.zephyr-sketch-tool.path}/zephyr-sketch-tool" {build.zsk_args.debug} {build.zsk_args.mode-{build.link_mode}} "{build.path}/{build.project_name}.elf" +recipe.hooks.objcopy.postobjcopy.2.pattern="{runtime.tools.zephyr-sketch-tool.path}/zephyr-sketch-tool" {build.zsk_args.debug} {build.zsk_args.mode-{build.link_mode}} "{build.path}/{build.project_name}.bin" ## Compute size recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" diff --git a/variants/_llext/linker_script.ld b/variants/_ldscripts/dynamic.ld similarity index 100% rename from variants/_llext/linker_script.ld rename to variants/_ldscripts/dynamic.ld diff --git a/variants/_linked/linker_script.ld b/variants/_ldscripts/static.ld similarity index 100% rename from variants/_linked/linker_script.ld rename to variants/_ldscripts/static.ld From 6f50e00584e0a76ae516976b7f66bc0d4763c7ce Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Fri, 11 Jul 2025 15:14:03 +0200 Subject: [PATCH 8/8] build: Add support for checking an llext build at compile time This commit adds compile-time checking of the sketch to verify that all symbols not directly resolved in the sketch are defined in the Zephyr core. This reuses the 'linked' logic, but defines the llext-specific symbols only. Signed-off-by: Luca Burelli --- .gitignore | 3 ++- extra/build.sh | 3 ++- platform.txt | 18 ++++++++++++++---- .../{dynamic.ld => build-dynamic.ld} | 0 .../_ldscripts/{static.ld => build-static.ld} | 13 ------------- variants/_ldscripts/memory-check.ld | 13 +++++++++++++ variants/_ldscripts/memory-static.ld | 9 +++++++++ 7 files changed, 40 insertions(+), 19 deletions(-) rename variants/_ldscripts/{dynamic.ld => build-dynamic.ld} (100%) rename variants/_ldscripts/{static.ld => build-static.ld} (85%) create mode 100644 variants/_ldscripts/memory-check.ld create mode 100644 variants/_ldscripts/memory-static.ld diff --git a/.gitignore b/.gitignore index 09974049..5c3ff0e6 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ llext-edk/ cflags.txt cxxflags.txt includes.txt -provides.ld +syms-dynamic.ld +syms-static.ld diff --git a/extra/build.sh b/extra/build.sh index c606f545..310a850d 100755 --- a/extra/build.sh +++ b/extra/build.sh @@ -91,6 +91,7 @@ done # Generate the provides.ld file for linked builds echo "Generating exported symbol scripts" +extra/gen_provides.py "${BUILD_DIR}/zephyr/zephyr.elf" -L > ${VARIANT_DIR}/syms-dynamic.ld extra/gen_provides.py "${BUILD_DIR}/zephyr/zephyr.elf" -LF \ "+kheap_llext_heap" \ "+kheap__system_heap" \ @@ -100,6 +101,6 @@ extra/gen_provides.py "${BUILD_DIR}/zephyr/zephyr.elf" -LF \ "free=__wrap_free" \ "realloc=__wrap_realloc" \ "calloc=__wrap_calloc" \ - "random=__wrap_random" > ${VARIANT_DIR}/provides.ld + "random=__wrap_random" > ${VARIANT_DIR}/syms-static.ld cmake -P extra/gen_arduino_files.cmake $variant diff --git a/platform.txt b/platform.txt index 26d671d9..0e145686 100644 --- a/platform.txt +++ b/platform.txt @@ -3,7 +3,7 @@ # For more info: # https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification -name=Arduino Zephyr Boards (llext) +name=Arduino Zephyr Boards version=9.9.9 # Compile variables @@ -55,13 +55,21 @@ upload.extension=elf-zsk.bin build.ldscript.path={runtime.platform.path}/variants/_ldscripts build.link_command="{compiler.path}{compiler.c.elf.cmd}" "-L{build.path}" "-L{build.variant.path}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} {build.extra_flags} {build.extra_ldflags} {compiler.zephyr.common_ldflags} --specs=picolibc.specs --specs=nosys.specs {compiler.ldflags} {object_files} -Wl,--start-group "{build.path}/{archive_file}" {compiler.zephyr.extra_ldflags} {compiler.libraries.ldflags} -Wl,--end-group {build.link_args.{build.link_mode}} +build.check_command-dynamic={build.link_command} {build.link_args.check-dynamic} -o "{build.path}/{build.project_name}_check.tmp" +build.check_command-static=/bin/true +build.check_command-static.windows=cmd /C cd . +build.combine_command={build.link_command} {build.link_args.build-{build.link_mode}} {build.link_args.build-common} + # link_args.* are included by any link_command depending on the link_mode build.link_args.dynamic=-e main build.link_args.static=-lc -lm -lgcc -Wl,--wrap=random -Wl,--wrap=calloc -Wl,--wrap=free -Wl,--wrap=malloc -Wl,--wrap=realloc +# link_args.check-* are used to check the build. Only LLEXT needs these to emulate a static build (no -r!). +build.link_args.check-dynamic="-T{build.variant.path}/syms-dynamic.ld" "-T{build.ldscript.path}/memory-check.ld" "-T{build.ldscript.path}/build-static.ld" + # link_args.build-* are used to create the final binary. -common are added to both static and dynamic. -build.link_args.build-dynamic="-T{build.ldscript.path}/dynamic.ld" -r -build.link_args.build-static="-T{build.variant.path}/provides.ld" "-T{build.ldscript.path}/static.ld" +build.link_args.build-dynamic="-T{build.ldscript.path}/build-dynamic.ld" -r +build.link_args.build-static="-T{build.variant.path}/syms-static.ld" "-T{build.ldscript.path}/memory-static.ld" "-T{build.ldscript.path}/build-static.ld" build.link_args.build-common="-Wl,-Map,{build.path}/{build.project_name}.map" -o "{build.path}/{build.project_name}_debug.elf" # zsk_args are used to create the final binary with zephyr-sketch-tool @@ -109,7 +117,9 @@ recipe.S.o.pattern="{compiler.path}{compiler.S.cmd}" {compiler.S.flags} -DARDUIN recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" ## Combine gc-sections, archives, and objects -recipe.c.combine.pattern={build.link_command} {build.link_args.build-{build.link_mode}} {build.link_args.build-common} +recipe.c.combine.1.pattern={build.check_command-{build.link_mode}} +recipe.c.combine.2.pattern={build.combine_command} +recipe.c.combine.pattern={build.combine_command} recipe.hooks.linking.postlink.1.pattern="{compiler.path}{build.crossprefix}strip" --strip-debug "{build.path}/{build.project_name}_debug.elf" -o "{build.path}/{build.project_name}.elf" ## Create eeprom diff --git a/variants/_ldscripts/dynamic.ld b/variants/_ldscripts/build-dynamic.ld similarity index 100% rename from variants/_ldscripts/dynamic.ld rename to variants/_ldscripts/build-dynamic.ld diff --git a/variants/_ldscripts/static.ld b/variants/_ldscripts/build-static.ld similarity index 85% rename from variants/_ldscripts/static.ld rename to variants/_ldscripts/build-static.ld index 64c3e86d..7154ee9a 100644 --- a/variants/_ldscripts/static.ld +++ b/variants/_ldscripts/build-static.ld @@ -1,18 +1,5 @@ -INCLUDE "provides.ld" - -MEMORY -{ - /* 16 below compensates for the zsk header that is added before the .bin */ - FLASH (rx) : ORIGIN = _sketch_start + 16, LENGTH = _sketch_max_size - 16 - RAM (rwx) : ORIGIN = kheap_llext_heap, LENGTH = kheap_llext_heap_size -} - -PROVIDE(__heap_start = kheap__system_heap); -PROVIDE(__heap_end = kheap__system_heap + kheap__system_heap_size); - ENTRY(entry_point) SECTIONS { - /DISCARD/ : { *(.ARM.attributes) *(.ARM.attributes.*) diff --git a/variants/_ldscripts/memory-check.ld b/variants/_ldscripts/memory-check.ld new file mode 100644 index 00000000..fd09c59f --- /dev/null +++ b/variants/_ldscripts/memory-check.ld @@ -0,0 +1,13 @@ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x10000000 + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x10000000 +} + +PROVIDE(__heap_start = 0x40000000); +PROVIDE(__heap_end = 0x50000000); +PROVIDE(kheap__system_heap = 0x40000000); +PROVIDE(kheap__system_heap_size = 0x10000000); + +PROVIDE(kheap_llext_heap = 0x60000000); +PROVIDE(kheap_llext_heap_size = 0x10000000); diff --git a/variants/_ldscripts/memory-static.ld b/variants/_ldscripts/memory-static.ld new file mode 100644 index 00000000..fce3d398 --- /dev/null +++ b/variants/_ldscripts/memory-static.ld @@ -0,0 +1,9 @@ +MEMORY +{ + /* 16 below compensates for the zsk header that is added before the .bin */ + FLASH (rx) : ORIGIN = _sketch_start + 16, LENGTH = _sketch_max_size - 16 + RAM (rwx) : ORIGIN = kheap_llext_heap, LENGTH = kheap_llext_heap_size +} + +PROVIDE(__heap_start = kheap__system_heap); +PROVIDE(__heap_end = kheap__system_heap + kheap__system_heap_size);