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

chore: DRY linker scripts, picolibc & LLVM toolchain #4287

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ if(EdgeTX_SUPERBUILD)
BINARY_DIR ${CMAKE_BINARY_DIR}/arm-none-eabi
CMAKE_ARGS ${CMAKE_ARGS} -Wno-dev -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
CMAKE_CACHE_ARGS
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=${CMAKE_SOURCE_DIR}/cmake/toolchain/arm-none-eabi.cmake
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=${CMAKE_SOURCE_DIR}/cmake/toolchain/gcc-arm-none-eabi.cmake
-DEdgeTX_SUPERBUILD:BOOL=0
-DNATIVE_BUILD:BOOL=0
INSTALL_COMMAND ""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,20 @@ set(CMAKE_EXECUTABLE_SUFFIX ".elf")
set(CMAKE_EXECUTABLE_SUFFIX_C ".elf")
set(CMAKE_EXECUTABLE_SUFFIX_CXX ".elf")

# Optimize for code size by default
set(C_FLAGS_INIT "-Os -Wall -fdata-sections -ffunction-sections -fomit-frame-pointer -fno-asynchronous-unwind-tables")
set(CXX_FLAGS_INIT "${C_FLAGS_INIT} -fno-rtti -fno-exceptions -fno-unwind-tables -fno-threadsafe-statics")

# Default C compiler flags
set(CMAKE_C_FLAGS_DEBUG_INIT "-g3 -Og -Wall -pedantic -DDEBUG")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG_INIT}" CACHE STRING "" FORCE)
set(CMAKE_C_FLAGS_RELEASE_INIT "-O3 -Wall")
set(CMAKE_C_FLAGS_INIT "${C_FLAGS_INIT} -g3")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS_INIT}" CACHE STRING "" FORCE)
set(CMAKE_C_FLAGS_RELEASE_INIT "${C_FLAGS_INIT}")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE_INIT}" CACHE STRING "" FORCE)

# Default C++ compiler flags
set(CMAKE_CXX_FLAGS_DEBUG_INIT "-g3 -Og -Wall -pedantic -DDEBUG")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG_INIT}" CACHE STRING "" FORCE)
set(CMAKE_CXX_FLAGS_RELEASE_INIT "-O3 -Wall")
set(CMAKE_CXX_FLAGS_INIT "${CXX_FLAGS_INIT}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_INIT}" CACHE STRING "" FORCE)
set(CMAKE_CXX_FLAGS_RELEASE_INIT "${CXX_FLAGS_INIT}")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE_INIT}" CACHE STRING "" FORCE)

# customize linker command
Expand Down
60 changes: 60 additions & 0 deletions cmake/toolchain/llvm-embedded.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# arm-none-eabi toolchain
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_CXX_STANDARD 11)

set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

if(MINGW OR WIN32)
set(EXE_SUFFIX ".exe")
set(CMAKE_OBJECT_PATH_MAX 200)
endif()

if(ARM_TOOLCHAIN_DIR)
cmake_path(SET ARM_TOOLCHAIN_DIR NORMALIZE ${ARM_TOOLCHAIN_DIR})
set(ARM_TOOLCHAIN_DIR "${ARM_TOOLCHAIN_DIR}/")
endif()

