mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
In cmakev1, the initial order of components linked to the executable is determined by the `__build_expand_requirements` function and stored as a list in the `BUILD_COMPONENT_ALIASES` build property. Later, the components from `BUILD_COMPONENT_ALIASES` are linked to the executable using `target_link_libraries`. The issue is that `BUILD_COMPONENT_ALIASES` contains components in a "reversed" order compared to how they would typically appear on the link command line. In other words, components (archives) deeper in the dependency chain are placed first. As a result, cmake has to repeat the archives in the link command more times than is actually necessary. This has the beneficial side effect of placing libfreertos.a before libmain.a, allowing the `app_main` symbol to be resolved. In cmakev2, there is no predefined order because it does not perform early evaluation. Instead, the entire link command is created based on actual component dependencies using `target_link_libraries`. Consequently, freertos must set the `app_main` symbols as undefined. This is already done for non-Linux targets, but it must also be done for the Linux target. Another issue arises with macOS, which mangles C symbols by prepending an underscore. We cannot use the same method as in `components/linux/assert_func.c` for `__assert_func`, so for macOS, `_app_main` is used. In the future, if more undefined symbols need to be added for the Linux target, we should consider introducing a helper. Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
262 lines
9.3 KiB
CMake
262 lines
9.3 KiB
CMake
# FreeRTOS Component Architecture
|
|
#
|
|
# The FreeRTOS component mainly contains
|
|
# - Different FreeRTOS kernel implementations (namely IDF FreeRTOS and Amazon SMP FreeRTOS).
|
|
# - Different ports of each architecture for each kernel implementation.
|
|
# - IDF additions to FreeRTOS (e.g., features and API) to augment FreeRTOS
|
|
#
|
|
# The FreeRTOS component organizes its files as follows
|
|
#
|
|
# - `./config`
|
|
# - Contains all "FreeRTOSConfig.h" files required by FreeRTOS
|
|
# - `./esp_additions`
|
|
# - Additional features added by ESP-IDF to augment FreeRTOS, and not part of the original kernel
|
|
# - `./FreeRTOS-Kernel-...`
|
|
# - Different FreeRTOS kernel implementations. Each implementation is kept in its own directory.
|
|
# - Ports for the implementation are kept in `FreeRTOS-Kernel-.../portable/xxx/`\
|
|
# - `./test_apps`
|
|
# - Contains all unit tests/test apps for the FreeRTOS component.
|
|
# - `./`
|
|
# - Files common across all kernel implementations and all ports
|
|
|
|
# Bootloader builds only needs FreeRTOS for config, not for anything else
|
|
idf_build_get_property(non_os_build NON_OS_BUILD)
|
|
|
|
if(non_os_build)
|
|
idf_component_register()
|
|
return()
|
|
endif()
|
|
|
|
# Set some convenience variables
|
|
idf_build_get_property(target IDF_TARGET)
|
|
|
|
if(CONFIG_FREERTOS_SMP)
|
|
set(kernel_impl "FreeRTOS-Kernel-SMP")
|
|
else()
|
|
set(kernel_impl "FreeRTOS-Kernel")
|
|
endif()
|
|
|
|
if(CONFIG_IDF_TARGET_ARCH_XTENSA)
|
|
set(arch "xtensa")
|
|
elseif(CONFIG_IDF_TARGET_ARCH_RISCV)
|
|
set(arch "riscv")
|
|
elseif(${target} STREQUAL "linux")
|
|
set(arch "linux")
|
|
endif()
|
|
|
|
set(srcs "")
|
|
set(include_dirs "")
|
|
set(private_include_dirs "")
|
|
set(private_requirements "")
|
|
set(ldfragments "")
|
|
|
|
# ---------------------------------------------------- Set Sources -----------------------------------------------------
|
|
|
|
# Add common source files
|
|
list(APPEND srcs
|
|
"heap_idf.c")
|
|
|
|
if((arch STREQUAL "xtensa") OR (arch STREQUAL "riscv"))
|
|
list(APPEND srcs
|
|
"app_startup.c"
|
|
"port_common.c"
|
|
"port_systick.c")
|
|
endif()
|
|
|
|
# Add FreeRTOS Kernel source files
|
|
list(APPEND srcs
|
|
"${kernel_impl}/list.c"
|
|
"${kernel_impl}/queue.c"
|
|
"${kernel_impl}/tasks.c"
|
|
"${kernel_impl}/timers.c"
|
|
"${kernel_impl}/event_groups.c"
|
|
"${kernel_impl}/stream_buffer.c")
|
|
|
|
# Add port source files
|
|
list(APPEND srcs
|
|
"${kernel_impl}/portable/${arch}/port.c")
|
|
|
|
if(arch STREQUAL "linux")
|
|
list(APPEND srcs
|
|
"${kernel_impl}/portable/${arch}/utils/wait_for_event.c")
|
|
if(kernel_impl STREQUAL "FreeRTOS-Kernel")
|
|
list(APPEND srcs
|
|
"${kernel_impl}/portable/${arch}/port_idf.c")
|
|
endif()
|
|
else()
|
|
list(APPEND srcs
|
|
"${kernel_impl}/portable/${arch}/portasm.S")
|
|
endif()
|
|
|
|
if(arch STREQUAL "xtensa")
|
|
list(APPEND srcs
|
|
"${kernel_impl}/portable/${arch}/xtensa_init.c"
|
|
"${kernel_impl}/portable/${arch}/xtensa_overlay_os_hook.c")
|
|
endif()
|
|
|
|
# Add ESP-additions source files
|
|
list(APPEND srcs
|
|
"esp_additions/idf_additions_event_groups.c"
|
|
"esp_additions/idf_additions.c")
|
|
|
|
if(arch STREQUAL "linux")
|
|
# Check if we need to address the FreeRTOS EINTR coexistence with linux system calls if we're building without
|
|
# lwIP enabled, we need to use linux system select which will receive EINTR event on every FreeRTOS interrupt, we
|
|
# workaround this problem by wrapping select() to bypass and silence the EINTR events
|
|
set(BYPASS_EINTR_ISSUE 0)
|
|
if(NOT CONFIG_LWIP_ENABLE)
|
|
set(BYPASS_EINTR_ISSUE 1)
|
|
list(APPEND srcs "esp_additions/FreeRTOSSimulator_wrappers.c")
|
|
endif()
|
|
endif()
|
|
|
|
# ------------------------------------------------ Set Public Includes -------------------------------------------------
|
|
|
|
# Add common public include directories
|
|
list(APPEND include_dirs
|
|
"config/include" # For `#include "freertos/FreeRTOSConfig.h"`
|
|
"config/include/freertos" # For `#include "FreeRTOSConfig.h"`
|
|
"config/${arch}/include") # For `#include "freertos/FreeRTOSConfig_arch.h"`
|
|
|
|
# Add FreeRTOS Kernel public include directories
|
|
list(APPEND include_dirs
|
|
"${kernel_impl}/include") # FreeRTOS headers via `#include "freertos/xxx.h"`
|
|
|
|
# Add port public include directories
|
|
list(APPEND include_dirs
|
|
"${kernel_impl}/portable/${arch}/include" # For port headers via `#include "freertos/...h"`
|
|
"${kernel_impl}/portable/${arch}/include/freertos") # For port headers via `#include "...h"`
|
|
|
|
# Add ESP-additions public include directories
|
|
list(APPEND include_dirs
|
|
"esp_additions/include") # For ESP-addition headers via
|
|
# - `#include "freertos/...h"`
|
|
# - `#include "esp_private/...h"`
|
|
|
|
# ----------------------------------------------- Set Private Includes -------------------------------------------------
|
|
|
|
# Add common private include directories
|
|
if((arch STREQUAL "xtensa") OR (arch STREQUAL "riscv"))
|
|
list(APPEND private_include_dirs
|
|
".") # For `#include "port_systick.h"
|
|
endif()
|
|
|
|
# Add FreeRTOS Kernel private include directories
|
|
list(APPEND private_include_dirs
|
|
"${kernel_impl}/include/freertos") # FreeRTOS headers via `#include "xxx.h"`
|
|
|
|
# Add port private include directories
|
|
if(arch STREQUAL "linux")
|
|
list(APPEND private_include_dirs
|
|
"${kernel_impl}/portable/${arch}/") # Linux port `#include "utils/wait_for_event.h"`
|
|
endif()
|
|
|
|
# Add ESP-additions private include directories
|
|
list(APPEND private_include_dirs
|
|
"esp_additions") # For `include "freertos_tasks_c_additions.h"`
|
|
|
|
# ------------------------------------------------------- Misc ---------------------------------------------------------
|
|
|
|
# Add linker fragments
|
|
list(APPEND ldfragments
|
|
"linker_common.lf")
|
|
|
|
if((arch STREQUAL "xtensa") OR (arch STREQUAL "riscv"))
|
|
if(kernel_impl STREQUAL "FreeRTOS-Kernel-SMP")
|
|
list(APPEND ldfragments
|
|
"linker_smp.lf")
|
|
else()
|
|
list(APPEND ldfragments
|
|
"linker.lf")
|
|
endif()
|
|
endif()
|
|
|
|
# ------------------------------------------------ Register Component --------------------------------------------------
|
|
|
|
idf_component_register(SRCS ${srcs}
|
|
INCLUDE_DIRS ${include_dirs}
|
|
PRIV_INCLUDE_DIRS ${private_include_dirs}
|
|
LDFRAGMENTS ${ldfragments}
|
|
PRIV_REQUIRES ${private_requirements})
|
|
|
|
if(arch STREQUAL "linux")
|
|
target_compile_definitions(${COMPONENT_LIB} PUBLIC "projCOVERAGE_TEST=0")
|
|
target_link_libraries(${COMPONENT_LIB} PUBLIC pthread)
|
|
if(BYPASS_EINTR_ISSUE)
|
|
target_link_libraries(${COMPONENT_LIB} PRIVATE dl)
|
|
endif()
|
|
|
|
# Disable strict prototype warnings in upstream code
|
|
# (struct event * event_create() is missing 'void')
|
|
set_source_files_properties(
|
|
"${kernel_impl}/portable/${arch}/utils/wait_for_event.c"
|
|
PROPERTIES COMPILE_OPTIONS
|
|
"-Wno-strict-prototypes"
|
|
)
|
|
if(APPLE)
|
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u _app_main")
|
|
else()
|
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u app_main")
|
|
endif()
|
|
else()
|
|
idf_component_get_property(COMPONENT_DIR freertos COMPONENT_DIR)
|
|
|
|
idf_component_set_property(freertos ORIG_INCLUDE_PATH "${COMPONENT_DIR}/${kernel_impl}/include/freertos/")
|
|
|
|
if(CONFIG_FREERTOS_DEBUG_OCDAWARE)
|
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--undefined=FreeRTOS_openocd_params")
|
|
endif()
|
|
|
|
set_source_files_properties(
|
|
tasks.c
|
|
event_groups.c
|
|
timers.c
|
|
queue.c
|
|
stream_buffer.c
|
|
PROPERTIES COMPILE_DEFINITIONS
|
|
_ESP_FREERTOS_INTERNAL
|
|
)
|
|
|
|
# The freertos component provides the `start_app` and `start_app_other_cores`
|
|
# if it is included in the build. It then calls `app_main`
|
|
# from the main task created, which must be provided by the user.
|
|
# Like for `start_app` and `start_app_other_cores`,
|
|
# we can't establish dependency on what we don't yet know, so we force the
|
|
# linker to not drop this symbol.
|
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u app_main")
|
|
|
|
if(CONFIG_ESP_TRACE_ENABLE)
|
|
idf_component_optional_requires(PUBLIC esp_trace)
|
|
endif()
|
|
|
|
if(CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME)
|
|
# [refactor-todo]: app_startup.c esp_startup_start_app_other_cores() calls esp_gdbstub_init() (called on CPU0).
|
|
# This should be resolved when link-time registration of startup functions is added.
|
|
idf_component_optional_requires(PRIVATE esp_gdbstub)
|
|
endif()
|
|
|
|
if(CONFIG_FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER)
|
|
# [refactor-todo]: esp_timer is required by FreeRTOS when we use esp_timer_get_time() to do profiling
|
|
# Introduce a port wrapper function to avoid including esp_timer.h into the public header
|
|
idf_component_optional_requires(PUBLIC esp_timer)
|
|
endif()
|
|
|
|
if(CONFIG_SPIRAM)
|
|
idf_component_optional_requires(PRIVATE esp_psram)
|
|
endif()
|
|
|
|
if(CONFIG_PM_TRACE)
|
|
# esp_pm is required by port_systick.c for tracing
|
|
idf_component_optional_requires(PRIVATE esp_pm)
|
|
endif()
|
|
|
|
if(NOT CONFIG_FREERTOS_SMP AND
|
|
CONFIG_COMPILER_STATIC_ANALYZER AND CMAKE_C_COMPILER_ID STREQUAL "GNU") # suppress false-positive warning
|
|
set_source_files_properties(
|
|
"${kernel_impl}/queue.c"
|
|
PROPERTIES COMPILE_OPTIONS
|
|
"-Wno-analyzer-null-argument"
|
|
)
|
|
endif()
|
|
endif()
|