Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Armclang / armlink support in Zephyr - Zephyr CMake linker functions #36140

Merged
merged 20 commits into from
Aug 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
9bad1f3
scripts: gen_handles.py: take device start symbol as argument.
tejlmand May 21, 2021
7a2a9a8
asm: .eabi_attribute Tag_ABI_align_preserved, 1
tejlmand Apr 20, 2021
db796af
cmake: CMake linker functions implemented
tejlmand Jun 10, 2021
cf9f2c4
cmake: CMake devicetree related linker functions implemented
tejlmand Aug 11, 2021
5c195e8
cmake: linker: converter arm and common ld scripts into CMake code
tejlmand May 6, 2021
c96d7a5
arch: linker: specify intList section in the IDT_LIST region
tejlmand Jun 1, 2021
b18b442
cmake: linker: arm: adding Zephyr CMake linker files for arm arch
tejlmand Jun 10, 2021
870d9b1
cmake: linker: arm: memory regions from devicetree added
tejlmand Aug 11, 2021
56690e1
cmake: ld: adding common linker script generator
tejlmand Aug 9, 2021
9cda5a5
cmake: ld: adding ld linker script generator
tejlmand Jun 10, 2021
703ede0
kconfig: cmake: CMake linker script generator symbol added
tejlmand Jun 9, 2021
1e11c73
armclang: adding toolchain/armclang.h header
tejlmand Apr 20, 2021
cd22ec0
armclang: bintools support for armclang (arm-ds/Keil)
tejlmand May 19, 2021
5d8b1b6
armclang: support for armclang compiler and armlink linker
tejlmand Nov 30, 2020
b3764ed
armclang: warn on non-Ninja generator for CMake 3.20.
tejlmand Aug 13, 2021
9e3041d
armclang: specify armlink link executable signature
tejlmand May 20, 2021
aee627b
armclang: armlinker: armlink symbol steering file
tejlmand Jun 1, 2021
e7a7df6
armclang: ARM Compiler C library support
tejlmand Aug 15, 2021
7eb670c
armclang: threading_weak.c source file added for armclang
tejlmand Aug 24, 2021
14b6ea7
tests: added kernel tests for arm arch with linker script generator
tejlmand Aug 26, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ zephyr_include_directories(
${STDINCLUDE}
)

include(${ZEPHYR_BASE}/cmake/linker_script/${ARCH}/linker.cmake OPTIONAL)

# Don't add non-existing include directories, it creates noise and
# warnings in some tooling
foreach(optional_include_dir
Expand Down Expand Up @@ -795,6 +797,7 @@ if(CONFIG_HAS_DTS)
--output-source dev_handles.c
--kernel $<TARGET_FILE:${ZEPHYR_PREBUILT_EXECUTABLE}>
--zephyr-base ${ZEPHYR_BASE}
--start-symbol "$<TARGET_PROPERTY:linker,devices_start_symbol>"
DEPENDS ${ZEPHYR_PREBUILT_EXECUTABLE}
)
set_property(GLOBAL APPEND PROPERTY GENERATED_KERNEL_SOURCE_FILES dev_handles.c)
Expand Down
32 changes: 31 additions & 1 deletion Kconfig.zephyr
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ source "$(BOARD_DIR)/Kconfig.defconfig"
osource "$(KCONFIG_BINARY_DIR)/Kconfig.soc.defconfig"
# This loads Zephyr base SoC root defconfigs
osource "soc/$(ARCH)/*/Kconfig.defconfig"
# This loads the toolchain defconfigs
osource "$(TOOLCHAIN_KCONFIG_DIR)/Kconfig.defconfig"

menu "Modules"

Expand Down Expand Up @@ -132,8 +134,36 @@ config ROM_START_OFFSET
alignment requirements on most ARM targets, although some targets
may require smaller or larger values.

config LD_LINKER_SCRIPT_SUPPORTED
bool
default y

choice LINKER_SCRIPT
prompt "Linker script"
default LD_LINKER_TEMPLATE if LD_LINKER_SCRIPT_SUPPORTED

