Browse Source

toolchain: iar: Add experimental IAR support

This adds experimental support for the IAR toolchain.

Signed-off-by: Robin Kastberg <robin.kastberg@iar.com>
pull/85809/head
Robin Kastberg 5 months ago committed by Fabio Baltieri
parent
commit
9ab06ec667
  1. 21
      arch/common/CMakeLists.txt
  2. 44
      cmake/bintools/iar/target.cmake
  3. 135
      cmake/bintools/iar/target_bintools.cmake
  4. 178
      cmake/compiler/iar/compiler_flags.cmake
  5. 15
      cmake/compiler/iar/generic.cmake
  6. 89
      cmake/compiler/iar/iccarm-cpu.cmake
  7. 53
      cmake/compiler/iar/iccarm-fpu.cmake
  8. 146
      cmake/compiler/iar/target.cmake
  9. 922
      cmake/linker/iar/config_file_script.cmake
  10. 14
      cmake/linker/iar/linker_flags.cmake
  11. 135
      cmake/linker/iar/target.cmake
  12. 40
      cmake/toolchain/iar/Kconfig
  13. 53
      cmake/toolchain/iar/Kconfig.defconfig
  14. 46
      cmake/toolchain/iar/generic.cmake
  15. 5
      cmake/toolchain/iar/target.cmake
  16. 4
      include/zephyr/arch/arm/asm_inline.h
  17. 2
      include/zephyr/toolchain.h
  18. 25
      include/zephyr/toolchain/iar.h
  19. 161
      include/zephyr/toolchain/iar/iar_missing_defs.h
  20. 456
      include/zephyr/toolchain/iar/iccarm.h
  21. 1
      lib/libc/CMakeLists.txt
  22. 19
      lib/libc/Kconfig
  23. 6
      lib/libc/iar/CMakeLists.txt
  24. 96
      lib/libc/iar/include/errno.h
  25. 22
      lib/libc/iar/include/limits.h
  26. 7
      lib/libc/iar/include/sys/_timespec.h
  27. 27
      lib/libc/iar/include/sys/_timeval.h
  28. 7
      lib/libc/iar/include/sys/cdefs.h
  29. 18
      lib/libc/iar/include/sys/timespec.h
  30. 21
      lib/libc/iar/include/sys/types.h
  31. 31
      lib/libc/iar/include/time.h
  32. 53
      lib/libc/iar/src/libc-hooks.c
  33. 3
      scripts/ci/check_compliance.py
  34. 2
      tests/kernel/fpu_sharing/generic/src/load_store.c

21
arch/common/CMakeLists.txt