set(CMAKE_AR ${ARM_TOOLCHAIN_DIR}llvm-ar${EXE_SUFFIX})
set(CMAKE_ASM_COMPILER ${ARM_TOOLCHAIN_DIR}clang${EXE_SUFFIX})
set(CMAKE_C_COMPILER ${ARM_TOOLCHAIN_DIR}clang${EXE_SUFFIX})
set(CMAKE_CXX_COMPILER ${ARM_TOOLCHAIN_DIR}clang++${EXE_SUFFIX})
set(CMAKE_LINKER ${ARM_TOOLCHAIN_DIR}lld${EXE_SUFFIX})
set(CMAKE_OBJCOPY ${ARM_TOOLCHAIN_DIR}llvm-objcopy${EXE_SUFFIX} CACHE INTERNAL "")
set(CMAKE_RANLIB ${ARM_TOOLCHAIN_DIR}llvm-ranlib${EXE_SUFFIX} CACHE INTERNAL "")
set(CMAKE_SIZE_UTIL ${ARM_TOOLCHAIN_DIR}llvm-size${EXE_SUFFIX} CACHE INTERNAL "")
set(CMAKE_STRIP ${ARM_TOOLCHAIN_DIR}llvm-strip${EXE_SUFFIX} CACHE INTERNAL "")
set(CMAKE_GCOV ${ARM_TOOLCHAIN_DIR}llvm-cov${EXE_SUFFIX} CACHE INTERNAL "")

# Generate .elf files
set(CMAKE_EXECUTABLE_SUFFIX ".elf")
set(CMAKE_EXECUTABLE_SUFFIX_C ".elf")
set(CMAKE_EXECUTABLE_SUFFIX_CXX ".elf")

# Optimize for code size by default
set(C_FLAGS_INIT "-Oz -Wall -fdata-sections -ffunction-sections -fomit-frame-pointer")
set(CXX_FLAGS_INIT "${C_FLAGS_INIT} -Wno-deprecated-register -fno-rtti -fno-exceptions -fno-unwind-tables -fno-c++-static-destructors -fno-threadsafe-statics")

# Default ASM compiler flags
set(CMAKE_ASM_FLAGS "-Wno-unused-command-line-argument")

# Default C compiler flags
set(CMAKE_C_FLAGS_INIT "${C_FLAGS_INIT} -g3")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS_INIT}" CACHE STRING "" FORCE)
set(CMAKE_C_FLAGS_RELEASE_INIT "${C_FLAGS_INIT}")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE_INIT}" CACHE STRING "" FORCE)

# Default C++ compiler flags
set(CMAKE_CXX_FLAGS_INIT "${CXX_FLAGS_INIT}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_INIT}" CACHE STRING "" FORCE)
set(CMAKE_CXX_FLAGS_RELEASE_INIT "${CXX_FLAGS_INIT}")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE_INIT}" CACHE STRING "" FORCE)

# customize linker command
set(CMAKE_EXE_LINKER_FLAGS "")
set(CMAKE_C_LINK_EXECUTABLE "<CMAKE_C_COMPILER> <FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_CXX_COMPILER> <FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
88 changes: 44 additions & 44 deletions radio/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ option(DEBUG_SEGGER_RTT "Debug output to Segger RTT" OFF)
option(DEBUG_WINDOWS "Turn on windows traces" OFF)
option(DEBUG_YAML "Turn on YAML traces" OFF)
option(DEBUG_LABELS "Turn on Labels traces" OFF)
option(NANO "Use nano newlib and binalloc")
option(TEST_BUILD_WARNING "Warn this is a test build" OFF)
option(MODULE_PROTOCOL_FCC "Add support for FCC modules" ON)
option(MODULE_PROTOCOL_LBT "Add support for EU/LBT modules" ON)
Expand Down Expand Up @@ -480,55 +479,24 @@ if(NATIVE_BUILD)
return()
endif()

set(CMAKE_C_FLAGS "${FIRMWARE_C_FLAGS}")
set(CMAKE_C_FLAGS_DEBUG "${FIRMWARE_C_FLAGS_DEBUG}")
set(CMAKE_C_FLAGS_RELEASE "${FIRMWARE_C_FLAGS}")

set(CMAKE_CXX_FLAGS "${FIRMWARE_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS_DEBUG "${FIRMWARE_CXX_FLAGS_DEBUG}")
set(CMAKE_CXX_FLAGS_RELEASE "${FIRMWARE_CXX_FLAGS}")

find_program(BASH bash
HINTS "c:/cygwin/bin/" "c:/msys/bin/"
DOC "bash shell for firmware size report (eg. c:/cygwin/bin/bash.exe on Windows)."
)

set(OPT "s" CACHE STRING "Optimization mode (0/1/2/s")

set(COMMON_FLAGS "-mcpu=${MCU} -mthumb -fomit-frame-pointer -fverbose-asm -Wa,-ahlms=firmware.lst")
set(COMMON_FLAGS "${COMMON_FLAGS} -gdwarf-2 -fno-exceptions -fdata-sections -ffunction-sections")
set(COMMON_FLAGS "${COMMON_FLAGS} -DHSE_VALUE=${HSE_VALUE}")
set(COMMON_FLAGS "${COMMON_FLAGS} -O${OPT} ${FPU_FLAGS}")
set(COMMON_FLAGS "${COMMON_FLAGS} ${WARNING_FLAGS}")
# if(SEMIHOSTING)
# add_definitions(-DSEMIHOSTING)
# set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --specs=rdimon.specs")
# endif()

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COMMON_FLAGS} -Wimplicit")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMMON_FLAGS} -fno-rtti")