config LD_LINKER_TEMPLATE
bool "LD template"
depends on LD_LINKER_SCRIPT_SUPPORTED
help
Select this option to use the LD linker script templates.
The templates are pre-processed by the C pre-processor to create the
final LD linker script.

config CMAKE_LINKER_GENERATOR
bool "CMake generator"
depends on ARM
help
Select this option to use the Zephyr CMake linker script generator.
The linker configuration is written in CMake and the final linker
script will be generated by the toolchain specific linker generator.
For LD based linkers, this will be the ld generator, for ARMClang /
armlink based linkers it will be the scatter generator.

endchoice

config HAVE_CUSTOM_LINKER_SCRIPT
bool "Custom linker scripts provided"
bool "Custom linker script provided"
help
Set this option if you have a custom linker script which needed to
be define in CUSTOM_LINKER_SCRIPT.
Expand Down
4 changes: 4 additions & 0 deletions arch/arm/core/aarch32/cortex_m/vector_table.S
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
#include "vector_table.h"

_ASM_FILE_PROLOGUE
/*
* Tell armclang that stack alignment are ensured.
*/
.eabi_attribute Tag_ABI_align_preserved, 1
Comment on lines +25 to +28
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since 8-byte stack alignment currently is/must always be ensured, it would be better to make this part of _ASM_FILE_PROLOGUE.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very good point, thanks

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since we are almost out of time, a reminder to myself to refactor this in the future. @stephanosio


GDATA(z_main_stack)

Expand Down
4 changes: 4 additions & 0 deletions arch/arm/core/aarch32/isr_wrapper.S
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
* Wrapper installed in vector table for handling dynamic interrupts that accept
* a parameter.
*/
/*
* Tell armclang that stack alignment are ensured.
*/
.eabi_attribute Tag_ABI_align_preserved, 1

#include <toolchain.h>
#include <linker/sections.h>
Expand Down
10 changes: 10 additions & 0 deletions arch/common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@ zephyr_linker_sources_ifdef(CONFIG_GEN_ISR_TABLES
${ZEPHYR_BASE}/include/linker/intlist.ld
)

if(CONFIG_GEN_ISR_TABLES)
zephyr_linker_section(NAME .intList VMA IDT_LIST LMA IDT_LIST NOINPUT PASS 1)
zephyr_linker_section_configure(SECTION .intList KEEP INPUT ".irq_info" FIRST)
zephyr_linker_section_configure(SECTION .intList KEEP INPUT ".intList")

zephyr_linker_section_configure(SECTION /DISCARD/ KEEP INPUT ".irq_info" PASS 2)
zephyr_linker_section_configure(SECTION /DISCARD/ KEEP INPUT ".intList" PASS 2)
endif()