@ -56,12 +56,21 @@ zephyr_linker_sources_ifdef(CONFIG_GEN_IRQ_VECTOR_TABLE @@ -56,12 +56,21 @@ zephyr_linker_sources_ifdef(CONFIG_GEN_IRQ_VECTOR_TABLE
)
if(CONFIG_GEN_ISR_TABLES)
zephyr_linker_section(NAME .intList VMA IDT_LIST LMA IDT_LIST NOINPUT PASS NOT LINKER_ZEPHYR_FINAL)
zephyr_linker_section_configure(SECTION .intList KEEP INPUT ".irq_info" FIRST)
zephyr_linker_section_configure(SECTION .intList KEEP INPUT ".intList")
zephyr_linker_section_configure(SECTION /DISCARD/ KEEP INPUT ".irq_info" PASS LINKER_ZEPHYR_FINAL)
zephyr_linker_section_configure(SECTION /DISCARD/ KEEP INPUT ".intList" PASS LINKER_ZEPHYR_FINAL)
# IAR Toolchain is having problems with discarding .intList
# This will always keep .intList in a harmless location
# until we can implement a proper DISCARD.
if(ZEPHYR_TOOLCHAIN_VARIANT STREQUAL "iar")
zephyr_linker_section(NAME .intList GROUP RODATA_REGION NOINPUT)
zephyr_linker_section_configure(SECTION .intList KEEP INPUT ".irq_info" FIRST)
zephyr_linker_section_configure(SECTION .intList KEEP INPUT ".intList")
else()
zephyr_linker_section(NAME .intList VMA IDT_LIST LMA IDT_LIST NOINPUT PASS NOT LINKER_ZEPHYR_FINAL)
zephyr_linker_section_configure(SECTION .intList KEEP INPUT ".irq_info" FIRST)
zephyr_linker_section_configure(SECTION .intList KEEP INPUT ".intList")
zephyr_linker_section_configure(SECTION /DISCARD/ KEEP INPUT ".irq_info" PASS LINKER_ZEPHYR_FINAL)
zephyr_linker_section_configure(SECTION /DISCARD/ KEEP INPUT ".intList" PASS LINKER_ZEPHYR_FINAL)
endif()
endif()
zephyr_linker_sources_ifdef(CONFIG_ARCH_HAS_RAMFUNC_SUPPORT

44
cmake/bintools/iar/target.cmake

@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
# Copyright (c) 2025 IAR Systems AB
#
# SPDX-License-Identifier: Apache-2.0
# Configures binary tools as GNU binutils
include(extensions)
# Specifically choose arm-zephyr-eabi from the zephyr sdk for objcopy and friends
if("${IAR_TOOLCHAIN_VARIANT}" STREQUAL "iccarm")
set(IAR_ZEPHYR_HOME ${ZEPHYR_SDK_INSTALL_DIR}/arm-zephyr-eabi/bin)
set(IAR_GNU_PREFIX arm-zephyr-eabi-)
else()
message(ERROR "IAR_TOOLCHAIN_VARIANT not set")
endif()
find_program(CMAKE_OBJCOPY ${IAR_GNU_PREFIX}objcopy PATHS ${IAR_ZEPHYR_HOME} NO_DEFAULT_PATH)
find_program(CMAKE_OBJDUMP ${IAR_GNU_PREFIX}objdump PATHS ${IAR_ZEPHYR_HOME} NO_DEFAULT_PATH)
find_program(CMAKE_AS ${IAR_GNU_PREFIX}as PATHS ${IAR_ZEPHYR_HOME} NO_DEFAULT_PATH)
find_program(CMAKE_AR ${IAR_GNU_PREFIX}ar PATHS ${IAR_ZEPHYR_HOME} NO_DEFAULT_PATH)
find_program(CMAKE_RANLIB ${IAR_GNU_PREFIX}ranlib PATHS ${IAR_ZEPHYR_HOME} NO_DEFAULT_PATH)
find_program(CMAKE_READELF ${IAR_GNU_PREFIX}readelf PATHS ${IAR_ZEPHYR_HOME} NO_DEFAULT_PATH)
find_program(CMAKE_NM ${IAR_GNU_PREFIX}nm PATHS ${IAR_ZEPHYR_HOME} NO_DEFAULT_PATH)
find_program(CMAKE_STRIP ${IAR_GNU_PREFIX}strip PATHS ${IAR_ZEPHYR_HOME} NO_DEFAULT_PATH)
find_program(CMAKE_GDB ${IAR_GNU_PREFIX}gdb-py PATHS ${IAR_ZEPHYR_HOME} NO_DEFAULT_PATH)
if(CMAKE_GDB)
execute_process(
COMMAND ${CMAKE_GDB} --configuration
RESULTS_VARIABLE GDB_CFG_ERR
OUTPUT_QUIET
ERROR_QUIET
)
endif()
if(NOT CMAKE_GDB OR GDB_CFG_ERR)
find_program(CMAKE_GDB_NO_PY ${CROSS_COMPILE}gdb PATHS ${TOOLCHAIN_HOME} NO_DEFAULT_PATH)
if(CMAKE_GDB_NO_PY)
set(CMAKE_GDB ${CMAKE_GDB_NO_PY} CACHE FILEPATH "Path to a program." FORCE)
endif()
endif()
# Include bin tool properties
include(${ZEPHYR_BASE}/cmake/bintools/iar/target_bintools.cmake)

135
cmake/bintools/iar/target_bintools.cmake

@ -0,0 +1,135 @@ @@ -0,0 +1,135 @@
# Copyright (c) 2025 IAR Systems AB
#
# SPDX-License-Identifier: Apache-2.0
#
# - elfconvert : Name of command for elf file conversion.
# In this implementation `objcopy` is used
# elfconvert_formats : Formats supported: ihex, srec, binary
# elfconvert_flag : empty
# elfconvert_flag_final : empty
# elfconvert_flag_strip_all : -S
# elfconvert_flag_strip_debug : -g
# elfconvert_flag_intarget : --input-target=
# elfconvert_flag_outtarget : --output-target=
# elfconvert_flag_section_remove: --remove-section=
# elfconvert_flag_section_only : --only-section=
# elfconvert_flag_section_rename: --rename-section;
# elfconvert_flag_gapfill : --gap-fill;
# Note: The ';' will be transformed into an
# empty space when executed
# elfconvert_flag_srec_len : --srec-len=
# elfconvert_flag_infile : empty, objcopy doesn't take arguments for filenames
# elfconvert_flag_outfile : empty, objcopy doesn't take arguments for filenames
#
# elfconvert to use for transforming an elf file into another format,
# such as intel hex, s-rec, binary, etc.
set_property(TARGET bintools PROPERTY elfconvert_command ${CMAKE_OBJCOPY})
# List of format the tool supports for converting, for example,
# GNU tools uses objectcopy, which supports the following: ihex, srec, binary
set_property(TARGET bintools PROPERTY elfconvert_formats ihex srec binary)
set_property(TARGET bintools PROPERTY elfconvert_flag "")
set_property(TARGET bintools PROPERTY elfconvert_flag_final "")
set_property(TARGET bintools PROPERTY elfconvert_flag_strip_all "-S")
set_property(TARGET bintools PROPERTY elfconvert_flag_strip_debug "-g")
set_property(TARGET bintools PROPERTY elfconvert_flag_intarget "--input-target=")
set_property(TARGET bintools PROPERTY elfconvert_flag_outtarget "--output-target=")
set_property(TARGET bintools PROPERTY elfconvert_flag_section_remove "--remove-section=")
set_property(TARGET bintools PROPERTY elfconvert_flag_section_only "--only-section=")
set_property(TARGET bintools PROPERTY elfconvert_flag_section_rename "--rename-section;")
set_property(TARGET bintools PROPERTY elfconvert_flag_lma_adjust "--change-section-lma;")
# Note, placing a ';' at the end results in the following param to be a list,
# and hence space separated.
# Thus the command line argument becomes:
# `--gap-file <value>` instead of `--gap-fill<value>` (The latter would result in an error)
set_property(TARGET bintools PROPERTY elfconvert_flag_gapfill "--gap-fill;")
set_property(TARGET bintools PROPERTY elfconvert_flag_srec_len "--srec-len=")
set_property(TARGET bintools PROPERTY elfconvert_flag_infile "")
set_property(TARGET bintools PROPERTY elfconvert_flag_outfile "")
#
# - disassembly : Name of command for disassembly of files
# In this implementation `objdump` is used
# disassembly_flag : -d
# disassembly_flag_final : empty
# disassembly_flag_inline_source : -S
# disassembly_flag_all : -SDz
# disassembly_flag_infile : empty, objdump doesn't take arguments for filenames
# disassembly_flag_outfile : '>', objdump doesn't take arguments for output file, but result is printed to standard out, and is redirected.
set_property(TARGET bintools PROPERTY disassembly_command ${CMAKE_OBJDUMP})
set_property(TARGET bintools PROPERTY disassembly_flag -d)
set_property(TARGET bintools PROPERTY disassembly_flag_final "")
set_property(TARGET bintools PROPERTY disassembly_flag_inline_source -S)
set_property(TARGET bintools PROPERTY disassembly_flag_all -SDz)
set_property(TARGET bintools PROPERTY disassembly_flag_infile "")
set_property(TARGET bintools PROPERTY disassembly_flag_outfile ">;" )
#
# - strip: Name of command for stripping symbols
# In this implementation `strip` is used
# strip_flag : empty
# strip_flag_final : empty
# strip_flag_all : --strip-all
# strip_flag_debug : --strip-debug
# strip_flag_dwo : --strip-dwo
# strip_flag_infile : empty, strip doesn't take arguments for input file
# strip_flag_outfile : -o
# This is using strip from bintools.
set_property(TARGET bintools PROPERTY strip_command ${CMAKE_STRIP})
# Any flag the strip command requires for processing
set_property(TARGET bintools PROPERTY strip_flag "")
set_property(TARGET bintools PROPERTY strip_flag_final "")
set_property(TARGET bintools PROPERTY strip_flag_all --strip-all)
set_property(TARGET bintools PROPERTY strip_flag_debug --strip-debug)
set_property(TARGET bintools PROPERTY strip_flag_dwo --strip-dwo)
set_property(TARGET bintools PROPERTY strip_flag_remove_section -R )
set_property(TARGET bintools PROPERTY strip_flag_infile "")
set_property(TARGET bintools PROPERTY strip_flag_outfile -o )
#
# - readelf : Name of command for reading elf files.
# In this implementation `readelf` is used
# readelf_flag : empty
# readelf_flag_final : empty
# readelf_flag_headers : -e
# readelf_flag_infile : empty, readelf doesn't take arguments for filenames
# readelf_flag_outfile : '>', readelf doesn't take arguments for output
# file, but result is printed to standard out, and
# is redirected.
# This is using readelf from bintools.
set_property(TARGET bintools PROPERTY readelf_command ${CMAKE_READELF})
set_property(TARGET bintools PROPERTY readelf_flag "")
set_property(TARGET bintools PROPERTY readelf_flag_final "")
set_property(TARGET bintools PROPERTY readelf_flag_headers -e)
set_property(TARGET bintools PROPERTY readelf_flag_infile "")
set_property(TARGET bintools PROPERTY readelf_flag_outfile ">;" )
# Example on how to support dwarfdump instead of readelf
#set_property(TARGET bintools PROPERTY readelf_command dwarfdump)
#set_property(TARGET bintools PROPERTY readelf_flag "")
#set_property(TARGET bintools PROPERTY readelf_flag_headers -E)
#set_property(TARGET bintools PROPERTY readelf_flag_infile "")
#set_property(TARGET bintools PROPERTY readelf_flag_outfile "-O file=" )
set_property(TARGET bintools PROPERTY symbols_command ${CMAKE_NM})
set_property(TARGET bintools PROPERTY symbols_flag "")
set_property(TARGET bintools PROPERTY symbols_final "")
set_property(TARGET bintools PROPERTY symbols_infile "")
set_property(TARGET bintools PROPERTY symbols_outfile ">;" )

178
cmake/compiler/iar/compiler_flags.cmake

@ -0,0 +1,178 @@ @@ -0,0 +1,178 @@
# Copyright (c) 2025 IAR Systems AB
#
# SPDX-License-Identifier: Apache-2.0
# Compiler options for the IAR C/C++ Compiler for Arm
#####################################################
# This section covers flags related to optimization #
#####################################################
set_compiler_property(PROPERTY no_optimization -On)
set_compiler_property(PROPERTY optimization_debug -Ol)
set_compiler_property(PROPERTY optimization_speed -Ohs)
set_compiler_property(PROPERTY optimization_size -Ohz)
set_compiler_property(PROPERTY optimization_size_aggressive -Ohz)
#######################################################
# This section covers flags related to warning levels #
#######################################################
# Property for standard warning base in Zephyr, this will always be set when
# compiling.
set_compiler_property(PROPERTY warning_base
--diag_error=Pe223 # function "xxx" declared implicitly
--diag_warning=Pe054 # too few arguments in invocation of macro
--diag_warning=Pe144 # a value of type "void *" cannot be used to initialize an entity of type [...] "void (*)(struct onoff_manager *, int)"
--diag_warning=Pe167 # argument of type "void *" is incompatible with [...] "void (*)(void *, void *, void *)"
--diag_suppress=Pe1675 # unrecognized GCC pragma
--diag_suppress=Pe111 # statement is unreachable
--diag_suppress=Pe1143 # arithmetic on pointer to void or function type
--diag_suppress=Pe068) # integer conversion resulted in a change of sign)
set(IAR_WARNING_DW_1
--diag_suppress=Pe188 # enumerated type mixed with another type
--diag_suppress=Pe128 # loop is not reachable
--diag_suppress=Pe550 # variable "res" was set but never used
--diag_suppress=Pe546 # transfer of control bypasses initialization
--diag_suppress=Pe186) # pointless comparison of unsigned integer with zero
set(IAR_WARNING_DW2
--diag_suppress=Pe1097 # unknown attribute
--diag_suppress=Pe381 # extra ";" ignored
--diag_suppress=Pa082 # undefined behavior: the order of volatile accesses is undefined
--diag_suppress=Pa084 # pointless integer comparison, the result is always false
--diag_suppress=Pe185 # dynamic initialization in unreachable code )
--diag_suppress=Pe167 # argument of type "onoff_notify_fn" is incompatible with...
--diag_suppress=Pe144 # a value of type "void *" cannot be used to initialize...
--diag_suppress=Pe177 # function "xxx" was declared but never referenced
--diag_suppress=Pe513) # a value of type "void *" cannot be assigned to an entity of type "int (*)(int)"
set(IAR_WARNING_DW3)
set_compiler_property(PROPERTY warning_dw_1
${IAR_WARNING_DW_3}
${IAR_WARNING_DW_2}
${IAR_WARNING_DW_1})
set_compiler_property(PROPERTY warning_dw_2
${IAR_WARNING_DW3}
${IAR_WARNING_DW2})
# no suppressions
set_compiler_property(PROPERTY warning_dw_3 ${IAR_WARNING_DW3})
# Extended warning set supported by the compiler
set_compiler_property(PROPERTY warning_extended)
# Compiler property that will issue error if a declaration does not specify a type
set_compiler_property(PROPERTY warning_error_implicit_int)
# Compiler flags to use when compiling according to MISRA
set_compiler_property(PROPERTY warning_error_misra_sane)
set_property(TARGET compiler PROPERTY warnings_as_errors --warnings_are_errors)
###########################################################################
# This section covers flags related to C or C++ standards / standard libs #
###########################################################################
# Compiler flags for C standard. The specific standard must be appended by user.
# For example, gcc specifies this as: set_compiler_property(PROPERTY cstd -std=)
# TC-WG: the `cstd99` is used regardless of this flag being useful for iccarm
# This flag will make it a symbol. Works for C,CXX,ASM
# Since ICCARM does not use C standard flags, we just make them a defined symbol
# instead
set_compiler_property(PROPERTY cstd -D__IAR_CSTD_)
# Compiler flags for disabling C standard include and instead specify include
# dirs in nostdinc_include to use.
set_compiler_property(PROPERTY nostdinc)
set_compiler_property(PROPERTY nostdinc_include)
# Compiler flags for disabling C++ standard include.
set_compiler_property(TARGET compiler-cpp PROPERTY nostdincxx)
# Required C++ flags when compiling C++ code
set_property(TARGET compiler-cpp PROPERTY required --c++)
# Compiler flags to use for specific C++ dialects
set_property(TARGET compiler-cpp PROPERTY dialect_cpp98)
set_property(TARGET compiler-cpp PROPERTY dialect_cpp11)
set_property(TARGET compiler-cpp PROPERTY dialect_cpp14)
set_property(TARGET compiler-cpp PROPERTY dialect_cpp17 --libc++)
set_property(TARGET compiler-cpp PROPERTY dialect_cpp2a --libc++)
set_property(TARGET compiler-cpp PROPERTY dialect_cpp20 --libc++)
set_property(TARGET compiler-cpp PROPERTY dialect_cpp2b --libc++)
# Flag for disabling strict aliasing rule in C and C++
set_compiler_property(PROPERTY no_strict_aliasing)
# Flag for disabling exceptions in C++
set_property(TARGET compiler-cpp PROPERTY no_exceptions --no_exceptions)
# Flag for disabling rtti in C++
set_property(TARGET compiler-cpp PROPERTY no_rtti --no_rtti)
###################################################
# This section covers all remaining C / C++ flags #
###################################################
# Flags for coverage generation
set_compiler_property(PROPERTY coverage)
# Security canaries flags.
set_compiler_property(PROPERTY security_canaries --stack_protection)
set_compiler_property(PROPERTY security_canaries_strong --stack_protection)
set_compiler_property(PROPERTY security_canaries_all --security_canaries_all_is_not_supported)
set_compiler_property(PROPERTY security_canaries_explicit --security_canaries_explicit_is_not_supported)
if(CONFIG_STACK_CANARIES_TLS)
check_set_compiler_property(APPEND PROPERTY security_canaries --stack_protector_guard=tls)
check_set_compiler_property(APPEND PROPERTY security_canaries_strong --stack_protector_guard=tls)
check_set_compiler_property(APPEND PROPERTY security_canaries_all --stack_protector_guard=tls)
check_set_compiler_property(APPEND PROPERTY security_canaries_explicit --stack_protector_guard=tls)
endif()
set_compiler_property(PROPERTY security_fortify)
# Flag for a hosted (no-freestanding) application
set_compiler_property(PROPERTY hosted)
# gcc flag for a freestanding application
set_compiler_property(PROPERTY freestanding)
# Flag to include debugging symbol in compilation
set_property(TARGET compiler PROPERTY debug --debug)
set_property(TARGET compiler-cpp PROPERTY debug --debug)
set_property(TARGET asm PROPERTY debug -gdwarf-4)
set_compiler_property(PROPERTY no_common)
# Flags for imacros. The specific header must be appended by user.
set_property(TARGET compiler PROPERTY imacros --preinclude)
set_property(TARGET compiler-cpp PROPERTY imacros --preinclude)
set_property(TARGET asm PROPERTY imacros -imacros)
# Compiler flag for turning off thread-safe initialization of local statics
set_property(TARGET compiler-cpp PROPERTY no_threadsafe_statics)
# Required ASM flags when compiling
set_property(TARGET asm PROPERTY required)
# Compiler flag for disabling pointer arithmetic warnings
set_compiler_property(PROPERTY warning_no_pointer_arithmetic)
# Compiler flags for disabling position independent code / executable
set_compiler_property(PROPERTY no_position_independent)
# Compiler flag for defining preinclude files.
set_compiler_property(PROPERTY include_file --preinclude)
set_compiler_property(PROPERTY cmse --cmse)
set_property(TARGET asm PROPERTY cmse -mcmse)

15
cmake/compiler/iar/generic.cmake

@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
# Copyright (c) 2025 IAR Systems AB
#
# SPDX-License-Identifier: Apache-2.0
if(NOT CMAKE_DTS_PREPROCESSOR)
find_program(CMAKE_DTS_PREPROCESSOR arm-zephyr-eabi-gcc PATHS ${ZEPHYR_SDK_INSTALL_DIR}/arm-zephyr-eabi/bin NO_DEFAULT_PATH)
endif()
if(NOT CMAKE_DTS_PREPROCESSOR)
message(FATAL_ERROR "Zephyr was unable to find \`arm-zephyr-eabi-gcc\` for DTS preprocessing")
endif()
if(CMAKE_C_COMPILER STREQUAL CMAKE_C_COMPILER-NOTFOUND)
message(FATAL_ERROR "Zephyr was unable to find the IAR toolchain. Was the environment misconfigured?")
endif()

89
cmake/compiler/iar/iccarm-cpu.cmake

@ -0,0 +1,89 @@ @@ -0,0 +1,89 @@
# Copyright (c) 2025 IAR Systems AB
#
# SPDX-License-Identifier: Apache-2.0
# Determines what argument to give to --cpu= based on the
# KConfig'uration and sets this to ICCARM_CPU
if("${ARCH}" STREQUAL "arm")
if(CONFIG_CPU_CORTEX_M0)
set(ICCARM_CPU Cortex-M0)
elseif(CONFIG_CPU_CORTEX_M0PLUS)
set(ICCARM_CPU Cortex-M0+)
elseif(CONFIG_CPU_CORTEX_M1)
set(ICCARM_CPU Cortex-M1)
elseif(CONFIG_CPU_CORTEX_M3)
set(ICCARM_CPU Cortex-M3)
elseif(CONFIG_CPU_CORTEX_M4)
set(ICCARM_CPU Cortex-M4)
elseif(CONFIG_CPU_CORTEX_M7)
set(ICCARM_CPU Cortex-M7)
elseif(CONFIG_CPU_CORTEX_M23)
set(ICCARM_CPU Cortex-M23)
elseif(CONFIG_CPU_CORTEX_M33)
if(CONFIG_ARMV8_M_DSP)
set(ICCARM_CPU Cortex-M33)
else()
set(ICCARM_CPU Cortex-M33.no_dsp)
endif()
elseif(CONFIG_CPU_CORTEX_M55)
if(CONFIG_ARMV8_1_M_MVEF)
set(ICCARM_CPU Cortex-M55)
elseif(CONFIG_ARMV8_1_M_MVEI)
set(ICCARM_CPU Cortex-M55.no_mve)
elseif(CONFIG_ARMV8_M_DSP)
set(ICCARM_CPU Cortex-M55.no_mve)
else()
set(ICCARM_CPU Cortex-M55.no_dsp)
endif()
elseif(CONFIG_CPU_CORTEX_R4)
if(CONFIG_FPU AND CONFIG_CPU_HAS_VFP)
set(ICCARM_CPU Cortex-R4F)
else()
set(ICCARM_CPU Cortex-R4)
endif()
elseif(CONFIG_CPU_CORTEX_R5)
set(ICCARM_CPU Cortex-R5)
if(CONFIG_FPU AND CONFIG_CPU_HAS_VFP)
if(NOT CONFIG_VFP_FEATURE_DOUBLE_PRECISION)
set(ICCARM_CPU ${ICCARM_CPU}+fp.sp)
endif()
else()
set(ICCARM_CPU ${ICCARM_CPU}+fp.dp)
endif()
elseif(CONFIG_CPU_CORTEX_R7)
set(ICCARM_CPU Cortex-R7)
if(CONFIG_FPU AND CONFIG_CPU_HAS_VFP)
if(NOT CONFIG_VFP_FEATURE_DOUBLE_PRECISION)
set(ICCARM_CPU ${ICCARM_CPU}+fp.sp)
endif()
else()
set(ICCARM_CPU ${ICCARM_CPU}+fp.dp)
endif()
elseif(CONFIG_CPU_CORTEX_R52)
set(ICCARM_CPU Cortex-R52)
if(CONFIG_FPU AND CONFIG_CPU_HAS_VFP)
if(NOT CONFIG_VFP_FEATURE_DOUBLE_PRECISION)
set(ICCARM_CPU ${ICCARM_CPU}+fp.sp)
endif()
endif()
elseif(CONFIG_CPU_CORTEX_A9)
set(ICCARM_CPU Cortex-A9)
else()
message(FATAL_ERROR "Expected CONFIG_CPU_CORTEX_x to be defined")
endif()
elseif("${ARCH}" STREQUAL "arm64")
if(CONFIG_CPU_CORTEX_A53)
set(ICCARM_CPU Cortex-A53)
elseif(CONFIG_CPU_CORTEX_A55)
set(ICCARM_CPU Cortex-A55)
elseif(CONFIG_CPU_CORTEX_A76)
set(ICCARM_CPU cortex-a76)
elseif(CONFIG_CPU_CORTEX_A76_A55)
set(ICCARM_CPU cortex-a76)
elseif(CONFIG_CPU_CORTEX_A72)
set(ICCARM_CPU Cortex-A72)
elseif(CONFIG_CPU_CORTEX_R82)
set(ICCARM_CPU Cortex-R82)
endif()
endif()

53
cmake/compiler/iar/iccarm-fpu.cmake

@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
# Copyright (c) 2025 IAR Systems AB
#
# SPDX-License-Identifier: Apache-2.0
# Determines what argument to give to --fpu= based on the
# KConfiguration and sets this to ICCARM_FPU
if(CONFIG_FPU)
# 32-bit
if("${ARCH}" STREQUAL "arm")
if(CONFIG_CPU_AARCH32_CORTEX_R)
if(CONFIG_CPU_CORTEX_R4 OR CONFIG_CPU_CORTEX_R5) # VFPv3
if(CONFIG_VFP_FEATURE_DOUBLE_PRECISION)
set(ICCARM_FPU VFPv3_D16)
elseif(CONFIG_VFP_FEATURE_SINGLE_PRECISION)
set(ICCARM_FPU VFPv3-SP)
endif()
if(CONFIG_VFP_FEATURE_HALF_PRECISION)
set(ICCARM_FPU ${ICCARM_FPU}_Fp16)
endif()
elseif(CONFIG_CPU_CORTEX_R52)
if(CONFIG_VFP_FEATURE_DOUBLE_PRECISION)
set(ICCARM_FPU VFPv5_D16)
elseif(CONFIG_VFP_FEATURE_SINGLE_PRECISION)
set(ICCARM_FPU VFPv5-SP)
endif()
endif()
elseif(CONFIG_CPU_CORTEX_M)
# Defines a mapping from ICCARM_CPU to FPU
if(CONFIG_CPU_HAS_FPU_DOUBLE_PRECISION)
set(PRECISION_TOKEN _D16)
else()
set(PRECISION_TOKEN -SP)
endif()
set(FPU_FOR_Cortex-M4 FPv4${PRECISION_TOKEN})
set(FPU_FOR_Cortex-M7 FPv5${PRECISION_TOKEN})
set(FPU_FOR_Cortex-M33 FPv5${PRECISION_TOKEN})
set(FPU_FOR_Cortex-M33.no_dsp FPv5${PRECISION_TOKEN})
set(FPU_FOR_Cortex-M55 auto)
set(FPU_FOR_Cortex-M55.no_mve auto)
# We don't have this one?
set(FPU_FOR_Cortex-M55.no_dsp auto)
set(ICCARM_FPU ${FPU_FOR_${ICCARM_CPU}})
endif()
# 64-bit
else()
set(ICCARM_FPU none)
endif()
endif() #CONFIG_FPU

146
cmake/compiler/iar/target.cmake

@ -0,0 +1,146 @@ @@ -0,0 +1,146 @@
# Copyright (c) 2025 IAR Systems AB
#
# SPDX-License-Identifier: Apache-2.0
# Avoids running the linker during try_compile()
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
set(NO_BUILD_TYPE_WARNING 1)
set(CMAKE_NOT_USING_CONFIG_FLAGS 1)
find_program(CMAKE_C_COMPILER
NAMES ${IAR_COMPILER}
PATHS ${TOOLCHAIN_HOME}
PATH_SUFFIXES bin
NO_DEFAULT_PATH
REQUIRED )
message(STATUS "Found C Compiler ${CMAKE_C_COMPILER}")
find_program(CMAKE_CXX_COMPILER
NAMES ${IAR_COMPILER}
PATHS ${TOOLCHAIN_HOME}
PATH_SUFFIXES bin
NO_DEFAULT_PATH
REQUIRED )
find_program(CMAKE_AR
NAMES iarchive
PATHS ${TOOLCHAIN_HOME}
PATH_SUFFIXES bin
NO_DEFAULT_PATH
REQUIRED )
set(CMAKE_ASM_COMPILER)
if("${IAR_TOOLCHAIN_VARIANT}" STREQUAL "iccarm")
find_program(CMAKE_ASM_COMPILER
arm-zephyr-eabi-gcc
PATHS ${ZEPHYR_SDK_INSTALL_DIR}/arm-zephyr-eabi/bin
NO_DEFAULT_PATH )
else()
find_program(CMAKE_ASM_COMPILER
riscv64-zephyr-elf-gcc
PATHS ${ZEPHYR_SDK_INSTALL_DIR}/riscv64-zephyr-elf/bin
NO_DEFAULT_PATH )
endif()
message(STATUS "Found assembler ${CMAKE_ASM_COMPILER}")
set(ICC_BASE ${ZEPHYR_BASE}/cmake/compiler/iar)
if("${IAR_TOOLCHAIN_VARIANT}" STREQUAL "iccarm")
# Used for settings correct cpu/fpu option for gnu assembler
include(${ZEPHYR_BASE}/cmake/gcc-m-cpu.cmake)
include(${ZEPHYR_BASE}/cmake/gcc-m-fpu.cmake)
# Map KConfig option to icc cpu/fpu
include(${ICC_BASE}/iccarm-cpu.cmake)
include(${ICC_BASE}/iccarm-fpu.cmake)
endif()
set(IAR_COMMON_FLAGS)
# Minimal C compiler flags
list(APPEND IAR_COMMON_FLAGS
"SHELL: --preinclude"
"${ZEPHYR_BASE}/include/zephyr/toolchain/iar/iar_missing_defs.h"
# Enable both IAR and GNU extensions
-e
--language gnu
--do_explicit_init_in_named_sections
--macro_positions_in_diagnostics
--no_wrap_diagnostics
)
if("${IAR_TOOLCHAIN_VARIANT}" STREQUAL "iccarm")
list(APPEND IAR_COMMON_FLAGS
--endian=little
--cpu=${ICCARM_CPU}
-DRTT_USE_ASM=0 #WA for VAAK-232
--diag_suppress=Ta184 # Using zero sized arrays except for as last member of a struct is discouraged and dereferencing elements in such an array has undefined behavior
)
endif()
# Minimal ASM compiler flags
if("${IAR_TOOLCHAIN_VARIANT}" STREQUAL "iccarm")
list(APPEND IAR_ASM_FLAGS
-mcpu=${GCC_M_CPU}
-mabi=aapcs
-DRTT_USE_ASM=0 #WA for VAAK-232
)
endif()
if(CONFIG_DEBUG)
# GCC defaults to Dwarf 5 output
list(APPEND IAR_ASM_FLAGS -gdwarf-4)
endif()
if(DEFINED CONFIG_ARM_SECURE_FIRMWARE)
list(APPEND IAR_COMMON_FLAGS --cmse)
list(APPEND IAR_ASM_FLAGS -mcmse)
endif()
# 64-bit
if("${IAR_TOOLCHAIN_VARIANT}" STREQUAL "iccarm")
if(CONFIG_ARM64)
list(APPEND IAR_COMMON_FLAGS --abi=lp64)
list(APPEND TOOLCHAIN_LD_FLAGS --abi=lp64)
# 32-bit
else()
list(APPEND IAR_COMMON_FLAGS --aeabi)
if(CONFIG_COMPILER_ISA_THUMB2)
list(APPEND IAR_COMMON_FLAGS --thumb)
list(APPEND IAR_ASM_FLAGS -mthumb)
endif()
if(CONFIG_FPU)
list(APPEND IAR_COMMON_FLAGS --fpu=${ICCARM_FPU})
list(APPEND IAR_ASM_FLAGS -mfpu=${GCC_M_FPU})
endif()
endif()
endif()
if("${IAR_TOOLCHAIN_VARIANT}" STREQUAL "iccarm")
if(CONFIG_IAR_LIBC)
# Zephyr requires AEABI portability to ensure correct functioning of the C
# library, for example error numbers, errno.h.
list(APPEND IAR_COMMON_FLAGS -D__AEABI_PORTABILITY_LEVEL=1)
endif()
endif()
if(CONFIG_IAR_LIBC)
message(STATUS "IAR C library used")
# Zephyr uses the type FILE for normal LIBC while IAR
# only has it for full LIBC support, so always choose
# full libc when using IAR C libraries.
list(APPEND IAR_COMMON_FLAGS --dlib_config full)
endif()
foreach(F ${IAR_COMMON_FLAGS})
list(APPEND TOOLCHAIN_C_FLAGS $<$<COMPILE_LANGUAGE:C>:${F}>)
list(APPEND TOOLCHAIN_C_FLAGS $<$<COMPILE_LANGUAGE:CXX>:${F}>)
endforeach()
foreach(F ${IAR_ASM_FLAGS})
list(APPEND TOOLCHAIN_C_FLAGS $<$<COMPILE_LANGUAGE:ASM>:${F}>)
endforeach()

922
cmake/linker/iar/config_file_script.cmake

@ -0,0 +1,922 @@ @@ -0,0 +1,922 @@
# Copyright (c) 2025 IAR Systems AB
#
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.17)
set(SORT_TYPE_NAME Lexical)
set_property(GLOBAL PROPERTY ILINK_REGION_SYMBOL_ICF)
# This function post process the region for easier use.
#
# Tasks:
# - Symbol translation using a steering file is configured.
function(process_region)
cmake_parse_arguments(REGION "" "OBJECT" "" ${ARGN})
process_region_common(${ARGN})
get_property(empty GLOBAL PROPERTY ${REGION_OBJECT}_EMPTY)
if(NOT empty)
# For scatter files we move any system symbols into first non-empty load section.
get_parent(OBJECT ${REGION_OBJECT} PARENT parent TYPE SYSTEM)
get_property(symbols GLOBAL PROPERTY ${parent}_SYMBOLS)
set_property(GLOBAL APPEND PROPERTY ${REGION_OBJECT}_SYMBOLS ${symbols})
set_property(GLOBAL PROPERTY ${parent}_SYMBOLS)
endif()
get_property(sections GLOBAL PROPERTY ${REGION_OBJECT}_SECTION_LIST_ORDERED)
foreach(section ${sections})
get_property(name GLOBAL PROPERTY ${section}_NAME)
get_property(name_clean GLOBAL PROPERTY ${section}_NAME_CLEAN)
get_property(noinput GLOBAL PROPERTY ${section}_NOINPUT)
get_property(type GLOBAL PROPERTY ${section}_TYPE)
get_property(nosymbols GLOBAL PROPERTY ${section}_NOSYMBOLS)
if(NOT nosymbols)
if(${name} STREQUAL .ramfunc)
create_symbol(OBJECT ${REGION_OBJECT} SYMBOL __${name_clean}_load_start
EXPR "@ADDR(.ramfunc_init)@"
)
else()
create_symbol(OBJECT ${REGION_OBJECT} SYMBOL __${name_clean}_load_start
EXPR "@LOADADDR(${name_clean})@"
)
endif()
endif()
get_property(indicies GLOBAL PROPERTY ${section}_SETTINGS_INDICIES)
list(LENGTH indicies length)
foreach(idx ${indicies})
set(steering_postfixes Base Limit)
get_property(symbols GLOBAL PROPERTY ${section}_SETTING_${idx}_SYMBOLS)
get_property(sort GLOBAL PROPERTY ${section}_SETTING_${idx}_SORT)
get_property(offset GLOBAL PROPERTY ${section}_SETTING_${idx}_OFFSET)
if(DEFINED offset AND NOT offset EQUAL 0 )
# Same behavior as in section_to_string
elseif(DEFINED offset AND offset STREQUAL 0 )
# Same behavior as in section_to_string
elseif(sort)
# Treated by labels in the icf or image symbols.
elseif(DEFINED symbols AND ${length} EQUAL 1 AND noinput)
endif()
endforeach()
# Symbols translation here.
get_property(symbol_val GLOBAL PROPERTY SYMBOL_TABLE___${name_clean}_end)
if("${symbol_val}" STREQUAL "${name_clean}")
create_symbol(OBJECT ${REGION_OBJECT} SYMBOL __${name_clean}_size
EXPR "@SIZE(${name_clean})@"
)
else()
# These seem to be thing that can't be transformed to $$Length
set_property(GLOBAL APPEND PROPERTY ILINK_REGION_SYMBOL_ICF
"define image symbol __${name_clean}_size = (__${symbol_val} - ADDR(${name_clean}))")
endif()
set(ZI)
if(${name_clean} STREQUAL last_ram_section)
# A trick to add the symbol for the nxp devices
# _flash_used = LOADADDR(.last_section) + SIZEOF(.last_section) - __rom_region_start;
create_symbol(OBJECT ${REGION_OBJECT} SYMBOL _flash_used
EXPR "(@LOADADDR(last_section)@ + @SIZE(last_section)@ - @__rom_region_start@)"
)
endif()
if(${name_clean} STREQUAL rom_start)
# The below two symbols is meant to make aliases to the _vector_table symbol.
list(GET symbols 0 symbol_start)
create_symbol(OBJECT ${REGION_OBJECT} SYMBOL __Vectors
EXPR "@ADDR(${symbol_start})@"
)
create_symbol(OBJECT ${REGION_OBJECT} SYMBOL __vector_table
EXPR "@ADDR(${symbol_start})@"
)
endif()
endforeach()
get_property(groups GLOBAL PROPERTY ${REGION_OBJECT}_GROUP_LIST_ORDERED)
foreach(group ${groups})
get_property(name GLOBAL PROPERTY ${group}_NAME)
string(TOLOWER ${name} name)
get_property(group_type GLOBAL PROPERTY ${group}_OBJ_TYPE)
get_property(parent GLOBAL PROPERTY ${group}_PARENT)
get_property(parent_type GLOBAL PROPERTY ${parent}_OBJ_TYPE)
# Need to find the init manually group or parent
if(${parent_type} STREQUAL GROUP)
get_property(vma GLOBAL PROPERTY ${parent}_VMA)
get_property(lma GLOBAL PROPERTY ${parent}_LMA)
else()
get_property(vma GLOBAL PROPERTY ${group}_VMA)
get_property(lma GLOBAL PROPERTY ${group}_LMA)
endif()
get_objects(LIST sections OBJECT ${group} TYPE SECTION)
list(GET sections 0 section)
get_property(first_section_name GLOBAL PROPERTY ${section}_NAME_CLEAN)
list(POP_BACK sections section)
get_property(last_section_name GLOBAL PROPERTY ${section}_NAME_CLEAN)
if(DEFINED vma AND DEFINED lma)
# Something to init
create_symbol(OBJECT ${REGION_OBJECT} SYMBOL __${name}_load_start
EXPR "@ADDR(${first_section_name}_init)@"
)
else()
create_symbol(OBJECT ${REGION_OBJECT} SYMBOL __${name}_load_start
EXPR "@LOADADDR(${first_section_name})@"
)
endif()
create_symbol(OBJECT ${REGION_OBJECT} SYMBOL __${name}_start
EXPR "@ADDR(${first_section_name})@"
)
create_symbol(OBJECT ${REGION_OBJECT} SYMBOL __${name}_end
EXPR "@END(${last_section_name})@"
)
create_symbol(OBJECT ${REGION_OBJECT} SYMBOL __${name}_size
EXPR "(@(__${name}_end)@ - @(__${name}_start)@)"
)
endforeach()
get_property(symbols GLOBAL PROPERTY ${REGION_OBJECT}_SYMBOLS)
foreach(symbol ${symbols})
get_property(name GLOBAL PROPERTY ${symbol}_NAME)
get_property(expr GLOBAL PROPERTY ${symbol}_EXPR)
if(NOT DEFINED expr)
create_symbol(OBJECT ${REGION_OBJECT} SYMBOL __${name}_size
EXPR "@(ADDR(${name})@"
)
endif()
endforeach()
# This is only a trick to get the memories
set(groups)
get_objects(LIST groups OBJECT ${REGION_OBJECT} TYPE GROUP)
foreach(group ${groups})
get_property(group_type GLOBAL PROPERTY ${group}_OBJ_TYPE)
get_property(parent GLOBAL PROPERTY ${group}_PARENT)
get_property(parent_type GLOBAL PROPERTY ${parent}_OBJ_TYPE)
if(${group_type} STREQUAL GROUP)
get_property(group_name GLOBAL PROPERTY ${group}_NAME)
get_property(group_lma GLOBAL PROPERTY ${group}_LMA)
if(${group_name} STREQUAL ROM_REGION)
set_property(GLOBAL PROPERTY ILINK_ROM_REGION_NAME ${group_lma})
endif()
endif()
if(${parent_type} STREQUAL GROUP)
get_property(vma GLOBAL PROPERTY ${parent}_VMA)
get_property(lma GLOBAL PROPERTY ${parent}_LMA)
set_property(GLOBAL PROPERTY ${group}_VMA ${vma})
set_property(GLOBAL PROPERTY ${group}_LMA ${lma})
endif()
endforeach()
endfunction()
#
# String functions - start
#
function(system_to_string)
cmake_parse_arguments(STRING "" "OBJECT;STRING" "" ${ARGN})
get_property(name GLOBAL PROPERTY ${STRING_OBJECT}_NAME)
get_property(regions GLOBAL PROPERTY ${STRING_OBJECT}_REGIONS)
get_property(format GLOBAL PROPERTY ${STRING_OBJECT}_FORMAT)
# Ilink specials
# set(${STRING_STRING} "build for rom;\n")
set(${STRING_STRING} "build for ram;\n")
if("${format}" MATCHES "aarch64")
set(${STRING_STRING} "${${STRING_STRING}}define memory mem with size = 16E;\n")
else()
set(${STRING_STRING} "${${STRING_STRING}}define memory mem with size = 4G;\n")
endif()
foreach(region ${regions})
get_property(name GLOBAL PROPERTY ${region}_NAME)
get_property(address GLOBAL PROPERTY ${region}_ADDRESS)
get_property(flags GLOBAL PROPERTY ${region}_FLAGS)
get_property(size GLOBAL PROPERTY ${region}_SIZE)
if(DEFINED flags)
if(${flags} STREQUAL rx)
set(flags " rom")
elseif(${flags} STREQUAL ro)
set(flags " rom")
elseif(${flags} STREQUAL wx)
set(flags " ram")
elseif(${flags} STREQUAL rw)
set(flags " ram")
endif()
endif()
if(${name} STREQUAL IDT_LIST)
# Need to use a untyped region for IDT_LIST
set(flags "")
endif()
if(DEFINED address)
set(start "${address}")
endif()
if(DEFINED size)
set(size "${size}")
endif()
# define rom region FLASH = mem:[from 0x0 size 0x40000];
set(memory_region "define${flags} region ${name} = mem:[from ${start} size ${size}];")
set(${STRING_STRING} "${${STRING_STRING}}${memory_region}\n")
set(flags)
endforeach()
set(${STRING_STRING} "${${STRING_STRING}}\n\n")
set_property(GLOBAL PROPERTY ILINK_SYMBOL_ICF)
set(${STRING_STRING} "${${STRING_STRING}}\n")
foreach(region ${regions})
get_property(empty GLOBAL PROPERTY ${region}_EMPTY)
if(NOT empty)
get_property(name GLOBAL PROPERTY ${region}_NAME)
set(ILINK_CURRENT_NAME ${name})
to_string(OBJECT ${region} STRING ${STRING_STRING})
set(ILINK_CURRENT_NAME)
endif()
endforeach()
set(${STRING_STRING} "${${STRING_STRING}}\n")
get_property(symbols_icf GLOBAL PROPERTY ILINK_SYMBOL_ICF)
foreach(image_symbol ${symbols_icf})
set(${STRING_STRING} "${${STRING_STRING}}define image symbol ${image_symbol};\n")
endforeach()
get_property(symbols_icf GLOBAL PROPERTY ILINK_REGION_SYMBOL_ICF)
set(${STRING_STRING} "${${STRING_STRING}}\n")
foreach(image_symbol ${symbols_icf})
set(${STRING_STRING} "${${STRING_STRING}}${image_symbol};\n")
endforeach()
if(IAR_LIBC)
set(${STRING_STRING} "${${STRING_STRING}}if (K_HEAP_MEM_POOL_SIZE>0)\n{\n")
set(${STRING_STRING} "${${STRING_STRING}} define block HEAP with alignment=8 { symbol kheap__system_heap };\n")
set(${STRING_STRING} "${${STRING_STRING}}}\nelse\n{\n")
set(${STRING_STRING} "${${STRING_STRING}} define block HEAP with alignment=8, expanding size { };\n")
set(${STRING_STRING} "${${STRING_STRING}}}\n")
set(${STRING_STRING} "${${STRING_STRING}}\"DLib heap\": place in RAM { block HEAP };\n")
# set(${STRING_STRING} "${${STRING_STRING}}define exported symbol HEAP$$Base=kheap__system_heap;\n")
# set(${STRING_STRING} "${${STRING_STRING}}define exported symbol HEAP$$Limit=END(kheap__system_heap);\n")
endif()
set(${STRING_STRING} ${${STRING_STRING}} PARENT_SCOPE)
endfunction()
function(group_to_string)
cmake_parse_arguments(STRING "" "OBJECT;STRING" "" ${ARGN})
get_property(type GLOBAL PROPERTY ${STRING_OBJECT}_OBJ_TYPE)
if(${type} STREQUAL REGION)
get_property(name GLOBAL PROPERTY ${STRING_OBJECT}_NAME)
get_property(address GLOBAL PROPERTY ${STRING_OBJECT}_ADDRESS)
get_property(size GLOBAL PROPERTY ${STRING_OBJECT}_SIZE)
get_property(empty GLOBAL PROPERTY ${STRING_OBJECT}_EMPTY)
if(empty)
return()
endif()
else()
get_property(else_name GLOBAL PROPERTY ${STRING_OBJECT}_NAME)
get_property(else_symbol GLOBAL PROPERTY ${STRING_OBJECT}_SYMBOL)
string(TOLOWER ${else_name} else_name)
get_objects(LIST sections OBJECT ${STRING_OBJECT} TYPE SECTION)
list(GET sections 0 section)
get_property(first_section_name GLOBAL PROPERTY ${section}_NAME)
endif()
if(${type} STREQUAL GROUP)
get_property(group_name GLOBAL PROPERTY ${STRING_OBJECT}_NAME)
get_property(group_address GLOBAL PROPERTY ${STRING_OBJECT}_ADDRESS)
get_property(group_vma GLOBAL PROPERTY ${STRING_OBJECT}_VMA)
get_property(group_lma GLOBAL PROPERTY ${STRING_OBJECT}_LMA)
endif()
get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_SECTIONS_FIXED)
foreach(section ${sections})
to_string(OBJECT ${section} STRING ${STRING_STRING})
get_property(name GLOBAL PROPERTY ${section}_NAME)
get_property(name_clean GLOBAL PROPERTY ${section}_NAME_CLEAN)
set(${STRING_STRING} "${${STRING_STRING}}\"${name}\": place at address mem:${address} { block ${name_clean} };\n")
endforeach()
get_property(groups GLOBAL PROPERTY ${STRING_OBJECT}_GROUPS)
foreach(group ${groups})
to_string(OBJECT ${group} STRING ${STRING_STRING})
endforeach()
get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_SECTIONS)
foreach(section ${sections})
to_string(OBJECT ${section} STRING ${STRING_STRING})
get_property(name GLOBAL PROPERTY ${section}_NAME)
get_property(name_clean GLOBAL PROPERTY ${section}_NAME_CLEAN)
get_property(parent GLOBAL PROPERTY ${section}_PARENT)
# This is only a trick to get the memories
get_property(parent_type GLOBAL PROPERTY ${parent}_OBJ_TYPE)
if(${parent_type} STREQUAL GROUP)
get_property(vma GLOBAL PROPERTY ${parent}_VMA)
get_property(lma GLOBAL PROPERTY ${parent}_LMA)
endif()
if(DEFINED vma)
set(ILINK_CURRENT_NAME ${vma})
elseif(DEFINED lma)
set(ILINK_CURRENT_NAME ${lma})
else()
# message(FATAL_ERROR "Need either vma or lma")
endif()
set(${STRING_STRING} "${${STRING_STRING}}\"${name}\": place in ${ILINK_CURRENT_NAME} { block ${name_clean} };\n")
if(DEFINED vma AND DEFINED lma)
set(${STRING_STRING} "${${STRING_STRING}}\"${name}_init\": place in ${lma} { block ${name_clean}_init };\n")
endif()
endforeach()
get_parent(OBJECT ${STRING_OBJECT} PARENT parent TYPE SYSTEM)
get_property(regions GLOBAL PROPERTY ${parent}_REGIONS)
list(REMOVE_ITEM regions ${STRING_OBJECT})
foreach(region ${regions})
get_property(vma GLOBAL PROPERTY ${region}_NAME)
get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_${vma}_SECTIONS_FIXED)
foreach(section ${sections})
to_string(OBJECT ${section} STRING ${STRING_STRING})
endforeach()
get_property(groups GLOBAL PROPERTY ${STRING_OBJECT}_${vma}_GROUPS)
foreach(group ${groups})
to_string(OBJECT ${group} STRING ${STRING_STRING})
endforeach()
get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_${vma}_SECTIONS)
foreach(section ${sections})
to_string(OBJECT ${section} STRING ${STRING_STRING})
get_property(name GLOBAL PROPERTY ${section}_NAME)
string(REGEX REPLACE "^[\.]" "" name_clean "${name}")
string(REPLACE "." "_" name_clean "${name_clean}")
set(${STRING_STRING} "${${STRING_STRING}}\"${name}\": place in ${vma} { block ${name_clean} };\n")
# Insert 'do not initialize' here
get_property(current_sections GLOBAL PROPERTY ILINK_CURRENT_SECTIONS)
if(${name} STREQUAL .bss)
if(DEFINED current_sections)
set(${STRING_STRING} "${${STRING_STRING}}do not initialize\n")
set(${STRING_STRING} "${${STRING_STRING}}{\n")
foreach(section ${current_sections})
set(${STRING_STRING} "${${STRING_STRING}} ${section},\n")
endforeach()
set(${STRING_STRING} "${${STRING_STRING}}};\n")
set(current_sections)
set_property(GLOBAL PROPERTY ILINK_CURRENT_SECTIONS)
endif()
endif()
if(${name_clean} STREQUAL last_ram_section)
get_property(group_name_lma GLOBAL PROPERTY ILINK_ROM_REGION_NAME)
set(${STRING_STRING} "${${STRING_STRING}}\n")
if(${CONFIG_LINKER_LAST_SECTION_ID})
set(${STRING_STRING} "${${STRING_STRING}}define section last_section_id { udata32 ${CONFIG_LINKER_LAST_SECTION_ID_PATTERN}; };\n")
set(${STRING_STRING} "${${STRING_STRING}}define block last_section with fixed order { section last_section_id };\n")
else()
set(${STRING_STRING} "${${STRING_STRING}}define block last_section with fixed order { };\n")
endif()
# Not really the right place, we want the last used flash bytes not end of the world!
# set(${STRING_STRING} "${${STRING_STRING}}\".last_section\": place at end of ${group_name_lma} { block last_section };\n")
set(${STRING_STRING} "${${STRING_STRING}}\".last_section\": place in ${group_name_lma} { block last_section };\n")
set(${STRING_STRING} "${${STRING_STRING}}keep { block last_section };\n")
endif()
endforeach()
endforeach()
get_property(symbols GLOBAL PROPERTY ${STRING_OBJECT}_SYMBOLS)
set(${STRING_STRING} "${${STRING_STRING}}\n")
foreach(symbol ${symbols})
to_string(OBJECT ${symbol} STRING ${STRING_STRING})
endforeach()
set(${STRING_STRING} ${${STRING_STRING}} PARENT_SCOPE)
endfunction()
function(section_to_string)
cmake_parse_arguments(STRING "" "SECTION;STRING" "" ${ARGN})
get_property(name GLOBAL PROPERTY ${STRING_SECTION}_NAME)
get_property(address GLOBAL PROPERTY ${STRING_SECTION}_ADDRESS)
get_property(type GLOBAL PROPERTY ${STRING_SECTION}_TYPE)
get_property(align GLOBAL PROPERTY ${STRING_SECTION}_ALIGN)
get_property(subalign GLOBAL PROPERTY ${STRING_SECTION}_SUBALIGN)
get_property(endalign GLOBAL PROPERTY ${STRING_SECTION}_ENDALIGN)
get_property(vma GLOBAL PROPERTY ${STRING_SECTION}_VMA)
get_property(lma GLOBAL PROPERTY ${STRING_SECTION}_LMA)
get_property(noinput GLOBAL PROPERTY ${STRING_SECTION}_NOINPUT)
get_property(noinit GLOBAL PROPERTY ${STRING_SECTION}_NOINIT)
get_property(nosymbols GLOBAL PROPERTY ${STRING_SECTION}_NOSYMBOLS)
get_property(start_syms GLOBAL PROPERTY ${STRING_SECTION}_START_SYMBOLS)
get_property(end_syms GLOBAL PROPERTY ${STRING_SECTION}_END_SYMBOLS)
get_property(parent GLOBAL PROPERTY ${STRING_SECTION}_PARENT)
get_property(parent_type GLOBAL PROPERTY ${parent}_OBJ_TYPE)
if(${parent_type} STREQUAL GROUP)
get_property(group_parent_vma GLOBAL PROPERTY ${parent}_VMA)
get_property(group_parent_lma GLOBAL PROPERTY ${parent}_LMA)
if(NOT DEFINED vma)
get_property(vma GLOBAL PROPERTY ${parent}_VMA)
endif()
if(NOT DEFINED lma)
get_property(lma GLOBAL PROPERTY ${parent}_LMA)
endif()
endif()
if(DEFINED group_parent_vma AND DEFINED group_parent_lma)
# Something to init
set(part "rw ")
else()
set(part)
endif()
set_property(GLOBAL PROPERTY ILINK_CURRENT_SECTIONS)
string(REGEX REPLACE "^[\.]" "" name_clean "${name}")
string(REPLACE "." "_" name_clean "${name_clean}")
# WA for 'Error[Lc036]: no block or place matches the pattern "ro data section .tdata_init"'
if("${name_clean}" STREQUAL "tdata")
set(TEMP "${TEMP}define block ${name_clean}_init { ro section .tdata_init };\n")
set(TEMP "${TEMP}\"${name_clean}_init\": place in ${ILINK_CURRENT_NAME} { block ${name_clean}_init };\n\n")
endif()
get_property(indicies GLOBAL PROPERTY ${STRING_SECTION}_SETTINGS_INDICIES)
# ZIP_LISTS partner
get_property(next_indicies GLOBAL PROPERTY ${STRING_SECTION}_SETTINGS_INDICIES)
list(POP_FRONT next_indicies first_index)
set(first_index_section)
set(first_index_section_name)
if(DEFINED first_index)
# Handle case where the first section has an offset
get_property(first_index_offset
GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${first_index}_OFFSET)
get_property(keep GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${first_index}_KEEP)
if(DEFINED keep)
set(root "root ")
else()
set(root)
endif()
if(DEFINED first_index_offset AND NOT first_index_offset EQUAL 0 )
set(first_index_section_name "${name_clean}_${first_index}_offset")
set(first_index_section
"define ${root}section ${first_index_section_name} {};")
else()
set(first_index)
endif()
endif()
foreach(start_symbol ${start_syms})
set_property(GLOBAL APPEND PROPERTY ILINK_SYMBOL_ICF "${start_symbol} = ADDR(${name_clean})")
endforeach()
foreach(end_symbol ${end_syms})
set_property(GLOBAL APPEND PROPERTY ILINK_SYMBOL_ICF "${end_symbol} = END(${name_clean})")
endforeach()
if(NOT nosymbols)
if("${name_clean}" STREQUAL "tdata")
set_property(GLOBAL APPEND PROPERTY ILINK_SYMBOL_ICF "__${name_clean}_start = (__iar_tls$$INIT_DATA$$Base)")
set_property(GLOBAL APPEND PROPERTY ILINK_SYMBOL_ICF "__${name_clean}_end = (__iar_tls$$INIT_DATA$$Limit)")
else()
set_property(GLOBAL APPEND PROPERTY ILINK_SYMBOL_ICF "__${name_clean}_start = ADDR(${name_clean})")
set_property(GLOBAL APPEND PROPERTY ILINK_SYMBOL_ICF "__${name_clean}_end = END(${name_clean})")
endif()
endif()
# Add keep to the sections that have 'KEEP:TRUE'
foreach(idx ${indicies})
get_property(keep GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_KEEP)
get_property(input GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_INPUT)
foreach(setting ${input})
if(keep)
# keep { section .abc* };
set(TEMP "${TEMP}keep { section ${setting} };\n")
endif()
endforeach()
endforeach()
if(DEFINED first_index_section)
set(TEMP "${TEMP}${first_index_section}\n")
endif()
set(TEMP "${TEMP}define block ${name_clean} with fixed order")
if(align)
set(TEMP "${TEMP}, alignment=${align}")
elseif(subalign)
set(TEMP "${TEMP}, alignment = ${subalign}")
elseif(part)
set(TEMP "${TEMP}, alignment = input")
else()
set(TEMP "${TEMP}, alignment=4")
endif()
if(endalign)
set(TEMP "${TEMP}, end alignment=${endalign}")
endif()
set(TEMP "${TEMP}\n{")
# foreach(start_symbol ${start_syms})
# set(TEMP "${TEMP}\n section ${start_symbol},")
# set_property(GLOBAL APPEND PROPERTY ILINK_CURRENT_SECTIONS "section ${start_symbol}")
# endforeach()
# if(NOT nosymbols)
# set(TEMP "${TEMP}\n section __${name_clean}_start,")
# set_property(GLOBAL APPEND PROPERTY ILINK_CURRENT_SECTIONS "section __${name_clean}_start")
# endif()
list(GET indicies -1 last_index)
list(LENGTH indicies length)
if(NOT noinput)
set(TEMP "${TEMP}\n block ${name_clean}_winput")
if(align)
list(APPEND block_attr "alignment = ${align}")
elseif(subalign)
list(APPEND block_attr "alignment = ${subalign}")
elseif(part)
# list(APPEND block_attr "alignment = input")
else()
list(APPEND block_attr "alignment=4")
endif()
list(APPEND block_attr "fixed order")
list(JOIN block_attr ", " block_attr_str)
if(block_attr_str)
set(TEMP "${TEMP} with ${block_attr_str}")
endif()
set(block_attr)
set(block_attr_str)
set(TEMP "${TEMP} { ${part}section ${name}, ${part}section ${name}.* }")
if(${length} GREATER 0)
set(TEMP "${TEMP},")
endif()
set_property(GLOBAL APPEND PROPERTY ILINK_CURRENT_SECTIONS "section ${name}")
set_property(GLOBAL APPEND PROPERTY ILINK_CURRENT_SECTIONS "section ${name}.*")
endif()
foreach(idx idx_next IN ZIP_LISTS indicies next_indicies)
get_property(align GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_ALIGN)
get_property(any GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_ANY)
get_property(first GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_FIRST)
get_property(keep GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_KEEP)
get_property(sort GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_SORT)
get_property(flags GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_FLAGS)
get_property(input GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_INPUT)
get_property(symbols GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_SYMBOLS)
# Get the next offset and use that as this ones size!
get_property(offset GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx_next}_OFFSET)
if(DEFINED symbols)
list(LENGTH symbols symbols_count)
if(${symbols_count} GREATER 0)
list(GET symbols 0 symbol_start)
endif()
if(${symbols_count} GREATER 1)
list(GET symbols 1 symbol_end)
endif()
endif()
if(DEFINED symbol_start)
# set(TEMP "${TEMP}\n section ${symbol_start},")
# set_property(GLOBAL APPEND PROPERTY ILINK_CURRENT_SECTIONS "section ${symbol_start}")
set_property(GLOBAL APPEND PROPERTY ILINK_SYMBOL_ICF "${symbol_start} = ADDR(${name_clean}_${idx})")
endif()
if(DEFINED first_index AND first_index EQUAL ${idx})
# Create the offset
set(TEMP "${TEMP}\n block ${first_index_section_name}")
list(APPEND block_attr "size = ${first_index_offset}")
if(sort)
if(${sort} STREQUAL NAME)
list(APPEND block_attr "alphabetical order")
endif()
endif()
if(align)
list(APPEND block_attr "alignment = ${align}")
elseif(subalign)
list(APPEND block_attr "alignment = ${subalign}")
elseif(part)
# list(APPEND block_attr "alignment = input")
else()
list(APPEND block_attr "alignment=4")
endif()
list(APPEND block_attr "fixed order")
list(JOIN block_attr ", " block_attr_str)
if(block_attr_str)
set(TEMP "${TEMP} with ${block_attr_str}")
endif()
set(block_attr)
set(block_attr_str)
set(TEMP "${TEMP} { section ${first_index_section_name} },\n")
endif()
# block init_100 with alphabetical order { section .z_init_EARLY?_}
set(TEMP "${TEMP}\n block ${name_clean}_${idx}")
if(DEFINED offset AND NOT offset EQUAL 0 )
list(APPEND block_attr "size = ${offset}")
elseif(DEFINED offset AND offset STREQUAL 0 )
# Do nothing
endif()
if(sort)
if(${sort} STREQUAL NAME)
list(APPEND block_attr "alphabetical order")
endif()
endif()
if(align)
list(APPEND block_attr "alignment = ${align}")
elseif(subalign)
list(APPEND block_attr "alignment = ${subalign}")
elseif(part)
# list(APPEND block_attr "alignment = input")
else()
list(APPEND block_attr "alignment=4")
endif()
# LD
# There are two ways to include more than one section:
#
# *(.text .rdata)
# *(.text) *(.rdata)
#
# The difference between these is the order in which
# the `.text' and `.rdata' input sections will appear in the output section.
# In the first example, they will be intermingled,
# appearing in the same order as they are found in the linker input.
# In the second example, all `.text' input sections will appear first,
# followed by all `.rdata' input sections.
#
# ILINK solved by adding 'fixed order'
if(NOT sort AND NOT first)
list(APPEND block_attr "fixed order")
endif()
list(JOIN block_attr ", " block_attr_str)
if(block_attr_str)
set(TEMP "${TEMP} with ${block_attr_str}")
endif()
set(block_attr)
set(block_attr_str)
if(empty)
set(TEMP "${TEMP}\n {")
set(empty FALSE)
endif()
list(GET input -1 last_input)
set(TEMP "${TEMP} {")
if(NOT DEFINED input AND NOT any)
set(TEMP "${TEMP} }")
endif()
foreach(setting ${input})
if(first)
set(TEMP "${TEMP} first")
set(first "")
endif()
set(section_type "")
# build for ram, no section_type
# if("${lma}" STREQUAL "${vma}")
# # if("${vma}" STREQUAL "")
# set(section_type "")
# # else()
# # set(section_type " readwrite")
# # endif()
# elseif(NOT "${vma}" STREQUAL "")
# set(section_type " readwrite")
# elseif(NOT "${lma}" STREQUAL "")
# set(section_type " readonly")
# else()
# message(FATAL_ERROR "How to handle this? lma=${lma} vma=${vma}")
# endif()
set(TEMP "${TEMP}${section_type} ${part}section ${setting}")
set_property(GLOBAL APPEND PROPERTY ILINK_CURRENT_SECTIONS "section ${setting}")
set(section_type "")
if("${setting}" STREQUAL "${last_input}")
set(TEMP "${TEMP} }")
else()
set(TEMP "${TEMP}, ")
endif()
# set(TEMP "${TEMP}\n *.o(${setting})")
endforeach()
if(any)
if(NOT flags)
message(FATAL_ERROR ".ANY requires flags to be set.")
endif()
set(ANY_FLAG "")
foreach(flag ${flags})
# if("${flag}" STREQUAL +RO OR "${flag}" STREQUAL +XO)
# set(ANY_FLAG "readonly")
# # elseif("${flag}" STREQUAL +RW)
# # set(ANY_FLAG "readwrite")
# else
if("${flag}" STREQUAL +ZI)
set(ANY_FLAG "zeroinit")
set_property(GLOBAL APPEND PROPERTY ILINK_CURRENT_SECTIONS "${ANY_FLAG}")
endif()
endforeach()
set(TEMP "${TEMP} ${ANY_FLAG} }")
endif()
if(DEFINED symbol_end)
# set(TEMP "${TEMP},\n section ${symbol_end}")
# set_property(GLOBAL APPEND PROPERTY ILINK_CURRENT_SECTIONS "section ${symbol_end}")
set_property(GLOBAL APPEND PROPERTY ILINK_SYMBOL_ICF "${symbol_end} = END(${name_clean}_${idx})")
endif()
if(${length} GREATER 0)
if(NOT "${idx}" STREQUAL "${last_index}")
set(TEMP "${TEMP},")
elseif()
endif()
endif()
set(symbol_start)
set(symbol_end)
endforeach()
set(next_indicies)
set(last_index)
set(last_input)
set(TEMP "${TEMP}")
# if(NOT nosymbols)
# set(TEMP "${TEMP},\n section __${name_clean}_end")
# set_property(GLOBAL APPEND PROPERTY ILINK_CURRENT_SECTIONS "section __${name_clean}_end")
# endif()
# foreach(end_symbol ${end_syms})
# set(TEMP "${TEMP},\n section ${end_symbol}")
# set_property(GLOBAL APPEND PROPERTY ILINK_CURRENT_SECTIONS "section ${end_symbol}")
# endforeach()
set(TEMP "${TEMP}\n};")
get_property(type GLOBAL PROPERTY ${parent}_OBJ_TYPE)
if(${type} STREQUAL REGION)
get_property(name GLOBAL PROPERTY ${parent}_NAME)
get_property(address GLOBAL PROPERTY ${parent}_ADDRESS)
get_property(size GLOBAL PROPERTY ${parent}_SIZE)
endif()
get_property(current_sections GLOBAL PROPERTY ILINK_CURRENT_SECTIONS)
if(DEFINED group_parent_vma AND DEFINED group_parent_lma)
if(DEFINED current_sections)
# "${TEMP}" is there too keep the ';' else it will be a list
string(REGEX REPLACE "(block[ \t\r\n]+)([^ \t\r\n]+)" "\\1\\2_init" INIT_TEMP "${TEMP}")
string(REGEX REPLACE "(rw)([ \t\r\n]+)(section[ \t\r\n]+)([^ \t\r\n,]+)" "\\1\\2\\3\\4_init" INIT_TEMP "${INIT_TEMP}")
string(REGEX REPLACE "(rw)([ \t\r\n]+)(section[ \t\r\n]+)" "ro\\2\\3" INIT_TEMP "${INIT_TEMP}")
string(REGEX REPLACE "alphabetical order, " "" INIT_TEMP "${INIT_TEMP}")
string(REGEX REPLACE "{ readwrite }" "{ }" INIT_TEMP "${INIT_TEMP}")
set(TEMP "${TEMP}\n${INIT_TEMP}\n")
set(TEMP "${TEMP}\ninitialize manually with copy friendly\n")
set(TEMP "${TEMP}{\n")
foreach(section ${current_sections})
set(TEMP "${TEMP} ${section},\n")
endforeach()
set(TEMP "${TEMP}};")
set(current_sections)
endif()
endif()
set(${STRING_STRING} "${${STRING_STRING}}\n${TEMP}\n" PARENT_SCOPE)
endfunction()
function(symbol_to_string)
cmake_parse_arguments(STRING "" "SYMBOL;STRING" "" ${ARGN})
get_property(name GLOBAL PROPERTY ${STRING_SYMBOL}_NAME)
get_property(expr GLOBAL PROPERTY ${STRING_SYMBOL}_EXPR)
get_property(size GLOBAL PROPERTY ${STRING_SYMBOL}_SIZE)
get_property(symbol GLOBAL PROPERTY ${STRING_SYMBOL}_SYMBOL)
get_property(subalign GLOBAL PROPERTY ${STRING_SYMBOL}_SUBALIGN)
string(REPLACE "\\" "" expr "${expr}")
string(REGEX MATCHALL "@([^@]*)@" match_res ${expr})
foreach(match ${match_res})
string(REPLACE "@" "" match ${match})
get_property(symbol_val GLOBAL PROPERTY SYMBOL_TABLE_${match})
string(REPLACE "@${match}@" "${match}" expr ${expr})
endforeach()
list(LENGTH match_res match_res_count)
if(match_res_count)
if(${match_res_count} GREATER 1)
set(${STRING_STRING}
"${${STRING_STRING}}define image symbol ${symbol} = ${expr};\n"
)
else()
if((expr MATCHES "Base|Limit|Length") OR (expr MATCHES "ADDR\\(|END\\(|SIZE\\("))
# Anything like $$Base/$$Limit/$$Length should be an image symbol
if( "${symbol}" STREQUAL "__tdata_size")
# This will handle the alignment of the TBSS block
set(${STRING_STRING}
"${${STRING_STRING}}define image symbol ${symbol}=(__iar_tls$$INIT_DATA$$Limit-__iar_tls$$INIT_DATA$$Base);\n"
)
elseif( "${symbol}" STREQUAL "__tbss_size")
# This will handle the alignment of the TBSS block by
# pre-padding bytes
set(${STRING_STRING}
"${${STRING_STRING}}define image symbol ${symbol}=((tbss$$Limit-__iar_tls$$DATA$$Base)-(__iar_tls$$INIT_DATA$$Limit-__iar_tls$$INIT_DATA$$Base));\n"
)
else()
set(${STRING_STRING}
"${${STRING_STRING}}define image symbol ${symbol} = ${expr};\n"
)
endif()
else()
list(GET match_res 0 match)
string(REPLACE "@" "" match ${match})
get_property(symbol_val GLOBAL PROPERTY SYMBOL_TABLE_${match})
if(symbol_val)
set(${STRING_STRING}
"${${STRING_STRING}}define image symbol ${symbol} = ${expr};\n"
)
else()
# Treatmen of "zephyr_linker_symbol(SYMBOL z_arm_platform_init EXPR "@SystemInit@")"
set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_FILE
"--redirect ${symbol}=${expr}\n"
)
endif()
endif()
endif()
else()
# Handle things like ADDR(.ramfunc)
if(${expr} MATCHES "^[A-Za-z]?ADDR\\(.+\\)")
# string(REGEX REPLACE "^[A-Za-z]?ADDR\\((.+)\\)" "(\\1$$Base)" expr ${expr})
set(${STRING_STRING}
"${${STRING_STRING}}define image symbol ${symbol} = ${expr};\n"
)
else()
set(${STRING_STRING}
"${${STRING_STRING}}define exported symbol ${symbol} = ${expr};\n"
)
endif()
endif()
set(${STRING_STRING} ${${STRING_STRING}} PARENT_SCOPE)
endfunction()
include(${CMAKE_CURRENT_LIST_DIR}/../linker_script_common.cmake)
if(DEFINED STEERING_FILE)
get_property(steering_content GLOBAL PROPERTY SYMBOL_STEERING_FILE)
file(WRITE ${STEERING_FILE} "/* AUTO-GENERATED - Do not modify\n")
file(APPEND ${STEERING_FILE} " * AUTO-GENERATED - All changes will be lost\n")
file(APPEND ${STEERING_FILE} " */\n")
file(APPEND ${STEERING_FILE} ${steering_content})
endif()

