46 changed files with 1597 additions and 245 deletions
@ -0,0 +1,19 @@
|
||||
# CMake splitter decides if firmware or test application is built depending on |
||||
# how the compiler is named. arm-none-eabi compiler will build firmware. Everything else tests. |
||||
# This is necessary as cmake is not built to easily invoke different compilers for different |
||||
# Build-targets. |
||||
|
||||
cmake_minimum_required(VERSION 3.15) |
||||
include("core/cmake/compilerSetup.cmake") |
||||
|
||||
project(cmake_splitter VERSION 0.0.1 LANGUAGES CXX C) |
||||
|
||||
if (NOT DEFINED isEmbeddedCompiler) |
||||
message(FATAL_ERROR "compiler type not known") |
||||
endif() |
||||
|
||||
if(${isEmbeddedCompiler}) |
||||
include("src/CMakeLists.txt") |
||||
else() |
||||
include("test/CMakeLists.txt") |
||||
endif() |
@ -1,24 +0,0 @@
|
||||
TARGET := solder_workspace_lighting
|
||||
DEVICE := stm32l432
|
||||
|
||||
DEFS += FW_USE_RTOS
|
||||
|
||||
INCDIRS := \
|
||||
src/oled-driver/include \ |
||||
src/oled-driver/ \ |
||||
src |
||||
|
||||
SOURCES := \
|
||||
src/Button/Button.cxx \ |
||||
src/Button/buttonHandler.cxx \ |
||||
src/adc.cxx \ |
||||
src/oled-driver/fonts/mono.cxx \ |
||||
src/oled-driver/src/Display.cxx \ |
||||
src/oled-driver/src/Image.cxx \ |
||||
src/oled-driver/src/Renderer.cxx \ |
||||
src/encoder.cxx \ |
||||
src/leds.cxx \ |
||||
src/OledDisplay.cxx |
||||
|
||||
# Actual build engine
|
||||
include core/mk/include.mk |
@ -0,0 +1,83 @@
|
||||
cmake_minimum_required(VERSION 3.0) |
||||
project(core VERSION 0.0.1 LANGUAGES CXX C) |
||||
|
||||
# generate build information every time compile is started |
||||
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/include/core) |
||||
add_custom_target(generateVersionHeader |
||||
${PROJECT_SOURCE_DIR}/scripts/generateVersionHeader.py |
||||
${PROJECT_SOURCE_DIR}/../ |
||||
${PROJECT_BINARY_DIR}/include/core/Version.h |
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) |
||||
|
||||
add_library(${PROJECT_NAME} STATIC |
||||
src/abi.cpp |
||||
src/fault_handler.cpp |
||||
src/hash.cpp |
||||
src/SafeAssert.cpp |
||||
src/std.cpp |
||||
) |
||||
target_include_directories(${PROJECT_NAME} PUBLIC |
||||
inc |
||||
chip |
||||
${PROJECT_BINARY_DIR}/include |
||||
) |
||||
add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} generateVersionHeader) |
||||
|
||||
target_link_libraries(${PROJECT_NAME} freertos hal_headers) |
||||
|
||||
# embedded / testing / fuzzing / emulator |
||||
if (NOT DEFINED core_BUILDCONFIGURATION) |
||||
message(FATAL_ERROR "Required variable core_BUILDCONFIGURATION is not defined") |
||||
endif() |
||||
if (core_BUILDCONFIGURATION STREQUAL "embedded") |
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC BUILDTYPE=2) |
||||
message("You chose embedded build configuration.") |
||||
elseif (core_BUILDCONFIGURATION STREQUAL "testing") |
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC BUILDTYPE=3) |
||||
message("You chose testing build configuration.") |
||||
elseif (core_BUILDCONFIGURATION STREQUAL "fuzzing") |
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC BUILDTYPE=4) |
||||
message("You chose fuzzing build configuration.") |
||||
elseif (core_BUILDCONFIGURATION STREQUAL "emulator") |
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC BUILDTYPE=5) |
||||
message("You chose emulator build configuration.") |
||||
else () |
||||
message(FATAL_ERROR "Please define a macro for your core_BUILDCONFIGURATION. You chose '${core_BUILDTYPE}'") |
||||
endif () |
||||
|
||||
# release / debug |
||||
if ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") |
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC BUILDCONFIG_DEBUG) |
||||
message("Buildtype is DEBUG.") |
||||
elseif ("${CMAKE_BUILD_TYPE}" STREQUAL "Release") |
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC BUILDCONFIG_RELEASE) |
||||
message("Buildtype is RELEASE.") |
||||
else () |
||||
message(FATAL_ERROR "Please define a macro for your CMAKE_BUILD_TYPE. You chose '${CMAKE_BUILD_TYPE}' which is not implemented yet. Did you forget to add -DCMAKE_BUILD_TYPE=Release or -DCMAKE_BUILD_TYPE=Debug?") |
||||
endif () |
||||
|
||||
if (NOT DEFINED isEmbeddedCompiler) |
||||
message(FATAL_ERROR "Required variable isEmbeddedCompiler is not in scope") |
||||
endif () |
||||
if (NOT ${isEmbeddedCompiler}) |
||||
include(CTest) |
||||
find_package(PkgConfig) |
||||
pkg_search_module(GTEST REQUIRED gtest) |
||||
pkg_search_module(GMOCK REQUIRED gmock) |
||||
|
||||
add_executable(${PROJECT_NAME}_test |
||||
tests/src/main.cpp |
||||
tests/src/SafeAssertTest.cpp |
||||
tests/src/HashTest.cpp |
||||
) |
||||
target_include_directories(${PROJECT_NAME}_test PRIVATE |
||||
tests/include) |
||||
target_link_libraries(${PROJECT_NAME}_test PRIVATE |
||||
${GTEST_LDFLAGS} |
||||
${GMOCK_LDFLAGS} |
||||
gcov |
||||
${PROJECT_NAME}) |
||||
target_link_options(${PROJECT_NAME}_test PRIVATE --coverage) |
||||
target_compile_options(${PROJECT_NAME}_test PRIVATE ${GTEST_CFLAGS} ${GMOCK_CFLAGS} --coverage) |
||||
add_test(${PROJECT_NAME} ${PROJECT_NAME}_test) |
||||
endif () |
@ -0,0 +1,48 @@
|
||||
# core |
||||
TODO DESCRIBE NEW BUILDSYSTEM BASED ON CMAKE |
||||
TODO DESCRIBE SETUP OF NEW PROJECT |
||||
TODO DESCRIBE BUILDSYSTEMS ASSUMPTIONS ABOUT COMPILER |
||||
TODO RECOMMEND NINJA BUILD GENERATOR |
||||
|
||||
|
||||
TODO DESCRIBE PROJECT SPLITTER |
||||
```cmake |
||||
cmake_minimum_required(VERSION 3.15) |
||||
include("libraries/core/cmake/compilerSetup.cmake") |
||||
|
||||
project(cmake_splitter VERSION 0.0.1 LANGUAGES CXX C) |
||||
|
||||
if(${isEmbeddedCompiler}) |
||||
include("src/CMakeLists.txt") |
||||
else() |
||||
include("test/CMakeLists.txt") |
||||
endif() |
||||
``` |
||||
|
||||
Core library containing the build system, common functionalities required by all firmwares. |
||||
|
||||
TODO UPDATE, MOVE OVER CUBEMX SETUP OF CORE |
||||
|
||||
### CMake setup |
||||
|
||||
Expects *isEmbeddedCompiler* variable from *core/cmake/detectCompilerType.cmake* in parent scope. |
||||
|
||||
Requires following libraries: |
||||
|
||||
- freertos |
||||
- hal_headers |
||||
|
||||
Exports following libraries: |
||||
|
||||
- core |
||||
|
||||
Core features automatic CMake translation of CubeMX Makefiles when the following is added to the Makefile |
||||
|
||||
```makefile |
||||
export: |
||||
@printf 'MakeExport_SOURCES $(C_SOURCES) $(ASM_SOURCES)\n' |
||||
@printf 'MakeExport_MCU_Flags $(MCU)\n' |
||||
@printf 'MakeExport_DEFS $(AS_DEFS) $(C_DEFS)\n' |
||||
@printf 'MakeExport_INCLUDES $(AS_INCLUDES) $(C_INCLUDES)\n' |
||||
@printf 'MakeExport_LDSCRIPT $(LDSCRIPT)\n' |
||||
``` |
@ -0,0 +1,26 @@
|
||||
#pragma once |
||||
|
||||
#include "hal_header.h" |
||||
|
||||
/**
|
||||
* @brief Defines that are necessary for uavcan stm32 driver's compile checks |
||||
* to pass.
|
||||
*/ |
||||
|
||||
#if defined(UAVCAN_STM32_NUM_IFACES) |
||||
#if defined(STM32F4) |
||||
#define CAN1_TX_IRQHandler CAN1_TX_IRQHandler |
||||
#define CAN1_RX0_IRQHandler CAN1_RX0_IRQHandler |
||||
#define CAN1_RX1_IRQHandler CAN1_RX1_IRQHandler |
||||
|
||||
#if UAVCAN_STM32_NUM_IFACES == 2 |
||||
#define CAN2_TX_IRQHandler CAN2_TX_IRQHandler |
||||
#define CAN2_RX0_IRQHandler CAN2_RX0_IRQHandler |
||||
#define CAN2_RX1_IRQHandler CAN2_RX1_IRQHandler |
||||
#endif |
||||
#endif |
||||
|
||||
#if defined(STM32F1) |
||||
#define CAN1_RX1_IRQHandler CAN1_RX1_IRQHandler |
||||
#endif |
||||
#endif |
@ -0,0 +1,13 @@
|
||||
#pragma once |
||||
|
||||
/**
|
||||
* @brief Chip "independant" cubeHAL include |
||||
*
|
||||
*/ |
||||
#if __has_include("stm32f4xx_hal.h") |
||||
#include "stm32f4xx_hal.h" |
||||
#define STM32F4 |
||||
#else |
||||
#include "stm32f1xx_hal.h" |
||||
#define STM32F1 |
||||
#endif |
@ -0,0 +1,48 @@
|
||||
include_guard(GLOBAL) |
||||
include(${CMAKE_CURRENT_LIST_DIR}/detectCompilerType.cmake) |
||||
DETECT_COMPILER_TYPE() |
||||
add_compile_options(-fdiagnostics-color) |
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS true) |
||||
|
||||
if (NOT DEFINED isEmbeddedCompiler) |
||||
message(FATAL_ERROR "Required variable isEmbeddedCompiler is not in scope") |
||||
endif () |
||||
if (isEmbeddedCompiler) |
||||
# fixes compiler detection with arm-none-eabi-gcc as cmake tries to |
||||
# build an executable but bare metal doesn't work like this |
||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) |
||||
endif () |
||||
|
||||
if (${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR}) |
||||
message(FATAL_ERROR "In-source build detected! Generate cmake in an extra folder to avoid a mess of files generated in your folder") |
||||
endif () |
||||
|
||||
if (${isEmbeddedCompiler}) |
||||
message("arm compiler detected") |
||||
set(CMAKE_SYSTEM_NAME Generic) |
||||
set(CMAKE_SYSTEM_PROCESSOR arm) |
||||
|
||||
# cmake and the programs orchestrating it are stupid sometimes and only detect the C compiler |
||||
# using the same path, set CXX/objcopy/objdump paths explicitly |
||||
# this of course breakes when you pull apart your compiler programs |
||||
# but why would you do that? |
||||
get_filename_component(CompilerPath "${CMAKE_C_COMPILER}" PATH) |
||||
if (CompilerPath STREQUAL "") |
||||
# some ci compilers dont include the full path to compiler |
||||
# assume default names for everything |
||||
set(CMAKE_CXX_COMPILER "arm-none-eabi-g++" CACHE INTERNAL "") |
||||
set(CMAKE_OBJCOPY "arm-none-eabi-objcopy" CACHE INTERNAL "") |
||||
set(CMAKE_OBJDUMP "arm-none-eabi-objdump" CACHE INTERNAL "") |
||||
else() |
||||
set(CMAKE_CXX_COMPILER ${CompilerPath}/arm-none-eabi-g++ CACHE INTERNAL "") |
||||
set(CMAKE_OBJCOPY ${CompilerPath}/arm-none-eabi-objcopy CACHE INTERNAL "") |
||||
set(CMAKE_OBJDUMP ${CompilerPath}/arm-none-eabi-objdump CACHE INTERNAL "") |
||||
endif() |
||||
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) |
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) |
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) |
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) |
||||
else () |
||||
message("non-arm compiler detected") |
||||
endif () |
@ -0,0 +1,10 @@
|
||||
include_guard(GLOBAL) |
||||
|
||||
# Sets isEmbeddedCompiler true or false in parent scope |
||||
function(DETECT_COMPILER_TYPE) |
||||
if (${CMAKE_C_COMPILER} MATCHES "arm-none-eabi-") |
||||
set(isEmbeddedCompiler true PARENT_SCOPE) |
||||
else() |
||||
set(isEmbeddedCompiler false PARENT_SCOPE) |
||||
endif() |
||||
endfunction() |
@ -0,0 +1,75 @@
|
||||
include_guard(GLOBAL) |
||||
# call specially created make file that prints out variables |
||||
# expecting output from the makefile code in mk/CubeMXMakefileInstrumentation.mk |
||||
|
||||
# Sets the following variables in parent scope |
||||
# MakeExport_SOURCES, MakeExport_MCU_Flags, MakeExport_DEFS, MakeExport_INCLUDES, MakeExport_LDSCRIPT |
||||
# prefixDirectory will be applied to sources, includes and ldscript |
||||
function(GET_CUBEMX_VARIABLES prefixDirectory) |
||||
execute_process(COMMAND make --no-print-directory -C ${PROJECT_SOURCE_DIR}/${prefixDirectory}/ |
||||
OUTPUT_VARIABLE out) |
||||
|
||||
# split output into list |
||||
# a list is a string separated by ; for cmake btw |
||||
string(REPLACE "\n" ";" out "${out}") |
||||
list(LENGTH out length) |
||||
if (NOT length MATCHES 6) |
||||
# 5 entries + one empty line |
||||
message(FATAL_ERROR "Unable to extract information from makefile: list of lists is too short. Did you properly prepare/instrument it?") |
||||
endif () |
||||
|
||||
set(foundSources false) |
||||
set(foundMCUFlags false) |
||||
set(foundDefs false) |
||||
set(foundIncludes false) |
||||
set(foundLDScript false) |
||||
foreach (entry IN LISTS out) |
||||
# strip away any -I or -D |
||||
string(REPLACE "-I" "" entry "${entry}") |
||||
#string(REPLACE "-D" "" entry "${entry}") |
||||
|
||||
# split into list, entries are expected to be whitespace separated |
||||
string(REPLACE " " ";" entryList "${entry}") |
||||
|
||||
list(LENGTH entryList length) |
||||
if (${length} LESS 2) |
||||
continue() |
||||
endif () |
||||
|
||||
# get first element (name of entry), save it and remove it from the main list |
||||
list(GET entryList 0 entryName) |
||||
list(REMOVE_AT entryList 0) |
||||
|
||||
if (entryName MATCHES "^MakeExport_SOURCES") |
||||
list(TRANSFORM entryList PREPEND "${prefixDirectory}/") |
||||
set(MakeExport_SOURCES ${entryList} PARENT_SCOPE) |
||||
set(foundSources true) |
||||
continue() |
||||
endif () |
||||
if (entryName MATCHES "^MakeExport_MCU_Flags") |
||||
set(MakeExport_MCU_Flags ${entryList} PARENT_SCOPE) |
||||
set(foundMCUFlags true) |
||||
continue() |
||||
endif () |
||||
if (entryName MATCHES "^MakeExport_DEFS") |
||||
set(MakeExport_DEFS ${entryList} PARENT_SCOPE) |
||||
set(foundDefs true) |
||||
continue() |
||||
endif () |
||||
if (entryName MATCHES "^MakeExport_INCLUDES") |
||||
list(TRANSFORM entryList PREPEND "${prefixDirectory}/") |
||||
set(MakeExport_INCLUDES ${entryList} PARENT_SCOPE) |
||||
set(foundIncludes true) |
||||
continue() |
||||
endif () |
||||
if (entryName MATCHES "^MakeExport_LDSCRIPT") |
||||
list(TRANSFORM entryList PREPEND "${prefixDirectory}/") |
||||
set(MakeExport_LDSCRIPT ${entryList} PARENT_SCOPE) |
||||
set(foundLDScript true) |
||||
continue() |
||||
endif () |
||||
endforeach () |
||||
if (NOT foundLDScript OR NOT foundIncludes OR NOT foundDefs OR NOT foundMCUFlags OR NOT foundSources) |
||||
message(FATAL_ERROR "CubeMX is not properly prepared with export statement") |
||||
endif () |
||||
endfunction() |
@ -0,0 +1,69 @@
|
||||
include_guard(GLOBAL) |
||||
include(${CMAKE_CURRENT_LIST_DIR}/extractBuildinfoFromMakefile.cmake) |
||||
include(${CMAKE_CURRENT_LIST_DIR}/detectCompilerType.cmake) |
||||
|
||||
# Extracts C and H files from cubemx makefile and creates three targets |
||||
# freertos - realtime os complete with heap, and port |
||||
# hel_headers - all cubemx generated headers without source files |
||||
# hal - complete hal with sources and headers |
||||
function(GENERATE_CUBEMX_TARGETS halDirectory generateFreertosTarget) |
||||
GET_CUBEMX_VARIABLES(${halDirectory}) |
||||
DETECT_COMPILER_TYPE() |
||||
|
||||
set(HalSources) |
||||
set(FreertosSources) |
||||
foreach (entry IN LISTS MakeExport_SOURCES) |
||||
if (entry MATCHES "Middlewares/Third_Party/FreeRTOS/Source/") |
||||
if (entry MATCHES "CMSIS_RTOS_V2") |
||||
# cmsis_os2.c is part of hal, but hides inside freertos sources |
||||
list(APPEND HalSources ${entry}) |
||||
else () |
||||
list(APPEND FreertosSources ${entry}) |
||||
|
||||
endif () |
||||
else () |
||||
list(APPEND HalSources ${entry}) |
||||
endif () |
||||
endforeach () |
||||
|
||||
set(HalIncludes) |
||||
set(FreertosIncludes) |
||||
foreach (entry IN LISTS MakeExport_INCLUDES) |
||||
if (entry MATCHES "Middlewares/Third_Party/FreeRTOS/Source") |
||||
if (entry MATCHES "CMSIS_RTOS_V2") |
||||
# cmsis_os2.c is part of hal, but hides inside freertos sources |
||||
list(APPEND HalIncludes ${entry}) |
||||
else () |
||||
list(APPEND FreertosIncludes ${entry}) |
||||
|
||||
endif () |
||||
else () |
||||
list(APPEND HalIncludes ${entry}) |
||||
endif () |
||||
endforeach () |
||||
|
||||
add_library(hal_headers INTERFACE) |
||||
target_include_directories(hal_headers INTERFACE ${HalIncludes}) |
||||
target_compile_definitions(hal_headers INTERFACE ${MakeExport_DEFS}) |
||||
|
||||
# in testing a custom freertos version is built |
||||
# this must be excluded to avoid duplicate target issues |
||||
if (${generateFreertosTarget}) |
||||
# freertos |
||||
add_library(freertos STATIC |
||||
${FreertosSources}) |
||||
target_include_directories(freertos PUBLIC ${FreertosIncludes}) |
||||
target_link_libraries(freertos PUBLIC hal_headers core) |
||||
endif () |
||||
|
||||
# complete hal |
||||
# following target doesn't compile on non embedded builds |
||||
# explicitly exclude from "All" build triggered by CTest |
||||
add_library(hal OBJECT |
||||
${HalSources} |
||||
) |
||||
target_link_libraries(hal PUBLIC hal_headers freertos) |
||||
set_target_properties(hal PROPERTIES |
||||
EXCLUDE_FROM_ALL TRUE |
||||
EXCLUDE_FROM_DEFAULT_BUILD TRUE) |
||||
endfunction() |
@ -0,0 +1,63 @@
|
||||
include_guard(GLOBAL) |
||||
include(${CMAKE_CURRENT_LIST_DIR}/extractBuildinfoFromMakefile.cmake) |
||||
|
||||
# Invokes GET_CUBEMX_VARIABLES to retrieve defines and options from cubemx makefile |
||||
# assumes halDirectory is given as relative path seen from folder of top level script |
||||
# (linker needs full path to .ld file, so correct path assembly is critical) |
||||
|
||||
function(SETUP_BUILD halDirectory firmwareName Cstandard CXXstandard) |
||||
GET_CUBEMX_VARIABLES(${halDirectory}) |
||||
|
||||
if (NOT DEFINED MakeExport_SOURCES OR NOT DEFINED MakeExport_MCU_Flags OR NOT DEFINED MakeExport_DEFS OR NOT DEFINED MakeExport_INCLUDES |
||||
OR NOT DEFINED MakeExport_LDSCRIPT) |
||||
message(FATAL_ERROR "Required variables are not in scope") |
||||
endif () |
||||
|
||||
set(Optimisaiton) |
||||
if (${CMAKE_BUILD_TYPE} STREQUAL "Release") |
||||
message("SETUP_BUILD configuring for Release.") |
||||
set(Optimisation -O2 -g) |
||||
elseif (${CMAKE_BUILD_TYPE} STREQUAL "Debug") |
||||
message("SETUP_BUILD configuring for Debug.") |
||||
set(Optimisation -Og -g) |
||||
else () |
||||
message(FATAL_ERROR "Unknown Buildtype") |
||||
endif () |
||||
|
||||
set(Specs --specs=nano.specs --specs=nosys.specs) |
||||
set(CFlags -std=${Cstandard} ${Optimisation} -fno-builtin-log) |
||||
set(CppFlags -ffunction-sections -fdata-sections -fno-common |
||||
-pedantic -Wall -Wextra |
||||
-Wno-unused-parameter -Wno-unused-variable |
||||
-fexec-charset=cp1252 |
||||
${Specs}) |
||||
set(CxxFlags -std=${CXXstandard} ${Optimisation} |
||||
-fno-exceptions -fno-rtti -fno-unwind-tables -Wno-register -fno-math-errno) |
||||
|
||||
# generator expressions have some quirky behaviour when multiple lists separated by spaces |
||||
# are directly used, to avoid it just concat all lists beforehand |
||||
set(c_lang_options ${MakeExport_MCU_Flags} ${CFlags} ${CppFlags}) |
||||
set(cpp_lang_options ${MakeExport_MCU_Flags} ${CxxFlags} ${CppFlags}) |
||||
set(asm_lang_options -x assembler-with-cpp ${MakeExport_MCU_Flags} ${CFlags} ${CppFlags}) |
||||
|
||||
# must come before any target has been defined or else options won't stick |
||||
# all targets must be built with the same compile options or bad things happen |
||||
add_compile_options( |
||||
"$<$<COMPILE_LANGUAGE:C>:${c_lang_options}>" |
||||
"$<$<COMPILE_LANGUAGE:CXX>:${cpp_lang_options}>" |
||||
"$<$<COMPILE_LANGUAGE:ASM>:${asm_lang_options}>" |
||||
) |
||||
add_definitions(${MakeExport_DEFS}) |
||||
|
||||
# -u _printf_float removes a bunch of dependencies on various |
||||
# internal libc functions. Adding nosys specs would achieve the same thing |
||||
add_link_options(${Specs} |
||||
--static |
||||
-Wl,--gc-sections |
||||
-Wl,--print-memory-usage |
||||
-Wl,-Map=${firmwareName}.map |
||||
-u _printf_float |
||||
-Wl,--start-group -lc_nano -lgcc -lnosys -Wl,--end-group |
||||
-T${CMAKE_CURRENT_SOURCE_DIR}/${MakeExport_LDSCRIPT} |
||||
${MakeExport_MCU_Flags}) |
||||
endfunction() |
@ -0,0 +1,39 @@
|
||||
include_guard(GLOBAL) |
||||
cmake_minimum_required(VERSION 3.17) |
||||
|
||||
# Adds generation of .bin and .list files |
||||
# Makes target generate as an .elf file |
||||
# Invokes static library analyzer see core issue #3 |
||||
# assumes CMAKE_OBJCOPY, CMAKE_OBJDUMP is correctly setup globally |
||||
|
||||
# TargetName: your target from add_executable |
||||
|
||||
function(SETUP_EXTRA_FILE_GENERATION TargetName) |
||||
# make it so firmware generates with .elf file ending |
||||
set_target_properties( |
||||
${TargetName} |
||||
PROPERTIES |
||||
OUTPUT_NAME ${TargetName} |
||||
SUFFIX ".elf" |
||||
) |
||||
|
||||
add_custom_command( |
||||
TARGET ${TargetName} |
||||
POST_BUILD |
||||
COMMAND ${CMAKE_OBJCOPY} ARGS -O ihex ${CMAKE_BINARY_DIR}/${TargetName}.elf ${CMAKE_BINARY_DIR}/${TargetName}.bin |
||||
BYPRODUCTS ${CMAKE_BINARY_DIR}/${TargetName}.bin |
||||
) |
||||
|
||||
add_custom_command( |
||||
TARGET ${TargetName} |
||||
POST_BUILD |
||||
COMMAND ${CMAKE_OBJDUMP} ARGS -S ${CMAKE_BINARY_DIR}/${TargetName}.elf > ${CMAKE_BINARY_DIR}/${TargetName}.list |
||||
BYPRODUCTS ${CMAKE_BINARY_DIR}/${TargetName}.list |
||||
) |
||||
|
||||
add_custom_command( |
||||
TARGET ${TargetName} |
||||
POST_BUILD |
||||
COMMAND ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../scripts/checkStaticLibraries.py ARGS ${CMAKE_BINARY_DIR} |
||||
) |
||||
endfunction() |
@ -0,0 +1,61 @@
|
||||
#pragma once |
||||
#include "core/BuildConfigurationTypes.h" |
||||
|
||||
namespace core |
||||
{ |
||||
/**
|
||||
* @brief Provides constexpr bools for usage in a bit more macro-free code |
||||
* Using the bools and if constexpr () is a more modern way of splitting |
||||
* code paths between the different builds. |
||||
* Macros are provided via compiler -D command. |
||||
* Multiple definitions are caught at compile time. |
||||
* |
||||
*/ |
||||
struct BuildConfiguration |
||||
{ |
||||
#if IS_EMBEDDED_BUILD() |
||||
static constexpr bool IsEmbeddedBuild = true; |
||||
#else |
||||
static constexpr bool IsEmbeddedBuild = false; |
||||
#endif |
||||
|
||||
#if IS_TESTING_BUILD() |
||||
static constexpr bool IsTestingBuild = true; |
||||
#else |
||||
static constexpr bool IsTestingBuild = false; |
||||
#endif |
||||
|
||||
#if IS_FUZZING_BUILD() |
||||
static constexpr bool IsFuzzingBuild = true; |
||||
#else |
||||
static constexpr bool IsFuzzingBuild = false; |
||||
#endif |
||||
|
||||
#if IS_EMULATOR_BUILD() |
||||
static constexpr bool IsEmulatorBuild = true; |
||||
#else |
||||
static constexpr bool IsEmulatorBuild = false; |
||||
#endif |
||||
|
||||
#if defined(BUILDCONFIG_DEBUG) |
||||
static constexpr bool IsDebugBuild = true; |
||||
#else |
||||
static constexpr bool IsDebugBuild = false; |
||||
#endif |
||||
|
||||
#if defined(BUILDCONFIG_RELEASE) |
||||
static constexpr bool IsReleaseBuild = true; |
||||
#else |
||||
static constexpr bool IsReleaseBuild = false; |
||||
#endif |
||||
|
||||
static constexpr void checkBuild() |
||||
{ |
||||
// sanity checks for macros
|
||||
static_assert(((IsEmbeddedBuild ? 1 : 0) + (IsTestingBuild ? 1 : 0) + |
||||
(IsFuzzingBuild ? 1 : 0) + (IsEmulatorBuild ? 1 : 0)) == 1); |
||||
static_assert(((IsDebugBuild ? 1 : 0) + (IsReleaseBuild ? 1 : 0)) == 1); |
||||
} |
||||
}; |
||||
|
||||
} // namespace core
|
@ -0,0 +1,24 @@
|
||||
#pragma once |
||||
|
||||
#define BUILDTYPE_EMBEDDED 2 |
||||
#define BUILDTYPE_TESTING 3 |
||||
#define BUILDTYPE_FUZZING 4 |
||||
#define BUILDTYPE_EMULATOR 5 |
||||
|
||||
#ifndef BUILDTYPE |
||||
#error "BUILDTYPE not defined" |
||||
#endif |
||||
|
||||
#if !((BUILDTYPE == BUILDTYPE_EMBEDDED) || (BUILDTYPE == BUILDTYPE_TESTING) || \ |
||||
(BUILDTYPE == BUILDTYPE_FUZZING) || (BUILDTYPE == BUILDTYPE_EMULATOR)) |
||||
#error "Unknown BUILDTYPE" |
||||
#endif |
||||
|
||||
// please don't use BUILDTYPE == ... by yourself but rather the following macros
|
||||
// the preprocessor doesn't consider a missing BUILDTYPE in a comparison about BUILDTYPE an
|
||||
// error..... so when you can use the following functions, you can be sure that BUILDTYPE existance
|
||||
// and validity is checked
|
||||
#define IS_EMBEDDED_BUILD() (BUILDTYPE == BUILDTYPE_EMBEDDED) |
||||
#define IS_TESTING_BUILD() (BUILDTYPE == BUILDTYPE_TESTING) |
||||
#define IS_FUZZING_BUILD() (BUILDTYPE == BUILDTYPE_FUZZING) |
||||
#define IS_EMULATOR_BUILD() (BUILDTYPE == BUILDTYPE_EMULATOR) |
@ -0,0 +1,38 @@
|
||||
#pragma once |
||||
#include "BuildConfigurationTypes.h" |
||||
#include <stdbool.h> // NOLINT |
||||
|
||||
/**
|
||||
* @brief Build configuration independant assert |
||||
* |
||||
*/ |
||||
|
||||
/**
|
||||
* @brief Asserts the given condition, aborts programm if false |
||||
* When compiled for embedded, disables interrupts and enters endless loop |
||||
* locking up the scheduler until the watchdog resets the device. |
||||
* Throws std::runtime_exception in testing and fuzzing builds |
||||
* |
||||
* May be used in C or C++ Code. |
||||
* @param condition |
||||
*/ |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" |
||||
{ |
||||
#endif |
||||
|
||||
void SafeAssert_Aux(bool condition, int line, const char *file); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#if !IS_EMBEDDED_BUILD() |
||||
#define SafeAssert(cond) SafeAssert_Aux(cond, __LINE__, __FILE__) // NOLINT
|
||||
#else |
||||
// avoids compiling in a bunch of path strings for embedded
|
||||
#define SafeAssert(cond) SafeAssert_Aux(cond, 0, "NOVAL") // NOLINT
|
||||
#endif |
||||
|
||||
#define UAVCAN_ASSERT(cond) SafeAssert(cond) |
@ -0,0 +1,82 @@
|
||||
#pragma once |
||||
|
||||
#include "BuildConfiguration.hpp" |
||||
#include "core/Version.h" // generated |
||||
#include <cstdint> |
||||
|
||||
namespace core |
||||
{ |
||||
struct BuildInformationTestingValues |
||||
{ |
||||
static constexpr uint32_t CommitHashShort = 42424242; |
||||
static constexpr bool IsDirty = true; |
||||
static constexpr bool IsDebugBuild = false; |
||||
static constexpr char BuildTime[] = "testing_value_time"; |
||||
static constexpr char CommitHashLong[] = "testing_value_commit"; |
||||
static constexpr char BranchName[] = "testing_value_brach"; |
||||
}; |
||||
|
||||
class BuildInformationHelper |
||||
{ |
||||
public: |
||||
static constexpr uint32_t getCommitHashShort() |
||||
{ |
||||
if constexpr (BuildConfiguration::isEmbeddedBuild) |
||||
{ |
||||
return BUILD_INFO_COMMIT_SHORT; |
||||
} |
||||
if constexpr (BuildConfiguration::isTestingBuild || BuildConfiguration::isFuzzingBuild) |
||||
{ |
||||
return BuildInformationTestingValues::CommitHashShort; |
||||
} |
||||
} |
||||
|
||||
static constexpr bool getIsDirty() |
||||
{ |
||||
if constexpr (BuildConfiguration::isEmbeddedBuild) |
||||
{ |
||||
return BUILD_INFO_IS_DIRTY > 0; |
||||
} |
||||
if constexpr (BuildConfiguration::isTestingBuild || BuildConfiguration::isFuzzingBuild) |
||||
{ |
||||
return BuildInformationTestingValues::IsDirty; |
||||
} |
||||
} |
||||
|
||||
// string literals can't easily be used as template parameters
|
||||
// so secondary step is neccessary
|
||||
static constexpr const char MacroBuildTime[] = BUILD_INFO_TIME; |
||||
static constexpr const char MacroCommitHashLong[] = BUILD_INFO_COMMIT_LONG; |
||||
static constexpr const char MacroBranchName[] = BUILD_INFO_BRANCH; |
||||
|
||||
template <const char *MacroValue, const char *FixedValue> |
||||
static constexpr const char *get() |
||||
{ |
||||
if constexpr (BuildConfiguration::isEmbeddedBuild) |
||||
{ |
||||
return MacroValue; |
||||
} |
||||
if constexpr (BuildConfiguration::isTestingBuild || BuildConfiguration::isFuzzingBuild) |
||||
{ |
||||
return FixedValue; |
||||
} |
||||
} |
||||
}; |
||||
|
||||
class BuildInformation |
||||
{ |
||||
public: |
||||
static constexpr uint32_t CommitHashShort = BuildInformationHelper::getCommitHashShort(); |
||||
static constexpr bool IsDirty = BuildInformationHelper::getIsDirty(); |
||||
static constexpr bool IsDebugBuild = BuildConfiguration::isDebugBuild; |
||||
static constexpr const char *BuildTime = |
||||
BuildInformationHelper::get<BuildInformationHelper::MacroBuildTime, |
||||
BuildInformationTestingValues::BuildTime>(); |
||||
static constexpr const char *CommitHashLong = |
||||
BuildInformationHelper::get<BuildInformationHelper::MacroCommitHashLong, |
||||
BuildInformationTestingValues::CommitHashLong>(); |
||||
static constexpr const char *BranchName = |
||||
BuildInformationHelper::get<BuildInformationHelper::MacroBranchName, |
||||
BuildInformationTestingValues::BranchName>(); |
||||
}; |
||||
} // namespace core
|
@ -0,0 +1,24 @@
|
||||
#pragma once |
||||
#include "core/BuildConfigurationTypes.h" |
||||
|
||||
/**
|
||||
* @brief Walks up the stack and looks for the last executed code's address. |
||||
* Used to retrieve from where the chip hardfaults. Do not use outside of |
||||
* crash handlers. __attribute__((naked)) is going to shoot you into the foot. |
||||
* |
||||
*/ |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" |
||||
{ |
||||
#endif |
||||
|
||||
#if IS_EMBEDDED_BUILD() |
||||
void faultHandler(void) __attribute__((naked)); |
||||
#else |
||||
void faultHandler(void); |
||||
#endif |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
@ -0,0 +1,14 @@
|
||||
#pragma once |
||||
|
||||
#include <cstdint> |
||||
|
||||
namespace core::hash |
||||
{ |
||||
static constexpr uint64_t HASH_SEED = 0xcbf29ce484222325; |
||||
static constexpr uint64_t MagicPrime = 0x00000100000001b3; |
||||
|
||||
uint64_t fnvWithSeed(uint64_t hash, const uint8_t *data, const uint8_t *const dataEnd); |
||||
|
||||
static constexpr uint64_t FirmwareHashTestingValue{0xDEADBEEFC0FFEE}; |
||||
uint64_t computeFirmwareHash(); |
||||
} // namespace bus_node_base
|
@ -0,0 +1,6 @@
|
||||
export: |
||||
@printf 'MakeExport_SOURCES $(C_SOURCES) $(ASM_SOURCES)\n'
|
||||
@printf 'MakeExport_MCU_Flags $(MCU)\n'
|
||||
@printf 'MakeExport_DEFS $(AS_DEFS) $(C_DEFS)\n'
|
||||
@printf 'MakeExport_INCLUDES $(AS_INCLUDES) $(C_INCLUDES)\n'
|
||||
@printf 'MakeExport_LDSCRIPT $(LDSCRIPT)\n'
|
@ -1,36 +0,0 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2014 Frantisek Burian <BuFran@seznam.cz>
|
||||
##
|
||||
## This library is free software: you can redistribute it and/or modify
|
||||
## it under the terms of the GNU Lesser General Public License as published by
|
||||
## the Free Software Foundation, either version 3 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This library is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU Lesser General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU Lesser General Public License
|
||||
## along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
###############################################################################
|
||||
# The support makefile for GCC compiler toolchain, the rules part.
|
||||
#
|
||||
# please read mk/README for specification how to use this file in your project
|
||||
|
||||
|
||||
PREFIX ?= arm-none-eabi
|
||||
|
||||
CC := $(PREFIX)-gcc
|
||||
CXX := $(PREFIX)-g++
|
||||
LD := $(PREFIX)-gcc
|
||||
ar := $(PREFIX)-ar
|
||||
as := $(PREFIX)-as
|
||||
OBJCOPY := $(PREFIX)-objcopy
|
||||
OBJDUMP := $(PREFIX)-objdump
|
||||
GDB := $(PREFIX)-gdb
|
||||
SIZE := $(PREFIX)-size
|
@ -1,34 +0,0 @@
|
||||
ifeq ($(RELEASE),1) |
||||
CONFIGURATION := release
|
||||
RELEASE_OPT ?= 3
|
||||
OPTIMIZATION := -O$(RELEASE_OPT) -g
|
||||
else |
||||
CONFIGURATION := debug
|
||||
OPTIMIZATION := -Og -g
|
||||
DEFS += DEBUG
|
||||
endif |
||||
|
||||
ROOTDIR := $(dir $(firstword $(MAKEFILE_LIST)))
|
||||
BASEDIR := $(dir $(lastword $(MAKEFILE_LIST)))../
|
||||
MXDIR := $(ROOTDIR)cubemx/
|
||||
OUTPUT_DIR := $(ROOTDIR)build/$(CONFIGURATION)/
|
||||
OBJDIR := $(OUTPUT_DIR)/obj
|
||||
|
||||
INCDIRS += \
|
||||
$(BASEDIR)include \ |
||||
|
||||
SOURCES += \
|
||||
$(BASEDIR)src/abi.cpp \ |
||||
$(BASEDIR)src/std.cpp |
||||
|
||||
# CubeMX
|
||||
include cubemx/Makefile |
||||
|
||||
SOURCES += $(foreach source,$(C_SOURCES) $(ASM_SOURCES),$(MXDIR)$(source))
|
||||
INCDIRS += $(C_INCLUDES:-I%=$(MXDIR)%)
|
||||
INCDIRS += $(AS_INCLUDES:-I%=$(MXDIR)%)
|
||||
|
||||
LDSCRIPT := $(MXDIR)$(LDSCRIPT)
|
||||
|
||||
# Include actual rules
|
||||
include $(BASEDIR)mk/rules.mk |
@ -1,100 +0,0 @@
|
||||
STFLASH = $(shell which st-flash)
|
||||
JFLASH = $(shell which JLinkExe)
|
||||
|
||||
# Object files
|
||||
TMP1 := $(patsubst %.c, $(OBJDIR)/%.o, $(SOURCES))
|
||||
TMP2 := $(patsubst %.cpp, $(OBJDIR)/%.o, $(TMP1))
|
||||
TMP3 := $(patsubst %.cxx, $(OBJDIR)/%.o, $(TMP2))
|
||||
OBJS := $(patsubst %.s, $(OBJDIR)/%.o, $(TMP3))
|
||||
|
||||
BINARY := $(OUTPUT_DIR)$(TARGET)
|
||||
|
||||
# C/C++ standards
|
||||
CSTD ?= c11
|
||||
CXXSTD ?= c++17
|
||||
|
||||
# Compiler flags
|
||||
SPECS ?= --specs=nano.specs
|
||||
|
||||
CFLAGS += -std=$(CSTD) $(OPTIMIZATION) -fno-builtin-log
|
||||
|
||||
CPPFLAGS += -ffunction-sections -fdata-sections -fno-common
|
||||
CPPFLAGS += -pedantic -Wall -Wextra
|
||||
CPPFLAGS += -Wno-unused-parameter -Wno-unused-variable
|
||||
CPPFLAGS += -fexec-charset=cp1252
|
||||
CPPFLAGS += $(DEFS:%=-D%)
|
||||
CPPFLAGS += $(C_DEFS) $(AS_DEFS)
|
||||
CPPFLAGS += $(INCDIRS:%=-I%)
|
||||
CPPFLAGS += -MMD -MP -MF"$(@:%.o=%.d)"
|
||||
CPPFLAGS += $(SPECS)
|
||||
|
||||
CXXFLAGS += -std=$(CXXSTD) $(OPTIMIZATION)
|
||||
CXXFLAGS += -fno-exceptions -fno-rtti -fno-unwind-tables -Wno-register -fno-math-errno
|
||||
|
||||
# Linker flags
|
||||
LDFLAGS += $(SPECS)
|
||||
LDFLAGS += --static
|
||||
LDFLAGS += -Wl,--gc-sections
|
||||
LDFLAGS += -Wl,--print-memory-usage
|
||||
LDFLAGS += -Wl,-Map=$(BINARY).map
|
||||
LDLIBS += -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group
|
||||
|
||||
# Be silent per default, but 'make V=1' will show all compiler calls.
|
||||
ifneq ($(V),1) |
||||
Q := @
|
||||
endif |
||||
|
||||
# Toolchain stuff
|
||||
include $(BASEDIR)mk/gcc-config.mk |
||||
|
||||
# Rules
|
||||
.PHONY: clean all stflash jflash |
||||
.SECONDARY: |
||||
|
||||
all: $(BINARY).bin $(BINARY).list |
||||
|
||||
print-%: |
||||
@echo $*=$($*)
|
||||
|
||||
%.bin: %.elf |
||||
@printf " OBJCOPY $@\n"
|
||||
$(Q)$(OBJCOPY) -Obinary $< $@
|
||||
|
||||
%.list: %.elf |
||||
@printf " OBJDUMP $@\n"
|
||||
$(Q)$(OBJDUMP) -S $< > $@
|
||||
|
||||
%.elf: $(OBJS) $(LIBDEPS) |
||||
@printf " LD $@\n"
|
||||
$(Q)$(LD) $(OBJS) $(LDLIBS) $(LDFLAGS) -T$(LDSCRIPT) $(MCU) -o $@
|
||||
|
||||
$(OBJDIR)/%.o: %.s |
||||
@printf " AS $<\n"
|
||||
@mkdir -p $(dir $@)
|
||||
$(Q)$(CC) -x assembler-with-cpp $(CFLAGS) $(CPPFLAGS) $(MCU) -c $< -o $@
|
||||
|
||||
$(OBJDIR)/%.o: %.c |
||||
@printf " CC $<\n"
|
||||
@mkdir -p $(dir $@)
|
||||
$(Q)$(CC) $(CFLAGS) $(CPPFLAGS) $(MCU) -c $< -o $@
|
||||
|
||||
$(OBJDIR)/%.o: %.cpp |
||||
@printf " CXX $<\n"
|
||||
@mkdir -p $(dir $@)
|
||||
$(Q)$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(MCU) -c $< -o $@
|
||||
|
||||
$(OBJDIR)/%.o: %.cxx |
||||
@printf " CXX $<\n"
|
||||
@mkdir -p $(dir $@)
|
||||
$(Q)$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(MCU) -c $< -o $@
|
||||
|
||||
clean: |
||||
@$(RM) -Rf build dsdlc_generated
|
||||
|
||||
stflash:$(BINARY).bin |
||||
$(STFLASH) $(FLASHSIZE) write $(BINARY).bin 0x8000000
|
||||
|
||||
jflash: $(BINARY).bin |
||||
$(JFLASH) -Autoconnect 1 -Device $(DEVICE) -If SWD -Speed 4000 -CommandFile flash_commands.jlink
|
||||
|
||||
-include $(OBJS:.o=.d) |
@ -0,0 +1,75 @@
|
||||
#!/usr/bin/python3 |
||||
from subprocess import Popen, PIPE |
||||
import re |
||||
import glob |
||||
import os |
||||
import sys |
||||
|
||||
def removeNoneAcii(str): |
||||
return ''.join([i if ord(i) < 128 else ' ' for i in str]) |
||||
|
||||
def analyzeAndCheckStaticLib(filepath): |
||||
# start nm and let it retrieve the names of all symbols |
||||
process = Popen(["nm", filepath], stdout=PIPE) |
||||
(output, err) = process.communicate() |
||||
exit_code = process.wait() |
||||
if exit_code != 0: |
||||
print("error calling nm command") |
||||
exit(1) |
||||
|
||||
output = removeNoneAcii(str(output)) |
||||
entries = output.split(sep="\\n") |
||||
|
||||
# extract letter (type) and function name from entries |
||||
# e.g. '00000001 T Error_Handler' first match is T, second one is Error_Handler |
||||
# all undefined functions without number are not matched and don't matter |
||||
# entry names starting with $ also dont matter |
||||
extracted = [] |
||||
for e in entries: |
||||
res = re.findall(r"\d+?\s(\w)\s([\w\d_]+)\b", e) |
||||
if len(res) == 1: |
||||
type = res[0][0] |
||||
name = res[0][1] |
||||
extracted.append({'type': type, 'name': name}) |
||||
# else: |
||||
# print(e) |
||||
|
||||
# extract all duplicate symbols and their type |
||||
duplicates = {} |
||||
for i in extracted: |
||||
for j in extracted: |
||||
if i is j: |
||||
continue |
||||
if i['name'] == j['name']: |
||||
if not i['name'] in duplicates: |
||||
duplicates[i['name']] = set() |
||||
duplicates[i['name']].add(str(i['type']).lower()) |
||||
duplicates[i['name']].add(str(j['type']).lower()) |
||||
|
||||
|
||||
foundDuplicatesWithDifferentTypes = False |
||||
for e in duplicates: |
||||
if len(duplicates[e]) > 1: |
||||
if not foundDuplicatesWithDifferentTypes: |
||||
print("Analyzing: " + str(os.path.basename(filepath))) |
||||
print("Symbol " + str(e) + "is defined multiple times with types: " + str(duplicates[e])) |
||||
foundDuplicatesWithDifferentTypes = True |
||||
|
||||
if foundDuplicatesWithDifferentTypes: |
||||
print("-------------------\n" |
||||
"The Linker will not necessarily select the appropriate function from a static library " |
||||
"without you defining --whole-archive.\nAs CMake doesn't have a convenient way of doing this. Please " |
||||
"change your library type from STATIC to OBJECT so you don't bugs due to wrongly linked applications. " |
||||
"See core issue #3.\n" |
||||
"-----------------") |
||||
exit(1) |
||||
|
||||
if __name__ == "__main__": |
||||
if len(sys.argv) != 2: |
||||
raise "not enough parameters" |
||||
|
||||
path = sys.argv[1] |
||||
text_files = glob.glob(path + "/**/*.a", recursive=True) |
||||
for file in text_files: |
||||
analyzeAndCheckStaticLib(file) |
||||
print("Checked " + str(len(text_files)) + " static libraries, all ok.") |
@ -0,0 +1,60 @@
|
||||
#!/usr/bin/python3 |
||||
import sys |
||||
import datetime |
||||
import git # pip3 install gitpython |
||||
|
||||
if len(sys.argv) != 3: |
||||
raise "not enough parameters" |
||||
|
||||
repoPath = sys.argv[1] |
||||
versionHeaderPath = sys.argv[2] |
||||
|
||||
repo = git.Repo(repoPath, search_parent_directories=True) |
||||
|
||||
#if len(repo.submodules) == 0: |
||||
# print("Tested git repository has no submodules, path is not pointing to the main repository") |
||||
# exit(1) |
||||
|
||||
commitHashLong = str(repo.head.object.hexsha) |
||||
commitHashShort = commitHashLong[:8] |
||||
isDirty = repo.is_dirty() |
||||
branch = "detached_head" |
||||
try: |
||||
branch = repo.active_branch.name |
||||
except: |
||||
print("git repository is in detached head state") |
||||
|
||||
# build time in 15 minute intervals to avoid new compilation every time |
||||
now = datetime.datetime.now() |
||||
currentTime = "%d-%02d-%02dT%02d:%02d:00" % (now.year, now.month, now.day, now.hour, now.minute - now.minute % 15) |
||||
|
||||
|
||||
fileContent = '#define BUILD_INFO_COMMIT_SHORT 0x' + commitHashShort + '\n' |
||||
if isDirty: |
||||
fileContent += '#define BUILD_INFO_IS_DIRTY true\n' |
||||
else: |
||||
fileContent += '#define BUILD_INFO_IS_DIRTY false\n' |
||||
fileContent += '#define BUILD_INFO_TIME "' + currentTime + '"\n' |
||||
fileContent += '#define BUILD_INFO_COMMIT_LONG "' + commitHashLong + '"\n' |
||||
fileContent += '#define BUILD_INFO_BRANCH "' + branch + '"\n' |
||||
|
||||
# read back file and compare, don't overwrite if nothing changes |
||||
# due to time being included, something always changes but in case |
||||
# this goes away, we can save some compile runs |
||||
doRegen = True |
||||
try: |
||||
with open(versionHeaderPath, mode='r') as oldFile: |
||||
content = oldFile.read() |
||||
if content == fileContent: |
||||
print("No change detected") |
||||
doRegen = False |
||||
else: |
||||
print("Version info changed") |
||||
except: |
||||
print("Old file not found") |
||||
|
||||
if doRegen: |
||||
with open(versionHeaderPath, mode='w+') as newFile: |
||||
newFile.write(fileContent) |
||||
print("Regenerated") |
||||
exit(0) |
@ -0,0 +1,34 @@
|
||||
#include "core/SafeAssert.h" |
||||
#include "core/BuildConfiguration.hpp" |
||||
|
||||
#if IS_EMBEDDED_BUILD() |
||||
#include <FreeRTOS.h> |
||||
#include <task.h> |
||||
void SafeAssert_Aux(bool condition, int line, const char *file) |
||||
{ |
||||
if (!condition) |
||||
{ |
||||
taskDISABLE_INTERRUPTS(); |
||||
if constexpr (core::BuildConfiguration::IsDebugBuild) |
||||
{ |
||||
__asm("bkpt"); |
||||
} |
||||
for (;;) |
||||
{ |
||||
} |
||||
} |
||||
} |
||||
#else |
||||
#include <sstream> |
||||
#include <stdexcept> |
||||
|
||||
void SafeAssert_Aux(bool condition, int line, const char *file) |
||||
{ |
||||
if (!condition) |
||||
{ |
||||
std::stringstream ss; |
||||
ss << "Assertion Failed " << file << ":" << line; |
||||
throw std::runtime_error(ss.str()); |
||||
} |
||||
} |
||||
#endif |
@ -0,0 +1,76 @@
|
||||
#include "core/fault_handler.h" |
||||
#include "core/BuildConfiguration.hpp" |
||||
#include <stdint.h> |
||||
|
||||
#if IS_EMBEDDED_BUILD() |
||||
|
||||
/* The fault handler implementation calls a function called
|
||||
prvGetRegistersFromStack(). */ |
||||
void __attribute__((aligned(4))) faultHandler(void) |
||||
{ |
||||
__asm volatile(" mrs r0, msp \n" |
||||
" mov r1, lr \n" |
||||
" mov r2, #4 \n" |
||||
" tst r1, r2 \n" |
||||
" beq prvGetRegistersFromStack \n" |
||||
" mrs r0, psp \n" |
||||