zephyr_linker_sources_ifdef(CONFIG_ARCH_HAS_RAMFUNC_SUPPORT
RAM_SECTIONS
ramfunc.ld
Expand All @@ -38,6 +47,7 @@ zephyr_linker_sources_ifdef(CONFIG_NOCACHE_MEMORY
if (DEFINED CONFIG_ARM OR DEFINED CONFIG_X86 OR DEFINED CONFIG_ARM64
OR DEFINED CONFIG_SOC_OPENISA_RV32M1_RISCV32)
zephyr_linker_sources(ROM_START SORT_KEY 0x0 rom_start_offset.ld)
# Handled in ld.cmake
endif()


Expand Down
54 changes: 54 additions & 0 deletions cmake/bintools/armclang/elfconvert_command.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# For armclang the elfconvert command is made into a script.
# Reason for that is because not a single command covers all use cases,
# and it must therefore be possible to call individual commands, depending
# on the arguments used.
cmake_minimum_required(VERSION 3.13)

# Handle stripping
if (STRIP_DEBUG OR STRIP_ALL)
set(obj_copy_target_output "--elf")
if(STRIP_ALL)
set(obj_copy_strip "--strip=all")
elseif(STRIP_DEBUG)
set(obj_copy_strip "--strip=debug")
endif()
endif()

# Unknown support of --srec-len in arm-ds

# Handle Input and Output target types
if(DEFINED OUTTARGET)
if(${OUTTARGET} STREQUAL "srec")
set(obj_copy_target_output "--m32")
elseif(${OUTTARGET} STREQUAL "ihex")
set(obj_copy_target_output "--i32combined")
elseif(${OUTTARGET} STREQUAL "binary")
set(obj_copy_target_output "--bincombined")
if(GAP_FILL)
set(obj_copy_gap_fill "--bincombined_padding=1,${GAP_FILL}")
endif()
endif()
endif()

if(DEFINED ONLY_SECTION AND "${OUTTARGET}" STREQUAL "binary")
set(obj_copy_target_output "--bin")
set(outfile_dir .dir)
string(REGEX REPLACE "^[\.]" "" only_section_clean "${ONLY_SECTION}")
endif()

# Note: fromelf is a little special regarding bin output, as each section gets
# its own file. This means that when only a specific section is required
# then that section must be moved to correct location.
execute_process(
COMMAND ${FROMELF}
${obj_copy_strip}
${obj_copy_gap_fill} ${obj_copy_target_output}
--output ${OUTFILE}${outfile_dir} ${INFILE}
)

if(DEFINED ONLY_SECTION AND "${OUTTARGET}" STREQUAL "binary")
execute_process(
COMMAND ${CMAKE_COMMAND} -E copy
${OUTFILE}${outfile_dir}/${only_section_clean} ${OUTFILE}
)
endif()
16 changes: 16 additions & 0 deletions cmake/bintools/armclang/target.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# SPDX-License-Identifier: Apache-2.0

# Configures binary tools as mwdt binutils

find_program(CMAKE_FROMELF fromelf PATH ${TOOLCHAIN_HOME}/bin NO_DEFAULT_PATH)
find_program(CMAKE_AS armasm PATH ${TOOLCHAIN_HOME}/bin NO_DEFAULT_PATH)
find_program(CMAKE_AR armar PATH ${TOOLCHAIN_HOME}/bin NO_DEFAULT_PATH)

SET(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> -rq <TARGET> <LINK_FLAGS> <OBJECTS>")
SET(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> -rq <TARGET> <LINK_FLAGS> <OBJECTS>")
SET(CMAKE_CXX_ARCHIVE_FINISH "<CMAKE_AR> -sq <TARGET>")
SET(CMAKE_C_ARCHIVE_FINISH "<CMAKE_AR> -sq <TARGET>")

find_program(CMAKE_GDB ${CROSS_COMPILE}mdb PATH ${TOOLCHAIN_HOME} NO_DEFAULT_PATH)

include(${CMAKE_CURRENT_LIST_DIR}/target_bintools.cmake)
71 changes: 71 additions & 0 deletions cmake/bintools/armclang/target_bintools.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# List of format the tool supports for converting, for example,
# GNU tools uses objectcopyy, which supports the following: ihex, srec, binary
set_property(TARGET bintools PROPERTY elfconvert_formats ihex binary)

# armclang toolchain does not support all options in a single command
# Therefore a CMake script is used, so that multiple commands can be executed
# successively.
set_property(TARGET bintools PROPERTY elfconvert_command ${CMAKE_COMMAND})

set_property(TARGET bintools PROPERTY elfconvert_flag
-DFROMELF=${CMAKE_FROMELF}
)

set_property(TARGET bintools PROPERTY elfconvert_flag_final
-P ${CMAKE_CURRENT_LIST_DIR}/elfconvert_command.cmake)

set_property(TARGET bintools PROPERTY elfconvert_flag_strip_all "-DSTRIP_ALL=True")
set_property(TARGET bintools PROPERTY elfconvert_flag_strip_debug "-DSTRIP_DEBUG=True")

set_property(TARGET bintools PROPERTY elfconvert_flag_intarget "-DINTARGET=")
set_property(TARGET bintools PROPERTY elfconvert_flag_outtarget "-DOUTTARGET=")

set_property(TARGET bintools PROPERTY elfconvert_flag_section_remove "-DREMOVE_SECTION=")
set_property(TARGET bintools PROPERTY elfconvert_flag_section_only "-DONLY_SECTION=")

# mwdt doesn't handle rename, consider adjusting abstraction.
set_property(TARGET bintools PROPERTY elfconvert_flag_section_rename "-DRENAME_SECTION=")

set_property(TARGET bintools PROPERTY elfconvert_flag_gapfill "-DGAP_FILL=")
set_property(TARGET bintools PROPERTY elfconvert_flag_srec_len "-DSREC_LEN=")

set_property(TARGET bintools PROPERTY elfconvert_flag_infile "-DINFILE=")
set_property(TARGET bintools PROPERTY elfconvert_flag_outfile "-DOUTFILE=")

#
# - disassembly : Name of command for disassembly of files
# In this implementation `fromelf` is used
# disassembly_flag : --disassemble
# disassembly_flag_final : empty
# disassembly_flag_inline_source : --interleave=source
# disassembly_flag_all : empty, fromelf does not differentiate on this.
# disassembly_flag_infile : empty, fromelf doesn't take arguments for filenames
# disassembly_flag_outfile : --output

set_property(TARGET bintools PROPERTY disassembly_command ${CMAKE_FROMELF})
set_property(TARGET bintools PROPERTY disassembly_flag --disassemble)
set_property(TARGET bintools PROPERTY disassembly_flag_final "")
set_property(TARGET bintools PROPERTY disassembly_flag_inline_source --interleave=source)
set_property(TARGET bintools PROPERTY disassembly_flag_all "")

set_property(TARGET bintools PROPERTY disassembly_flag_infile "")
set_property(TARGET bintools PROPERTY disassembly_flag_outfile "--output=" )

#
# - readelf : Name of command for reading elf files.
# In this implementation `fromelf` is used
# readelf_flag : empty
# readelf_flag_final : empty
# readelf_flag_headers : --text
# readelf_flag_infile : empty, fromelf doesn't take arguments for filenames
# readelf_flag_outfile : --output

# This is using fromelf from arm-ds / Keil.
set_property(TARGET bintools PROPERTY readelf_command ${CMAKE_FROMELF})

set_property(TARGET bintools PROPERTY readelf_flag "")
set_property(TARGET bintools PROPERTY readelf_flag_final "")
set_property(TARGET bintools PROPERTY readelf_flag_headers --text)

set_property(TARGET bintools PROPERTY readelf_flag_infile "")
set_property(TARGET bintools PROPERTY readelf_flag_outfile "--output=")
9 changes: 9 additions & 0 deletions cmake/compiler/armclang/compiler_flags.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# First step is to inherit all properties from gcc, as clang is compatible with most flags.
include(${ZEPHYR_BASE}/cmake/compiler/clang/compiler_flags.cmake)

# Required ASM flags when using armclang, this should be handled by CMake, but
# fails because of: https://gitlab.kitware.com/cmake/cmake/-/issues/19963
set_property(TARGET asm APPEND PROPERTY required "--target=${triple}")

# Only the ARM Compiler C library is currently supported.
set_compiler_property(PROPERTY nostdinc)
38 changes: 38 additions & 0 deletions cmake/compiler/armclang/generic.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# SPDX-License-Identifier: Apache-2.0

# Configures CMake for using ccac

find_program(CMAKE_C_COMPILER ${CROSS_COMPILE}armclang PATH ${TOOLCHAIN_HOME}/bin NO_DEFAULT_PATH)

set(triple arm-arm-none-eabi)

set(CMAKE_DTS_PREPROCESSOR
${CMAKE_C_COMPILER}
"--target=${triple}"
# -march=armv6-m is added to silence the warnings:
# 'armv4t' and 'arm7tdmi' is unsupported.
# We only do preprocessing so the actual arch is not important.
"-march=armv6-m"
)

set(CMAKE_C_COMPILER_TARGET ${triple})
set(CMAKE_ASM_COMPILER_TARGET ${triple})
set(CMAKE_CXX_COMPILER_TARGET ${triple})

if(CMAKE_C_COMPILER STREQUAL CMAKE_C_COMPILER-NOTFOUND)
message(FATAL_ERROR "Zephyr was unable to find the armclang compiler")
endif()

execute_process(
COMMAND ${CMAKE_C_COMPILER} --version
RESULT_VARIABLE ret
OUTPUT_QUIET
ERROR_QUIET
)

if(ret)
message(FATAL_ERROR "Executing the below command failed. "
"Are permissions set correctly? '${CMAKE_C_COMPILER} --version' "
"And is the license setup correctly ?"
)
endif()
77 changes: 77 additions & 0 deletions cmake/compiler/armclang/target.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# find the compilers for C, CPP, assembly
find_program(CMAKE_C_COMPILER ${CROSS_COMPILE}armclang PATH ${TOOLCHAIN_HOME} NO_DEFAULT_PATH)
find_program(CMAKE_CXX_COMPILER ${CROSS_COMPILE}armclang PATH ${TOOLCHAIN_HOME} NO_DEFAULT_PATH)
find_program(CMAKE_ASM_COMPILER ${CROSS_COMPILE}armclang PATH ${TOOLCHAIN_HOME} NO_DEFAULT_PATH)

# The CMAKE_REQUIRED_FLAGS variable is used by check_c_compiler_flag()
# (and other commands which end up calling check_c_source_compiles())
# to add additional compiler flags used during checking. These flags
# are unused during "real" builds of Zephyr source files linked into
# the final executable.
#
include(${ZEPHYR_BASE}/cmake/gcc-m-cpu.cmake)
set(CMAKE_SYSTEM_PROCESSOR ${GCC_M_CPU})

list(APPEND TOOLCHAIN_C_FLAGS
-fshort-enums
)

if(CONFIG_ARM64)
list(APPEND TOOLCHAIN_C_FLAGS -mcpu=${GCC_M_CPU})

list(APPEND TOOLCHAIN_C_FLAGS -mabi=lp64)
list(APPEND TOOLCHAIN_LD_FLAGS -mabi=lp64)
else()
list(APPEND TOOLCHAIN_C_FLAGS -mcpu=${GCC_M_CPU})

if(CONFIG_COMPILER_ISA_THUMB2)
list(APPEND TOOLCHAIN_C_FLAGS -mthumb)
endif()

list(APPEND TOOLCHAIN_C_FLAGS -mabi=aapcs)

# Defines a mapping from GCC_M_CPU to FPU

if(CONFIG_CPU_HAS_FPU_DOUBLE_PRECISION)
set(PRECISION_TOKEN)
else()
set(PRECISION_TOKEN sp-)
endif()

set(FPU_FOR_cortex-m4 fpv4-${PRECISION_TOKEN}d16)
set(FPU_FOR_cortex-m7 fpv5-${PRECISION_TOKEN}d16)
set(FPU_FOR_cortex-m33 fpv5-${PRECISION_TOKEN}d16)

if(CONFIG_FPU)
list(APPEND TOOLCHAIN_C_FLAGS -mfpu=${FPU_FOR_${GCC_M_CPU}})
if (CONFIG_FP_SOFTABI)
list(APPEND TOOLCHAIN_C_FLAGS -mfloat-abi=softfp)
elseif(CONFIG_FP_HARDABI)
list(APPEND TOOLCHAIN_C_FLAGS -mfloat-abi=hard)
endif()
endif()
endif()

foreach(file_name include/stddef.h)
execute_process(
COMMAND ${CMAKE_C_COMPILER} --print-file-name=${file_name}
OUTPUT_VARIABLE _OUTPUT
)
get_filename_component(_OUTPUT "${_OUTPUT}" DIRECTORY)
string(REGEX REPLACE "\n" "" _OUTPUT ${_OUTPUT})

list(APPEND NOSTDINC ${_OUTPUT})
endforeach()

foreach(isystem_include_dir ${NOSTDINC})
list(APPEND isystem_include_flags -isystem ${isystem_include_dir})
endforeach()

set(CMAKE_REQUIRED_FLAGS ${isystem_include_flags})
string(REPLACE ";" " " CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")

if(CONFIG_ARMCLANG_STD_LIBC)
# Zephyr requires AEABI portability to ensure correct functioning of the C
# library, for example error numbers, errno.h.
list(APPEND TOOLCHAIN_C_FLAGS -D_AEABI_PORTABILITY_LEVEL=1)
endif()
Loading