# these are in addition to CMAKE_CXX_FLAGS
set(CMAKE_EXE_LINKER_FLAGS "-lm -T${RADIO_SRC_DIR}/${LINKER_SCRIPT}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-Map=firmware.map,--cref,--no-warn-mismatch,--gc-sections")

if(SEMIHOSTING)
add_definitions(-DSEMIHOSTING)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --specs=rdimon.specs")
endif()

# Use newlib nano, which saves a few kilobytes.
if(NOT NANO STREQUAL NO)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --specs=nano.specs")
if(LUA)
# Lua needs %g and %f
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -u _printf_float -u _scanf_float")
endif()
if(SDRAM)
# Target with SDRAM do not need a custom allocator for now
# as the custom allocator has alignement issues
message("Target has SDRAM, do not use BIN_ALLOCATOR")
else()
# Nano's malloc does work well with lua, use our own
add_definitions(-DUSE_BIN_ALLOCATOR)
set(SRC ${SRC} bin_allocator.cpp)
endif()
if(SDRAM)
# Target with SDRAM do not need a custom allocator for now
# as the custom allocator has alignement issues
message("Target has SDRAM, do not use BIN_ALLOCATOR")
else()
# Nano's malloc does work well with lua, use our own
add_definitions(-DUSE_BIN_ALLOCATOR)
set(SRC ${SRC} bin_allocator.cpp)
endif()

# Bootloader
Expand All @@ -545,6 +513,38 @@ link_libraries(firmware -lstdc++)
add_dependencies(firmware ${RADIO_DEPENDENCIES})
set_target_properties(firmware PROPERTIES EXCLUDE_FROM_ALL TRUE)

target_link_options(firmware PRIVATE
-lm -T${LINKER_DIR}/firmware.ld
-Wl,-Map=firmware.map,--cref,--no-warn-mismatch,--gc-sections
)

if (DEFINED TARGET_FLASH_SIZE)
message("TARGET_FLASH_SIZE = ${TARGET_FLASH_SIZE}")
target_link_options(firmware PRIVATE
-Wl,--defsym=__flash_size=${TARGET_FLASH_SIZE}
)
endif()

if (DEFINED TARGET_SDRAM_START)
message("TARGET_SDRAM_START = ${TARGET_SDRAM_START}")
target_link_options(firmware PRIVATE
-Wl,--defsym=__sdram_start=${TARGET_SDRAM_START}
)
endif()

if (LUA)
# ??? Lua needs %g and %f ???
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
target_link_options(firmware PRIVATE
-Wl,--defsym=vfprintf=__f_vfprintf
)
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_link_options(firmware PRIVATE
"SHELL:-u _printf_float" "SHELL:-u _scanf_float"
)
endif()
endif()

if(ACCESS_DENIED)
add_subdirectory(thirdparty/AccessDenied)
include_directories(thirdparty/AccessDenied)
Expand Down
27 changes: 27 additions & 0 deletions radio/src/boards/generic_stm32/linker/bootloader.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
Generic bootloader linker script for STM32
*/