14
cmake/linker/iar/linker_flags.cmake

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
# Copyright (c) 2025 IAR Systems AB
#
# SPDX-License-Identifier: Apache-2.0
# Override the default CMake's IAR ILINK linker signature
string(APPEND CMAKE_C_LINK_FLAGS --no-wrap-diagnostics )
foreach(lang C CXX ASM)
set(commands "--log modules,libraries,initialization,redirects,sections")
set(CMAKE_${lang}_LINK_EXECUTABLE
"<CMAKE_LINKER> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> ${commands} <LINK_LIBRARIES> <OBJECTS> -o <TARGET>")
set(commands)
endforeach()

135
cmake/linker/iar/target.cmake

@ -0,0 +1,135 @@ @@ -0,0 +1,135 @@
# Copyright (c) 2025 IAR Systems AB
#
# SPDX-License-Identifier: Apache-2.0
set_property(TARGET linker PROPERTY devices_start_symbol "_device_list_start")
find_program(CMAKE_LINKER
NAMES ${CROSS_COMPILE}${IAR_LINKER}
PATHS ${TOOLCHAIN_HOME}
PATH_SUFFIXES bin
NO_DEFAULT_PATH
)
add_custom_target(${IAR_LINKER})
set(ILINK_THUMB_CALLS_WARNING_SUPPRESSED)
set(IAR_LIB_USED)
function(toolchain_ld_force_undefined_symbols "")
# foreach(symbol ${ARGN})
# zephyr_link_libraries(--place_holder=${symbol})
# endforeach()
endfunction()
# NOTE: ${linker_script_gen} will be produced at build-time; not at configure-time
macro(configure_linker_script linker_script_gen linker_pass_define)
set(extra_dependencies ${ARGN})
set(STEERING_FILE "${CMAKE_CURRENT_BINARY_DIR}/${linker_script_gen}.xcl")
set(STEERING_FILE_ARG "-DSTEERING_FILE=${STEERING_FILE}")
set(cmake_linker_script_settings
${PROJECT_BINARY_DIR}/include/generated/ld_script_settings_${linker_pass_define}.cmake
)
if("${linker_pass_define}" STREQUAL "LINKER_ZEPHYR_PREBUILT")
set(ILINK_THUMB_CALLS_WARNING_SUPPRESSED "--diag_suppress=Lt056")
else()
set(ILINK_THUMB_CALLS_WARNING_SUPPRESSED "")
endif()
if(CONFIG_IAR_LIBC OR CONFIG_IAR_LIBCPP)
set(IAR_LIB_USED "-DIAR_LIBC=1")
else()
set(IAR_LIB_USED "")
endif()
file(GENERATE OUTPUT ${cmake_linker_script_settings} CONTENT
"set(FORMAT \"$<TARGET_PROPERTY:linker,FORMAT>\" CACHE INTERNAL \"\")\n
set(ENTRY \"$<TARGET_PROPERTY:linker,ENTRY>\" CACHE INTERNAL \"\")\n
set(MEMORY_REGIONS \"$<TARGET_PROPERTY:linker,MEMORY_REGIONS>\" CACHE INTERNAL \"\")\n
set(GROUPS \"$<TARGET_PROPERTY:linker,GROUPS>\" CACHE INTERNAL \"\")\n
set(SECTIONS \"$<TARGET_PROPERTY:linker,SECTIONS>\" CACHE INTERNAL \"\")\n
set(SECTION_SETTINGS \"$<TARGET_PROPERTY:linker,SECTION_SETTINGS>\" CACHE INTERNAL \"\")\n
set(SYMBOLS \"$<TARGET_PROPERTY:linker,SYMBOLS>\" CACHE INTERNAL \"\")\n
"
)
add_custom_command(
OUTPUT ${linker_script_gen}
${STEERING_FILE}
DEPENDS
${extra_dependencies}
${DEVICE_API_LD_TARGET}
COMMAND ${CMAKE_COMMAND}
-C ${DEVICE_API_LINKER_SECTIONS_CMAKE}
-C ${cmake_linker_script_settings}
-DPASS="${linker_pass_define}"
${STEERING_FILE_ARG}
-DCONFIG_LINKER_LAST_SECTION_ID=${CONFIG_LINKER_LAST_SECTION_ID}
-DCONFIG_LINKER_LAST_SECTION_ID_PATTERN=${CONFIG_LINKER_LAST_SECTION_ID_PATTERN}
-DOUT_FILE=${CMAKE_CURRENT_BINARY_DIR}/${linker_script_gen}
${IAR_LIB_USED}
-P ${ZEPHYR_BASE}/cmake/linker/iar/config_file_script.cmake
)
endmacro()
function(toolchain_ld_link_elf)
cmake_parse_arguments(
TOOLCHAIN_LD_LINK_ELF # prefix of output variables
"" # list of names of the boolean arguments
"TARGET_ELF;OUTPUT_MAP;LINKER_SCRIPT" # list of names of scalar arguments
"LIBRARIES_PRE_SCRIPT;LIBRARIES_POST_SCRIPT;DEPENDENCIES" # list of names of list arguments
${ARGN} # input args to parse
)
foreach(lib ${ZEPHYR_LIBS_PROPERTY})
list(APPEND ZEPHYR_LIBS_OBJECTS $<TARGET_OBJECTS:${lib}>)
list(APPEND ZEPHYR_LIBS_OBJECTS $<TARGET_PROPERTY:${lib},LINK_LIBRARIES>)
endforeach()
set(ILINK_SEMIHOSTING)
set(ILINK_BUFFERED_WRITE)
if(${CONFIG_IAR_SEMIHOSTING})
set(ILINK_SEMIHOSTING "--semihosting")
endif()
if(${CONFIG_IAR_BUFFERED_WRITE})
set(ILINK_BUFFERED_WRITE "--redirect __write=__write_buffered")
endif()
set(ILINK_XCL "-f ${TOOLCHAIN_LD_LINK_ELF_LINKER_SCRIPT}.xcl")
set(ILINK_TLS_LIBRARY)
if(${CONFIG_THREAD_LOCAL_STORAGE})
set(ILINK_TLS_LIBRARY "--threaded_lib=manual")
endif()
set(ILINK_TZONE_LIBRARY)
# if(${CONFIG_IAR_LIBC})
# set(ILINK_TZONE_LIBRARY "--timezone_lib")
# endif()
target_link_libraries(
${TOOLCHAIN_LD_LINK_ELF_TARGET_ELF}
${TOOLCHAIN_LD_LINK_ELF_LIBRARIES_PRE_SCRIPT}
--config=${TOOLCHAIN_LD_LINK_ELF_LINKER_SCRIPT}
${TOOLCHAIN_LD_LINK_ELF_LIBRARIES_POST_SCRIPT}
--map=${TOOLCHAIN_LD_LINK_ELF_OUTPUT_MAP}
--log_file=${TOOLCHAIN_LD_LINK_ELF_OUTPUT_MAP}.log
${ZEPHYR_LIBS_OBJECTS}
kernel
$<TARGET_OBJECTS:${OFFSETS_LIB}>
--entry=$<TARGET_PROPERTY:linker,ENTRY>
${ILINK_SEMIHOSTING}
${ILINK_BUFFERED_WRITE}
${ILINK_TLS_LIBRARY}
${ILINK_TZONE_LIBRARY}
${ILINK_THUMB_CALLS_WARNING_SUPPRESSED}
# Do not remove symbols
#--no_remove
${ILINK_XCL}
${TOOLCHAIN_LIBS_OBJECTS}
${TOOLCHAIN_LD_LINK_ELF_DEPENDENCIES}
)
endfunction(toolchain_ld_link_elf)
include(${ZEPHYR_BASE}/cmake/linker/ld/target_relocation.cmake)
include(${ZEPHYR_BASE}/cmake/linker/ld/target_configure.cmake)

40
cmake/toolchain/iar/Kconfig

@ -0,0 +1,40 @@ @@ -0,0 +1,40 @@
# Copyright (c) 2025 IAR Systems AB
#
# SPDX-License-Identifier: Apache-2.0
config LD_LINKER_SCRIPT_SUPPORTED
default n
choice LINKER_SCRIPT
default CMAKE_LINKER_GENERATOR
endchoice
menu "IAR library options"
config IAR_SEMIHOSTING
bool "Use the IAR semihosting implementation."
depends on IAR_LIBC
help
Use the semihosting implementation in the IAR library
instead of the Zephyr implementation.
config IAR_BUFFERED_WRITE
bool "Use buffered write"
depends on IAR_SEMIHOSTING
help
Instead of printing one character at a time
this option uses a buffer to print a line
at a time instead, increasing speed of printout.
endmenu
config TOOLCHAIN_IAR_SUPPORTS_THREAD_LOCAL_STORAGE
def_bool y
select TOOLCHAIN_SUPPORTS_THREAD_LOCAL_STORAGE
# Should we set this? It doesn't seem to be used
# We support most but don't set __GNUC__
#
config TOOLCHAIN_IAR_SUPPORTS_GNU_EXTENSIONS
def_bool y
select TOOLCHAIN_SUPPORTS_GNU_EXTENSIONS

53
cmake/toolchain/iar/Kconfig.defconfig

@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
# Copyright (c) 2025 IAR Systems AB
#
# SPDX-License-Identifier: Apache-2.0
config MISRA_SANE
default y
config PICOLIBC_SUPPORTED
default n
config TOOLCHAIN_HAS_BUILTIN_FFS
default n
config FP16
default y
config IAR_LIBC_SUPPORTED
default y
config COMPILER_FREESTANDING
default y
config CBPRINTF_LIBC_SUBSTS
default y
# IAR has slightly different types
config ENFORCE_ZEPHYR_STDINT
default n
# IAR uses a little bit more stack than GCC
config TEST_EXTRA_STACK_SIZE
default 64
# ICCARM does not support relaxation
config LINKER_USE_NO_RELAX
default y
# ICCARM support C17 with some additional features from C23
config REQUIRES_STD_C17
default y
config CODING_GUIDELINE_CHECK
default n
help
Not applicable to ICCARM
config TC_PROVIDES_POSIX_C_LANG_SUPPORT_R
default n
# ICCARM does not support <threads.h>
config COMMON_LIBC_THRD
default n

46
cmake/toolchain/iar/generic.cmake

@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
# Copyright (c) 2025 IAR Systems AB
#
# SPDX-License-Identifier: Apache-2.0
zephyr_get(IAR_TOOLCHAIN_PATH)
assert(IAR_TOOLCHAIN_PATH "IAR_TOOLCHAIN_PATH is not set")
set(IAR_TOOLCHAIN_VARIANT none)
if(NOT EXISTS ${IAR_TOOLCHAIN_PATH})
message(FATAL_ERROR "Nothing found at IAR_TOOLCHAIN_PATH: '${IAR_TOOLCHAIN_PATH}'")
endif()
if(EXISTS ${IAR_TOOLCHAIN_PATH}/bin/iccarm)
message(STATUS "Found toolchain: IAR C/C++ Compiler for Arm (${IAR_TOOLCHAIN_PATH})")
set(IAR_COMPILER iccarm)
set(IAR_LINKER ilinkarm)
elseif(EXISTS ${IAR_TOOLCHAIN_PATH}/bin/iccarm.exe)
message(STATUS "Found toolchain: IAR C/C++ Compiler for Arm (${IAR_TOOLCHAIN_PATH})")
set(IAR_COMPILER iccarm)
set(IAR_LINKER ilinkarm)
endif()
set(IAR_TOOLCHAIN_VARIANT ${IAR_COMPILER})
# iar relies on Zephyr SDK for the use of C preprocessor (devicetree) and objcopy
find_package(Zephyr-sdk 0.16 REQUIRED)
message(STATUS "Found Zephyr SDK at ${ZEPHYR_SDK_INSTALL_DIR}")
set(TOOLCHAIN_HOME ${IAR_TOOLCHAIN_PATH})
# Handling to be improved in Zephyr SDK, to avoid overriding ZEPHYR_TOOLCHAIN_VARIANT by
# find_package(Zephyr-sdk) if it's already set
set(ZEPHYR_TOOLCHAIN_VARIANT iar)
set(COMPILER iar)
set(LINKER iar)
set(BINTOOLS iar)
if("${IAR_TOOLCHAIN_VARIANT}" STREQUAL "iccarm")
set(SYSROOT_TARGET arm)
else()
set(SYSROOT_TARGET riscv)
endif()
set(CROSS_COMPILE ${TOOLCHAIN_HOME}/bin/)
set(TOOLCHAIN_HAS_NEWLIB OFF CACHE BOOL "True if toolchain supports NewLib")

5
cmake/toolchain/iar/target.cmake

@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
# Copyright (c) 2025 IAR Systems AB
#
# SPDX-License-Identifier: Apache-2.0
# Intentionally left blank.

4
include/zephyr/arch/arm/asm_inline.h

@ -14,10 +14,10 @@ @@ -14,10 +14,10 @@
* Include kernel.h instead
*/
#if defined(__GNUC__)
#if defined(__GNUC__) || defined(__ICCARM__)
#include <zephyr/arch/arm/asm_inline_gcc.h>
#else
#include <arch/arm/asm_inline_other.h>
#error Unknown toolchain in asm_inline.h
#endif
#endif /* ZEPHYR_INCLUDE_ARCH_ARM_ASM_INLINE_H_ */

2
include/zephyr/toolchain.h

@ -44,6 +44,8 @@ @@ -44,6 +44,8 @@
#include <zephyr/toolchain/mwdt.h>
#elif defined(__ARMCOMPILER_VERSION)
#include <zephyr/toolchain/armclang.h>
#elif defined(__IAR_SYSTEMS_ICC__)
#include <zephyr/toolchain/iar.h>
#elif defined(__llvm__) || (defined(_LINKER) && defined(__LLD_LINKER_CMD__))
#include <zephyr/toolchain/llvm.h>
#elif defined(__GNUC__) || (defined(_LINKER) && defined(__GCC_LINKER_CMD__))

25
include/zephyr/toolchain/iar.h

@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
/*
* Copyright (c) 2025 IAR Systems AB
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_TOOLCHAIN_IAR_H_
#define ZEPHYR_INCLUDE_TOOLCHAIN_IAR_H_
#ifdef TOOLCHAIN_PRAGMA
#define _TOOLCHAIN_DISABLE_WARNING(warning) TOOLCHAIN_PRAGMA(diag_suppress = warning)
#define _TOOLCHAIN_ENABLE_WARNING(warning) TOOLCHAIN_PRAGMA(diag_default = warning)
#define TOOLCHAIN_DISABLE_WARNING(warning) _TOOLCHAIN_DISABLE_WARNING(warning)
#define TOOLCHAIN_ENABLE_WARNING(warning) _TOOLCHAIN_ENABLE_WARNING(warning)
#endif
#ifdef __ICCARM__
#include "iar/iccarm.h"
#endif
#ifdef __ICCRISCV__
#include "iar/iccriscv.h"
#endif
#endif /* ZEPHYR_INCLUDE_TOOLCHAIN_ICCARM_H_ */

161
include/zephyr/toolchain/iar/iar_missing_defs.h

@ -0,0 +1,161 @@ @@ -0,0 +1,161 @@
/*
* Copyright (c) 2025 IAR Systems AB
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* Basic macro definitions that gcc and clang provide on their own
* but that iccarm lacks. Only those that Zephyr requires are provided here.
*/
#ifndef ZEPHYR_INCLUDE_TOOLCHAIN_ICCARM_MISSING_DEFS_H_
#define ZEPHYR_INCLUDE_TOOLCHAIN_ICCARM_MISSING_DEFS_H_
/* We need to define NULL with a parenthesis around _NULL
* otherwise the DEBRACE macros won't work correctly
*/
#undef NULL
#define NULL (_NULL)
#if defined(__IAR_SYSTEMS_ICC__)
#ifndef __CHAR_BIT__
#define __CHAR_BIT__ __CHAR_BITS__
#endif
#define __SCHAR_MAX__ __SIGNED_CHAR_MAX__
#define __INT_MAX__ __SIGNED_INT_MAX__
#define __INT_WIDTH__ (__INT_SIZE__*8)
#define __SIZEOF_INT__ __INT_SIZE__
#define __SHRT_MAX__ __SIGNED_SHORT_MAX__
#define __SHRT_WIDTH__ (__SHORT_SIZE__*8)
#define __SIZEOF_SHORT__ __SHORT_SIZE__
#define __LONG_MAX__ __SIGNED_LONG_MAX__
#define __LONG_WIDTH__ (__LONG_SIZE__*8)
#define __SIZEOF_LONG__ __LONG_SIZE__
#define __LONG_LONG_MAX__ __SIGNED_LONG_LONG_MAX__
#define __LONG_LONG_WIDTH__ (__LONG_LONG_SIZE__*8)
#define __SIZEOF_LONG_LONG__ __LONG_LONG_SIZE__
#define __INTMAX_MAX__ __INTMAX_T_MAX__
#define __SIZEOF_INTMAX__ sizeof(__INTMAX_T_TYPE__)
#define __INTMAX_WIDTH__ (__SIZEOF_INTMAX__*8)
#define __UINTMAX_MAX__ __UINTMAX_T_MAX__
#define __SIZEOF_UINTMAX__ sizeof(__UINTMAX_T_TYPE__)
#define __UINTMAX_WIDTH__ (__SIZEOF_UINTMAX__*8)
#define __INTPTR_MAX__ __INTPTR_T_MAX__
#define __INTPTR_TYPE__ __INTPTR_T_TYPE__
#define __INTPTR_WIDTH__ (__INTPTR_T_SIZE__*8)
#define __SIZEOF_POINTER__ __INTPTR_T_SIZE__
#define __PTRDIFF_MAX__ __PTRDIFF_T_MAX__
#define __PTRDIFF_WIDTH__ (__PTRDIFF_T_SIZE__*8)
#define __SIZEOF_PTRDIFF_T__ __PTRDIFF_T_SIZE__
#define __UINTPTR_MAX__ __UINTPTR_T_MAX__
#define __UINTPTR_TYPE__ __UINTPTR_T_TYPE__
/*
* ICCARM already defines __SIZE_T_MAX__ as "unsigned int" but there is no way
* to safeguard that here with preprocessor equality.
*/
#define __SIZE_TYPE__ __SIZE_T_TYPE__
#define __SIZE_MAX__ __SIZE_T_MAX__
#define __SIZE_WIDTH__ ((__SIZEOF_SIZE_T__)*8)
/* #define __SIZEOF_SIZE_T__ 4 */
/*
* The following defines are inferred from the ICCARM provided defines
* already tested above.
*/
#define __INT8_MAX__ __INT8_T_MAX__
#define __INT8_TYPE__ __INT8_T_TYPE__
#define __UINT8_MAX__ __UINT8_T_MAX__
#define __UINT8_TYPE__ __UINT8_T_TYPE__
#define __INT16_MAX__ __INT16_T_MAX__
#define __INT16_TYPE__ __INT16_T_TYPE__
#define __UINT16_MAX__ __UINT16_T_MAX__
#define __UINT16_TYPE__ __UINT16_T_TYPE__
#define __INT32_MAX__ __INT32_T_MAX__
#define __INT32_TYPE__ __INT32_T_TYPE__
#define __UINT32_MAX__ __UINT32_T_MAX__
#define __UINT32_TYPE__ __UINT32_T_TYPE__
#define __INT64_MAX__ __INT64_T_MAX__
#define __INT64_TYPE__ __INT64_T_TYPE__
#define __UINT64_MAX__ __UINT64_T_MAX__
#define __UINT64_TYPE__ __UINT64_T_TYPE__
#define __INT_FAST8_MAX__ __INT_FAST8_T_MAX__
#define __INT_FAST8_TYPE__ __INT_FAST8_T_TYPE__
#define __INT_FAST8_WIDTH__ (__INT_FAST8_T_SIZE__*8)
#define __INT_FAST16_MAX__ __INT_FAST16_T_MAX__
#define __INT_FAST16_TYPE__ __INT_FAST16_T_TYPE__
#define __INT_FAST16_WIDTH__ (__INT_FAST16_T_SIZE__*8)
#define __INT_FAST32_MAX__ __INT_FAST32_T_MAX__
#define __INT_FAST32_TYPE__ __INT_FAST32_T_TYPE__
#define __INT_FAST32_WIDTH__ (__INT_FAST32_T_SIZE__*8)
#define __INT_FAST64_MAX__ __INT_FAST64_T_MAX__
#define __INT_FAST64_TYPE__ __INT_FAST64_T_TYPE__
#define __INT_FAST64_WIDTH__ (__INT_FAST64_T_SIZE__*8)
#define __INT_LEAST8_MAX__ __INT_LEAST8_T_MAX__
#define __INT_LEAST8_TYPE__ __INT_LEAST8_T_TYPE__
#define __INT_LEAST8_WIDTH__ (__INT_LEAST8_T_SIZE__*8)
#define __INT_LEAST16_MAX__ __INT_LEAST16_T_MAX__
#define __INT_LEAST16_TYPE__ __INT_LEAST16_T_TYPE__
#define __INT_LEAST16_WIDTH__ (__INT_LEAST16_T_SIZE__*8)
#define __INT_LEAST32_MAX__ __INT_LEAST32_T_MAX__
#define __INT_LEAST32_TYPE__ __INT_LEAST32_T_TYPE__
#define __INT_LEAST32_WIDTH__ (__INT_LEAST32_T_SIZE__*8)
#define __INT_LEAST64_MAX__ __INT_LEAST64_T_MAX__
#define __INT_LEAST64_TYPE__ __INT_LEAST64_T_TYPE__
#define __INT_LEAST64_WIDTH__ (__INT_LEAST64_T_SIZE__*8)
#define __UINT_FAST8_MAX__ __UINT_FAST8_T_MAX__
#define __UINT_FAST8_TYPE__ __UINT_FAST8_T_TYPE__
#define __UINT_FAST16_MAX__ __UINT_FAST16_T_MAX__
#define __UINT_FAST16_TYPE__ __UINT_FAST16_T_TYPE__
#define __UINT_FAST32_MAX__ __UINT_FAST32_T_MAX__
#define __UINT_FAST32_TYPE__ __UINT_FAST32_T_TYPE__
#define __UINT_FAST64_MAX__ __UINT_FAST64_T_MAX__
#define __UINT_FAST64_TYPE__ __UINT_FAST64_T_TYPE__
#define __UINT_LEAST8_MAX__ __UINT_LEAST8_T_MAX__
#define __UINT_LEAST8_TYPE__ __UINT_LEAST8_T_TYPE__
#define __UINT_LEAST16_MAX__ __UINT_LEAST16_T_MAX__
#define __UINT_LEAST16_TYPE__ __UINT_LEAST16_T_TYPE__
#define __UINT_LEAST32_MAX__ __UINT_LEAST32_T_MAX__
#define __UINT_LEAST32_TYPE__ __UINT_LEAST32_T_TYPE__
#define __UINT_LEAST64_MAX__ __UINT_LEAST64_T_MAX__
#define __UINT_LEAST64_TYPE__ __UINT_LEAST64_T_TYPE__
#endif /* __IAR_SYSTEMS_ICC__ */
#endif

456
include/zephyr/toolchain/iar/iccarm.h

@ -0,0 +1,456 @@ @@ -0,0 +1,456 @@
/*
* Copyright (c) 2025 IAR Systems AB
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_TOOLCHAIN_ICCARM_H_
#define ZEPHYR_INCLUDE_TOOLCHAIN_ICCARM_H_
/**
* @file
* @brief ICCARM toolchain abstraction
*
* Macros to abstract compiler capabilities for ICCARM toolchain.
*/
/* ICCARM supports its own #pragma diag_{warning,default,error,warning}. */
/* #define TOOLCHAIN_HAS_PRAGMA_DIAG 0 */
#define TOOLCHAIN_HAS_C_GENERIC 1
#define TOOLCHAIN_HAS_C_AUTO_TYPE 1
/* #define TOOLCHAIN_HAS_ZLA 1 */
/*
* IAR do not define __BYTE_ORDER__, so it must be manually
* detected and defined using arch-specific definitions.
*/
#ifndef _LINKER
#ifndef __ORDER_BIG_ENDIAN__
#define __ORDER_BIG_ENDIAN__ (1)
#endif /* __ORDER_BIG_ENDIAN__ */
#ifndef __ORDER_LITTLE_ENDIAN__
#define __ORDER_LITTLE_ENDIAN__ (2)
#endif /* __ORDER_LITTLE_ENDIAN__ */
#ifndef __ORDER_PDP_ENDIAN__
#define __ORDER_PDP_ENDIAN__ (3)
#endif /* __ORDER_PDP_ENDIAN__ */
#ifndef __BYTE_ORDER__
#if __LITTLE_ENDIAN__ == 1
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
#else
#define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__
#endif /* __LITTLE_ENDIAN__ == 1 */
#endif /* __BYTE_ORDER__ */
#if defined(__cplusplus) && (__cplusplus >= 201103L)
#define BUILD_ASSERT(EXPR, MSG...) static_assert(EXPR, "" MSG)
#elif defined(__ICCARM__)
#define BUILD_ASSERT(EXPR, MSG...) _Static_assert(EXPR, "" MSG)
#endif
/* Zephyr makes use of __ATOMIC_SEQ_CST */
#ifdef __STDC_NO_ATOMICS__
#ifndef __ATOMIC_SEQ_CST
#define __MEMORY_ORDER_SEQ_CST__ 5
#endif
#endif
#ifndef __ATOMIC_SEQ_CST
#define __ATOMIC_SEQ_CST __MEMORY_ORDER_SEQ_CST__
#endif
/* By default, restrict is recognized in Standard C
* __restrict is always recognized
*/
#define ZRESTRICT __restrict
#include <zephyr/toolchain/common.h>
#include <stdbool.h>
#define ALIAS_OF(of) __attribute__((alias(#of)))
#define FUNC_ALIAS(real_func, new_alias, return_type) \
return_type new_alias() ALIAS_OF(real_func)
#define CODE_UNREACHABLE __builtin_unreachable()
#define FUNC_NORETURN __attribute__((__noreturn__))
#define _NODATA_SECTION(segment) __attribute__((section(#segment)))
/* Unaligned access */
#define UNALIGNED_GET(p) \
__extension__ ({ \
struct __attribute__((__packed__)) { \
__typeof__(*(p)) __v; \
} *__p = (__typeof__(__p)) (p); \
__p->__v; \
})
#define UNALIGNED_PUT(v, p) \
do { \
struct __attribute__((__packed__)) { \
__typeof__(*p) __v; \
} *__p = (__typeof__(__p)) (p); \
__p->__v = (v); \
} while (false)
/* Double indirection to ensure section names are expanded before
* stringification
*/
#define __GENERIC_SECTION(segment) __attribute__((section(STRINGIFY(segment))))
#define Z_GENERIC_SECTION(segment) __GENERIC_SECTION(segment)
#define __GENERIC_DOT_SECTION(segment) \
__attribute__((section("." STRINGIFY(segment))))
#define Z_GENERIC_DOT_SECTION(segment) __GENERIC_DOT_SECTION(segment)
#define ___in_section(a, b, c) \
__attribute__((section("." Z_STRINGIFY(a) \
"." Z_STRINGIFY(b) \
"." Z_STRINGIFY(c))))
#define __in_section(a, b, c) ___in_section(a, b, c)
#define __in_section_unique(seg) ___in_section(seg, __FILE__, __COUNTER__)
#define __in_section_unique_named(seg, name) \
___in_section(seg, __FILE__, name)
/* When using XIP, using '__ramfunc' places a function into RAM instead
* of FLASH. Make sure '__ramfunc' is defined only when
* CONFIG_ARCH_HAS_RAMFUNC_SUPPORT is defined, so that the compiler can
* report an error if '__ramfunc' is used but the architecture does not
* support it.
*/
#if !defined(CONFIG_XIP)
#define __ramfunc
#elif defined(CONFIG_ARCH_HAS_RAMFUNC_SUPPORT)
/* Use this instead of the IAR keyword __ramfunc to make sure it
* ends up in the correct section.
*/
#define __ramfunc __attribute__((noinline, section(".ramfunc")))
#endif /* !CONFIG_XIP */
/* TG-WG: ICCARM does not support __fallthrough */
#define __fallthrough [[fallthrough]]
#ifndef __packed
#define __packed __attribute__((__packed__))
#endif
#ifndef __aligned
#define __aligned(x) __attribute__((__aligned__(x)))
#endif
#ifndef __noinline
#define __noinline __attribute__((noinline))
#endif
#if defined(__cplusplus)
#define __alignof(x) alignof(x)
#else
#define __alignof(x) _Alignof(x)
#endif
#define __may_alias __attribute__((__may_alias__))
#ifndef __printf_like
/*
* The Zephyr stdint convention enforces int32_t = int, int64_t = long long,
* and intptr_t = long so that short string format length modifiers can be
* used universally across ILP32 and LP64 architectures. Without that it
* is possible for ILP32 toolchains to have int32_t = long and intptr_t = int
* clashing with the Zephyr convention and generating pointless warnings
* as they're still the same size. Inhibit the format argument type
* validation in that case and let the other configs do it.
*/
#define __printf_like(f, a)
#endif
#define __used __attribute__((__used__))
#define __unused __attribute__((__unused__))
#define __maybe_unused __attribute__((__unused__))
#ifndef __deprecated
#define __deprecated __attribute__((deprecated))
#endif
#define FUNC_NO_STACK_PROTECTOR _Pragma("no_stack_protect")
#ifndef __attribute_const__
#if __VER__ > 0x09000000
#define __attribute_const__ __attribute__((const))
#else
#define __attribute_const__
#endif
#endif
#ifndef __must_check
/* #warning "The attribute __warn_unused_result is not supported in ICCARM". */
#define __must_check
/* #define __must_check __attribute__((warn_unused_result)) */
#endif
#define __PRAGMA(...) _Pragma(#__VA_ARGS__)
#define ARG_UNUSED(x) (void)(x)
#define likely(x) (__builtin_expect((bool)!!(x), true) != 0L)
#define unlikely(x) (__builtin_expect((bool)!!(x), false) != 0L)
#define POPCOUNT(x) __builtin_popcount(x)
#ifndef __no_optimization
#define __no_optimization __PRAGMA(optimize = none)
#endif
#ifndef __attribute_nonnull
#define __attribute_nonnull(...) __attribute__((nonnull(__VA_ARGS__)))
#endif
/* __weak is an ICCARM built-in, but it doesn't work in all positions */
/* the Zephyr uses it so we replace it with an attribute((weak)) */
#define __weak __attribute__((__weak__))
/* Builtins */
#include <intrinsics.h>
/*
* Be *very* careful with these. You cannot filter out __DEPRECATED_MACRO with
* -wno-deprecated, which has implications for -Werror.
*/
/*
* Expands to nothing and generates a warning. Used like
*
* #define FOO __WARN("Please use BAR instead") ...
*
* The warning points to the location where the macro is expanded.
*/
#define __WARN(s) __PRAGMA(message = #s)
#define __WARN1(s) __PRAGMA(message = #s)
/* Generic message */
#ifndef __DEPRECATED_MACRO
#define __DEPRECATED_MACRO __WARN("Macro is deprecated")
#endif
/* These macros allow having ARM asm functions callable from thumb */
#if defined(_ASMLANGUAGE)
#if defined(CONFIG_ASSEMBLER_ISA_THUMB2)
#define FUNC_CODE() .code 32
#define FUNC_INSTR(a)
/* '.syntax unified' is a gcc-ism used in thumb-2 asm files */
#define _ASM_FILE_PROLOGUE .text; .syntax unified; .thumb
#else
#define FUNC_CODE()
#define FUNC_INSTR(a)
#define _ASM_FILE_PROLOGUE .text; .code 32
#endif /* CONFIG_ASSEMBLER_ISA_THUMB2 */
/*
* These macros are used to declare assembly language symbols that need
* to be typed properly(func or data) to be visible to the OMF tool.
* So that the build tool could mark them as an entry point to be linked
* correctly. This is an elfism. Use #if 0 for a.out.
*/
/* This is not implemented yet for IAR */
#define GTEXT(sym)
#define GDATA(sym)
#define WTEXT(sym)
#define WDATA(sym)
#define SECTION_VAR(sect, sym)
#define SECTION_FUNC(sect, sym)
#define SECTION_SUBSEC_FUNC(sect, subsec, sym)
#endif /* _ASMLANGUAGE */
/*
* These macros generate absolute symbols for IAR
*/
/* create an extern reference to the absolute symbol */
#define GEN_OFFSET_EXTERN(name) extern const char name[]
#define GEN_ABS_SYM_BEGIN(name) \
EXTERN_C void name(void); \
void name(void) \
{
#define GEN_ABS_SYM_END }
/*
* Note that GEN_ABSOLUTE_SYM(), depending on the architecture
* and toolchain, may restrict the range of values permitted
* for assignment to the named symbol.
*/
#define GEN_ABSOLUTE_SYM(name, value) \
__PRAGMA(public_equ = #name, (unsigned int)value)
/*
* GEN_ABSOLUTE_SYM_KCONFIG() is outputted by the build system
* to generate named symbol/value pairs for kconfigs.
*/
#define GEN_ABSOLUTE_SYM_KCONFIG(name, value) \
__PRAGMA(public_equ = #name, (unsigned int)value)
#define compiler_barrier() do { \
__asm volatile("" ::: "memory"); \
} while (false)
/** @brief Return larger value of two provided expressions.
*
* Macro ensures that expressions are evaluated only once.
*
* @note Macro has limited usage compared to the standard macro as it cannot be
* used:
* - to generate constant integer, e.g. __aligned(Z_MAX(4,5))
* - static variable, e.g. array like static uint8_t array[Z_MAX(...)];
*/
#define Z_MAX(a, b) ({ \
/* random suffix to avoid naming conflict */ \
__typeof__(a) _value_a_ = (a); \
__typeof__(b) _value_b_ = (b); \
_value_a_ > _value_b_ ? _value_a_ : _value_b_; \
})
/** @brief Return smaller value of two provided expressions.
*
* Macro ensures that expressions are evaluated only once. See @ref Z_MAX for
* macro limitations.
*/
#define Z_MIN(a, b) ({ \
/* random suffix to avoid naming conflict */ \
__typeof__(a) _value_a_ = (a); \
__typeof__(b) _value_b_ = (b); \
_value_a_ < _value_b_ ? _value_a_ : _value_b_; \
})
/** @brief Return a value clamped to a given range.
*
* Macro ensures that expressions are evaluated only once. See @ref Z_MAX for
* macro limitations.
*/
#define Z_CLAMP(val, low, high) ({ \
/* random suffix to avoid naming conflict */ \
__typeof__(val) _value_val_ = (val); \
__typeof__(low) _value_low_ = (low); \
__typeof__(high) _value_high_ = (high); \
(_value_val_ < _value_low_) ? _value_low_ : \
(_value_val_ > _value_high_) ? _value_high_ : \
_value_val_; \
})
/**
* @brief Calculate power of two ceiling for some nonzero value
*
* @param x Nonzero unsigned long value
* @return X rounded up to the next power of two
*/
#define Z_POW2_CEIL(x) \
((x) <= 2UL ? (x) : (1UL << (8 * sizeof(long) - __builtin_clzl((x) - 1))))
/**
* @brief Check whether or not a value is a power of 2
*
* @param x The value to check
* @return true if x is a power of 2, false otherwise
*/
#define Z_IS_POW2(x) (((x) != 0) && (((x) & ((x)-1)) == 0))
#ifndef __INT8_C
#define __INT8_C(x) x
#endif
#ifndef INT8_C
#define INT8_C(x) __INT8_C(x)
#endif
#ifndef __UINT8_C
#define __UINT8_C(x) x ## U
#endif
#ifndef UINT8_C
#define UINT8_C(x) __UINT8_C(x)
#endif
#ifndef __INT16_C
#define __INT16_C(x) x
#endif
#ifndef INT16_C
#define INT16_C(x) __INT16_C(x)
#endif
#ifndef __UINT16_C
#define __UINT16_C(x) x ## U
#endif
#ifndef UINT16_C
#define UINT16_C(x) __UINT16_C(x)
#endif
#ifndef __INT32_C
#define __INT32_C(x) x
#endif
#ifndef INT32_C
#define INT32_C(x) __INT32_C(x)
#endif
#ifndef __UINT32_C
#define __UINT32_C(x) x ## U
#endif
#ifndef UINT32_C
#define UINT32_C(x) __UINT32_C(x)
#endif
#ifndef __INT64_C
#define __INT64_C(x) x ## LL
#endif
#ifndef INT64_C
#define INT64_C(x) __INT64_C(x)
#endif
#ifndef __UINT64_C
#define __UINT64_C(x) x ## ULL
#endif
#ifndef UINT64_C
#define UINT64_C(x) __UINT64_C(x)
#endif
/* Convenience macros */
#undef _GLUE_B
#undef _GLUE
#define _GLUE_B(x, y) x##y
#define _GLUE(x, y) _GLUE_B(x, y)
#ifndef INTMAX_C
#define INTMAX_C(x) _GLUE(x, __INTMAX_C_SUFFIX__)
#endif
#ifndef UINTMAX_C
#define UINTMAX_C(x) _GLUE(x, __UINTMAX_C_SUFFIX__)
#endif
#endif /* !_LINKER */
#endif /* ZEPHYR_INCLUDE_TOOLCHAIN_ICCARM_H_ */

1
lib/libc/CMakeLists.txt

@ -6,6 +6,7 @@ zephyr_syscall_header( @@ -6,6 +6,7 @@ zephyr_syscall_header(
add_subdirectory_ifdef(CONFIG_ARCMWDT_LIBC arcmwdt)
add_subdirectory_ifdef(CONFIG_ARMCLANG_STD_LIBC armstdc)
add_subdirectory_ifdef(CONFIG_IAR_LIBC iar)
add_subdirectory_ifdef(CONFIG_MINIMAL_LIBC minimal)
add_subdirectory_ifdef(CONFIG_NEWLIB_LIBC newlib)
add_subdirectory_ifdef(CONFIG_PICOLIBC picolibc)

19
lib/libc/Kconfig

@ -51,6 +51,13 @@ config PICOLIBC_SUPPORTED @@ -51,6 +51,13 @@ config PICOLIBC_SUPPORTED
help
Selected when the target has support for picolibc.
config IAR_LIBC_SUPPORTED
bool
default n
select FULL_LIBC_SUPPORTED
help
Selected if the target is an IAR Systems compiler
config NATIVE_LIBC_INCOMPATIBLE
bool
help
@ -65,6 +72,7 @@ choice LIBC_IMPLEMENTATION @@ -65,6 +72,7 @@ choice LIBC_IMPLEMENTATION
default PICOLIBC
default NEWLIB_LIBC if REQUIRES_FULL_LIBC
default MINIMAL_LIBC
default IAR_LIBC
config MINIMAL_LIBC
bool "Minimal C library"
@ -124,6 +132,17 @@ config EXTERNAL_LIBC @@ -124,6 +132,17 @@ config EXTERNAL_LIBC
help
Build with external/user provided C library.
config IAR_LIBC
bool "IAR C Runtime Library"
depends on IAR_LIBC_SUPPORTED
depends on "$(ZEPHYR_TOOLCHAIN_VARIANT)" = "iar"
select COMMON_LIBC_STRNLEN
select COMMON_LIBC_TIME if POSIX_TIMERS
help
Use the full IAR Compiler runtime libraries.
A reduced Zephyr minimal libc will be used for library functionality
not provided by the IAR C Runtime Library.
endchoice # LIBC_IMPLEMENTATION
config HAS_NEWLIB_LIBC_NANO

6
lib/libc/iar/CMakeLists.txt

@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
# SPDX-License-Identifier: Apache-2.0
zephyr_library()
zephyr_library_sources(src/libc-hooks.c)
zephyr_system_include_directories(include)

96
lib/libc/iar/include/errno.h

@ -0,0 +1,96 @@ @@ -0,0 +1,96 @@
/*
* Copyright (c) 2025 IAR Systems AB
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief Defines additional error numbers based on POSIX
*/
#ifndef ZEPHYR_LIB_LIBC_IAR_INCLUDE_ERRNO_H_
#define ZEPHYR_LIB_LIBC_IAR_INCLUDE_ERRNO_H_
#include_next <errno.h>
#ifndef __cplusplus
#define EPERM 1 /**< Not owner */
#define ENOENT 2 /**< No such file or directory */
#define ESRCH 3 /**< No such context */
#define EINTR 4 /**< Interrupted system call */
#define EIO 5 /**< I/O error */
#define ENXIO 6 /**< No such device or address */
#define E2BIG 7 /**< Arg list too long */
#define ENOEXEC 8 /**< Exec format error */
#define EBADF 9 /**< Bad file number */
#define ECHILD 10 /**< No children */
#define EAGAIN 11 /**< No more contexts */
#define ENOMEM 12 /**< Not enough core */
#define EACCES 13 /**< Permission denied */
#define EFAULT 14 /**< Bad address */
#define ENOTBLK 15 /**< Block device required */
#define EBUSY 16 /**< Mount device busy */
#define EEXIST 17 /**< File exists */
#define EXDEV 18 /**< Cross-device link */
#define ENODEV 19 /**< No such device */
#define ENOTDIR 20 /**< Not a directory */
#define EISDIR 21 /**< Is a directory */
#define EINVAL 22 /**< Invalid argument */
#define ENFILE 23 /**< File table overflow */
#define EMFILE 24 /**< Too many open files */
#define ENOTTY 25 /**< Not a typewriter */
#define ETXTBSY 26 /**< Text file busy */
#define EFBIG 27 /**< File too large */
#define ENOSPC 28 /**< No space left on device */
#define ESPIPE 29 /**< Illegal seek */
#define EROFS 30 /**< Read-only file system */
#define EMLINK 31 /**< Too many links */
#define EPIPE 32 /**< Broken pipe */
#define ENOMSG 35 /**< Unexpected message type */
#define EDEADLK 45 /**< Resource deadlock avoided */
#define ENOLCK 46 /**< No locks available */
#define ENOSTR 60 /**< STREAMS device required */
#define ENODATA 61 /**< Missing expected message data */
#define ETIME 62 /**< STREAMS timeout occurred */
#define ENOSR 63 /**< Insufficient memory */
#define EPROTO 71 /**< Generic STREAMS error */
#define EBADMSG 77 /**< Invalid STREAMS message */
#define ENOSYS 88 /**< Function not implemented */
#define ENOTEMPTY 90 /**< Directory not empty */
#define ENAMETOOLONG 91 /**< File name too long */
#define ELOOP 92 /**< Too many levels of symbolic links */
#define EOPNOTSUPP 95 /**< Operation not supported on socket */
#define EPFNOSUPPORT 96 /**< Protocol family not supported */
#define ECONNRESET 104 /**< Connection reset by peer */
#define ENOBUFS 105 /**< No buffer space available */
#define EAFNOSUPPORT 106 /**< Addr family not supported */
#define EPROTOTYPE 107 /**< Protocol wrong type for socket */
#define ENOTSOCK 108 /**< Socket operation on non-socket */
#define ENOPROTOOPT 109 /**< Protocol not available */
#define ESHUTDOWN 110 /**< Can't send after socket shutdown */
#define ECONNREFUSED 111 /**< Connection refused */
#define EADDRINUSE 112 /**< Address already in use */
#define ECONNABORTED 113 /**< Software caused connection abort */
#define ENETUNREACH 114 /**< Network is unreachable */
#define ENETDOWN 115 /**< Network is down */
#define ETIMEDOUT 116 /**< Connection timed out */
#define EHOSTDOWN 117 /**< Host is down */
#define EHOSTUNREACH 118 /**< No route to host */
#define EINPROGRESS 119 /**< Operation now in progress */
#define EALREADY 120 /**< Operation already in progress */
#define EDESTADDRREQ 121 /**< Destination address required */
#define EMSGSIZE 122 /**< Message size */
#define EPROTONOSUPPORT 123 /**< Protocol not supported */
#define ESOCKTNOSUPPORT 124 /**< Socket type not supported */
#define EADDRNOTAVAIL 125 /**< Can't assign requested address */
#define ENETRESET 126 /**< Network dropped connection on reset */
#define EISCONN 127 /**< Socket is already connected */
#define ENOTCONN 128 /**< Socket is not connected */
#define ETOOMANYREFS 129 /**< Too many references: can't splice */
#define ENOTSUP 134 /**< Unsupported value */
#define EOVERFLOW 139 /**< Value overflow */
#define ECANCELED 140 /**< Operation canceled */
#define EWOULDBLOCK EAGAIN /**< Operation would block */
#endif /* __cplusplus */
#endif /* ZEPHYR_LIB_LIBC_IAR_INCLUDE_ERRNO_H_ */

22
lib/libc/iar/include/limits.h

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
/*
* Copyright (c) 2025 IAR Systems AB
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_LIB_LIBC_IAR_INCLUDE_LIMITS_H_
#define ZEPHYR_LIB_LIBC_IAR_INCLUDE_LIMITS_H_
#include_next <limits.h>
#ifdef __cplusplus
extern "C" {
#endif
#define PATH_MAX 256
#ifdef __cplusplus
}
#endif
#endif /* ZEPHYR_LIB_LIBC_IAR_INCLUDE_LIMITS_H_ */

7
lib/libc/iar/include/sys/_timespec.h

@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
/*
* Copyright (c) 2025 IAR Systems AB
*
* SPDX-License-Identifier: Apache-2.0
*/
/* file is intentionally empty */

27
lib/libc/iar/include/sys/_timeval.h

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
/*
* Copyright (c) 2025 IAR Systems AB
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_LIB_LIBC_IAR_INCLUDE_SYS__TIMEVAL_H_
#define ZEPHYR_LIB_LIBC_IAR_INCLUDE_SYS__TIMEVAL_H_
#include <stdint.h>
#if !defined(__time_t_defined)
#define __time_t_defined
typedef long long time_t;
#endif
#if !defined(__suseconds_t_defined)
#define __suseconds_t_defined
typedef int32_t suseconds_t;
#endif
struct timeval {
time_t tv_sec;
suseconds_t tv_usec;
};
#endif /* ZEPHYR_LIB_LIBC_IAR_INCLUDE_SYS__TIMEVAL_H_ */

7
lib/libc/iar/include/sys/cdefs.h

@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
/*
* Copyright (c) 2025 IAR Systems AB
*
* SPDX-License-Identifier: Apache-2.0
*/
/* file is intentionally empty */

18
lib/libc/iar/include/sys/timespec.h

@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
/*
* Copyright (c) 2025 IAR Systems AB
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_LIB_LIBC_IAR_INCLUDE_SYS_TIMESPEC_H_
#define ZEPHYR_LIB_LIBC_IAR_INCLUDE_SYS_TIMESPEC_H_
#include <sys/types.h>
#include <sys/_timespec.h>
struct itimerspec {
struct timespec it_interval; /* Timer interval */
struct timespec it_value; /* Timer expiration */
};
#endif /* ZEPHYR_LIB_LIBC_IAR_INCLUDE_SYS_TIMESPEC_H_ */

21
lib/libc/iar/include/sys/types.h

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
/*
* Copyright (c) 2025 IAR Systems AB
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_LIB_LIBC_IAR_INCLUDE_SYS_TYPES_H_
#define ZEPHYR_LIB_LIBC_IAR_INCLUDE_SYS_TYPES_H_
typedef unsigned int mode_t;
typedef signed long ssize_t;
typedef int off_t;
typedef __INT64_TYPE__ time_t;
#if !defined(_CLOCK_T_DECLARED) && !defined(__clock_t_defined)
typedef unsigned int clock_t;
#define _CLOCK_T_DECLARED
#define __clock_t_defined
#endif
#endif /* ZEPHYR_LIB_LIBC_IAR_INCLUDE_SYS_TYPES_H_ */

31
lib/libc/iar/include/time.h

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
/*
* Copyright (c) 2025 IAR Systems AB
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief Declares additional time related functions based on POSIX
*/
#ifndef ZEPHYR_LIB_LIBC_IAR_INCLUDE_TIME_H_
#define ZEPHYR_LIB_LIBC_IAR_INCLUDE_TIME_H_
#include <zephyr/toolchain.h>
#include_next <time.h>
#ifdef __cplusplus
extern "C" {
#endif
char *asctime_r(const struct tm *ZRESTRICT tp, char *ZRESTRICT buf);
char *ctime_r(const time_t *clock, char *buf);
struct tm *gmtime_r(const time_t *ZRESTRICT timep, struct tm *ZRESTRICT result);
struct tm *localtime_r(const time_t *ZRESTRICT timer, struct tm *ZRESTRICT result);
#ifdef __cplusplus
}
#endif
#endif /* ZEPHYR_LIB_LIBC_IAR_INCLUDE_TIME_H_ */

53
lib/libc/iar/src/libc-hooks.c

@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
/*
* Copyright (c) 2025 IAR Systems AB
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <stdio.h>
static int _stdout_hook_default(int c)
{
(void)(c); /* Prevent warning about unused argument */
return EOF;
}
static int (*_stdout_hook)(int) = _stdout_hook_default;
void __stdout_hook_install(int (*hook)(int))
{
_stdout_hook = hook;
}
int fputc(int c, FILE *f)
{
return (_stdout_hook)(c);
}
#pragma weak __write
size_t __write(int handle, const unsigned char *buf, size_t bufSize)
{
size_t nChars = 0;
/* Check for the command to flush all handles */
if (handle == -1) {
return 0;
}
/* Check for stdout and stderr
* (only necessary if FILE descriptors are enabled.)
*/
if (handle != 1 && handle != 2) {
return -1;
}
for (/* Empty */; bufSize > 0; --bufSize) {
int ret = (_stdout_hook)(*buf);
if (ret == EOF) {
break;
}
++buf;
++nChars;
}
return nChars;
}

3
scripts/ci/check_compliance.py

@ -1059,6 +1059,9 @@ flagged. @@ -1059,6 +1059,9 @@ flagged.
"FOO_SETTING_2",
"HEAP_MEM_POOL_ADD_SIZE_", # Used as an option matching prefix
"HUGETLBFS", # Linux, in boards/xtensa/intel_adsp_cavs25/doc
"IAR_BUFFERED_WRITE",
"IAR_LIBCPP",
"IAR_SEMIHOSTING",
"IPC_SERVICE_ICMSG_BOND_NOTIFY_REPEAT_TO_MS", # Used in ICMsg tests for intercompatibility
# with older versions of the ICMsg.
"LIBGCC_RTLIB",

2
tests/kernel/fpu_sharing/generic/src/load_store.c

@ -46,7 +46,7 @@ @@ -46,7 +46,7 @@
#endif /* __GNUC__ */
#elif defined(CONFIG_ARM)
#if defined(CONFIG_ARMV7_M_ARMV8_M_FP) || defined(CONFIG_ARMV7_R_FP) || defined(CONFIG_CPU_HAS_VFP)
#if defined(__GNUC__)
#if defined(__GNUC__) || defined(__ICCARM__)
#include "float_regs_arm_gcc.h"
#else
#include "float_regs_arm_other.h"

Loading…
Cancel
Save