Browse Source
This adds experimental support for the IAR toolchain. Signed-off-by: Robin Kastberg <robin.kastberg@iar.com>pull/85809/head
34 changed files with 2848 additions and 9 deletions
@ -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) |
@ -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 ">;" ) |
@ -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) |
@ -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() |
@ -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() |
@ -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 |
@ -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() |
@ -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() |
@ -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() |
@ -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) |
@ -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 |
@ -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 |
@ -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") |
@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
|
||||
# Copyright (c) 2025 IAR Systems AB |
||||
# |
||||
# SPDX-License-Identifier: Apache-2.0 |
||||
|
||||
# Intentionally left blank. |
@ -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_ */ |
@ -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 |
@ -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_ */ |
@ -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) |
@ -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_ */ |
@ -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_ */ |
@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2025 IAR Systems AB |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
|
||||
/* file is intentionally empty */ |
@ -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_ */ |
@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2025 IAR Systems AB |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
|
||||
/* file is intentionally empty */ |
@ -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_ */ |
@ -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_ */ |
@ -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_ */ |
@ -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; |
||||
} |
Loading…
Reference in new issue