INCLUDE definitions.ld

/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */

/* The program code and other data goes into FLASH */
.text :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
KEEP(*(.version))
KEEP(*(.bootversiondata))

INCLUDE common_text.ld

. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >FLASH

INCLUDE common_sections.ld
}
89 changes: 89 additions & 0 deletions radio/src/boards/generic_stm32/linker/common_sections.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@

/*
* Needs to be in its own segment with the PLT entries first
* so that the linker will compute the offsets to those
* entries correctly.
*/
.got : {
*(.got.plt)
*(.got)
} >FLASH AT>FLASH :text

.toc : {
*(.toc .toc.*)
} >FLASH AT>FLASH :text

/* Initialized data sections goes into RAM, load LMA copy after code */
.data : {
*(.data .data*)
*(.gnu.linkonce.d.*)

. = ALIGN(4);
*(.sdata .sdata.* .sdata2.*)
*(.gnu.linkonce.s.*)
} >REGION_DATA AT>FLASH :ram_init

/* Thread local storage */
.tdata : ALIGN(8) {
*(.tdata .tdata.* .gnu.linkonce.td.*)
PROVIDE(__data_end = .);
PROVIDE(__tdata_end = .);
} >REGION_DATA AT>FLASH :tls :ram_init

PROVIDE(__data_start = ADDR(.data));
PROVIDE(__data_source = LOADADDR(.data));

PROVIDE( _sdata = __data_start);
PROVIDE( _edata = __data_end);
PROVIDE( _sidata = __data_source);

/* Thread local storage */
.tbss (NOLOAD) : {
*(.tbss .tbss.* .gnu.linkonce.tb.*)
*(.tcommon)
PROVIDE( __tls_end = . );
PROVIDE( __tbss_end = . );
} >REGION_BSS AT>REGION_BSS :ram

/* Uninitialized data section */
.bss(NOLOAD) : {
*(.sbss*)
*(.gnu.linkonce.sb.*)
*(.bss .bss*)
*(.gnu.linkonce.b.*)
*(COMMON)

. = ALIGN(4);
__bss_end = .;
} >REGION_BSS AT>REGION_BSS :ram

PROVIDE( _sbss = ADDR(.tbss) );
PROVIDE( _ebss = __bss_end );

/* collect all uninitialized .ram sections (force DMA accessible) */
.ram (NOLOAD) :
{
. = ALIGN(4);
_sram = .;
*(.ram)
. = ALIGN(4);
_eram = .;
} >REGION_RAM AT>REGION_RAM :ram

INCLUDE extra_sections.ld

/DISCARD/ :
{
/* Remove information from the standard libraries */
libc.a ( * )
libm.a ( * )
libgcc.a ( * )

/* Throw away C++ exception handling information */
*(.note .note.*)
*(.eh_frame .eh_frame.*)
*(.ARM.extab* .gnu.linkonce.armextab.*)
*(.ARM.exidx*)
}

.ARM.attributes 0 : { *(.ARM.attributes) }
52 changes: 52 additions & 0 deletions radio/src/boards/generic_stm32/linker/common_text.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/* .text sections (code) */
*(.text .text* .gnu.linkonce.t.*)

/* read-only data */
*(.rdata)
*(.rodata .rodata*)
*(.data.rel.ro .data.rel.ro.*)
*(.srodata .srodata.*)
*(.data.rel.ro .data.rel.ro.*)

/* GCC / newlib special treatment */
*(.eh_frame)
*(.data.__global_locale)

/*
C++ Runtime: initializers for static variables.
C Runtime: designated constructors
*/
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;

. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;

/*
C++ runtime: destructors for static variables.
C runtime: designated finializers
*/
. = ALIGN(4);
KEEP(*(.fini))

. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;

/*
C++ runtime: static constructors
*/
. = ALIGN(4);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*crtend.o(.ctors))
Loading