mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
Merge branch 'feat/cmakev2_ulp_full_subproject' into 'master'
feat(ulp): initial support for building ULP projects as full subprojects under CMake v2 See merge request espressif/esp-idf!50134
This commit is contained in:
@@ -1,12 +1,18 @@
|
|||||||
idf_build_get_property(target IDF_TARGET)
|
idf_build_get_property(target IDF_TARGET)
|
||||||
|
|
||||||
if(${target} STREQUAL "linux")
|
# TODO(IDF-15945): potentially remove __ULP_BUILD handling from esp_common
|
||||||
|
if(${target} STREQUAL "linux" OR __ULP_BUILD)
|
||||||
|
# ULP sources include esp_err.h from components/ulp public and shared headers.
|
||||||
set(ldfragments)
|
set(ldfragments)
|
||||||
else()
|
else()
|
||||||
set(ldfragments common.lf soc.lf linker.lf)
|
set(ldfragments common.lf soc.lf linker.lf)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(srcs)
|
||||||
|
|
||||||
|
if(NOT __ULP_BUILD)
|
||||||
set(srcs "src/esp_err_to_name.c")
|
set(srcs "src/esp_err_to_name.c")
|
||||||
|
endif()
|
||||||
|
|
||||||
idf_component_register(SRCS "${srcs}"
|
idf_component_register(SRCS "${srcs}"
|
||||||
INCLUDE_DIRS include
|
INCLUDE_DIRS include
|
||||||
|
|||||||
@@ -2,6 +2,24 @@ idf_build_get_property(target IDF_TARGET)
|
|||||||
|
|
||||||
set(srcs)
|
set(srcs)
|
||||||
set(public_include "include")
|
set(public_include "include")
|
||||||
|
|
||||||
|
# TODO(IDF-15946): potentially remove __ULP_BUILD handling from esp_driver_uart
|
||||||
|
if(__ULP_BUILD)
|
||||||
|
# LP-core UART wakeup shared code includes driver/uart_wakeup.h from
|
||||||
|
# ulp/lp_core/shared/include/ulp_lp_core_lp_uart_shared.h.
|
||||||
|
set(ulp_srcs)
|
||||||
|
if(ULP_TYPE STREQUAL "lp_core" AND
|
||||||
|
CONFIG_SOC_UART_SUPPORTED AND
|
||||||
|
(CONFIG_SOC_DEEP_SLEEP_SUPPORTED OR CONFIG_SOC_LIGHT_SLEEP_SUPPORTED))
|
||||||
|
list(APPEND ulp_srcs "src/uart_wakeup.c")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
idf_component_register(SRCS ${ulp_srcs}
|
||||||
|
INCLUDE_DIRS ${public_include}
|
||||||
|
REQUIRES esp_common esp_hal_uart esp_hw_support log soc)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
if(CONFIG_SOC_UART_SUPPORTED)
|
if(CONFIG_SOC_UART_SUPPORTED)
|
||||||
list(APPEND srcs "src/uart.c")
|
list(APPEND srcs "src/uart.c")
|
||||||
|
|
||||||
|
|||||||
@@ -5,14 +5,27 @@ endif()
|
|||||||
|
|
||||||
set(srcs)
|
set(srcs)
|
||||||
set(includes "include")
|
set(includes "include")
|
||||||
|
# Public clock HAL headers include soc/ and hal/ headers directly, and some
|
||||||
|
# target clk_tree_ll.h headers include hal/regi2c_ctrl.h.
|
||||||
|
set(requires soc hal esp_hal_regi2c)
|
||||||
|
|
||||||
# Target-specific include directory if present
|
# Target-specific include directory if present
|
||||||
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${target}/include")
|
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${target}/include")
|
||||||
list(APPEND includes "${target}/include")
|
list(APPEND includes "${target}/include")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# TODO(IDF-15947): potentially remove __ULP_BUILD handling from esp_hal_clock
|
||||||
|
if(__ULP_BUILD)
|
||||||
|
# LP-core timer shared code includes hal/clk_tree_ll.h from
|
||||||
|
# ulp/lp_core/shared/ulp_lp_core_lp_timer_shared.c. Some target
|
||||||
|
# clk_tree_ll.h headers include hal/regi2c_ctrl.h.
|
||||||
|
idf_component_register(INCLUDE_DIRS ${includes}
|
||||||
|
REQUIRES ${requires})
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
list(APPEND srcs "${target}/clk_tree_hal.c")
|
list(APPEND srcs "${target}/clk_tree_hal.c")
|
||||||
|
|
||||||
idf_component_register(SRCS ${srcs}
|
idf_component_register(SRCS ${srcs}
|
||||||
INCLUDE_DIRS ${includes}
|
INCLUDE_DIRS ${includes}
|
||||||
REQUIRES soc hal)
|
REQUIRES ${requires})
|
||||||
|
|||||||
@@ -7,19 +7,23 @@ if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${target}/include")
|
|||||||
list(APPEND includes "${target}/include")
|
list(APPEND includes "${target}/include")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CONFIG_SOC_GPIO_PORT GREATER 0)
|
# ULP GPIO helpers include GPIO/RTC IO HAL headers from
|
||||||
|
# ulp/ulp_riscv/ulp_core/include/ulp_riscv_gpio.h and
|
||||||
|
# ulp/lp_core/lp_core/include/ulp_lp_core_gpio.h.
|
||||||
|
# TODO(IDF-15948): potentially remove __ULP_BUILD source exclusions from esp_hal_gpio
|
||||||
|
if(CONFIG_SOC_GPIO_PORT GREATER 0 AND NOT __ULP_BUILD)
|
||||||
list(APPEND srcs "gpio_hal.c")
|
list(APPEND srcs "gpio_hal.c")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CONFIG_SOC_RTCIO_PIN_COUNT GREATER 0)
|
if(CONFIG_SOC_RTCIO_PIN_COUNT GREATER 0 AND NOT __ULP_BUILD)
|
||||||
list(APPEND srcs "rtc_io_hal.c" "${target}/rtc_io_periph.c")
|
list(APPEND srcs "rtc_io_hal.c" "${target}/rtc_io_periph.c")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CONFIG_SOC_DEDICATED_GPIO_SUPPORTED)
|
if(CONFIG_SOC_DEDICATED_GPIO_SUPPORTED AND NOT __ULP_BUILD)
|
||||||
list(APPEND srcs "${target}/dedic_gpio_periph.c")
|
list(APPEND srcs "${target}/dedic_gpio_periph.c")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CONFIG_SOC_SDM_SUPPORTED)
|
if(CONFIG_SOC_SDM_SUPPORTED AND NOT __ULP_BUILD)
|
||||||
list(APPEND srcs "sdm_hal.c" "${target}/sdm_periph.c")
|
list(APPEND srcs "sdm_hal.c" "${target}/sdm_periph.c")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,19 @@ endif()
|
|||||||
|
|
||||||
set(srcs)
|
set(srcs)
|
||||||
set(public_include "include" "${target}/include")
|
set(public_include "include" "${target}/include")
|
||||||
|
# Public PMU/RTC control HAL headers include hal/regi2c_ctrl.h on several
|
||||||
|
# targets, so CMake v2 builds need esp_hal_regi2c explicitly.
|
||||||
|
set(requires soc hal esp_rom esp_hal_regi2c)
|
||||||
|
|
||||||
|
# TODO(IDF-15949): potentially remove __ULP_BUILD handling from esp_hal_pmu
|
||||||
|
if(__ULP_BUILD)
|
||||||
|
# LP-core runtime code includes hal/pmu_ll.h from
|
||||||
|
# ulp/lp_core/lp_core/lp_core_utils.c. Some target brownout/VBAT headers
|
||||||
|
# include hal/regi2c_ctrl.h.
|
||||||
|
idf_component_register(INCLUDE_DIRS ${public_include}
|
||||||
|
REQUIRES ${requires})
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
# New chips with PMU peripheral
|
# New chips with PMU peripheral
|
||||||
if(CONFIG_SOC_PMU_SUPPORTED)
|
if(CONFIG_SOC_PMU_SUPPORTED)
|
||||||
@@ -31,5 +44,5 @@ endif()
|
|||||||
|
|
||||||
idf_component_register(SRCS ${srcs}
|
idf_component_register(SRCS ${srcs}
|
||||||
INCLUDE_DIRS ${public_include}
|
INCLUDE_DIRS ${public_include}
|
||||||
REQUIRES soc hal esp_rom
|
REQUIRES ${requires}
|
||||||
LDFRAGMENTS linker.lf)
|
LDFRAGMENTS linker.lf)
|
||||||
|
|||||||
@@ -11,6 +11,15 @@ if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${target}/include")
|
|||||||
list(APPEND includes "${target}/include")
|
list(APPEND includes "${target}/include")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# TODO(IDF-15950): potentially remove __ULP_BUILD handling from esp_hal_regi2c
|
||||||
|
if(__ULP_BUILD)
|
||||||
|
# ULP ADC support reaches REGI2C headers through ADC HAL includes used by
|
||||||
|
# ulp/ulp_riscv/ulp_core/ulp_riscv_adc.c.
|
||||||
|
idf_component_register(INCLUDE_DIRS ${includes}
|
||||||
|
REQUIRES soc hal esp_rom)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
# Per-target regi2c implementation sources (replaces ROM implementation when needed)
|
# Per-target regi2c implementation sources (replaces ROM implementation when needed)
|
||||||
if(NOT CONFIG_ESP_ROM_HAS_REGI2C_IMPL)
|
if(NOT CONFIG_ESP_ROM_HAS_REGI2C_IMPL)
|
||||||
list(APPEND srcs "${target}/regi2c_impl.c")
|
list(APPEND srcs "${target}/regi2c_impl.c")
|
||||||
|
|||||||
@@ -8,5 +8,8 @@ components/esp_hal_security/test_apps/crypto:
|
|||||||
- esp_security
|
- esp_security
|
||||||
|
|
||||||
components/esp_hal_security/test_apps/tee:
|
components/esp_hal_security/test_apps/tee:
|
||||||
|
disable+:
|
||||||
|
- if: IDF_BUILD_V2 == "1"
|
||||||
|
reason: Legacy ULP apps are covered by CMake v1; buildv2 covers full_subproject ULP apps.
|
||||||
disable:
|
disable:
|
||||||
- if: IDF_TARGET not in ["esp32c6", "esp32h2", "esp32c5", "esp32c61", "esp32p4"]
|
- if: IDF_TARGET not in ["esp32c6", "esp32h2", "esp32c5", "esp32c61", "esp32p4"]
|
||||||
|
|||||||
@@ -12,6 +12,34 @@ if(${target} STREQUAL "linux")
|
|||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(public_include_dirs "include" "include/soc"
|
||||||
|
"ldo/include" "debug_probe/include" "etm/include"
|
||||||
|
"mspi/mspi_timing_tuning/include" "mspi/mspi_timing_tuning/tuning_scheme_impl/include"
|
||||||
|
"mspi/mspi_intr/include"
|
||||||
|
"power_supply/include" "modem/include")
|
||||||
|
|
||||||
|
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/include/soc/${target}")
|
||||||
|
list(APPEND public_include_dirs
|
||||||
|
"include/soc/${target}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/port/${target}/include")
|
||||||
|
list(APPEND public_include_dirs
|
||||||
|
"port/${target}/include"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# TODO(IDF-15951): potentially remove __ULP_BUILD handling from esp_hw_support
|
||||||
|
if(__ULP_BUILD)
|
||||||
|
# ULP headers and LP-core runtime include esp_intr_alloc.h and esp_cpu.h from
|
||||||
|
# ulp/ulp_riscv/include/ulp_riscv.h and
|
||||||
|
# ulp/lp_core/lp_core/lp_core_ubsan.c.
|
||||||
|
idf_component_register(INCLUDE_DIRS ${public_include_dirs}
|
||||||
|
REQUIRES esp_common esp_hal_gpio hal soc)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
set(requires esp_hal_gpio esp_hal_usb esp_hal_pmu esp_hal_regi2c esp_hal_uart)
|
set(requires esp_hal_gpio esp_hal_usb esp_hal_pmu esp_hal_regi2c esp_hal_uart)
|
||||||
set(priv_requires efuse # only esp_hw_support/adc_share_hw_ctrl.c requires efuse component
|
set(priv_requires efuse # only esp_hw_support/adc_share_hw_ctrl.c requires efuse component
|
||||||
spi_flash
|
spi_flash
|
||||||
@@ -180,18 +208,6 @@ else()
|
|||||||
list(APPEND priv_requires "esp_system")
|
list(APPEND priv_requires "esp_system")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(public_include_dirs "include" "include/soc"
|
|
||||||
"ldo/include" "debug_probe/include" "etm/include"
|
|
||||||
"mspi/mspi_timing_tuning/include" "mspi/mspi_timing_tuning/tuning_scheme_impl/include"
|
|
||||||
"mspi/mspi_intr/include"
|
|
||||||
"power_supply/include" "modem/include")
|
|
||||||
|
|
||||||
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/include/soc/${target}")
|
|
||||||
list(APPEND public_include_dirs
|
|
||||||
"include/soc/${target}"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(${target} STREQUAL "esp32p4")
|
if(${target} STREQUAL "esp32p4")
|
||||||
# for mipi_csi_share_hw_ctrl.c
|
# for mipi_csi_share_hw_ctrl.c
|
||||||
list(APPEND priv_requires esp_hal_cam)
|
list(APPEND priv_requires esp_hal_cam)
|
||||||
|
|||||||
@@ -103,6 +103,8 @@ components/esp_hw_support/test_apps/vad_wakeup:
|
|||||||
- ulp
|
- ulp
|
||||||
- soc
|
- soc
|
||||||
disable:
|
disable:
|
||||||
|
- if: IDF_BUILD_V2 == "1"
|
||||||
|
reason: Legacy ULP apps are covered by CMake v1; buildv2 covers full_subproject ULP apps.
|
||||||
- if: SOC_LP_VAD_SUPPORTED != 1
|
- if: SOC_LP_VAD_SUPPORTED != 1
|
||||||
|
|
||||||
components/esp_hw_support/test_apps/wakeup_tests:
|
components/esp_hw_support/test_apps/wakeup_tests:
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
# Sub-projects with a custom toolchain (e.g. ULP) do not use the IDF
|
||||||
|
# toolchain response file machinery. Skip flag manipulation.
|
||||||
|
if(IDF_CUSTOM_TOOLCHAIN)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
if(CONFIG_IDF_TOOLCHAIN_GCC)
|
if(CONFIG_IDF_TOOLCHAIN_GCC)
|
||||||
if(CONFIG_STDATOMIC_S32C1I_SPIRAM_WORKAROUND)
|
if(CONFIG_STDATOMIC_S32C1I_SPIRAM_WORKAROUND)
|
||||||
idf_toolchain_add_flags(COMPILE_OPTIONS "-mdisable-hardware-atomics")
|
idf_toolchain_add_flags(COMPILE_OPTIONS "-mdisable-hardware-atomics")
|
||||||
|
|||||||
@@ -10,4 +10,5 @@ endif()
|
|||||||
idf_component_register(SRCS ${sources}
|
idf_component_register(SRCS ${sources}
|
||||||
INCLUDE_DIRS "."
|
INCLUDE_DIRS "."
|
||||||
PRIV_REQUIRES unity esp_pm ulp esp_timer esp_psram esp_driver_gptimer vfs esp_hal_gpio
|
PRIV_REQUIRES unity esp_pm ulp esp_timer esp_psram esp_driver_gptimer vfs esp_hal_gpio
|
||||||
|
esp_driver_gpio
|
||||||
WHOLE_ARCHIVE)
|
WHOLE_ARCHIVE)
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
if(IDF_CUSTOM_TOOLCHAIN)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
if(CONFIG_IDF_TOOLCHAIN_GCC)
|
if(CONFIG_IDF_TOOLCHAIN_GCC)
|
||||||
# Remove all "-mfix-esp32-psram-cache*" from toolchain flags
|
# Remove all "-mfix-esp32-psram-cache*" from toolchain flags
|
||||||
# that may have appeared during configuration changes.
|
# that may have appeared during configuration changes.
|
||||||
|
|||||||
@@ -7,6 +7,22 @@ set(include_dirs "include"
|
|||||||
"${target_folder}/include/${target_folder}"
|
"${target_folder}/include/${target_folder}"
|
||||||
"${target_folder}")
|
"${target_folder}")
|
||||||
|
|
||||||
|
# TODO(IDF-15952): potentially remove __ULP_BUILD handling from esp_rom
|
||||||
|
if(__ULP_BUILD)
|
||||||
|
# LP-core runtime and print code include ROM headers from
|
||||||
|
# ulp/lp_core/lp_core/lp_core_startup.c and
|
||||||
|
# ulp/lp_core/lp_core/lp_core_print.c.
|
||||||
|
idf_component_register(INCLUDE_DIRS ${include_dirs})
|
||||||
|
if(ULP_TYPE STREQUAL "lp_core" AND CONFIG_ESP_ROM_HAS_LP_ROM)
|
||||||
|
target_linker_script(${COMPONENT_LIB} INTERFACE
|
||||||
|
"${target_folder}/ld/${target}lp.rom.ld"
|
||||||
|
"${target_folder}/ld/${target}lp.rom.newlib.ld"
|
||||||
|
"${target_folder}/ld/${target}lp.rom.version.ld"
|
||||||
|
"${target_folder}/ld/${target}lp.rom.api.ld")
|
||||||
|
endif()
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
set(private_required_comp "")
|
set(private_required_comp "")
|
||||||
|
|
||||||
set(sources "patches/esp_rom_sys.c"
|
set(sources "patches/esp_rom_sys.c"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
idf_build_get_property(target IDF_TARGET)
|
idf_build_get_property(target IDF_TARGET)
|
||||||
idf_build_get_property(esp_tee_build ESP_TEE_BUILD)
|
idf_build_get_property(esp_tee_build ESP_TEE_BUILD)
|
||||||
|
|
||||||
set(srcs "hal_utils.c")
|
set(srcs)
|
||||||
set(includes "platform_port/include")
|
set(includes "platform_port/include")
|
||||||
set(priv_include)
|
set(priv_include)
|
||||||
set(requires)
|
set(requires)
|
||||||
@@ -12,6 +12,18 @@ list(APPEND includes "${target}/include")
|
|||||||
|
|
||||||
list(APPEND includes "include")
|
list(APPEND includes "include")
|
||||||
|
|
||||||
|
# ULP runtime code includes generic HAL headers, for example hal/lp_core_ll.h
|
||||||
|
# from ulp/lp_core/lp_core/lp_core_interrupt.c.
|
||||||
|
# TODO(IDF-15953): potentially remove __ULP_BUILD handling from hal
|
||||||
|
if(__ULP_BUILD)
|
||||||
|
idf_component_register(INCLUDE_DIRS ${includes}
|
||||||
|
PRIV_INCLUDE_DIRS ${priv_include}
|
||||||
|
REQUIRES esp_common ${requires})
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
list(APPEND srcs "hal_utils.c")
|
||||||
|
|
||||||
if(CONFIG_SOC_EFUSE_SUPPORTED)
|
if(CONFIG_SOC_EFUSE_SUPPORTED)
|
||||||
list(APPEND srcs "efuse_hal.c" "${target}/efuse_hal.c")
|
list(APPEND srcs "efuse_hal.c" "${target}/efuse_hal.c")
|
||||||
endif()
|
endif()
|
||||||
@@ -46,11 +58,13 @@ if(NOT esp_tee_build AND NOT BOOTLOADER_BUILD)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(ldfragments linker.lf)
|
||||||
|
|
||||||
idf_component_register(SRCS ${srcs}
|
idf_component_register(SRCS ${srcs}
|
||||||
INCLUDE_DIRS ${includes}
|
INCLUDE_DIRS ${includes}
|
||||||
PRIV_INCLUDE_DIRS ${priv_include}
|
PRIV_INCLUDE_DIRS ${priv_include}
|
||||||
REQUIRES ${requires}
|
REQUIRES ${requires}
|
||||||
LDFRAGMENTS linker.lf)
|
LDFRAGMENTS ${ldfragments})
|
||||||
|
|
||||||
if(CONFIG_HAL_DEFAULT_ASSERTION_LEVEL EQUAL 1)
|
if(CONFIG_HAL_DEFAULT_ASSERTION_LEVEL EQUAL 1)
|
||||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u abort")
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u abort")
|
||||||
|
|||||||
@@ -1,6 +1,16 @@
|
|||||||
idf_build_get_property(target IDF_TARGET)
|
idf_build_get_property(target IDF_TARGET)
|
||||||
idf_build_get_property(non_os_build NON_OS_BUILD)
|
idf_build_get_property(non_os_build NON_OS_BUILD)
|
||||||
|
|
||||||
|
# TODO(IDF-15954): potentially remove __ULP_BUILD handling from log
|
||||||
|
if(__ULP_BUILD)
|
||||||
|
# LP-core UART wakeup support builds components/esp_driver_uart/src/uart_wakeup.c,
|
||||||
|
# which includes ESP log headers.
|
||||||
|
idf_component_register(INCLUDE_DIRS "include"
|
||||||
|
PRIV_INCLUDE_DIRS "include/esp_private"
|
||||||
|
REQUIRES esp_rom)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
if(non_os_build)
|
if(non_os_build)
|
||||||
set(system_target "noos")
|
set(system_target "noos")
|
||||||
else()
|
else()
|
||||||
|
|||||||
@@ -2,10 +2,20 @@ idf_build_get_property(target IDF_TARGET)
|
|||||||
idf_build_get_property(arch IDF_TARGET_ARCH)
|
idf_build_get_property(arch IDF_TARGET_ARCH)
|
||||||
idf_build_get_property(esp_tee_build ESP_TEE_BUILD)
|
idf_build_get_property(esp_tee_build ESP_TEE_BUILD)
|
||||||
|
|
||||||
if(NOT "${arch}" STREQUAL "riscv")
|
# TODO(IDF-15955): potentially remove __ULP_BUILD handling from riscv
|
||||||
|
if(NOT "${arch}" STREQUAL "riscv" AND NOT (__ULP_BUILD AND "${ULP_TYPE}" STREQUAL "riscv"))
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(__ULP_BUILD AND "${ULP_TYPE}" STREQUAL "riscv")
|
||||||
|
# RISC-V ULP interrupt support includes riscv/interrupt.h from
|
||||||
|
# ulp/ulp_riscv/ulp_core/include/ulp_riscv_interrupt.h.
|
||||||
|
idf_component_register(INCLUDE_DIRS "include")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# When __ULP_BUILD and ULP_TYPE is lp_core, keep the normal RISC-V helper sources for headers
|
||||||
|
# used by ulp/lp_core/lp_core/lp_core_pmp.c and vector.S.
|
||||||
|
|
||||||
if(BOOTLOADER_BUILD)
|
if(BOOTLOADER_BUILD)
|
||||||
set(priv_requires soc hal)
|
set(priv_requires soc hal)
|
||||||
|
|||||||
@@ -4,14 +4,6 @@ set(target_folder "${target}")
|
|||||||
|
|
||||||
set(srcs)
|
set(srcs)
|
||||||
|
|
||||||
# On Linux the soc component is a simple wrapper, without much functionality
|
|
||||||
if(NOT ${target} STREQUAL "linux")
|
|
||||||
set(srcs "lldesc.c"
|
|
||||||
"dport_access_common.c"
|
|
||||||
"${target_folder}/interrupts.c"
|
|
||||||
"${target_folder}/gpio_periph.c")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(includes "include" "${target_folder}")
|
set(includes "include" "${target_folder}")
|
||||||
|
|
||||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${target_folder}/include")
|
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${target_folder}/include")
|
||||||
@@ -39,6 +31,33 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# TODO(IDF-15956): potentially remove __ULP_BUILD handling from soc
|
||||||
|
if(__ULP_BUILD)
|
||||||
|
idf_component_register(INCLUDE_DIRS ${includes}
|
||||||
|
REQUIRES esp_common)
|
||||||
|
|
||||||
|
# For an embedded system, the MMU page size should always be defined statically
|
||||||
|
# For IDF, we define it according to the Flash size that user selects
|
||||||
|
# Replace this value in an adaptive way, if Kconfig isn't available on your platform
|
||||||
|
target_compile_definitions(${COMPONENT_LIB} INTERFACE SOC_MMU_PAGE_SIZE=CONFIG_MMU_PAGE_SIZE)
|
||||||
|
|
||||||
|
target_compile_definitions(${COMPONENT_LIB} INTERFACE SOC_XTAL_FREQ_MHZ=CONFIG_XTAL_FREQ)
|
||||||
|
|
||||||
|
if(ULP_TYPE STREQUAL "lp_core")
|
||||||
|
target_linker_script(${COMPONENT_LIB} INTERFACE "${target_folder}/ld/${target}.peripherals.ld")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# On Linux the soc component is a simple wrapper, without much functionality.
|
||||||
|
if(NOT ${target} STREQUAL "linux")
|
||||||
|
set(srcs "lldesc.c"
|
||||||
|
"dport_access_common.c"
|
||||||
|
"${target_folder}/interrupts.c"
|
||||||
|
"${target_folder}/gpio_periph.c")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(target STREQUAL "esp32")
|
if(target STREQUAL "esp32")
|
||||||
list(APPEND srcs "${target_folder}/dport_access.c")
|
list(APPEND srcs "${target_folder}/dport_access.c")
|
||||||
endif()
|
endif()
|
||||||
@@ -55,9 +74,11 @@ if(CONFIG_SOC_BOD_SUPPORTED)
|
|||||||
list(APPEND srcs "${target_folder}/power_supply_periph.c")
|
list(APPEND srcs "${target_folder}/power_supply_periph.c")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(ldfragments "linker.lf")
|
||||||
|
|
||||||
idf_component_register(SRCS ${srcs}
|
idf_component_register(SRCS ${srcs}
|
||||||
INCLUDE_DIRS ${includes}
|
INCLUDE_DIRS ${includes}
|
||||||
LDFRAGMENTS "linker.lf")
|
LDFRAGMENTS ${ldfragments})
|
||||||
|
|
||||||
# For an embedded system, the MMU page size should always be defined statically
|
# For an embedded system, the MMU page size should always be defined statically
|
||||||
# For IDF, we define it according to the Flash size that user selects
|
# For IDF, we define it according to the Flash size that user selects
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
if(IDF_CUSTOM_TOOLCHAIN)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
if(CONFIG_IDF_TOOLCHAIN_GCC)
|
if(CONFIG_IDF_TOOLCHAIN_GCC)
|
||||||
# Common flags
|
# Common flags
|
||||||
idf_toolchain_add_flags(LINK_OPTIONS "-nostartfiles")
|
idf_toolchain_add_flags(LINK_OPTIONS "-nostartfiles")
|
||||||
|
|||||||
@@ -4,6 +4,11 @@ if(${target} STREQUAL "linux")
|
|||||||
return() # This component is not supported by the POSIX/Linux simulator
|
return() # This component is not supported by the POSIX/Linux simulator
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(IDF_BUILD_V2)
|
||||||
|
include(${CMAKE_CURRENT_LIST_DIR}/CMakeLists_v2.txt)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
set(srcs "")
|
set(srcs "")
|
||||||
set(includes "")
|
set(includes "")
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,183 @@
|
|||||||
|
set(srcs "")
|
||||||
|
set(includes "")
|
||||||
|
set(requires "")
|
||||||
|
set(priv_requires "")
|
||||||
|
|
||||||
|
if(__ULP_BUILD)
|
||||||
|
if(ULP_TYPE STREQUAL "riscv")
|
||||||
|
list(APPEND includes
|
||||||
|
ulp_riscv/shared/include
|
||||||
|
ulp_riscv/ulp_core/include)
|
||||||
|
list(APPEND srcs
|
||||||
|
"ulp_riscv/ulp_core/ulp_riscv_vectors.S"
|
||||||
|
"ulp_riscv/ulp_core/start.S"
|
||||||
|
"ulp_riscv/ulp_core/ulp_riscv_utils.c")
|
||||||
|
list(APPEND requires
|
||||||
|
riscv
|
||||||
|
soc)
|
||||||
|
elseif(ULP_TYPE STREQUAL "lp_core")
|
||||||
|
list(APPEND includes
|
||||||
|
lp_core/lp_core/include
|
||||||
|
lp_core/shared/include)
|
||||||
|
list(APPEND srcs
|
||||||
|
"lp_core/lp_core/start.S"
|
||||||
|
"lp_core/lp_core/vector.S"
|
||||||
|
"lp_core/lp_core/port/${target}/vector_table.S"
|
||||||
|
"lp_core/shared/ulp_lp_core_memory_shared.c"
|
||||||
|
"lp_core/lp_core/lp_core_startup.c"
|
||||||
|
"lp_core/lp_core/lp_core_pmp.c"
|
||||||
|
"lp_core/lp_core/lp_core_utils.c"
|
||||||
|
"lp_core/lp_core/lp_core_panic.c"
|
||||||
|
"lp_core/lp_core/lp_core_interrupt.c"
|
||||||
|
"lp_core/shared/ulp_lp_core_lp_uart_shared.c"
|
||||||
|
"lp_core/lp_core/lp_core_uart.c"
|
||||||
|
"lp_core/shared/ulp_lp_core_lp_timer_shared.c"
|
||||||
|
"lp_core/shared/ulp_lp_core_critical_section_shared.c")
|
||||||
|
|
||||||
|
list(APPEND requires
|
||||||
|
esp_common
|
||||||
|
esp_driver_uart
|
||||||
|
esp_hal_gpio
|
||||||
|
esp_hal_uart
|
||||||
|
esp_rom
|
||||||
|
hal
|
||||||
|
riscv
|
||||||
|
soc)
|
||||||
|
list(APPEND priv_requires
|
||||||
|
esp_hal_clock
|
||||||
|
esp_hal_i2s
|
||||||
|
esp_hal_rtc_timer
|
||||||
|
esp_hal_pmu
|
||||||
|
esp_hw_support)
|
||||||
|
|
||||||
|
elseif(ULP_TYPE STREQUAL "fsm")
|
||||||
|
list(APPEND includes
|
||||||
|
ulp_common/include
|
||||||
|
ulp_fsm/include
|
||||||
|
ulp_fsm/include/${target})
|
||||||
|
list(APPEND requires soc)
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "__ULP_BUILD requires ULP_TYPE to be one of: riscv, lp_core, fsm.")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
if(CONFIG_ULP_COPROC_ENABLED)
|
||||||
|
list(APPEND includes
|
||||||
|
ulp_common/include)
|
||||||
|
list(APPEND requires
|
||||||
|
esp_common
|
||||||
|
soc)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CONFIG_ULP_COPROC_TYPE_FSM)
|
||||||
|
list(APPEND includes
|
||||||
|
ulp_fsm/include
|
||||||
|
ulp_fsm/include/${target})
|
||||||
|
list(APPEND srcs
|
||||||
|
"ulp_common/ulp_common.c"
|
||||||
|
"ulp_fsm/ulp.c"
|
||||||
|
"ulp_fsm/ulp_macro.c")
|
||||||
|
list(APPEND requires esp_hw_support)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CONFIG_ULP_COPROC_TYPE_RISCV)
|
||||||
|
list(APPEND includes
|
||||||
|
ulp_riscv/include
|
||||||
|
ulp_riscv/shared/include
|
||||||
|
ulp_riscv/ulp_core/include)
|
||||||
|
list(APPEND srcs
|
||||||
|
"ulp_common/ulp_common.c"
|
||||||
|
"ulp_riscv/ulp_riscv.c")
|
||||||
|
list(APPEND requires
|
||||||
|
esp_hw_support
|
||||||
|
esp_hal_pmu)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CONFIG_ULP_COPROC_TYPE_LP_CORE)
|
||||||
|
list(APPEND includes
|
||||||
|
lp_core/include
|
||||||
|
lp_core/lp_core/include
|
||||||
|
lp_core/shared/include)
|
||||||
|
list(APPEND srcs
|
||||||
|
"lp_core/lp_core.c"
|
||||||
|
"lp_core/shared/ulp_lp_core_memory_shared.c"
|
||||||
|
"lp_core/shared/ulp_lp_core_lp_timer_shared.c"
|
||||||
|
"lp_core/shared/ulp_lp_core_critical_section_shared.c")
|
||||||
|
list(APPEND requires
|
||||||
|
esp_hw_support
|
||||||
|
esp_hal_clock
|
||||||
|
esp_hal_pmu
|
||||||
|
esp_hal_rtc_timer
|
||||||
|
esp_rom
|
||||||
|
hal
|
||||||
|
riscv
|
||||||
|
soc)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(requires)
|
||||||
|
list(REMOVE_DUPLICATES requires)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(priv_requires)
|
||||||
|
list(REMOVE_DUPLICATES priv_requires)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
idf_component_register(SRCS ${srcs}
|
||||||
|
INCLUDE_DIRS ${includes}
|
||||||
|
REQUIRES ${requires}
|
||||||
|
PRIV_REQUIRES ${priv_requires})
|
||||||
|
|
||||||
|
# In the parent app build, the ulp component only provides the host-side API.
|
||||||
|
# The executable/linker setup below is for native ULP child projects.
|
||||||
|
if(NOT __ULP_BUILD)
|
||||||
|
idf_define_esp_err_codes(HEADERS ulp_fsm/include/ulp_fsm_common.h)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Preprocessor flags shared by every ULP memory-layout template. The template
|
||||||
|
# is a ".in" file, so the standard target_linker_script flow runs the C
|
||||||
|
# preprocessor on it. -D__ASSEMBLER__ keeps SoC headers to their macro-only
|
||||||
|
# form, and the component's own ld directory is available for relative
|
||||||
|
# includes.
|
||||||
|
set(ulp_ld_flags "-D__ASSEMBLER__ -I\"${CMAKE_CURRENT_SOURCE_DIR}/ld\"")
|
||||||
|
|
||||||
|
# Select the linker template and target-specific link options used by the ULP
|
||||||
|
# executable created in the child project. The memory-layout template is
|
||||||
|
# registered with target_linker_script so the standard build system
|
||||||
|
# preprocesses and attaches it; per-type FLAGS supply the include directories
|
||||||
|
# its #include lines need.
|
||||||
|
if(ULP_TYPE STREQUAL "riscv")
|
||||||
|
target_linker_script(${COMPONENT_LIB} INTERFACE "ld/ulp_riscv.ld.in" MEMORY
|
||||||
|
FLAGS "${ulp_ld_flags}")
|
||||||
|
target_linker_script(${COMPONENT_LIB} INTERFACE "ld/${target}.peripherals.ld")
|
||||||
|
target_link_options(${COMPONENT_LIB} INTERFACE
|
||||||
|
-nostartfiles
|
||||||
|
-Wl,--gc-sections
|
||||||
|
-Wl,--no-warn-rwx-segments
|
||||||
|
LINKER:-u,main)
|
||||||
|
target_compile_definitions(${COMPONENT_LIB} PUBLIC
|
||||||
|
IS_ULP_COCPU
|
||||||
|
ULP_RISCV_REGISTER_OPS)
|
||||||
|
elseif(ULP_TYPE STREQUAL "lp_core")
|
||||||
|
# lp_core_riscv.ld includes soc/soc.h and esp_common headers, which are
|
||||||
|
# resolved automatically from the linked component graph. It also includes
|
||||||
|
# the esp_system ld snippets (ld.common, ld.hp_mem_defs); those live in the
|
||||||
|
# component's ld/ directory, which is not a public include dir, so pass it
|
||||||
|
# via FLAGS.
|
||||||
|
idf_component_get_property(esp_system_dir esp_system COMPONENT_DIR)
|
||||||
|
set(lp_core_ld_flags "${ulp_ld_flags} -I\"${esp_system_dir}/ld\" -I\"${esp_system_dir}/ld/${target}\"")
|
||||||
|
target_linker_script(${COMPONENT_LIB} INTERFACE "ld/lp_core_riscv.ld.in" MEMORY
|
||||||
|
FLAGS "${lp_core_ld_flags}")
|
||||||
|
|
||||||
|
target_link_options(${COMPONENT_LIB} INTERFACE
|
||||||
|
-nostartfiles
|
||||||
|
-Wl,--gc-sections
|
||||||
|
-Wl,--no-warn-rwx-segments
|
||||||
|
LINKER:-u,main)
|
||||||
|
target_compile_definitions(${COMPONENT_LIB} PUBLIC IS_ULP_COCPU)
|
||||||
|
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-implicit-fallthrough)
|
||||||
|
elseif(ULP_TYPE STREQUAL "fsm")
|
||||||
|
target_linker_script(${COMPONENT_LIB} INTERFACE "ld/ulp_fsm.ld.in" MEMORY
|
||||||
|
FLAGS "${ulp_ld_flags}")
|
||||||
|
target_link_options(${COMPONENT_LIB} INTERFACE "SHELL:-u entry")
|
||||||
|
endif()
|
||||||
@@ -1,35 +1,56 @@
|
|||||||
|
# This is the CMake v1 (legacy) ULP child entry point, used by ulp_embed_binary.
|
||||||
|
# CMake v2 full-subproject builds include components/ulp/cmake/ulp_project.cmake
|
||||||
|
# instead.
|
||||||
|
#
|
||||||
|
# Legacy ULP child projects are plain CMake projects, so the parent-provided
|
||||||
|
# sdkconfig.cmake has to be loaded here before the common ULP helpers inspect
|
||||||
|
# CONFIG_* values. CMake v1 callers pass this path explicitly.
|
||||||
include(${SDKCONFIG_CMAKE})
|
include(${SDKCONFIG_CMAKE})
|
||||||
|
include(${CMAKE_CURRENT_LIST_DIR}/IDFULPProjectCommon.cmake)
|
||||||
enable_language(C ASM)
|
enable_language(C ASM)
|
||||||
set(CMAKE_EXECUTABLE_SUFFIX ".elf")
|
set(CMAKE_EXECUTABLE_SUFFIX ".elf")
|
||||||
|
|
||||||
# Logic to determine ULP type and set reusable flags
|
ulp_detect_build_type()
|
||||||
set(BUILD_RISCV OFF)
|
ulp_apply_build_type_options()
|
||||||
set(BUILD_FSM OFF)
|
|
||||||
set(BUILD_LP_CORE OFF)
|
|
||||||
|
|
||||||
# If ULP_TYPE is explicitly set, use it; otherwise fall back to CONFIG checks
|
|
||||||
if(ULP_TYPE)
|
|
||||||
string(TOLOWER "${ULP_TYPE}" ulp_type_lower)
|
|
||||||
if(ulp_type_lower STREQUAL "riscv")
|
|
||||||
set(BUILD_RISCV ON)
|
|
||||||
elseif(ulp_type_lower STREQUAL "fsm")
|
|
||||||
set(BUILD_FSM ON)
|
|
||||||
elseif(ulp_type_lower STREQUAL "lp_core")
|
|
||||||
set(BUILD_LP_CORE ON)
|
|
||||||
endif()
|
|
||||||
elseif(CONFIG_ULP_COPROC_TYPE_RISCV)
|
|
||||||
set(BUILD_RISCV ON)
|
|
||||||
elseif(CONFIG_ULP_COPROC_TYPE_LP_CORE)
|
|
||||||
set(BUILD_LP_CORE ON)
|
|
||||||
elseif(CONFIG_ULP_COPROC_TYPE_FSM)
|
|
||||||
set(BUILD_FSM ON)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Check the supported assembler version
|
# Check the supported assembler version
|
||||||
if(BUILD_FSM)
|
if(BUILD_FSM)
|
||||||
check_expected_tool_version("esp32ulp-elf" ${CMAKE_ASM_COMPILER})
|
check_expected_tool_version("esp32ulp-elf" ${CMAKE_ASM_COMPILER})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# CMake v1-only helpers that preprocess the ULP memory-layout linker template
|
||||||
|
# with the C preprocessor. The CMake v2 path attaches the template through
|
||||||
|
# target_linker_script(... FLAGS) and does not use these.
|
||||||
|
function(__ulp_create_arg_file arguments output_file)
|
||||||
|
# Escape all spaces
|
||||||
|
list(TRANSFORM arguments REPLACE " " "\\\\ ")
|
||||||
|
# Create a single string with all args separated by space
|
||||||
|
list(JOIN arguments " " arguments)
|
||||||
|
# Generate the response file late enough for target generator expressions
|
||||||
|
# in include directories to resolve to their final build-system values.
|
||||||
|
file(GENERATE OUTPUT "${output_file}" CONTENT "${arguments}")
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(__ulp_add_preprocessed_linker_script ulp_app_name ld_template ld_script ld_script_target)
|
||||||
|
# Use the C preprocessor so sdkconfig and SoC constants can shape the
|
||||||
|
# linker template before the ULP executable is linked.
|
||||||
|
set(preprocessor_args -D__ASSEMBLER__ -E -P -xc -o ${ld_script} ${ARGN} ${ld_template})
|
||||||
|
set(compiler_arguments_file ${CMAKE_CURRENT_BINARY_DIR}/${ld_script}_args.txt)
|
||||||
|
__ulp_create_arg_file("${preprocessor_args}" "${compiler_arguments_file}")
|
||||||
|
|
||||||
|
add_custom_command(OUTPUT ${ld_script}
|
||||||
|
COMMAND ${CMAKE_C_COMPILER} @${compiler_arguments_file}
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
MAIN_DEPENDENCY ${ld_template}
|
||||||
|
DEPENDS ${SDKCONFIG_HEADER}
|
||||||
|
COMMENT "Generating ${ld_script} linker script..."
|
||||||
|
VERBATIM)
|
||||||
|
|
||||||
|
add_custom_target(${ld_script_target} DEPENDS ${ld_script})
|
||||||
|
add_dependencies(${ulp_app_name} ${ld_script_target})
|
||||||
|
target_link_options(${ulp_app_name} PRIVATE SHELL:-T ${CMAKE_CURRENT_BINARY_DIR}/${ld_script})
|
||||||
|
endfunction()
|
||||||
|
|
||||||
function(ulp_apply_default_options ulp_app_name)
|
function(ulp_apply_default_options ulp_app_name)
|
||||||
if(BUILD_RISCV)
|
if(BUILD_RISCV)
|
||||||
target_link_options(${ulp_app_name} PRIVATE "-nostartfiles")
|
target_link_options(${ulp_app_name} PRIVATE "-nostartfiles")
|
||||||
@@ -47,16 +68,6 @@ function(ulp_apply_default_options ulp_app_name)
|
|||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
function(ulp_apply_default_sources ulp_app_name)
|
function(ulp_apply_default_sources ulp_app_name)
|
||||||
|
|
||||||
function(create_arg_file arguments output_file)
|
|
||||||
# Escape all spaces
|
|
||||||
list(TRANSFORM arguments REPLACE " " "\\\\ ")
|
|
||||||
# Create a single string with all args separated by space
|
|
||||||
list(JOIN arguments " " arguments)
|
|
||||||
# Write it into the response file
|
|
||||||
file(WRITE ${output_file} ${arguments})
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
message(STATUS "Building ULP app ${ulp_app_name}")
|
message(STATUS "Building ULP app ${ulp_app_name}")
|
||||||
|
|
||||||
get_filename_component(sdkconfig_dir ${SDKCONFIG_HEADER} DIRECTORY)
|
get_filename_component(sdkconfig_dir ${SDKCONFIG_HEADER} DIRECTORY)
|
||||||
@@ -76,32 +87,19 @@ function(ulp_apply_default_sources ulp_app_name)
|
|||||||
|
|
||||||
# Pre-process the linker script
|
# Pre-process the linker script
|
||||||
if(BUILD_RISCV)
|
if(BUILD_RISCV)
|
||||||
set(ULP_LD_TEMPLATE ${IDF_PATH}/components/ulp/ld/ulp_riscv.ld)
|
set(ULP_LD_TEMPLATE ${IDF_PATH}/components/ulp/ld/ulp_riscv.ld.in)
|
||||||
elseif(BUILD_LP_CORE)
|
elseif(BUILD_LP_CORE)
|
||||||
set(ULP_LD_TEMPLATE ${IDF_PATH}/components/ulp/ld/lp_core_riscv.ld)
|
set(ULP_LD_TEMPLATE ${IDF_PATH}/components/ulp/ld/lp_core_riscv.ld.in)
|
||||||
elseif(BUILD_FSM)
|
elseif(BUILD_FSM)
|
||||||
set(ULP_LD_TEMPLATE ${IDF_PATH}/components/ulp/ld/ulp_fsm.ld)
|
set(ULP_LD_TEMPLATE ${IDF_PATH}/components/ulp/ld/ulp_fsm.ld.in)
|
||||||
else()
|
else()
|
||||||
message(FATAL_ERROR "Unable to determine ULP type. ")
|
message(FATAL_ERROR "Unable to determine ULP type. ")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
get_filename_component(ULP_LD_SCRIPT ${ULP_LD_TEMPLATE} NAME)
|
# Strip the .in suffix so the generated script keeps its .ld name.
|
||||||
|
get_filename_component(ULP_LD_SCRIPT ${ULP_LD_TEMPLATE} NAME_WLE)
|
||||||
# Put all arguments to the list
|
__ulp_add_preprocessed_linker_script(${ulp_app_name} ${ULP_LD_TEMPLATE} ${ULP_LD_SCRIPT}
|
||||||
set(preprocessor_args -D__ASSEMBLER__ -E -P -xc -o ${ULP_LD_SCRIPT} ${ULP_PREPRO_ARGS} ${ULP_LD_TEMPLATE})
|
ld_script ${ULP_PREPRO_ARGS})
|
||||||
set(compiler_arguments_file ${CMAKE_CURRENT_BINARY_DIR}/${ULP_LD_SCRIPT}_args.txt)
|
|
||||||
create_arg_file("${preprocessor_args}" "${compiler_arguments_file}")
|
|
||||||
|
|
||||||
add_custom_command(OUTPUT ${ULP_LD_SCRIPT}
|
|
||||||
COMMAND ${CMAKE_C_COMPILER} @${compiler_arguments_file}
|
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
|
||||||
MAIN_DEPENDENCY ${ULP_LD_TEMPLATE}
|
|
||||||
DEPENDS ${SDKCONFIG_HEADER}
|
|
||||||
COMMENT "Generating ${ULP_LD_SCRIPT} linker script..."
|
|
||||||
VERBATIM)
|
|
||||||
add_custom_target(ld_script DEPENDS ${ULP_LD_SCRIPT})
|
|
||||||
add_dependencies(${ulp_app_name} ld_script)
|
|
||||||
target_link_options(${ulp_app_name} PRIVATE SHELL:-T ${CMAKE_CURRENT_BINARY_DIR}/${ULP_LD_SCRIPT})
|
|
||||||
|
|
||||||
# To avoid warning "Manually-specified variables were not used by the project"
|
# To avoid warning "Manually-specified variables were not used by the project"
|
||||||
set(bypassWarning "${IDF_TARGET}")
|
set(bypassWarning "${IDF_TARGET}")
|
||||||
@@ -146,7 +144,7 @@ function(ulp_apply_default_sources ulp_app_name)
|
|||||||
set(preprocessor_args -D__ASSEMBLER__ -E -P -xc -o ${ulp_ps_output} ${ULP_PREPRO_ARGS} ${ulp_s_source})
|
set(preprocessor_args -D__ASSEMBLER__ -E -P -xc -o ${ulp_ps_output} ${ULP_PREPRO_ARGS} ${ulp_s_source})
|
||||||
|
|
||||||
set(compiler_arguments_file ${CMAKE_CURRENT_BINARY_DIR}/${ulp_ps_source}_args.txt)
|
set(compiler_arguments_file ${CMAKE_CURRENT_BINARY_DIR}/${ulp_ps_source}_args.txt)
|
||||||
create_arg_file("${preprocessor_args}" "${compiler_arguments_file}")
|
__ulp_create_arg_file("${preprocessor_args}" "${compiler_arguments_file}")
|
||||||
|
|
||||||
# Generate preprocessed assembly files.
|
# Generate preprocessed assembly files.
|
||||||
add_custom_command(OUTPUT ${ulp_ps_output}
|
add_custom_command(OUTPUT ${ulp_ps_output}
|
||||||
@@ -237,59 +235,3 @@ function(ulp_apply_default_sources ulp_app_name)
|
|||||||
|
|
||||||
endif()
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
function(ulp_add_build_binary_targets ulp_app_name)
|
|
||||||
cmake_parse_arguments(ULP "" "PREFIX" "" ${ARGN})
|
|
||||||
if(NOT ULP_PREFIX)
|
|
||||||
set(ULP_PREFIX "ulp_")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(ADD_PICOLIBC_SPECS)
|
|
||||||
target_compile_options(${ulp_app_name} PRIVATE $<$<COMPILE_LANG_AND_ID:C,GNU>:-specs=picolibc.specs>)
|
|
||||||
target_compile_options(${ulp_app_name} PRIVATE $<$<COMPILE_LANG_AND_ID:CXX,GNU>:-specs=picolibcpp.specs>)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(BUILD_LP_CORE)
|
|
||||||
set(ULP_BASE_ADDR "0x0")
|
|
||||||
else()
|
|
||||||
set(ULP_BASE_ADDR "0x50000000")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(ULP_MAP_GEN ${PYTHON} ${IDF_PATH}/components/ulp/esp32ulp_mapgen.py)
|
|
||||||
|
|
||||||
# Dump the list of global symbols in a convenient format
|
|
||||||
add_custom_command(OUTPUT ${ULP_APP_NAME}.sym
|
|
||||||
COMMAND ${CMAKE_READELF} -sW $<TARGET_FILE:${ulp_app_name}> > ${ulp_app_name}.sym
|
|
||||||
DEPENDS ${ulp_app_name}
|
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
|
||||||
|
|
||||||
# Dump the binary for inclusion into the project
|
|
||||||
if(BUILD_LP_CORE AND CONFIG_ULP_COPROC_RUN_FROM_HP_MEM)
|
|
||||||
add_custom_command(OUTPUT ${ulp_app_name}.bin
|
|
||||||
COMMAND ${PYTHON} -m esptool --chip ${IDF_TARGET} elf2image
|
|
||||||
--output ${ulp_app_name}.bin $<TARGET_FILE:${ulp_app_name}>
|
|
||||||
DEPENDS ${ulp_app_name}
|
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
|
||||||
else()
|
|
||||||
add_custom_command(OUTPUT ${ulp_app_name}.bin
|
|
||||||
COMMAND ${CMAKE_OBJCOPY} -O binary $<TARGET_FILE:${ulp_app_name}> ${ulp_app_name}.bin
|
|
||||||
DEPENDS ${ulp_app_name}
|
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_custom_command(OUTPUT ${ulp_app_name}.ld ${ulp_app_name}.h
|
|
||||||
COMMAND ${ULP_MAP_GEN} -s ${ulp_app_name}.sym -o ${ulp_app_name}
|
|
||||||
--base ${ULP_BASE_ADDR} --prefix ${ULP_PREFIX}
|
|
||||||
--target ${IDF_TARGET}
|
|
||||||
DEPENDS ${ulp_app_name}.sym
|
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
|
||||||
|
|
||||||
# Building the component separately from the project should result in
|
|
||||||
# ULP files being built.
|
|
||||||
add_custom_target(build
|
|
||||||
DEPENDS ${ulp_app_name} ${ulp_app_name}.bin ${ulp_app_name}.sym
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/${ulp_app_name}.ld
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/${ulp_app_name}.h
|
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
|
||||||
|
|
||||||
endfunction()
|
|
||||||
|
|||||||
@@ -0,0 +1,96 @@
|
|||||||
|
macro(ulp_detect_build_type)
|
||||||
|
# Logic to determine ULP type and set reusable flags
|
||||||
|
set(BUILD_RISCV OFF)
|
||||||
|
set(BUILD_FSM OFF)
|
||||||
|
set(BUILD_LP_CORE OFF)
|
||||||
|
|
||||||
|
# If ULP_TYPE is explicitly set, use it; otherwise fall back to CONFIG checks
|
||||||
|
if(ULP_TYPE)
|
||||||
|
string(TOLOWER "${ULP_TYPE}" ulp_type_lower)
|
||||||
|
if(ulp_type_lower STREQUAL "riscv")
|
||||||
|
set(BUILD_RISCV ON)
|
||||||
|
elseif(ulp_type_lower STREQUAL "fsm")
|
||||||
|
set(BUILD_FSM ON)
|
||||||
|
elseif(ulp_type_lower STREQUAL "lp_core")
|
||||||
|
set(BUILD_LP_CORE ON)
|
||||||
|
endif()
|
||||||
|
elseif(CONFIG_ULP_COPROC_TYPE_RISCV)
|
||||||
|
set(BUILD_RISCV ON)
|
||||||
|
elseif(CONFIG_ULP_COPROC_TYPE_LP_CORE)
|
||||||
|
set(BUILD_LP_CORE ON)
|
||||||
|
elseif(CONFIG_ULP_COPROC_TYPE_FSM)
|
||||||
|
set(BUILD_FSM ON)
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
macro(ulp_apply_build_type_options)
|
||||||
|
# CMake initializes GNU ASM definitions as --defsym during enable_language().
|
||||||
|
# Native full-subproject FSM sources are preprocessed by the toolchain rule,
|
||||||
|
# so use C preprocessor definitions for generated ASM rules.
|
||||||
|
if(BUILD_FSM AND ULP_PREPROCESS_FSM_ASM_IN_TOOLCHAIN)
|
||||||
|
set(CMAKE_ASM_DEFINE_FLAG "-D")
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
function(ulp_add_build_binary_targets ulp_app_name)
|
||||||
|
cmake_parse_arguments(ULP "" "PREFIX" "" ${ARGN})
|
||||||
|
if(NOT ULP_PREFIX)
|
||||||
|
set(ULP_PREFIX "ulp_")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(ADD_PICOLIBC_SPECS)
|
||||||
|
target_compile_options(${ulp_app_name} PRIVATE $<$<COMPILE_LANG_AND_ID:C,GNU>:-specs=picolibc.specs>)
|
||||||
|
target_compile_options(${ulp_app_name} PRIVATE $<$<COMPILE_LANG_AND_ID:CXX,GNU>:-specs=picolibcpp.specs>)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(BUILD_LP_CORE)
|
||||||
|
set(ULP_BASE_ADDR "0x0")
|
||||||
|
else()
|
||||||
|
set(ULP_BASE_ADDR "0x50000000")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(ULP_MAP_GEN ${PYTHON} ${IDF_PATH}/components/ulp/esp32ulp_mapgen.py)
|
||||||
|
|
||||||
|
# Dump the list of global symbols in a convenient format
|
||||||
|
add_custom_command(OUTPUT ${ulp_app_name}.sym
|
||||||
|
COMMAND ${CMAKE_READELF} -sW $<TARGET_FILE:${ulp_app_name}> > ${ulp_app_name}.sym
|
||||||
|
DEPENDS ${ulp_app_name}
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
|
# Dump the binary for inclusion into the project
|
||||||
|
if(BUILD_LP_CORE AND CONFIG_ULP_COPROC_RUN_FROM_HP_MEM)
|
||||||
|
# LP-core images running from HP memory use the normal ESP image format;
|
||||||
|
# RTC-memory ULP binaries are raw object-copy output.
|
||||||
|
add_custom_command(OUTPUT ${ulp_app_name}.bin
|
||||||
|
COMMAND ${PYTHON} -m esptool --chip ${IDF_TARGET} elf2image
|
||||||
|
--output ${ulp_app_name}.bin $<TARGET_FILE:${ulp_app_name}>
|
||||||
|
DEPENDS ${ulp_app_name}
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
else()
|
||||||
|
add_custom_command(OUTPUT ${ulp_app_name}.bin
|
||||||
|
COMMAND ${CMAKE_OBJCOPY} -O binary $<TARGET_FILE:${ulp_app_name}> ${ulp_app_name}.bin
|
||||||
|
DEPENDS ${ulp_app_name}
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_custom_command(OUTPUT ${ulp_app_name}.ld ${ulp_app_name}.h
|
||||||
|
COMMAND ${ULP_MAP_GEN} -s ${ulp_app_name}.sym -o ${ulp_app_name}
|
||||||
|
--base ${ULP_BASE_ADDR} --prefix ${ULP_PREFIX}
|
||||||
|
--target ${IDF_TARGET}
|
||||||
|
DEPENDS ${ulp_app_name}.sym
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
|
add_custom_target(${ulp_app_name}_binary_artifacts
|
||||||
|
DEPENDS ${ulp_app_name} ${ulp_app_name}.bin ${ulp_app_name}.sym
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/${ulp_app_name}.ld
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/${ulp_app_name}.h
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
|
# Building the component separately from the project should result in all
|
||||||
|
# ULP files being built. Multiple ULP executables in one child project all
|
||||||
|
# contribute their artifact targets here.
|
||||||
|
if(NOT TARGET build)
|
||||||
|
add_custom_target(build)
|
||||||
|
endif()
|
||||||
|
add_dependencies(build ${ulp_app_name}_binary_artifacts)
|
||||||
|
endfunction()
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
foreach(required_var ULP_FSM_PREPROCESSOR ULP_FSM_ASSEMBLER ULP_FSM_TARGET ULP_FSM_SOURCE ULP_FSM_OBJECT)
|
||||||
|
if(NOT DEFINED ${required_var} OR "${${required_var}}" STREQUAL "")
|
||||||
|
message(FATAL_ERROR "${required_var} is required")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
set(extra_args)
|
||||||
|
set(extra_args_started OFF)
|
||||||
|
math(EXPR last_arg_index "${CMAKE_ARGC} - 1")
|
||||||
|
foreach(arg_index RANGE 0 ${last_arg_index})
|
||||||
|
if("${CMAKE_ARGV${arg_index}}" STREQUAL "--")
|
||||||
|
set(extra_args_started ON)
|
||||||
|
continue()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(extra_args_started)
|
||||||
|
list(APPEND extra_args "${CMAKE_ARGV${arg_index}}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
set(preprocessed_source "${ULP_FSM_OBJECT}.ulp.S")
|
||||||
|
set(listing_file "${ULP_FSM_OBJECT}.lst")
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${ULP_FSM_PREPROCESSOR}"
|
||||||
|
-D__ASSEMBLER__ -E -P -x c
|
||||||
|
${extra_args}
|
||||||
|
-o "${preprocessed_source}"
|
||||||
|
"${ULP_FSM_SOURCE}"
|
||||||
|
RESULT_VARIABLE preprocess_result
|
||||||
|
)
|
||||||
|
if(NOT preprocess_result EQUAL 0)
|
||||||
|
message(FATAL_ERROR "Failed to preprocess ${ULP_FSM_SOURCE}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${ULP_FSM_ASSEMBLER}"
|
||||||
|
"--mcpu=${ULP_FSM_TARGET}"
|
||||||
|
"-al=${listing_file}"
|
||||||
|
-o "${ULP_FSM_OBJECT}"
|
||||||
|
-c "${preprocessed_source}"
|
||||||
|
RESULT_VARIABLE assemble_result
|
||||||
|
)
|
||||||
|
if(NOT assemble_result EQUAL 0)
|
||||||
|
message(FATAL_ERROR "Failed to assemble ${preprocessed_source}")
|
||||||
|
endif()
|
||||||
@@ -9,9 +9,28 @@ set(CMAKE_ASM_COMPILER "esp32ulp-elf-as")
|
|||||||
set(CMAKE_OBJCOPY "esp32ulp-elf-objcopy")
|
set(CMAKE_OBJCOPY "esp32ulp-elf-objcopy")
|
||||||
set(CMAKE_LINKER "esp32ulp-elf-ld")
|
set(CMAKE_LINKER "esp32ulp-elf-ld")
|
||||||
|
|
||||||
|
# Native CMake v2 ULP projects include cmakev2/idf.cmake before project(),
|
||||||
|
# making idf_project_init visible when this toolchain is loaded. Legacy child
|
||||||
|
# projects, even when launched by a CMake v2 parent, include the old IDF CMake
|
||||||
|
# entrypoint and keep the historical explicit preprocessing path.
|
||||||
|
set(ULP_PREPROCESS_FSM_ASM_IN_TOOLCHAIN OFF)
|
||||||
|
if(IDF_BUILD_V2 AND COMMAND idf_project_init)
|
||||||
|
set(ULP_PREPROCESS_FSM_ASM_IN_TOOLCHAIN ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(ULP_PREPROCESS_FSM_ASM_IN_TOOLCHAIN)
|
||||||
|
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OBJECT
|
||||||
|
"${CMAKE_COMMAND} \
|
||||||
|
-DULP_FSM_PREPROCESSOR=${CMAKE_C_COMPILER} \
|
||||||
|
-DULP_FSM_ASSEMBLER=${CMAKE_ASM${ASM_DIALECT}_COMPILER} \
|
||||||
|
-DULP_FSM_TARGET=esp32 \
|
||||||
|
-DULP_FSM_SOURCE=<SOURCE> \
|
||||||
|
-DULP_FSM_OBJECT=<OBJECT> \
|
||||||
|
-P ${CMAKE_CURRENT_LIST_DIR}/preprocess_fsm_asm.cmake -- <DEFINES> <INCLUDES>")
|
||||||
|
else()
|
||||||
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OBJECT "${CMAKE_ASM${ASM_DIALECT}_COMPILER} \
|
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OBJECT "${CMAKE_ASM${ASM_DIALECT}_COMPILER} \
|
||||||
--mcpu=esp32 <DEFINES> <INCLUDES> -o <OBJECT> -c <SOURCE>")
|
--mcpu=esp32 <DEFINES> <INCLUDES> -o <OBJECT> -c <SOURCE>")
|
||||||
|
endif()
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "-A elf32-esp32ulp -nostdlib" CACHE STRING "ULP Linker Base Flags")
|
set(CMAKE_EXE_LINKER_FLAGS "-A elf32-esp32ulp -nostdlib" CACHE STRING "ULP Linker Base Flags")
|
||||||
set(CMAKE_ASM_LINK_EXECUTABLE "${CMAKE_LINKER} <FLAGS> <CMAKE_ASM_LINK_FLAGS> \
|
set(CMAKE_ASM_LINK_EXECUTABLE "${CMAKE_LINKER} <FLAGS> <CMAKE_ASM_LINK_FLAGS> \
|
||||||
<LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
|
<LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
|
||||||
|
|||||||
@@ -9,8 +9,28 @@ set(CMAKE_ASM_COMPILER "esp32ulp-elf-as")
|
|||||||
set(CMAKE_OBJCOPY "esp32ulp-elf-objcopy")
|
set(CMAKE_OBJCOPY "esp32ulp-elf-objcopy")
|
||||||
set(CMAKE_LINKER "esp32ulp-elf-ld")
|
set(CMAKE_LINKER "esp32ulp-elf-ld")
|
||||||
|
|
||||||
|
# Native CMake v2 ULP projects include cmakev2/idf.cmake before project(),
|
||||||
|
# making idf_project_init visible when this toolchain is loaded. Legacy child
|
||||||
|
# projects, even when launched by a CMake v2 parent, include the old IDF CMake
|
||||||
|
# entrypoint and keep the historical explicit preprocessing path.
|
||||||
|
set(ULP_PREPROCESS_FSM_ASM_IN_TOOLCHAIN OFF)
|
||||||
|
if(IDF_BUILD_V2 AND COMMAND idf_project_init)
|
||||||
|
set(ULP_PREPROCESS_FSM_ASM_IN_TOOLCHAIN ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(ULP_PREPROCESS_FSM_ASM_IN_TOOLCHAIN)
|
||||||
|
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OBJECT
|
||||||
|
"${CMAKE_COMMAND} \
|
||||||
|
-DULP_FSM_PREPROCESSOR=${CMAKE_C_COMPILER} \
|
||||||
|
-DULP_FSM_ASSEMBLER=${CMAKE_ASM${ASM_DIALECT}_COMPILER} \
|
||||||
|
-DULP_FSM_TARGET=esp32s2 \
|
||||||
|
-DULP_FSM_SOURCE=<SOURCE> \
|
||||||
|
-DULP_FSM_OBJECT=<OBJECT> \
|
||||||
|
-P ${CMAKE_CURRENT_LIST_DIR}/preprocess_fsm_asm.cmake -- <DEFINES> <INCLUDES>")
|
||||||
|
else()
|
||||||
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OBJECT "${CMAKE_ASM${ASM_DIALECT}_COMPILER} \
|
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OBJECT "${CMAKE_ASM${ASM_DIALECT}_COMPILER} \
|
||||||
--mcpu=esp32s2 <DEFINES> <INCLUDES> -o <OBJECT> -c <SOURCE>")
|
--mcpu=esp32s2 <DEFINES> <INCLUDES> -o <OBJECT> -c <SOURCE>")
|
||||||
|
endif()
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "-A elf32-esp32s2ulp -nostdlib" CACHE STRING "ULP Linker Base Flags")
|
set(CMAKE_EXE_LINKER_FLAGS "-A elf32-esp32s2ulp -nostdlib" CACHE STRING "ULP Linker Base Flags")
|
||||||
set(CMAKE_ASM_LINK_EXECUTABLE "${CMAKE_LINKER} <FLAGS> <CMAKE_ASM_LINK_FLAGS> \
|
set(CMAKE_ASM_LINK_EXECUTABLE "${CMAKE_LINKER} <FLAGS> <CMAKE_ASM_LINK_FLAGS> \
|
||||||
<LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
|
<LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
|
||||||
|
|||||||
@@ -9,8 +9,28 @@ set(CMAKE_ASM_COMPILER "esp32ulp-elf-as")
|
|||||||
set(CMAKE_OBJCOPY "esp32ulp-elf-objcopy")
|
set(CMAKE_OBJCOPY "esp32ulp-elf-objcopy")
|
||||||
set(CMAKE_LINKER "esp32ulp-elf-ld")
|
set(CMAKE_LINKER "esp32ulp-elf-ld")
|
||||||
|
|
||||||
|
# Native CMake v2 ULP projects include cmakev2/idf.cmake before project(),
|
||||||
|
# making idf_project_init visible when this toolchain is loaded. Legacy child
|
||||||
|
# projects, even when launched by a CMake v2 parent, include the old IDF CMake
|
||||||
|
# entrypoint and keep the historical explicit preprocessing path.
|
||||||
|
set(ULP_PREPROCESS_FSM_ASM_IN_TOOLCHAIN OFF)
|
||||||
|
if(IDF_BUILD_V2 AND COMMAND idf_project_init)
|
||||||
|
set(ULP_PREPROCESS_FSM_ASM_IN_TOOLCHAIN ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(ULP_PREPROCESS_FSM_ASM_IN_TOOLCHAIN)
|
||||||
|
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OBJECT
|
||||||
|
"${CMAKE_COMMAND} \
|
||||||
|
-DULP_FSM_PREPROCESSOR=${CMAKE_C_COMPILER} \
|
||||||
|
-DULP_FSM_ASSEMBLER=${CMAKE_ASM${ASM_DIALECT}_COMPILER} \
|
||||||
|
-DULP_FSM_TARGET=esp32s3 \
|
||||||
|
-DULP_FSM_SOURCE=<SOURCE> \
|
||||||
|
-DULP_FSM_OBJECT=<OBJECT> \
|
||||||
|
-P ${CMAKE_CURRENT_LIST_DIR}/preprocess_fsm_asm.cmake -- <DEFINES> <INCLUDES>")
|
||||||
|
else()
|
||||||
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OBJECT "${CMAKE_ASM${ASM_DIALECT}_COMPILER} \
|
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OBJECT "${CMAKE_ASM${ASM_DIALECT}_COMPILER} \
|
||||||
--mcpu=esp32s3 <DEFINES> <INCLUDES> -o <OBJECT> -c <SOURCE>")
|
--mcpu=esp32s3 <DEFINES> <INCLUDES> -o <OBJECT> -c <SOURCE>")
|
||||||
|
endif()
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "-A elf32-esp32s3ulp -nostdlib" CACHE STRING "ULP Linker Base Flags")
|
set(CMAKE_EXE_LINKER_FLAGS "-A elf32-esp32s3ulp -nostdlib" CACHE STRING "ULP Linker Base Flags")
|
||||||
set(CMAKE_ASM_LINK_EXECUTABLE "${CMAKE_LINKER} <FLAGS> <CMAKE_ASM_LINK_FLAGS> \
|
set(CMAKE_ASM_LINK_EXECUTABLE "${CMAKE_LINKER} <FLAGS> <CMAKE_ASM_LINK_FLAGS> \
|
||||||
<LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
|
<LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
|
||||||
|
|||||||
@@ -0,0 +1,188 @@
|
|||||||
|
# ULP subproject entry point for CMake v2 full-subproject builds.
|
||||||
|
#
|
||||||
|
# A ULP child project includes this file instead of tools/cmakev2/idf.cmake
|
||||||
|
# directly. It pulls in the cmakev2 build system and layers the ULP subproject
|
||||||
|
# API on top: ulp_project_init, ulp_build_executable, ulp_build_binary and
|
||||||
|
# ulp_project_default, the ULP analogs of idf_project_init,
|
||||||
|
# idf_build_executable, idf_build_binary and idf_project_default.
|
||||||
|
|
||||||
|
include(${IDF_PATH}/tools/cmakev2/idf.cmake)
|
||||||
|
include(${CMAKE_CURRENT_LIST_DIR}/IDFULPProjectCommon.cmake)
|
||||||
|
|
||||||
|
# Reset the compile/link state inherited from the parent app build and select
|
||||||
|
# ULP-specific build behavior. Idempotent within a child configure.
|
||||||
|
function(__ulp_prepare_build)
|
||||||
|
idf_build_get_property(ulp_build_prepared __ULP_BUILD_PREPARED)
|
||||||
|
if(ulp_build_prepared)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(BUILD_FSM)
|
||||||
|
check_expected_tool_version("esp32ulp-elf" ${CMAKE_ASM_COMPILER})
|
||||||
|
# FSM links with esp32ulp-elf-ld directly, not through GCC, so avoid
|
||||||
|
# GCC-driver link grouping flags from the generic executable helper.
|
||||||
|
idf_build_set_property(LINKER_TYPE ULP_FSM)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# ULP projects use their own toolchain files and component-provided options,
|
||||||
|
# so discard compile/link options added for normal app builds.
|
||||||
|
foreach(property IN ITEMS
|
||||||
|
COMPILE_OPTIONS
|
||||||
|
C_COMPILE_OPTIONS
|
||||||
|
CXX_COMPILE_OPTIONS
|
||||||
|
ASM_COMPILE_OPTIONS
|
||||||
|
COMPILE_DEFINITIONS
|
||||||
|
LINK_OPTIONS)
|
||||||
|
idf_build_set_property(${property} "")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# Do not apply the default app component closure to ULP child projects.
|
||||||
|
# ULP components should contribute dependencies explicitly.
|
||||||
|
idf_build_set_property(__COMPONENT_REQUIRES_COMMON "")
|
||||||
|
idf_build_set_property(__COMMON_COMPONENT_INTERFACES "")
|
||||||
|
idf_build_set_property(__COMMON_COMPONENTS_INITIALIZED YES)
|
||||||
|
|
||||||
|
idf_build_set_property(__ULP_BUILD_PREPARED YES)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
#[[api
|
||||||
|
.. cmakev2:macro:: ulp_project_init
|
||||||
|
|
||||||
|
.. code-block:: cmake
|
||||||
|
|
||||||
|
ulp_project_init()
|
||||||
|
|
||||||
|
Initialize a ULP full-subproject build. Calls :cmakev2:ref:`idf_project_init`
|
||||||
|
and then applies the ULP-specific setup: it detects the ULP type (RISC-V, LP
|
||||||
|
core or FSM) from the ``ULP_TYPE`` variable or the project configuration and
|
||||||
|
resets the compile and link options inherited from the parent application
|
||||||
|
build, so the ULP executable uses only its own toolchain and
|
||||||
|
component-provided options.
|
||||||
|
|
||||||
|
This is the ULP analog of :cmakev2:ref:`idf_project_init` and is the entry
|
||||||
|
point for projects that build more than one ULP executable, followed by
|
||||||
|
:cmakev2:ref:`ulp_build_executable` and :cmakev2:ref:`ulp_build_binary`
|
||||||
|
calls. For the common single-executable case use
|
||||||
|
:cmakev2:ref:`ulp_project_default` instead.
|
||||||
|
#]]
|
||||||
|
macro(ulp_project_init)
|
||||||
|
idf_project_init()
|
||||||
|
ulp_detect_build_type()
|
||||||
|
ulp_apply_build_type_options()
|
||||||
|
__ulp_prepare_build()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
#[[api
|
||||||
|
.. cmakev2:function:: ulp_build_executable
|
||||||
|
|
||||||
|
.. code-block:: cmake
|
||||||
|
|
||||||
|
ulp_build_executable(<executable>
|
||||||
|
[COMPONENTS <component>...]
|
||||||
|
[MAPFILE_TARGET <target>])
|
||||||
|
|
||||||
|
*executable[in]*
|
||||||
|
|
||||||
|
Name of the ULP executable target to create.
|
||||||
|
|
||||||
|
Build a ULP executable. This is the ULP analog of
|
||||||
|
:cmakev2:ref:`idf_build_executable` and forwards its arguments to
|
||||||
|
:cmakev2:ref:`idf_build_executable`. Call :cmakev2:ref:`ulp_build_binary`
|
||||||
|
for each executable that should produce embeddable ULP artifacts.
|
||||||
|
#]]
|
||||||
|
function(ulp_build_executable executable)
|
||||||
|
if("PREFIX" IN_LIST ARGN)
|
||||||
|
message(FATAL_ERROR "Use ulp_build_binary(${executable} PREFIX ...) to set ULP symbol prefixes.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
idf_build_executable(${executable} ${ARGN})
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
#[[api
|
||||||
|
.. cmakev2:function:: ulp_build_binary
|
||||||
|
|
||||||
|
.. code-block:: cmake
|
||||||
|
|
||||||
|
ulp_build_binary(<executable>
|
||||||
|
[PREFIX <prefix>])
|
||||||
|
|
||||||
|
*executable[in]*
|
||||||
|
|
||||||
|
ULP executable target for which to generate embeddable artifacts.
|
||||||
|
|
||||||
|
*PREFIX[in,opt]*
|
||||||
|
|
||||||
|
Symbol name prefix for the generated symbol header and linker export
|
||||||
|
files. Defaults to ``ulp_``. Use a distinct prefix per executable when a
|
||||||
|
project builds several ULP binaries.
|
||||||
|
|
||||||
|
Generate the ``.bin`` payload and symbol header/linker export files for a
|
||||||
|
ULP executable. This is the ULP analog of :cmakev2:ref:`idf_build_binary`.
|
||||||
|
#]]
|
||||||
|
function(ulp_build_binary executable)
|
||||||
|
cmake_parse_arguments(_ULP "" "PREFIX" "" ${ARGN})
|
||||||
|
if(_ULP_UNPARSED_ARGUMENTS)
|
||||||
|
message(FATAL_ERROR "Unexpected arguments to ulp_build_binary(): ${_ULP_UNPARSED_ARGUMENTS}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(DEFINED _ULP_PREFIX)
|
||||||
|
ulp_add_build_binary_targets(${executable} PREFIX "${_ULP_PREFIX}")
|
||||||
|
elseif(ULP_PREFIX_APPEND_BIN_NAME)
|
||||||
|
set(prefix "ulp_")
|
||||||
|
if(DEFINED ULP_VAR_PREFIX)
|
||||||
|
set(prefix "${ULP_VAR_PREFIX}")
|
||||||
|
endif()
|
||||||
|
string(MAKE_C_IDENTIFIER "${prefix}${executable}_" prefix)
|
||||||
|
ulp_add_build_binary_targets(${executable} PREFIX "${prefix}")
|
||||||
|
else()
|
||||||
|
ulp_add_build_binary_targets("${executable}")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# Build the single default ULP executable from the main component.
|
||||||
|
function(__ulp_project_default)
|
||||||
|
set(ulp_app_name "${PROJECT_NAME}")
|
||||||
|
|
||||||
|
set(executable_args COMPONENTS main)
|
||||||
|
set(binary_args)
|
||||||
|
if(NOT BUILD_FSM)
|
||||||
|
list(APPEND executable_args MAPFILE_TARGET ${ulp_app_name}_mapfile)
|
||||||
|
endif()
|
||||||
|
if(DEFINED ULP_VAR_PREFIX AND NOT "${ULP_VAR_PREFIX}" STREQUAL "")
|
||||||
|
list(APPEND binary_args PREFIX ${ULP_VAR_PREFIX})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
ulp_build_executable(${ulp_app_name} ${executable_args})
|
||||||
|
ulp_build_binary(${ulp_app_name} ${binary_args})
|
||||||
|
|
||||||
|
idf_build_generate_metadata(EXECUTABLE ${ulp_app_name})
|
||||||
|
|
||||||
|
if(TARGET "${ulp_app_name}_mapfile")
|
||||||
|
idf_create_size_report("${ulp_app_name}_mapfile" TARGET size)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
idf_build_generate_depgraph("${ulp_app_name}")
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
#[[api
|
||||||
|
.. cmakev2:macro:: ulp_project_default
|
||||||
|
|
||||||
|
.. code-block:: cmake
|
||||||
|
|
||||||
|
ulp_project_default()
|
||||||
|
|
||||||
|
Build a single ULP executable from the ``main`` component and its transitive
|
||||||
|
dependencies, the ULP analog of :cmakev2:ref:`idf_project_default`. Calls
|
||||||
|
:cmakev2:ref:`ulp_project_init`, then builds the executable (named after
|
||||||
|
``PROJECT_NAME``) with :cmakev2:ref:`ulp_build_executable` and generates its
|
||||||
|
embeddable artifacts with :cmakev2:ref:`ulp_build_binary`.
|
||||||
|
#]]
|
||||||
|
macro(ulp_project_default)
|
||||||
|
ulp_project_init()
|
||||||
|
|
||||||
|
# A single executable is built, so DEFERRED optional-requires resolution is
|
||||||
|
# safe and keeps the linked component set minimal.
|
||||||
|
idf_build_set_property(IDF_COMPONENT_OPTIONAL_REQUIRES_MODE DEFERRED)
|
||||||
|
|
||||||
|
__ulp_project_default()
|
||||||
|
endmacro()
|
||||||
@@ -1,10 +1,16 @@
|
|||||||
|
if(IDF_BUILD_V2 AND __ULP_BUILD)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
# ulp_embed_binary
|
# ulp_embed_binary
|
||||||
#
|
#
|
||||||
# Create ULP binary and embed into the application.
|
# Create ULP binary and embed into the application.
|
||||||
|
|
||||||
function(__setup_ulp_project app_name project_path prefix type s_sources exp_dep_srcs)
|
function(__setup_ulp_project app_name project_path prefix prefix_append_bin_name type binary_names
|
||||||
|
s_sources exp_dep_srcs)
|
||||||
|
|
||||||
if(NOT CMAKE_BUILD_EARLY_EXPANSION)
|
if(NOT CMAKE_BUILD_EARLY_EXPANSION)
|
||||||
|
set(ulp_cmake_dir "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/cmake")
|
||||||
set(sources "")
|
set(sources "")
|
||||||
spaces2list(s_sources)
|
spaces2list(s_sources)
|
||||||
foreach(source ${s_sources})
|
foreach(source ${s_sources})
|
||||||
@@ -12,28 +18,69 @@ function(__setup_ulp_project app_name project_path prefix type s_sources exp_dep
|
|||||||
list(APPEND sources ${source})
|
list(APPEND sources ${source})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
|
# In cmakev2, anchor the ULP sub-project's binary dir to the parent's
|
||||||
|
# BUILD_DIR so it is not nested under the component that happened to
|
||||||
|
# register it, and so that wiping the parent build dir removes the ULP
|
||||||
|
# artifacts together with any child-owned sdkconfig.
|
||||||
|
if(IDF_BUILD_V2)
|
||||||
|
idf_build_get_property(build_dir BUILD_DIR)
|
||||||
|
set(ulp_binary_dir "${build_dir}/subprojects/${app_name}")
|
||||||
|
|
||||||
|
# Safety net for cases where the build directory is not wiped
|
||||||
|
# before changing target (e.g. someone reconfigures directly via
|
||||||
|
# `cmake -B build -DIDF_TARGET=...` instead of `idf.py set-target`,
|
||||||
|
# which would normally pull in `fullclean` and remove the whole
|
||||||
|
# build tree). When `_IDF_PY_SET_TARGET_ACTION=1` is set, mirror
|
||||||
|
# what the parent does to its own sdkconfig (cmakev1 renames it,
|
||||||
|
# cmakev2 relaxes the consistency check) and move the sub-project's
|
||||||
|
# sdkconfig aside. The ULP's externalproject_add configure is lazy
|
||||||
|
# and runs after the parent's configure exits, so by then
|
||||||
|
# _IDF_PY_SET_TARGET_ACTION is no longer in the environment.
|
||||||
|
# Without this, a stale sub-project sdkconfig from a previous
|
||||||
|
# target would trip the cross-check inside the ULP's
|
||||||
|
# __init_idf_target.
|
||||||
|
set(ulp_sdkconfig "${ulp_binary_dir}/sdkconfig")
|
||||||
|
if("$ENV{_IDF_PY_SET_TARGET_ACTION}" STREQUAL "1" AND EXISTS "${ulp_sdkconfig}")
|
||||||
|
file(RENAME "${ulp_sdkconfig}" "${ulp_sdkconfig}.old")
|
||||||
|
message(STATUS "Existing sub-project sdkconfig '${ulp_sdkconfig}' "
|
||||||
|
"renamed to '${ulp_sdkconfig}.old'.")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
set(ulp_binary_dir "${CMAKE_CURRENT_BINARY_DIR}/${app_name}")
|
||||||
|
endif()
|
||||||
|
|
||||||
foreach(source ${sources})
|
foreach(source ${sources})
|
||||||
get_filename_component(ps_source ${source} NAME_WE)
|
get_filename_component(ps_source ${source} NAME_WE)
|
||||||
set(ps_output ${CMAKE_CURRENT_BINARY_DIR}/${app_name}/${ps_source}.ulp.S)
|
set(ps_output ${ulp_binary_dir}/${ps_source}.ulp.S)
|
||||||
list(APPEND ps_sources ${ps_output})
|
list(APPEND ps_sources ${ps_output})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
set(ulp_artifacts_prefix ${CMAKE_CURRENT_BINARY_DIR}/${app_name}/${app_name})
|
if(NOT binary_names)
|
||||||
|
set(binary_names "${app_name}")
|
||||||
|
endif()
|
||||||
|
|
||||||
set(ulp_artifacts ${ulp_artifacts_prefix}.bin
|
# Full ULP subprojects may emit multiple binaries. Embed each declared
|
||||||
|
# output in the main app so runtime code can choose which ULP program
|
||||||
|
# to load.
|
||||||
|
foreach(binary_name IN LISTS binary_names)
|
||||||
|
set(ulp_artifacts_prefix ${ulp_binary_dir}/${binary_name})
|
||||||
|
|
||||||
|
list(APPEND ulp_artifacts
|
||||||
|
${ulp_artifacts_prefix}.bin
|
||||||
${ulp_artifacts_prefix}.ld
|
${ulp_artifacts_prefix}.ld
|
||||||
${ulp_artifacts_prefix}.h)
|
${ulp_artifacts_prefix}.h)
|
||||||
|
|
||||||
set(ulp_artifacts_extras ${ulp_artifacts_prefix}.map
|
list(APPEND ulp_artifacts_extras
|
||||||
|
${ulp_artifacts_prefix}.map
|
||||||
${ulp_artifacts_prefix}.sym
|
${ulp_artifacts_prefix}.sym
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/${app_name}/esp32.ulp.ld)
|
${ulp_binary_dir}/${binary_name}.elf)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
# Replace the separator for the list of ULP source files that will be passed to
|
# Replace the separator for the list of ULP source files that will be passed to
|
||||||
# the external ULP project. This is a workaround to the bug https://public.kitware.com/Bug/view.php?id=16137.
|
# the external ULP project. This is a workaround to the bug https://public.kitware.com/Bug/view.php?id=16137.
|
||||||
string(REPLACE ";" "|" ulp_s_sources "${ulp_s_sources}")
|
string(REPLACE ";" "|" ulp_s_sources "${ulp_s_sources}")
|
||||||
|
|
||||||
idf_build_get_property(sdkconfig_header SDKCONFIG_HEADER)
|
idf_build_get_property(sdkconfig SDKCONFIG)
|
||||||
idf_build_get_property(sdkconfig_cmake SDKCONFIG_CMAKE)
|
|
||||||
idf_build_get_property(idf_path IDF_PATH)
|
idf_build_get_property(idf_path IDF_PATH)
|
||||||
idf_build_get_property(idf_target IDF_TARGET)
|
idf_build_get_property(idf_target IDF_TARGET)
|
||||||
idf_build_get_property(python PYTHON)
|
idf_build_get_property(python PYTHON)
|
||||||
@@ -48,7 +95,7 @@ function(__setup_ulp_project app_name project_path prefix type s_sources exp_dep
|
|||||||
"Only FSM type is available for ULP on this target.")
|
"Only FSM type is available for ULP on this target.")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
set(TOOLCHAIN_FLAG ${idf_path}/components/ulp/cmake/toolchain-${idf_target}-ulp.cmake)
|
set(TOOLCHAIN_FLAG ${ulp_cmake_dir}/toolchain-${idf_target}-ulp.cmake)
|
||||||
set(ULP_IS_RISCV OFF)
|
set(ULP_IS_RISCV OFF)
|
||||||
elseif(IDF_TARGET STREQUAL "esp32s2" OR IDF_TARGET STREQUAL "esp32s3")
|
elseif(IDF_TARGET STREQUAL "esp32s2" OR IDF_TARGET STREQUAL "esp32s3")
|
||||||
# If both FSM and RISC-V are enabled in sdkconfig and a TYPE was
|
# If both FSM and RISC-V are enabled in sdkconfig and a TYPE was
|
||||||
@@ -58,63 +105,118 @@ function(__setup_ulp_project app_name project_path prefix type s_sources exp_dep
|
|||||||
message(STATUS "Both RISCV and FSM are enabled, using '${type}' toolchain for ${app_name} ULP project.")
|
message(STATUS "Both RISCV and FSM are enabled, using '${type}' toolchain for ${app_name} ULP project.")
|
||||||
string(TOLOWER "${type}" type_lower)
|
string(TOLOWER "${type}" type_lower)
|
||||||
if(type_lower STREQUAL "riscv")
|
if(type_lower STREQUAL "riscv")
|
||||||
set(TOOLCHAIN_FLAG ${idf_path}/components/ulp/cmake/toolchain-ulp-riscv.cmake)
|
set(TOOLCHAIN_FLAG ${ulp_cmake_dir}/toolchain-ulp-riscv.cmake)
|
||||||
elseif(type_lower STREQUAL "fsm")
|
elseif(type_lower STREQUAL "fsm")
|
||||||
set(TOOLCHAIN_FLAG ${idf_path}/components/ulp/cmake/toolchain-${idf_target}-ulp.cmake)
|
set(TOOLCHAIN_FLAG ${ulp_cmake_dir}/toolchain-${idf_target}-ulp.cmake)
|
||||||
else()
|
else()
|
||||||
message(FATAL_ERROR "Invalid ULP_TYPE '${type}'; expected 'fsm' or 'riscv'.")
|
message(FATAL_ERROR "Invalid ULP_TYPE '${type}'; expected 'fsm' or 'riscv'.")
|
||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
if(CONFIG_ULP_COPROC_TYPE_RISCV STREQUAL "y")
|
if(CONFIG_ULP_COPROC_TYPE_RISCV STREQUAL "y")
|
||||||
set(TOOLCHAIN_FLAG ${idf_path}/components/ulp/cmake/toolchain-ulp-riscv.cmake)
|
set(TOOLCHAIN_FLAG ${ulp_cmake_dir}/toolchain-ulp-riscv.cmake)
|
||||||
else()
|
else()
|
||||||
set(TOOLCHAIN_FLAG ${idf_path}/components/ulp/cmake/toolchain-${idf_target}-ulp.cmake)
|
set(TOOLCHAIN_FLAG ${ulp_cmake_dir}/toolchain-${idf_target}-ulp.cmake)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
elseif(CONFIG_ULP_COPROC_TYPE_LP_CORE)
|
elseif(CONFIG_ULP_COPROC_TYPE_LP_CORE)
|
||||||
set(TOOLCHAIN_FLAG ${idf_path}/components/ulp/cmake/toolchain-lp-core-riscv.cmake)
|
set(TOOLCHAIN_FLAG ${ulp_cmake_dir}/toolchain-lp-core-riscv.cmake)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(ulp_project_args)
|
||||||
|
if(IDF_BUILD_V2)
|
||||||
|
set(ulp_project_args
|
||||||
|
# The parent passes a superset of variables that different ULP
|
||||||
|
# subproject styles consume (e.g. ULP_VAR_PREFIX only by
|
||||||
|
# ulp_project_default, COMPONENT_INCLUDES only by hand-written
|
||||||
|
# subprojects). Do not warn about the ones a given child ignores.
|
||||||
|
--no-warn-unused-cli
|
||||||
|
-DIDF_DEFAULT_PROJECT_NAME=${app_name}
|
||||||
|
-DIDF_BUILD_V2=y
|
||||||
|
# Internal marker for the ULP child project component graph.
|
||||||
|
-D__ULP_BUILD=1
|
||||||
|
-DIDF_PARENT_BUILD_DIR=${build_dir}
|
||||||
|
-DULP_PREFIX_APPEND_BIN_NAME=${prefix_append_bin_name}
|
||||||
|
-DSDKCONFIG=${sdkconfig}
|
||||||
|
-DSDKCONFIG_HEADER=${SDKCONFIG_HEADER}
|
||||||
|
-DSDKCONFIG_CMAKE=${SDKCONFIG_CMAKE}
|
||||||
|
-DSDKCONFIG_DEFAULTS=
|
||||||
|
-DGENERATE_SDKCONFIG=0
|
||||||
|
-DDEPENDENCIES_LOCK=${ulp_binary_dir}/dependencies.lock
|
||||||
|
# All ULP child builds use ULP-specific toolchain files today.
|
||||||
|
# LP core and ULP RISC-V are GCC-based and could eventually
|
||||||
|
# share more of the normal IDF app toolchain response-file
|
||||||
|
# setup, but keep them under IDF_CUSTOM_TOOLCHAIN for now.
|
||||||
|
-DIDF_CUSTOM_TOOLCHAIN=1)
|
||||||
|
if(s_sources)
|
||||||
|
list(APPEND ulp_project_args
|
||||||
|
-DULP_S_SOURCES=$<TARGET_PROPERTY:${app_name},ULP_SOURCES>)
|
||||||
|
endif()
|
||||||
|
if(DEFINED COMPONENT_TARGET AND TARGET ${COMPONENT_TARGET})
|
||||||
|
# Backward compatibility for existing ULP subprojects that
|
||||||
|
# include headers from the parent component. New full
|
||||||
|
# subprojects should declare their own component include
|
||||||
|
# directories and dependencies instead.
|
||||||
|
list(APPEND ulp_project_args
|
||||||
|
-DCOMPONENT_INCLUDES=$<TARGET_PROPERTY:${COMPONENT_TARGET},INTERFACE_INCLUDE_DIRECTORIES>)
|
||||||
|
endif()
|
||||||
|
if(COMPONENT_DIR)
|
||||||
|
list(APPEND ulp_project_args
|
||||||
|
-DCOMPONENT_DIR=${COMPONENT_DIR})
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
list(APPEND ulp_project_args
|
||||||
|
-DULP_S_SOURCES=$<TARGET_PROPERTY:${app_name},ULP_SOURCES>
|
||||||
|
-DULP_APP_NAME=${app_name}
|
||||||
|
-DCOMPONENT_DIR=${COMPONENT_DIR}
|
||||||
|
-DCOMPONENT_INCLUDES=$<TARGET_PROPERTY:${COMPONENT_TARGET},INTERFACE_INCLUDE_DIRECTORIES>
|
||||||
|
-DSDKCONFIG_HEADER=${SDKCONFIG_HEADER}
|
||||||
|
-DSDKCONFIG_CMAKE=${SDKCONFIG_CMAKE}
|
||||||
|
# The v1 ULP child resolves include(IDFULPProject) via the module path.
|
||||||
|
-DCMAKE_MODULE_PATH=${ulp_cmake_dir})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
externalproject_add(${app_name}
|
externalproject_add(${app_name}
|
||||||
SOURCE_DIR ${project_path}
|
SOURCE_DIR ${project_path}
|
||||||
BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${app_name}
|
BINARY_DIR ${ulp_binary_dir}
|
||||||
INSTALL_COMMAND ""
|
INSTALL_COMMAND ""
|
||||||
CMAKE_ARGS -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
|
CMAKE_ARGS -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
|
||||||
-DCMAKE_GENERATOR=${CMAKE_GENERATOR}
|
-DCMAKE_GENERATOR=${CMAKE_GENERATOR}
|
||||||
-DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FLAG}
|
-DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FLAG}
|
||||||
-DULP_S_SOURCES=$<TARGET_PROPERTY:${app_name},ULP_SOURCES>
|
|
||||||
-DULP_APP_NAME=${app_name}
|
|
||||||
-DADD_PICOLIBC_SPECS=${CONFIG_LIBC_PICOLIBC}
|
-DADD_PICOLIBC_SPECS=${CONFIG_LIBC_PICOLIBC}
|
||||||
-DULP_VAR_PREFIX=${prefix}
|
-DULP_VAR_PREFIX=${prefix}
|
||||||
-DULP_TYPE=${type}
|
-DULP_TYPE=${type}
|
||||||
-DCOMPONENT_DIR=${COMPONENT_DIR}
|
${ulp_project_args}
|
||||||
-DCOMPONENT_INCLUDES=$<TARGET_PROPERTY:${COMPONENT_TARGET},INTERFACE_INCLUDE_DIRECTORIES>
|
|
||||||
-DIDF_TARGET=${idf_target}
|
-DIDF_TARGET=${idf_target}
|
||||||
-DIDF_PATH=${idf_path}
|
-DIDF_PATH=${idf_path}
|
||||||
-DSDKCONFIG_HEADER=${SDKCONFIG_HEADER}
|
|
||||||
-DSDKCONFIG_CMAKE=${SDKCONFIG_CMAKE}
|
|
||||||
-DPYTHON=${python}
|
-DPYTHON=${python}
|
||||||
-DCMAKE_MODULE_PATH=${idf_path}/components/ulp/cmake/
|
|
||||||
${extra_cmake_args}
|
${extra_cmake_args}
|
||||||
BUILD_COMMAND ${CMAKE_COMMAND} --build ${CMAKE_CURRENT_BINARY_DIR}/${app_name} --target build
|
BUILD_COMMAND ${CMAKE_COMMAND} --build ${ulp_binary_dir} --target build
|
||||||
BUILD_BYPRODUCTS ${ulp_artifacts} ${ulp_artifacts_extras} ${ulp_ps_sources}
|
BUILD_BYPRODUCTS ${ulp_artifacts} ${ulp_artifacts_extras} ${ulp_ps_sources}
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/${app_name}/${app_name}
|
${ulp_binary_dir}/${app_name}
|
||||||
BUILD_ALWAYS 1
|
BUILD_ALWAYS 1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Only the CMake v1 path reads this property when passing ULP_S_SOURCES
|
||||||
|
# to the child project. Leaving it set for v2 is harmless and keeps the
|
||||||
|
# post-ExternalProject artifact wiring common. Can be dropped when
|
||||||
|
# v1 support is dropped.
|
||||||
set_property(TARGET ${app_name} PROPERTY ULP_SOURCES "${sources}")
|
set_property(TARGET ${app_name} PROPERTY ULP_SOURCES "${sources}")
|
||||||
|
|
||||||
spaces2list(exp_dep_srcs)
|
spaces2list(exp_dep_srcs)
|
||||||
|
if(exp_dep_srcs)
|
||||||
set_source_files_properties(${exp_dep_srcs} PROPERTIES OBJECT_DEPENDS ${ulp_artifacts})
|
set_source_files_properties(${exp_dep_srcs} PROPERTIES OBJECT_DEPENDS ${ulp_artifacts})
|
||||||
|
endif()
|
||||||
|
|
||||||
include_directories(${CMAKE_CURRENT_BINARY_DIR}/${app_name})
|
include_directories(${ulp_binary_dir})
|
||||||
|
|
||||||
add_custom_target(${app_name}_artifacts DEPENDS ${app_name})
|
add_custom_target(${app_name}_artifacts DEPENDS ${app_name})
|
||||||
|
|
||||||
add_dependencies(${COMPONENT_LIB} ${app_name}_artifacts)
|
add_dependencies(${COMPONENT_LIB} ${app_name}_artifacts)
|
||||||
|
|
||||||
target_linker_script(${COMPONENT_LIB} INTERFACE ${CMAKE_CURRENT_BINARY_DIR}/${app_name}/${app_name}.ld)
|
foreach(binary_name IN LISTS binary_names)
|
||||||
target_add_binary_data(${COMPONENT_LIB} ${CMAKE_CURRENT_BINARY_DIR}/${app_name}/${app_name}.bin BINARY)
|
target_linker_script(${COMPONENT_LIB} INTERFACE ${ulp_binary_dir}/${binary_name}.ld)
|
||||||
|
target_add_binary_data(${COMPONENT_LIB} ${ulp_binary_dir}/${binary_name}.bin BINARY)
|
||||||
|
endforeach()
|
||||||
endif()
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
@@ -139,6 +241,23 @@ function(validate_ulp_type ULP_TYPE)
|
|||||||
endif()
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
function(__ulp_resolve_type out_var type)
|
||||||
|
# CMake v2 ULP subprojects receive an explicit ULP_TYPE argument because the
|
||||||
|
# child project uses it to choose the component graph. CMake v1 legacy builds
|
||||||
|
# keep the historical empty/uppercase TYPE handling in __setup_ulp_project.
|
||||||
|
if(type)
|
||||||
|
string(TOLOWER "${type}" resolved_type)
|
||||||
|
elseif(CONFIG_ULP_COPROC_TYPE_RISCV)
|
||||||
|
set(resolved_type "riscv")
|
||||||
|
elseif(CONFIG_ULP_COPROC_TYPE_LP_CORE)
|
||||||
|
set(resolved_type "lp_core")
|
||||||
|
elseif(CONFIG_ULP_COPROC_TYPE_FSM)
|
||||||
|
set(resolved_type "fsm")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(${out_var} "${resolved_type}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
function(ulp_embed_binary app_name s_sources exp_dep_srcs)
|
function(ulp_embed_binary app_name s_sources exp_dep_srcs)
|
||||||
cmake_parse_arguments(ULP "" "PREFIX;TYPE" "" ${ARGN})
|
cmake_parse_arguments(ULP "" "PREFIX;TYPE" "" ${ARGN})
|
||||||
if(NOT ULP_PREFIX)
|
if(NOT ULP_PREFIX)
|
||||||
@@ -146,18 +265,38 @@ function(ulp_embed_binary app_name s_sources exp_dep_srcs)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
validate_ulp_type("${ULP_TYPE}")
|
validate_ulp_type("${ULP_TYPE}")
|
||||||
|
if(IDF_BUILD_V2)
|
||||||
|
__ulp_resolve_type(ULP_TYPE "${ULP_TYPE}")
|
||||||
|
endif()
|
||||||
|
set(ulp_cmake_dir "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/cmake")
|
||||||
|
|
||||||
__setup_ulp_project("${app_name}" "${idf_path}/components/ulp/cmake"
|
__setup_ulp_project("${app_name}" "${ulp_cmake_dir}"
|
||||||
"${ULP_PREFIX}" "${ULP_TYPE}" "${s_sources}" "${exp_dep_srcs}")
|
"${ULP_PREFIX}" FALSE "${ULP_TYPE}"
|
||||||
|
"${app_name}"
|
||||||
|
"${s_sources}" "${exp_dep_srcs}")
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
function(ulp_add_project app_name project_path)
|
function(ulp_add_project app_name project_path)
|
||||||
cmake_parse_arguments(ULP "" "PREFIX;TYPE" "" ${ARGN})
|
cmake_parse_arguments(ULP "" "PREFIX;TYPE" "BINARIES" ${ARGN})
|
||||||
|
if(NOT ULP_BINARIES)
|
||||||
|
set(ULP_BINARIES "${app_name}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
list(LENGTH ULP_BINARIES ULP_BINARY_COUNT)
|
||||||
|
set(ULP_PREFIX_APPEND_BIN_NAME FALSE)
|
||||||
|
if(IDF_BUILD_V2 AND ULP_BINARY_COUNT GREATER 1)
|
||||||
|
set(ULP_PREFIX_APPEND_BIN_NAME TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(NOT ULP_PREFIX)
|
if(NOT ULP_PREFIX)
|
||||||
set(ULP_PREFIX "ulp_")
|
set(ULP_PREFIX "ulp_")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
validate_ulp_type("${ULP_TYPE}")
|
validate_ulp_type("${ULP_TYPE}")
|
||||||
|
if(IDF_BUILD_V2)
|
||||||
|
__ulp_resolve_type(ULP_TYPE "${ULP_TYPE}")
|
||||||
|
endif()
|
||||||
|
|
||||||
__setup_ulp_project("${app_name}" "${project_path}" "${ULP_PREFIX}" "${ULP_TYPE}" "" "")
|
__setup_ulp_project("${app_name}" "${project_path}" "${ULP_PREFIX}"
|
||||||
|
"${ULP_PREFIX_APPEND_BIN_NAME}" "${ULP_TYPE}" "${ULP_BINARIES}" "" "")
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps
|
# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps
|
||||||
|
|
||||||
|
.ulp_legacy_buildv2_disable: &ulp_legacy_buildv2_disable
|
||||||
|
if: IDF_BUILD_V2 == "1"
|
||||||
|
reason: Legacy ULP apps are covered by CMake v1; buildv2 covers full_subproject ULP apps.
|
||||||
|
|
||||||
components/ulp/test_apps/lp_core/lp_core_basic_tests:
|
components/ulp/test_apps/lp_core/lp_core_basic_tests:
|
||||||
|
disable+:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
disable:
|
disable:
|
||||||
- if: SOC_LP_CORE_SUPPORTED != 1
|
- if: SOC_LP_CORE_SUPPORTED != 1
|
||||||
- if: CONFIG_NAME == "xtal" and SOC_CLK_LP_FAST_SUPPORT_XTAL != 1
|
- if: CONFIG_NAME == "xtal" and SOC_CLK_LP_FAST_SUPPORT_XTAL != 1
|
||||||
@@ -20,6 +26,8 @@ components/ulp/test_apps/lp_core/lp_core_basic_tests:
|
|||||||
|
|
||||||
|
|
||||||
components/ulp/test_apps/lp_core/lp_core_gpio_wakeup_tests:
|
components/ulp/test_apps/lp_core/lp_core_gpio_wakeup_tests:
|
||||||
|
disable:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
enable:
|
enable:
|
||||||
- if: (SOC_LP_CORE_SUPPORTED == 1) and (SOC_RTCIO_PIN_COUNT > 0) and (SOC_DEEP_SLEEP_SUPPORTED == 1) and (SOC_RTC_GPIO_EDGE_WAKEUP_SUPPORTED == 1)
|
- if: (SOC_LP_CORE_SUPPORTED == 1) and (SOC_RTCIO_PIN_COUNT > 0) and (SOC_DEEP_SLEEP_SUPPORTED == 1) and (SOC_RTC_GPIO_EDGE_WAKEUP_SUPPORTED == 1)
|
||||||
depends_components:
|
depends_components:
|
||||||
@@ -31,6 +39,8 @@ components/ulp/test_apps/lp_core/lp_core_gpio_wakeup_tests:
|
|||||||
|
|
||||||
|
|
||||||
components/ulp/test_apps/lp_core/lp_core_hp_mem:
|
components/ulp/test_apps/lp_core/lp_core_hp_mem:
|
||||||
|
disable+:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
disable:
|
disable:
|
||||||
- if: SOC_LP_CORE_SUPPORTED != 1
|
- if: SOC_LP_CORE_SUPPORTED != 1
|
||||||
depends_components:
|
depends_components:
|
||||||
@@ -41,6 +51,8 @@ components/ulp/test_apps/lp_core/lp_core_hp_mem:
|
|||||||
|
|
||||||
|
|
||||||
components/ulp/test_apps/lp_core/lp_core_hp_uart:
|
components/ulp/test_apps/lp_core/lp_core_hp_uart:
|
||||||
|
disable+:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
disable:
|
disable:
|
||||||
- if: SOC_LP_CORE_SUPPORTED != 1
|
- if: SOC_LP_CORE_SUPPORTED != 1
|
||||||
depends_components:
|
depends_components:
|
||||||
@@ -51,6 +63,8 @@ components/ulp/test_apps/lp_core/lp_core_hp_uart:
|
|||||||
|
|
||||||
|
|
||||||
components/ulp/test_apps/ulp_fsm:
|
components/ulp/test_apps/ulp_fsm:
|
||||||
|
disable:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
enable:
|
enable:
|
||||||
- if: SOC_ULP_FSM_SUPPORTED == 1
|
- if: SOC_ULP_FSM_SUPPORTED == 1
|
||||||
depends_components:
|
depends_components:
|
||||||
@@ -61,6 +75,8 @@ components/ulp/test_apps/ulp_fsm:
|
|||||||
|
|
||||||
|
|
||||||
components/ulp/test_apps/ulp_riscv:
|
components/ulp/test_apps/ulp_riscv:
|
||||||
|
disable+:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
disable:
|
disable:
|
||||||
- if: SOC_RISCV_COPROC_SUPPORTED != 1
|
- if: SOC_RISCV_COPROC_SUPPORTED != 1
|
||||||
depends_components:
|
depends_components:
|
||||||
|
|||||||
@@ -21,6 +21,12 @@ endif()
|
|||||||
message(STATUS "Compiler supported targets: ${dump_machine}")
|
message(STATUS "Compiler supported targets: ${dump_machine}")
|
||||||
|
|
||||||
if(NOT (${CMAKE_SYSTEM_NAME} STREQUAL "Generic" AND ${dump_machine} MATCHES xtensa))
|
if(NOT (${CMAKE_SYSTEM_NAME} STREQUAL "Generic" AND ${dump_machine} MATCHES xtensa))
|
||||||
|
# Sub-projects (e.g. ULP RISC-V on an xtensa target) may use a
|
||||||
|
# non-IDF toolchain provided by the parent build. Skip validation
|
||||||
|
# when a custom toolchain is explicitly declared.
|
||||||
|
if(IDF_CUSTOM_TOOLCHAIN)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
message(FATAL_ERROR "Internal error, toolchain has not been set correctly by project "
|
message(FATAL_ERROR "Internal error, toolchain has not been set correctly by project "
|
||||||
"(or an invalid CMakeCache.txt file has been generated somehow)")
|
"(or an invalid CMakeCache.txt file has been generated somehow)")
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -6,12 +6,20 @@
|
|||||||
- esp_hw_support
|
- esp_hw_support
|
||||||
- esp_hal_pmu
|
- esp_hal_pmu
|
||||||
|
|
||||||
|
.ulp_legacy_buildv2_disable: &ulp_legacy_buildv2_disable
|
||||||
|
if: IDF_BUILD_V2 == "1"
|
||||||
|
reason: Legacy ULP apps are covered by CMake v1; buildv2 covers full_subproject ULP apps.
|
||||||
|
|
||||||
examples/system/ulp/lp_core/build_system:
|
examples/system/ulp/lp_core/build_system:
|
||||||
|
disable:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
enable:
|
enable:
|
||||||
- if: SOC_LP_CORE_SUPPORTED == 1
|
- if: SOC_LP_CORE_SUPPORTED == 1
|
||||||
<<: *ulp_default_depends
|
<<: *ulp_default_depends
|
||||||
|
|
||||||
examples/system/ulp/lp_core/debugging:
|
examples/system/ulp/lp_core/debugging:
|
||||||
|
disable:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
enable:
|
enable:
|
||||||
- if: SOC_LP_CORE_SUPPORTED == 1
|
- if: SOC_LP_CORE_SUPPORTED == 1
|
||||||
disable_test:
|
disable_test:
|
||||||
@@ -21,6 +29,8 @@ examples/system/ulp/lp_core/debugging:
|
|||||||
<<: *ulp_default_depends
|
<<: *ulp_default_depends
|
||||||
|
|
||||||
examples/system/ulp/lp_core/gpio:
|
examples/system/ulp/lp_core/gpio:
|
||||||
|
disable+:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
disable:
|
disable:
|
||||||
- if: SOC_DEEP_SLEEP_SUPPORTED != 1
|
- if: SOC_DEEP_SLEEP_SUPPORTED != 1
|
||||||
enable:
|
enable:
|
||||||
@@ -30,6 +40,8 @@ examples/system/ulp/lp_core/gpio:
|
|||||||
- esp_hal_gpio
|
- esp_hal_gpio
|
||||||
|
|
||||||
examples/system/ulp/lp_core/gpio_intr_pulse_counter:
|
examples/system/ulp/lp_core/gpio_intr_pulse_counter:
|
||||||
|
disable:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
enable:
|
enable:
|
||||||
- if: (SOC_LP_CORE_SUPPORTED == 1) and (SOC_ULP_LP_UART_SUPPORTED == 1 and SOC_DEEP_SLEEP_SUPPORTED == 1)
|
- if: (SOC_LP_CORE_SUPPORTED == 1) and (SOC_ULP_LP_UART_SUPPORTED == 1 and SOC_DEEP_SLEEP_SUPPORTED == 1)
|
||||||
<<: *ulp_default_depends
|
<<: *ulp_default_depends
|
||||||
@@ -37,6 +49,8 @@ examples/system/ulp/lp_core/gpio_intr_pulse_counter:
|
|||||||
- esp_hal_gpio
|
- esp_hal_gpio
|
||||||
|
|
||||||
examples/system/ulp/lp_core/gpio_wakeup:
|
examples/system/ulp/lp_core/gpio_wakeup:
|
||||||
|
disable:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
enable:
|
enable:
|
||||||
- if: (SOC_LP_CORE_SUPPORTED == 1) and (SOC_RTCIO_PIN_COUNT > 0) and (SOC_DEEP_SLEEP_SUPPORTED == 1) and (SOC_RTC_GPIO_EDGE_WAKEUP_SUPPORTED == 1) # TODO: [ESP32S31] IDF-15884 SOC_RTC_GPIO_EDGE_WAKEUP_SUPPORTED not declared yet
|
- if: (SOC_LP_CORE_SUPPORTED == 1) and (SOC_RTCIO_PIN_COUNT > 0) and (SOC_DEEP_SLEEP_SUPPORTED == 1) and (SOC_RTC_GPIO_EDGE_WAKEUP_SUPPORTED == 1) # TODO: [ESP32S31] IDF-15884 SOC_RTC_GPIO_EDGE_WAKEUP_SUPPORTED not declared yet
|
||||||
<<: *ulp_default_depends
|
<<: *ulp_default_depends
|
||||||
@@ -45,16 +59,22 @@ examples/system/ulp/lp_core/gpio_wakeup:
|
|||||||
- esp_hal_gpio
|
- esp_hal_gpio
|
||||||
|
|
||||||
examples/system/ulp/lp_core/inter_cpu_critical_section/:
|
examples/system/ulp/lp_core/inter_cpu_critical_section/:
|
||||||
|
disable:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
enable:
|
enable:
|
||||||
- if: SOC_LP_CORE_SUPPORTED == 1
|
- if: SOC_LP_CORE_SUPPORTED == 1
|
||||||
<<: *ulp_default_depends
|
<<: *ulp_default_depends
|
||||||
|
|
||||||
examples/system/ulp/lp_core/interrupt:
|
examples/system/ulp/lp_core/interrupt:
|
||||||
|
disable:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
enable:
|
enable:
|
||||||
- if: SOC_LP_CORE_SUPPORTED == 1
|
- if: SOC_LP_CORE_SUPPORTED == 1
|
||||||
<<: *ulp_default_depends
|
<<: *ulp_default_depends
|
||||||
|
|
||||||
examples/system/ulp/lp_core/lp_adc:
|
examples/system/ulp/lp_core/lp_adc:
|
||||||
|
disable+:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
disable:
|
disable:
|
||||||
- if: (SOC_LP_ADC_SUPPORTED != 1)
|
- if: (SOC_LP_ADC_SUPPORTED != 1)
|
||||||
<<: *ulp_default_depends
|
<<: *ulp_default_depends
|
||||||
@@ -64,6 +84,8 @@ examples/system/ulp/lp_core/lp_adc:
|
|||||||
- esp_hal_uart
|
- esp_hal_uart
|
||||||
|
|
||||||
examples/system/ulp/lp_core/lp_i2c:
|
examples/system/ulp/lp_core/lp_i2c:
|
||||||
|
disable:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
enable:
|
enable:
|
||||||
- if: SOC_LP_CORE_SUPPORT_I2C == 1 and (SOC_DEEP_SLEEP_SUPPORTED == 1 and SOC_LP_CORE_SUPPORTED == 1)
|
- if: SOC_LP_CORE_SUPPORT_I2C == 1 and (SOC_DEEP_SLEEP_SUPPORTED == 1 and SOC_LP_CORE_SUPPORTED == 1)
|
||||||
<<: *ulp_default_depends
|
<<: *ulp_default_depends
|
||||||
@@ -71,11 +93,15 @@ examples/system/ulp/lp_core/lp_i2c:
|
|||||||
- esp_hal_i2c
|
- esp_hal_i2c
|
||||||
|
|
||||||
examples/system/ulp/lp_core/lp_mailbox:
|
examples/system/ulp/lp_core/lp_mailbox:
|
||||||
|
disable:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
enable:
|
enable:
|
||||||
- if: SOC_LP_CORE_SUPPORTED == 1
|
- if: SOC_LP_CORE_SUPPORTED == 1
|
||||||
<<: *ulp_default_depends
|
<<: *ulp_default_depends
|
||||||
|
|
||||||
examples/system/ulp/lp_core/lp_spi:
|
examples/system/ulp/lp_core/lp_spi:
|
||||||
|
disable:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
enable:
|
enable:
|
||||||
- if: SOC_LP_SPI_SUPPORTED == 1 and SOC_DEEP_SLEEP_SUPPORTED == 1
|
- if: SOC_LP_SPI_SUPPORTED == 1 and SOC_DEEP_SLEEP_SUPPORTED == 1
|
||||||
<<: *ulp_default_depends
|
<<: *ulp_default_depends
|
||||||
@@ -83,11 +109,15 @@ examples/system/ulp/lp_core/lp_spi:
|
|||||||
- esp_hal_gpspi
|
- esp_hal_gpspi
|
||||||
|
|
||||||
examples/system/ulp/lp_core/lp_timer_interrupt:
|
examples/system/ulp/lp_core/lp_timer_interrupt:
|
||||||
|
disable+:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
disable:
|
disable:
|
||||||
- if: (SOC_LP_CORE_SUPPORTED != 1) or (SOC_LP_TIMER_SUPPORTED != 1)
|
- if: (SOC_LP_CORE_SUPPORTED != 1) or (SOC_LP_TIMER_SUPPORTED != 1)
|
||||||
<<: *ulp_default_depends
|
<<: *ulp_default_depends
|
||||||
|
|
||||||
examples/system/ulp/lp_core/lp_touch:
|
examples/system/ulp/lp_core/lp_touch:
|
||||||
|
disable:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
enable:
|
enable:
|
||||||
- if: SOC_TOUCH_SENSOR_SUPPORTED == 1 and (SOC_DEEP_SLEEP_SUPPORTED == 1 and SOC_LP_CORE_SUPPORTED == 1)
|
- if: SOC_TOUCH_SENSOR_SUPPORTED == 1 and (SOC_DEEP_SLEEP_SUPPORTED == 1 and SOC_LP_CORE_SUPPORTED == 1)
|
||||||
<<: *ulp_default_depends
|
<<: *ulp_default_depends
|
||||||
@@ -96,6 +126,8 @@ examples/system/ulp/lp_core/lp_touch:
|
|||||||
- esp_hal_touch_sens
|
- esp_hal_touch_sens
|
||||||
|
|
||||||
examples/system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup:
|
examples/system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup:
|
||||||
|
disable+:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
disable:
|
disable:
|
||||||
- if: (SOC_ULP_LP_UART_SUPPORTED != 1) or (SOC_DEEP_SLEEP_SUPPORTED != 1)
|
- if: (SOC_ULP_LP_UART_SUPPORTED != 1) or (SOC_DEEP_SLEEP_SUPPORTED != 1)
|
||||||
<<: *ulp_default_depends
|
<<: *ulp_default_depends
|
||||||
@@ -103,6 +135,8 @@ examples/system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup:
|
|||||||
- esp_hal_uart
|
- esp_hal_uart
|
||||||
|
|
||||||
examples/system/ulp/lp_core/lp_uart/lp_uart_echo:
|
examples/system/ulp/lp_core/lp_uart/lp_uart_echo:
|
||||||
|
disable+:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
disable:
|
disable:
|
||||||
- if: (SOC_ULP_LP_UART_SUPPORTED != 1) or (SOC_DEEP_SLEEP_SUPPORTED != 1)
|
- if: (SOC_ULP_LP_UART_SUPPORTED != 1) or (SOC_DEEP_SLEEP_SUPPORTED != 1)
|
||||||
<<: *ulp_default_depends
|
<<: *ulp_default_depends
|
||||||
@@ -110,6 +144,8 @@ examples/system/ulp/lp_core/lp_uart/lp_uart_echo:
|
|||||||
- esp_hal_uart
|
- esp_hal_uart
|
||||||
|
|
||||||
examples/system/ulp/lp_core/lp_uart/lp_uart_print:
|
examples/system/ulp/lp_core/lp_uart/lp_uart_print:
|
||||||
|
disable+:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
disable:
|
disable:
|
||||||
- if: (SOC_ULP_LP_UART_SUPPORTED != 1) or (SOC_DEEP_SLEEP_SUPPORTED != 1)
|
- if: (SOC_ULP_LP_UART_SUPPORTED != 1) or (SOC_DEEP_SLEEP_SUPPORTED != 1)
|
||||||
<<: *ulp_default_depends
|
<<: *ulp_default_depends
|
||||||
@@ -117,11 +153,15 @@ examples/system/ulp/lp_core/lp_uart/lp_uart_print:
|
|||||||
- esp_hal_uart
|
- esp_hal_uart
|
||||||
|
|
||||||
examples/system/ulp/ulp_fsm/ulp:
|
examples/system/ulp/ulp_fsm/ulp:
|
||||||
|
disable+:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
disable:
|
disable:
|
||||||
- if: SOC_ULP_FSM_SUPPORTED != 1
|
- if: SOC_ULP_FSM_SUPPORTED != 1
|
||||||
<<: *ulp_default_depends
|
<<: *ulp_default_depends
|
||||||
|
|
||||||
examples/system/ulp/ulp_fsm/ulp_adc:
|
examples/system/ulp/ulp_fsm/ulp_adc:
|
||||||
|
disable:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
enable:
|
enable:
|
||||||
- if: IDF_TARGET in ["esp32", "esp32s3"]
|
- if: IDF_TARGET in ["esp32", "esp32s3"]
|
||||||
temporary: true
|
temporary: true
|
||||||
@@ -132,6 +172,8 @@ examples/system/ulp/ulp_fsm/ulp_adc:
|
|||||||
- esp_hal_ana_conv
|
- esp_hal_ana_conv
|
||||||
|
|
||||||
examples/system/ulp/ulp_riscv/adc:
|
examples/system/ulp/ulp_riscv/adc:
|
||||||
|
disable:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
enable:
|
enable:
|
||||||
- if: SOC_RISCV_COPROC_SUPPORTED == 1
|
- if: SOC_RISCV_COPROC_SUPPORTED == 1
|
||||||
<<: *ulp_default_depends
|
<<: *ulp_default_depends
|
||||||
@@ -140,6 +182,8 @@ examples/system/ulp/ulp_riscv/adc:
|
|||||||
- esp_hal_ana_conv
|
- esp_hal_ana_conv
|
||||||
|
|
||||||
examples/system/ulp/ulp_riscv/ds18b20_onewire:
|
examples/system/ulp/ulp_riscv/ds18b20_onewire:
|
||||||
|
disable:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
enable:
|
enable:
|
||||||
- if: IDF_TARGET == "esp32s2"
|
- if: IDF_TARGET == "esp32s2"
|
||||||
temporary: true
|
temporary: true
|
||||||
@@ -149,6 +193,8 @@ examples/system/ulp/ulp_riscv/ds18b20_onewire:
|
|||||||
- esp_hal_gpio
|
- esp_hal_gpio
|
||||||
|
|
||||||
examples/system/ulp/ulp_riscv/gpio:
|
examples/system/ulp/ulp_riscv/gpio:
|
||||||
|
disable:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
enable:
|
enable:
|
||||||
- if: SOC_RISCV_COPROC_SUPPORTED == 1
|
- if: SOC_RISCV_COPROC_SUPPORTED == 1
|
||||||
<<: *ulp_default_depends
|
<<: *ulp_default_depends
|
||||||
@@ -156,6 +202,8 @@ examples/system/ulp/ulp_riscv/gpio:
|
|||||||
- esp_hal_gpio
|
- esp_hal_gpio
|
||||||
|
|
||||||
examples/system/ulp/ulp_riscv/gpio_interrupt:
|
examples/system/ulp/ulp_riscv/gpio_interrupt:
|
||||||
|
disable:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
enable:
|
enable:
|
||||||
- if: SOC_RISCV_COPROC_SUPPORTED == 1
|
- if: SOC_RISCV_COPROC_SUPPORTED == 1
|
||||||
<<: *ulp_default_depends
|
<<: *ulp_default_depends
|
||||||
@@ -164,6 +212,8 @@ examples/system/ulp/ulp_riscv/gpio_interrupt:
|
|||||||
- esp_hal_gpio
|
- esp_hal_gpio
|
||||||
|
|
||||||
examples/system/ulp/ulp_riscv/gpio_pulse_counter:
|
examples/system/ulp/ulp_riscv/gpio_pulse_counter:
|
||||||
|
disable:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
enable:
|
enable:
|
||||||
- if: SOC_RISCV_COPROC_SUPPORTED == 1
|
- if: SOC_RISCV_COPROC_SUPPORTED == 1
|
||||||
<<: *ulp_default_depends
|
<<: *ulp_default_depends
|
||||||
@@ -171,6 +221,8 @@ examples/system/ulp/ulp_riscv/gpio_pulse_counter:
|
|||||||
- esp_hal_gpio
|
- esp_hal_gpio
|
||||||
|
|
||||||
examples/system/ulp/ulp_riscv/i2c:
|
examples/system/ulp/ulp_riscv/i2c:
|
||||||
|
disable:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
enable:
|
enable:
|
||||||
- if: SOC_RISCV_COPROC_SUPPORTED == 1
|
- if: SOC_RISCV_COPROC_SUPPORTED == 1
|
||||||
<<: *ulp_default_depends
|
<<: *ulp_default_depends
|
||||||
@@ -178,11 +230,15 @@ examples/system/ulp/ulp_riscv/i2c:
|
|||||||
- esp_hal_i2c
|
- esp_hal_i2c
|
||||||
|
|
||||||
examples/system/ulp/ulp_riscv/interrupts:
|
examples/system/ulp/ulp_riscv/interrupts:
|
||||||
|
disable:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
enable:
|
enable:
|
||||||
- if: SOC_RISCV_COPROC_SUPPORTED == 1
|
- if: SOC_RISCV_COPROC_SUPPORTED == 1
|
||||||
<<: *ulp_default_depends
|
<<: *ulp_default_depends
|
||||||
|
|
||||||
examples/system/ulp/ulp_riscv/touch:
|
examples/system/ulp/ulp_riscv/touch:
|
||||||
|
disable:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
enable:
|
enable:
|
||||||
- if: SOC_RISCV_COPROC_SUPPORTED == 1
|
- if: SOC_RISCV_COPROC_SUPPORTED == 1
|
||||||
<<: *ulp_default_depends
|
<<: *ulp_default_depends
|
||||||
@@ -191,6 +247,8 @@ examples/system/ulp/ulp_riscv/touch:
|
|||||||
- esp_hal_touch_sens
|
- esp_hal_touch_sens
|
||||||
|
|
||||||
examples/system/ulp/ulp_riscv/uart_print:
|
examples/system/ulp/ulp_riscv/uart_print:
|
||||||
|
disable:
|
||||||
|
- *ulp_legacy_buildv2_disable
|
||||||
enable:
|
enable:
|
||||||
- if: SOC_RISCV_COPROC_SUPPORTED == 1
|
- if: SOC_RISCV_COPROC_SUPPORTED == 1
|
||||||
<<: *ulp_default_depends
|
<<: *ulp_default_depends
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
examples/system/ulp/ulp_fsm_riscv_combined/counter:
|
examples/system/ulp/ulp_fsm_riscv_combined/counter:
|
||||||
|
disable:
|
||||||
|
- if: IDF_BUILD_V2 == "1"
|
||||||
|
reason: Legacy ULP apps are covered by CMake v1; buildv2 covers full_subproject ULP apps.
|
||||||
enable:
|
enable:
|
||||||
- if: SOC_ULP_FSM_SUPPORTED == 1 and SOC_RISCV_COPROC_SUPPORTED == 1 and IDF_TARGET in ["esp32s2", "esp32s3"]
|
- if: SOC_ULP_FSM_SUPPORTED == 1 and SOC_RISCV_COPROC_SUPPORTED == 1 and IDF_TARGET in ["esp32s2", "esp32s3"]
|
||||||
temporary: false
|
temporary: false
|
||||||
|
|||||||
@@ -125,6 +125,10 @@ KNOWN_MISSING = {
|
|||||||
'system/ulp/lp_core/lp_spi',
|
'system/ulp/lp_core/lp_spi',
|
||||||
'system/ulp/lp_core/lp_timer_interrupt',
|
'system/ulp/lp_core/lp_timer_interrupt',
|
||||||
'system/ulp/lp_core/lp_touch',
|
'system/ulp/lp_core/lp_touch',
|
||||||
|
'system/ulp/ulp_fsm/ulp/main/ulp',
|
||||||
|
'system/ulp/ulp_fsm_riscv_combined/counter/main/ulp_fsm',
|
||||||
|
'system/ulp/ulp_fsm_riscv_combined/counter/main/ulp_riscv',
|
||||||
|
'system/ulp/ulp_riscv/gpio/main/ulp',
|
||||||
'system/ulp/ulp_riscv/gpio_pulse_counter',
|
'system/ulp/ulp_riscv/gpio_pulse_counter',
|
||||||
'system/unit_test/test',
|
'system/unit_test/test',
|
||||||
# TODO IDF-15382: add :example: references for peripherals examples
|
# TODO IDF-15382: add :example: references for peripherals examples
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ The buildv2 build child pipeline is generated by ``idf-ci gitlab build-child-pip
|
|||||||
from the same manifest as the default pipeline. This script post-processes that
|
from the same manifest as the default pipeline. This script post-processes that
|
||||||
generated YAML so the cmakev2 path is exercised end to end:
|
generated YAML so the cmakev2 path is exercised end to end:
|
||||||
|
|
||||||
1. Inject ``IDF_BUILD_V2`` into each child build job so cmake activates the
|
1. Point child build jobs at the buildv2 generator artifacts, then inject
|
||||||
cmakev2 shim.
|
``IDF_BUILD_V2`` so cmake activates the cmakev2 shim.
|
||||||
|
|
||||||
2. Inject ``PIPELINE_COMMIT_SHA: ${PIPELINE_COMMIT_SHA}_buildv2`` into each child
|
2. Inject ``PIPELINE_COMMIT_SHA: ${PIPELINE_COMMIT_SHA}_buildv2`` into each child
|
||||||
build job. idf-ci reads ``PIPELINE_COMMIT_SHA`` when computing the s3
|
build job. idf-ci reads ``PIPELINE_COMMIT_SHA`` when computing the s3
|
||||||
@@ -27,6 +27,13 @@ import argparse
|
|||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
PIPELINE_COMMIT_SHA_V2 = '${PIPELINE_COMMIT_SHA}_buildv2'
|
PIPELINE_COMMIT_SHA_V2 = '${PIPELINE_COMMIT_SHA}_buildv2'
|
||||||
|
BUILDV2_GENERATOR_JOB = 'generate_build_child_pipeline_buildv2'
|
||||||
|
|
||||||
|
|
||||||
|
def _use_buildv2_generator_artifacts(job: dict) -> None:
|
||||||
|
for need in job.get('needs', []):
|
||||||
|
if isinstance(need, dict) and need.get('job') == 'generate_build_child_pipeline':
|
||||||
|
need['job'] = BUILDV2_GENERATOR_JOB
|
||||||
|
|
||||||
|
|
||||||
def patch(path: str) -> None:
|
def patch(path: str) -> None:
|
||||||
@@ -36,6 +43,7 @@ def patch(path: str) -> None:
|
|||||||
injected = []
|
injected = []
|
||||||
for k, v in d.items():
|
for k, v in d.items():
|
||||||
if isinstance(v, dict) and 'extends' in v:
|
if isinstance(v, dict) and 'extends' in v:
|
||||||
|
_use_buildv2_generator_artifacts(v)
|
||||||
v.setdefault('variables', {})['IDF_BUILD_V2'] = '1'
|
v.setdefault('variables', {})['IDF_BUILD_V2'] = '1'
|
||||||
v['variables']['PIPELINE_COMMIT_SHA'] = PIPELINE_COMMIT_SHA_V2
|
v['variables']['PIPELINE_COMMIT_SHA'] = PIPELINE_COMMIT_SHA_V2
|
||||||
injected.append(k)
|
injected.append(k)
|
||||||
|
|||||||
@@ -4,7 +4,11 @@
|
|||||||
# Note: Paths are expected to be quoted in the CFLAGS variable
|
# Note: Paths are expected to be quoted in the CFLAGS variable
|
||||||
separate_arguments(CFLAGS_LIST UNIX_COMMAND "${CFLAGS}")
|
separate_arguments(CFLAGS_LIST UNIX_COMMAND "${CFLAGS}")
|
||||||
|
|
||||||
execute_process(COMMAND "${CC}" "-C" "-P" "-x" "c" "-E" ${CFLAGS_LIST} "${SOURCE}"
|
# Comment handling is left to the caller via CFLAGS. The default linker-script
|
||||||
|
# CFLAGS keep comments (-C) to preserve historical output. Callers whose
|
||||||
|
# templates include headers with C++-style "//" comments, which ld rejects,
|
||||||
|
# e.g. the ULP memory layout including soc/soc.h, omit -C in their flags.
|
||||||
|
execute_process(COMMAND "${CC}" "-P" "-x" "c" "-E" ${CFLAGS_LIST} "${SOURCE}"
|
||||||
RESULT_VARIABLE RET_CODE
|
RESULT_VARIABLE RET_CODE
|
||||||
OUTPUT_VARIABLE PREPROCESSED_LINKER_SCRIPT
|
OUTPUT_VARIABLE PREPROCESSED_LINKER_SCRIPT
|
||||||
ERROR_VARIABLE ERROR_VAR)
|
ERROR_VARIABLE ERROR_VAR)
|
||||||
|
|||||||
@@ -214,13 +214,16 @@ function(preprocess_linker_file cmake_target script_in output_var preserve_suffi
|
|||||||
set(extra_cflags "-I\"${dir_to_include}\"")
|
set(extra_cflags "-I\"${dir_to_include}\"")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Keep comments (-C): historical behavior for cmakev1 linker scripts. It was
|
||||||
|
# previously hardcoded in linker_script_preprocessor.cmake, which now leaves
|
||||||
|
# comment handling to the caller.
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT ${script_out}
|
OUTPUT ${script_out}
|
||||||
COMMAND ${CMAKE_COMMAND}
|
COMMAND ${CMAKE_COMMAND}
|
||||||
"-DCC=${CMAKE_C_COMPILER}"
|
"-DCC=${CMAKE_C_COMPILER}"
|
||||||
"-DSOURCE=${script_in}"
|
"-DSOURCE=${script_in}"
|
||||||
"-DTARGET=${script_out}"
|
"-DTARGET=${script_out}"
|
||||||
"-DCFLAGS=-I\"${config_dir}\" ${extra_cflags}"
|
"-DCFLAGS=-C -I\"${config_dir}\" ${extra_cflags}"
|
||||||
-P "${linker_script_generator}"
|
-P "${linker_script_generator}"
|
||||||
MAIN_DEPENDENCY ${script_in}
|
MAIN_DEPENDENCY ${script_in}
|
||||||
DEPENDS ${sdkconfig_header}
|
DEPENDS ${sdkconfig_header}
|
||||||
|
|||||||
+98
-21
@@ -473,8 +473,33 @@ function(idf_build_library library)
|
|||||||
string(MAKE_C_IDENTIFIER "_${library}" suffix)
|
string(MAKE_C_IDENTIFIER "_${library}" suffix)
|
||||||
|
|
||||||
idf_library_get_property(component_interfaces_linked "${library}" LIBRARY_COMPONENT_INTERFACES_LINKED)
|
idf_library_get_property(component_interfaces_linked "${library}" LIBRARY_COMPONENT_INTERFACES_LINKED)
|
||||||
|
|
||||||
|
# Build -I arguments for the public include dirs of every component in the
|
||||||
|
# linked closure. These are appended to every linker-script preprocess so a
|
||||||
|
# template can #include any component header (e.g. the ULP memory layout
|
||||||
|
# including soc/soc.h) without the component having to know about it.
|
||||||
|
# INCLUDE_DIRS is stored relative to each component's COMPONENT_DIR.
|
||||||
|
set(component_include_flags "")
|
||||||
|
foreach(ci IN LISTS component_interfaces_linked)
|
||||||
|
idf_component_get_property(ci_dir "${ci}" COMPONENT_DIR)
|
||||||
|
idf_component_get_property(ci_includes "${ci}" INCLUDE_DIRS)
|
||||||
|
foreach(ci_include IN LISTS ci_includes)
|
||||||
|
get_filename_component(ci_include_abs "${ci_include}" ABSOLUTE BASE_DIR "${ci_dir}")
|
||||||
|
# Quote the path: the preprocessor invocation splits CFLAGS with
|
||||||
|
# separate_arguments(UNIX_COMMAND), so unquoted paths containing
|
||||||
|
# spaces would fall apart.
|
||||||
|
string(APPEND component_include_flags " -I\"${ci_include_abs}\"")
|
||||||
|
endforeach()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# Linker scripts marked MEMORY (the memory-layout base for the link) are
|
||||||
|
# emitted as -T before the rest, so section-placement scripts from any
|
||||||
|
# component can reference their MEMORY regions and REGION_ALIASes. Collect
|
||||||
|
# across all components into two ordered lists and emit memory ones first.
|
||||||
|
set(memory_scripts "")
|
||||||
|
set(other_scripts "")
|
||||||
|
|
||||||
foreach(component_interface IN LISTS component_interfaces_linked)
|
foreach(component_interface IN LISTS component_interfaces_linked)
|
||||||
set(scripts)
|
|
||||||
idf_component_get_property(component_dir "${component_interface}" COMPONENT_DIR)
|
idf_component_get_property(component_dir "${component_interface}" COMPONENT_DIR)
|
||||||
idf_component_get_property(component_build_dir "${component_interface}" COMPONENT_BUILD_DIR)
|
idf_component_get_property(component_build_dir "${component_interface}" COMPONENT_BUILD_DIR)
|
||||||
idf_component_get_property(preprocessed "${component_interface}" __LINKER_SCRIPTS_PREPROCESSED)
|
idf_component_get_property(preprocessed "${component_interface}" __LINKER_SCRIPTS_PREPROCESSED)
|
||||||
@@ -483,6 +508,9 @@ function(idf_build_library library)
|
|||||||
idf_component_get_property(scripts_static "${component_interface}" LINKER_SCRIPTS)
|
idf_component_get_property(scripts_static "${component_interface}" LINKER_SCRIPTS)
|
||||||
__get_absolute_paths(PATHS "${scripts_static}" BASE_DIR "${component_dir}" OUTPUT scripts_static_abs)
|
__get_absolute_paths(PATHS "${scripts_static}" BASE_DIR "${component_dir}" OUTPUT scripts_static_abs)
|
||||||
foreach(script IN LISTS scripts_static_abs)
|
foreach(script IN LISTS scripts_static_abs)
|
||||||
|
__linker_script_key("${script}" script_key)
|
||||||
|
idf_component_get_property(script_is_memory "${component_interface}"
|
||||||
|
"LINKER_SCRIPT_MEMORY_${script_key}")
|
||||||
if(script MATCHES "\\.in$")
|
if(script MATCHES "\\.in$")
|
||||||
# If the linker script file name ends with the ".in" extension,
|
# If the linker script file name ends with the ".in" extension,
|
||||||
# preprocess it with the C preprocessor.
|
# preprocess it with the C preprocessor.
|
||||||
@@ -492,27 +520,37 @@ function(idf_build_library library)
|
|||||||
|
|
||||||
if(NOT preprocessed)
|
if(NOT preprocessed)
|
||||||
file(MAKE_DIRECTORY "${component_build_dir}/ld")
|
file(MAKE_DIRECTORY "${component_build_dir}/ld")
|
||||||
__preprocess_linker_script("${script}" "${script_out}")
|
idf_component_get_property(script_flags "${component_interface}"
|
||||||
|
"LINKER_SCRIPT_FLAGS_${script_key}")
|
||||||
|
__preprocess_linker_script("${script}" "${script_out}"
|
||||||
|
"${script_flags}" "${component_include_flags}")
|
||||||
# Add a custom target for the preprocessed script.
|
# Add a custom target for the preprocessed script.
|
||||||
add_custom_target(${script_target} DEPENDS "${script_out}")
|
add_custom_target(${script_target} DEPENDS "${script_out}")
|
||||||
endif()
|
endif()
|
||||||
# Add dependency for the library interface to ensure the script is
|
# Add dependency for the library interface to ensure the script is
|
||||||
# generated before linking.
|
# generated before linking.
|
||||||
add_dependencies("${library}" ${script_target})
|
add_dependencies("${library}" ${script_target})
|
||||||
list(APPEND scripts "${script_out}")
|
set(emit_script "${script_out}")
|
||||||
else()
|
else()
|
||||||
list(APPEND scripts "${script}")
|
set(emit_script "${script}")
|
||||||
|
endif()
|
||||||
|
if(script_is_memory)
|
||||||
|
list(APPEND memory_scripts "${emit_script}")
|
||||||
|
else()
|
||||||
|
list(APPEND other_scripts "${emit_script}")
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
# Generate linker scripts from templates.
|
# Generate linker scripts from templates. The generated output path and
|
||||||
# LINKER_SCRIPTS_TEMPLATE and LINKER_SCRIPTS_GENERATED are parallel
|
# the optional preprocessor flags for each template are stored as
|
||||||
# lists. The first holds the template linker script path, and the
|
# component properties keyed by the template, so no second list has to
|
||||||
# second holds the generated linker script path.
|
# stay index-aligned with LINKER_SCRIPTS_TEMPLATE.
|
||||||
idf_component_get_property(template_scripts "${component_interface}" LINKER_SCRIPTS_TEMPLATE)
|
idf_component_get_property(template_scripts "${component_interface}" LINKER_SCRIPTS_TEMPLATE)
|
||||||
idf_component_get_property(generated_scripts "${component_interface}" LINKER_SCRIPTS_GENERATED)
|
|
||||||
|
|
||||||
foreach(template script IN ZIP_LISTS template_scripts generated_scripts)
|
foreach(template IN LISTS template_scripts)
|
||||||
|
__linker_script_key("${template}" template_key)
|
||||||
|
idf_component_get_property(script "${component_interface}"
|
||||||
|
"LINKER_SCRIPT_GENERATED_${template_key}")
|
||||||
if(template MATCHES "\\.in$")
|
if(template MATCHES "\\.in$")
|
||||||
# If the linker script file name ends with the ".in" extension,
|
# If the linker script file name ends with the ".in" extension,
|
||||||
# preprocess it with the C preprocessor.
|
# preprocess it with the C preprocessor.
|
||||||
@@ -520,7 +558,10 @@ function(idf_build_library library)
|
|||||||
set(template_out "${component_build_dir}/ld/${template_name}")
|
set(template_out "${component_build_dir}/ld/${template_name}")
|
||||||
if(NOT preprocessed)
|
if(NOT preprocessed)
|
||||||
file(MAKE_DIRECTORY "${component_build_dir}/ld")
|
file(MAKE_DIRECTORY "${component_build_dir}/ld")
|
||||||
__preprocess_linker_script("${template}" "${template_out}")
|
idf_component_get_property(template_flags "${component_interface}"
|
||||||
|
"LINKER_SCRIPT_FLAGS_${template_key}")
|
||||||
|
__preprocess_linker_script("${template}" "${template_out}"
|
||||||
|
"${template_flags}" "${component_include_flags}")
|
||||||
endif()
|
endif()
|
||||||
set(template "${template_out}")
|
set(template "${template_out}")
|
||||||
endif()
|
endif()
|
||||||
@@ -529,7 +570,13 @@ function(idf_build_library library)
|
|||||||
TEMPLATE "${template}"
|
TEMPLATE "${template}"
|
||||||
SUFFIX "${suffix}"
|
SUFFIX "${suffix}"
|
||||||
OUTPUT "${script}")
|
OUTPUT "${script}")
|
||||||
list(APPEND scripts "${script}")
|
idf_component_get_property(template_is_memory "${component_interface}"
|
||||||
|
"LINKER_SCRIPT_MEMORY_${template_key}")
|
||||||
|
if(template_is_memory)
|
||||||
|
list(APPEND memory_scripts "${script}")
|
||||||
|
else()
|
||||||
|
list(APPEND other_scripts "${script}")
|
||||||
|
endif()
|
||||||
# Add a custom target for the generated script and include it as a
|
# Add a custom target for the generated script and include it as a
|
||||||
# dependency for the library interface to ensure the script is
|
# dependency for the library interface to ensure the script is
|
||||||
# generated before linking.
|
# generated before linking.
|
||||||
@@ -545,22 +592,30 @@ function(idf_build_library library)
|
|||||||
# property to indicate that the linker scripts have already been
|
# property to indicate that the linker scripts have already been
|
||||||
# preprocessed.
|
# preprocessed.
|
||||||
idf_component_set_property("${component_interface}" __LINKER_SCRIPTS_PREPROCESSED YES)
|
idf_component_set_property("${component_interface}" __LINKER_SCRIPTS_PREPROCESSED YES)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
# Finally, add all preprocessed and ldgen-generated linker scripts to
|
# Emit the collected linker scripts as -T on the library interface, with
|
||||||
# the library interface.
|
# memory-layout scripts first so their MEMORY regions and REGION_ALIASes are
|
||||||
foreach(script IN LISTS scripts)
|
# seen before any section-placement script references them.
|
||||||
|
foreach(script IN LISTS memory_scripts other_scripts)
|
||||||
get_filename_component(script_dir "${script}" DIRECTORY)
|
get_filename_component(script_dir "${script}" DIRECTORY)
|
||||||
get_filename_component(script_name "${script}" NAME)
|
# Add the linker script directory to the linker search path so INCLUDE
|
||||||
# Add linker script directory to the linker search path.
|
# directives inside a script can resolve sibling scripts by name.
|
||||||
target_link_directories("${library}" INTERFACE "${script_dir}")
|
target_link_directories("${library}" INTERFACE "${script_dir}")
|
||||||
# Add linker script to link. Regarding the usage of SHELL, see
|
# Add the linker script to the link by absolute path. Passing the full
|
||||||
|
# path (rather than a bare name resolved via -L) keeps this working for
|
||||||
|
# direct linker drivers such as the ULP FSM esp32ulp-elf-ld link, where
|
||||||
|
# the -L search directories follow the -T options on the command line
|
||||||
|
# and GNU ld therefore does not use them to locate the -T script.
|
||||||
|
# Regarding the usage of SHELL, see
|
||||||
# https://cmake.org/cmake/help/latest/command/target_link_options.html#option-de-duplication
|
# https://cmake.org/cmake/help/latest/command/target_link_options.html#option-de-duplication
|
||||||
target_link_options("${library}" INTERFACE "SHELL:-T ${script_name}")
|
# Quote the path: SHELL: strings are re-split on spaces, so an unquoted
|
||||||
|
# path containing spaces would fall apart.
|
||||||
|
target_link_options("${library}" INTERFACE "SHELL:-T \"${script}\"")
|
||||||
# Add the linker script as a dependency to ensure the executable is
|
# Add the linker script as a dependency to ensure the executable is
|
||||||
# re-linked if the script changes.
|
# re-linked if the script changes.
|
||||||
set_property(TARGET "${library}" APPEND PROPERTY INTERFACE_LINK_DEPENDS "${script}")
|
set_property(TARGET "${library}" APPEND PROPERTY INTERFACE_LINK_DEPENDS "${script}")
|
||||||
endforeach()
|
endforeach()
|
||||||
endforeach()
|
|
||||||
|
|
||||||
# Validate components linked to this library
|
# Validate components linked to this library
|
||||||
__component_validation_run_checks(LIBRARY "${library}")
|
__component_validation_run_checks(LIBRARY "${library}")
|
||||||
@@ -625,15 +680,33 @@ function(idf_build_executable executable)
|
|||||||
set(ARG_SUFFIX ".elf")
|
set(ARG_SUFFIX ".elf")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
get_property(enabled_languages GLOBAL PROPERTY ENABLED_LANGUAGES)
|
||||||
|
if(C IN_LIST enabled_languages)
|
||||||
|
set(stub_language C)
|
||||||
|
set(stub_extension c)
|
||||||
|
elseif(CXX IN_LIST enabled_languages)
|
||||||
|
set(stub_language CXX)
|
||||||
|
set(stub_extension c)
|
||||||
|
elseif(ASM IN_LIST enabled_languages)
|
||||||
|
set(stub_language ASM)
|
||||||
|
set(stub_extension S)
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "idf_build_executable() requires C, CXX, or ASM to be enabled.")
|
||||||
|
endif()
|
||||||
|
|
||||||
idf_build_get_property(build_dir BUILD_DIR)
|
idf_build_get_property(build_dir BUILD_DIR)
|
||||||
|
|
||||||
set(library "library_${executable}")
|
set(library "library_${executable}")
|
||||||
idf_build_library(${library} COMPONENTS "${ARG_COMPONENTS}")
|
idf_build_library(${library} COMPONENTS "${ARG_COMPONENTS}")
|
||||||
|
|
||||||
set(executable_src ${CMAKE_BINARY_DIR}/executable_${executable}.c)
|
set(executable_src ${CMAKE_BINARY_DIR}/executable_${executable}.${stub_extension})
|
||||||
if(NOT EXISTS "${executable_src}")
|
if(NOT EXISTS "${executable_src}")
|
||||||
file(TOUCH "${executable_src}")
|
file(TOUCH "${executable_src}")
|
||||||
endif()
|
endif()
|
||||||
|
if(stub_language STREQUAL "CXX")
|
||||||
|
set_source_files_properties("${executable_src}" PROPERTIES LANGUAGE CXX)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_executable(${executable} "${executable_src}")
|
add_executable(${executable} "${executable_src}")
|
||||||
|
|
||||||
set_target_properties(${executable} PROPERTIES OUTPUT_NAME ${ARG_NAME})
|
set_target_properties(${executable} PROPERTIES OUTPUT_NAME ${ARG_NAME})
|
||||||
@@ -642,6 +715,10 @@ function(idf_build_executable executable)
|
|||||||
set_target_properties(${executable} PROPERTIES SUFFIX ${ARG_SUFFIX})
|
set_target_properties(${executable} PROPERTIES SUFFIX ${ARG_SUFFIX})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(NOT stub_language STREQUAL "C")
|
||||||
|
set_target_properties(${executable} PROPERTIES LINKER_LANGUAGE ${stub_language})
|
||||||
|
endif()
|
||||||
|
|
||||||
target_link_libraries(${executable} PRIVATE ${library})
|
target_link_libraries(${executable} PRIVATE ${library})
|
||||||
|
|
||||||
idf_build_get_property(linker_type LINKER_TYPE)
|
idf_build_get_property(linker_type LINKER_TYPE)
|
||||||
|
|||||||
+94
-39
@@ -165,6 +165,25 @@ endfunction()
|
|||||||
``linkerscript`` template. The ``linkerscript`` is processed with ldgen
|
``linkerscript`` template. The ``linkerscript`` is processed with ldgen
|
||||||
to produce the ``output``.
|
to produce the ``output``.
|
||||||
|
|
||||||
|
*FLAGS[in,opt]*
|
||||||
|
|
||||||
|
Explicit preprocessor flags for the linker script(s) registered by this
|
||||||
|
call, for example ``-D`` defines or extra ``-I`` include directories.
|
||||||
|
When given, they replace the default parent-dir==target include
|
||||||
|
heuristic while a ``.in`` script or template is preprocessed.
|
||||||
|
``-I<config_dir>`` and the linked components' include directories are
|
||||||
|
always added regardless. Applies to every ``scriptfile`` in the same
|
||||||
|
call.
|
||||||
|
|
||||||
|
*MEMORY[opt]*
|
||||||
|
|
||||||
|
Marks the script(s) as the memory-layout base for the link. Such
|
||||||
|
scripts are emitted as ``-T`` before all other linker scripts, so that
|
||||||
|
section-placement scripts from other components can reference their
|
||||||
|
``MEMORY`` regions and ``REGION_ALIAS`` names. Needed when the memory
|
||||||
|
layout lives in a different component than the section scripts that
|
||||||
|
depend on it.
|
||||||
|
|
||||||
This function adds one or more linker scripts to the specified component
|
This function adds one or more linker scripts to the specified component
|
||||||
target, incorporating the linker script into the linking process.
|
target, incorporating the linker script into the linking process.
|
||||||
|
|
||||||
@@ -178,23 +197,76 @@ function(target_linker_script target deptype scriptfiles)
|
|||||||
# The linker script files, templates, and their output filenames are stored
|
# The linker script files, templates, and their output filenames are stored
|
||||||
# only as component properties. The script files are generated and added to
|
# only as component properties. The script files are generated and added to
|
||||||
# the library link interface in the idf_build_library function.
|
# the library link interface in the idf_build_library function.
|
||||||
set(options)
|
set(options MEMORY)
|
||||||
set(one_value PROCESS)
|
set(one_value PROCESS FLAGS)
|
||||||
set(multi_value)
|
set(multi_value)
|
||||||
cmake_parse_arguments(ARG "${options}" "${one_value}" "${multi_value}" ${ARGN})
|
cmake_parse_arguments(ARG "${options}" "${one_value}" "${multi_value}" ${ARGN})
|
||||||
foreach(scriptfile ${scriptfiles})
|
foreach(scriptfile ${scriptfiles})
|
||||||
get_filename_component(scriptfile "${scriptfile}" ABSOLUTE)
|
get_filename_component(scriptfile "${scriptfile}" ABSOLUTE)
|
||||||
idf_msg("Adding linker script ${scriptfile}")
|
idf_msg("Adding linker script ${scriptfile}")
|
||||||
|
__linker_script_key("${scriptfile}" script_key)
|
||||||
if(ARG_PROCESS)
|
if(ARG_PROCESS)
|
||||||
get_filename_component(output "${ARG_PROCESS}" ABSOLUTE)
|
get_filename_component(output "${ARG_PROCESS}" ABSOLUTE)
|
||||||
idf_component_set_property("${target}" LINKER_SCRIPTS_TEMPLATE "${scriptfile}" APPEND)
|
idf_component_set_property("${target}" LINKER_SCRIPTS_TEMPLATE "${scriptfile}" APPEND)
|
||||||
idf_component_set_property("${target}" LINKER_SCRIPTS_GENERATED "${output}" APPEND)
|
# Key the generated output path by the template instead of keeping a
|
||||||
|
# second list index-aligned with LINKER_SCRIPTS_TEMPLATE.
|
||||||
|
idf_component_set_property("${target}" "LINKER_SCRIPT_GENERATED_${script_key}" "${output}")
|
||||||
else()
|
else()
|
||||||
idf_component_set_property("${target}" LINKER_SCRIPTS ${scriptfile} APPEND)
|
idf_component_set_property("${target}" LINKER_SCRIPTS "${scriptfile}" APPEND)
|
||||||
|
endif()
|
||||||
|
# Memory-layout scripts are emitted before other scripts in the link,
|
||||||
|
# so section-placement scripts can reference their MEMORY regions.
|
||||||
|
if(ARG_MEMORY)
|
||||||
|
idf_component_set_property("${target}" "LINKER_SCRIPT_MEMORY_${script_key}" TRUE)
|
||||||
|
endif()
|
||||||
|
# Per-script preprocessor flags, consumed by __preprocess_linker_script
|
||||||
|
# when a ".in" script or template is built. The "__DEFAULT__" sentinel
|
||||||
|
# means FLAGS was not given (use the parent-dir==target heuristic); any
|
||||||
|
# other value, including empty, means FLAGS was given and replaces it.
|
||||||
|
# This distinguishes "not given" from "given empty", which the property
|
||||||
|
# value alone cannot (both would read back as empty).
|
||||||
|
if(DEFINED ARG_FLAGS)
|
||||||
|
idf_component_set_property("${target}" "LINKER_SCRIPT_FLAGS_${script_key}" "${ARG_FLAGS}")
|
||||||
|
else()
|
||||||
|
idf_component_set_property("${target}" "LINKER_SCRIPT_FLAGS_${script_key}" "__DEFAULT__")
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
function(__idf_component_link_optional_requirement component target link_type req_interface output)
|
||||||
|
# Config-only cmakev1 components are represented by INTERFACE libraries.
|
||||||
|
# CMake cannot apply PRIVATE links to an INTERFACE library, so optional
|
||||||
|
# private requirements are ignored for those components.
|
||||||
|
idf_component_get_property(component_target_type "${component}" COMPONENT_REAL_TARGET_TYPE)
|
||||||
|
if("${component_target_type}" STREQUAL "INTERFACE_LIBRARY")
|
||||||
|
if("${link_type}" STREQUAL "PRIVATE")
|
||||||
|
set(${output} FALSE PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
target_link_libraries("${target}" INTERFACE "${req_interface}")
|
||||||
|
else()
|
||||||
|
target_link_libraries("${target}" "${link_type}" "${req_interface}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if("${link_type}" STREQUAL "PRIVATE")
|
||||||
|
set(req_type PRIV_REQUIRES)
|
||||||
|
elseif("${link_type}" STREQUAL "PUBLIC" OR "${link_type}" STREQUAL "INTERFACE")
|
||||||
|
set(req_type REQUIRES)
|
||||||
|
else()
|
||||||
|
set(req_type "")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(req_type)
|
||||||
|
idf_component_get_property(req_name "${req_interface}" COMPONENT_NAME)
|
||||||
|
idf_component_get_property(existing "${component}" ${req_type})
|
||||||
|
if(NOT "${req_name}" IN_LIST existing)
|
||||||
|
idf_component_set_property("${component}" ${req_type} "${req_name}" APPEND)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(${output} TRUE PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
#[[
|
#[[
|
||||||
__idf_component_process_optional_requires()
|
__idf_component_process_optional_requires()
|
||||||
|
|
||||||
@@ -269,22 +341,10 @@ function(__idf_component_process_optional_requires)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Link the caller's real target to the requirement's interface target.
|
# Link the caller's real target to the requirement's interface target.
|
||||||
target_link_libraries("${caller_target}" "${link_type}" "${req_interface}")
|
__idf_component_link_optional_requirement("${caller_interface}" "${caller_target}"
|
||||||
|
"${link_type}" "${req_interface}" linked)
|
||||||
# Update the caller's REQUIRES or PRIV_REQUIRES property.
|
if(NOT linked)
|
||||||
idf_component_get_property(req_name "${req_interface}" COMPONENT_NAME)
|
continue()
|
||||||
if("${link_type}" STREQUAL "PRIVATE")
|
|
||||||
idf_component_get_property(existing "${caller_interface}" PRIV_REQUIRES)
|
|
||||||
if(NOT "${req_name}" IN_LIST existing)
|
|
||||||
idf_component_set_property("${caller_interface}" PRIV_REQUIRES
|
|
||||||
"${req_name}" APPEND)
|
|
||||||
endif()
|
|
||||||
elseif("${link_type}" STREQUAL "PUBLIC" OR "${link_type}" STREQUAL "INTERFACE")
|
|
||||||
idf_component_get_property(existing "${caller_interface}" REQUIRES)
|
|
||||||
if(NOT "${req_name}" IN_LIST existing)
|
|
||||||
idf_component_set_property("${caller_interface}" REQUIRES
|
|
||||||
"${req_name}" APPEND)
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Mark this pair as done so it is not processed again for subsequent
|
# Mark this pair as done so it is not processed again for subsequent
|
||||||
@@ -372,24 +432,8 @@ function(idf_component_optional_requires type)
|
|||||||
endif()
|
endif()
|
||||||
idf_component_include("${req}")
|
idf_component_include("${req}")
|
||||||
|
|
||||||
if("${type}" STREQUAL "PRIVATE")
|
__idf_component_link_optional_requirement("${COMPONENT_NAME}" "${COMPONENT_TARGET}"
|
||||||
set(req_type PRIV_REQUIRES)
|
"${type}" "${req_interface}" linked)
|
||||||
elseif("${type}" STREQUAL "PUBLIC")
|
|
||||||
set(req_type REQUIRES)
|
|
||||||
else()
|
|
||||||
set(req_type "")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(req_type)
|
|
||||||
idf_component_get_property(req_name "${req_interface}" COMPONENT_NAME)
|
|
||||||
idf_component_get_property(target_reqs "${COMPONENT_NAME}" ${req_type})
|
|
||||||
if(NOT "${req_name}" IN_LIST target_reqs)
|
|
||||||
idf_component_set_property("${COMPONENT_NAME}" ${req_type} "${req_name}" APPEND)
|
|
||||||
target_link_libraries(${COMPONENT_TARGET} ${type} ${req_interface})
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
target_link_libraries(${COMPONENT_TARGET} ${type} ${req_interface})
|
|
||||||
endif()
|
|
||||||
endforeach()
|
endforeach()
|
||||||
endif()
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
@@ -700,7 +744,10 @@ function(idf_component_register)
|
|||||||
target_include_directories("${COMPONENT_TARGET}" PRIVATE "${include_dir}")
|
target_include_directories("${COMPONENT_TARGET}" PRIVATE "${include_dir}")
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
set_target_properties(${COMPONENT_TARGET} PROPERTIES OUTPUT_NAME ${COMPONENT_NAME} LINKER_LANGUAGE C)
|
__idf_component_get_linker_language(component_linker_language)
|
||||||
|
set_target_properties(${COMPONENT_TARGET} PROPERTIES
|
||||||
|
OUTPUT_NAME ${COMPONENT_NAME}
|
||||||
|
LINKER_LANGUAGE ${component_linker_language})
|
||||||
|
|
||||||
set(component_type LIBRARY)
|
set(component_type LIBRARY)
|
||||||
|
|
||||||
@@ -819,6 +866,14 @@ function(idf_component_register)
|
|||||||
idf_component_set_property("${COMPONENT_NAME}" PRIV_REQUIRES "${__merged_priv_requires}")
|
idf_component_set_property("${COMPONENT_NAME}" PRIV_REQUIRES "${__merged_priv_requires}")
|
||||||
idf_component_set_property("${COMPONENT_NAME}" REQUIRED_IDF_TARGETS "${ARG_REQUIRED_IDF_TARGETS}")
|
idf_component_set_property("${COMPONENT_NAME}" REQUIRED_IDF_TARGETS "${ARG_REQUIRED_IDF_TARGETS}")
|
||||||
idf_component_set_property("${COMPONENT_NAME}" COMPONENT_TYPE "${component_type}")
|
idf_component_set_property("${COMPONENT_NAME}" COMPONENT_TYPE "${component_type}")
|
||||||
|
idf_component_set_property("${COMPONENT_NAME}" COMPONENT_REAL_TARGET "${COMPONENT_TARGET}")
|
||||||
|
# Optional requirements need to know whether the backward-compatible
|
||||||
|
# component target is STATIC or INTERFACE before deciding how to link it.
|
||||||
|
if("${component_type}" STREQUAL "CONFIG_ONLY")
|
||||||
|
idf_component_set_property("${COMPONENT_NAME}" COMPONENT_REAL_TARGET_TYPE INTERFACE_LIBRARY)
|
||||||
|
else()
|
||||||
|
idf_component_set_property("${COMPONENT_NAME}" COMPONENT_REAL_TARGET_TYPE STATIC_LIBRARY)
|
||||||
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
#[[
|
#[[
|
||||||
|
|||||||
@@ -88,6 +88,20 @@ function(__idf_component_get_property_unchecked variable component_interface pro
|
|||||||
set(${variable} ${value} PARENT_SCOPE)
|
set(${variable} ${value} PARENT_SCOPE)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
function(__idf_component_get_linker_language variable)
|
||||||
|
get_property(enabled_languages GLOBAL PROPERTY ENABLED_LANGUAGES)
|
||||||
|
if(C IN_LIST enabled_languages)
|
||||||
|
set(language C)
|
||||||
|
elseif(CXX IN_LIST enabled_languages)
|
||||||
|
set(language CXX)
|
||||||
|
elseif(ASM IN_LIST enabled_languages)
|
||||||
|
set(language ASM)
|
||||||
|
else()
|
||||||
|
idf_die("No supported language is enabled for component targets")
|
||||||
|
endif()
|
||||||
|
set(${variable} ${language} PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
#[[api
|
#[[api
|
||||||
.. cmakev2:function:: idf_component_get_property
|
.. cmakev2:function:: idf_component_get_property
|
||||||
|
|
||||||
@@ -1197,7 +1211,10 @@ function(idf_component_include name)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Set the component archive file name.
|
# Set the component archive file name.
|
||||||
set_target_properties(${component_real_target} PROPERTIES OUTPUT_NAME ${component_name} LINKER_LANGUAGE C)
|
__idf_component_get_linker_language(component_linker_language)
|
||||||
|
set_target_properties(${component_real_target} PROPERTIES
|
||||||
|
OUTPUT_NAME ${component_name}
|
||||||
|
LINKER_LANGUAGE ${component_linker_language})
|
||||||
|
|
||||||
idf_build_get_property(include_directories INCLUDE_DIRECTORIES GENERATOR_EXPRESSION)
|
idf_build_get_property(include_directories INCLUDE_DIRECTORIES GENERATOR_EXPRESSION)
|
||||||
target_include_directories("${component_real_target}" BEFORE PRIVATE "${include_directories}")
|
target_include_directories("${component_real_target}" BEFORE PRIVATE "${include_directories}")
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ include_guard(GLOBAL)
|
|||||||
|
|
||||||
cmake_minimum_required(VERSION 3.22)
|
cmake_minimum_required(VERSION 3.22)
|
||||||
|
|
||||||
|
if(NOT DEFINED IDF_DEFAULT_PROJECT_NAME)
|
||||||
|
get_filename_component(IDF_DEFAULT_PROJECT_NAME "${CMAKE_CURRENT_SOURCE_DIR}" NAME)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Update the CMAKE_MODULE_PATH to ensure that additional cmakev2 build system
|
# Update the CMAKE_MODULE_PATH to ensure that additional cmakev2 build system
|
||||||
# modules can be included. The third_party directory from cmakev1 is also
|
# modules can be included. The third_party directory from cmakev1 is also
|
||||||
# included for third-party modules shared with cmakev1.
|
# included for third-party modules shared with cmakev1.
|
||||||
@@ -313,6 +317,16 @@ function(__init_toolchain)
|
|||||||
set(cache_toolchain $CACHE{IDF_TOOLCHAIN})
|
set(cache_toolchain $CACHE{IDF_TOOLCHAIN})
|
||||||
set(cache_toolchain_file $CACHE{CMAKE_TOOLCHAIN_FILE})
|
set(cache_toolchain_file $CACHE{CMAKE_TOOLCHAIN_FILE})
|
||||||
|
|
||||||
|
# When IDF_CUSTOM_TOOLCHAIN is set, the toolchain was provided
|
||||||
|
# externally by the parent build (e.g. ULP sub-project via
|
||||||
|
# externalproject_add -DCMAKE_TOOLCHAIN_FILE=...). Skip
|
||||||
|
# IDF_TARGET-based resolution and validation, and trust the
|
||||||
|
# caller-provided CMAKE_TOOLCHAIN_FILE.
|
||||||
|
if(IDF_CUSTOM_TOOLCHAIN AND cache_toolchain_file)
|
||||||
|
idf_build_set_property(IDF_TOOLCHAIN_FILE "${cache_toolchain_file}")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
idf_build_get_property(idf_path IDF_PATH)
|
idf_build_get_property(idf_path IDF_PATH)
|
||||||
idf_build_get_property(idf_target IDF_TARGET)
|
idf_build_get_property(idf_target IDF_TARGET)
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,10 @@ function(__init_kconfig)
|
|||||||
# include(project.cmake) but before project().
|
# include(project.cmake) but before project().
|
||||||
__resolve_sdkconfig_defaults()
|
__resolve_sdkconfig_defaults()
|
||||||
|
|
||||||
idf_build_set_property(GENERATE_SDKCONFIG 1)
|
__get_default_value(VARIABLE GENERATE_SDKCONFIG
|
||||||
|
DEFAULT 1
|
||||||
|
OUTPUT generate_sdkconfig)
|
||||||
|
idf_build_set_property(GENERATE_SDKCONFIG "${generate_sdkconfig}")
|
||||||
|
|
||||||
# Setup ESP-IDF root Kconfig and sdkconfig.rename files.
|
# Setup ESP-IDF root Kconfig and sdkconfig.rename files.
|
||||||
idf_build_set_property(__ROOT_KCONFIG "${idf_path}/Kconfig")
|
idf_build_set_property(__ROOT_KCONFIG "${idf_path}/Kconfig")
|
||||||
@@ -994,6 +997,97 @@ function(idf_create_menuconfig executable)
|
|||||||
endif()
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
#[[
|
||||||
|
.. cmakev2:function:: idf_register_menuconfig
|
||||||
|
|
||||||
|
.. code-block:: cmake
|
||||||
|
|
||||||
|
idf_register_menuconfig(NAME <human-label>
|
||||||
|
TARGET <cmake-target>)
|
||||||
|
|
||||||
|
*NAME[in]*
|
||||||
|
|
||||||
|
Human-readable label shown in the dispatcher picker (e.g. ``"Main application"``,
|
||||||
|
``"ULP (lp_core)"``).
|
||||||
|
|
||||||
|
*TARGET[in]*
|
||||||
|
|
||||||
|
Name of an existing CMake target that, when built, launches a menuconfig
|
||||||
|
session for some configuration. May be a target created by
|
||||||
|
``idf_create_menuconfig`` or any other custom target (for example a proxy
|
||||||
|
target forwarding to a sub-project's ``menuconfig`` via
|
||||||
|
``externalproject_add``).
|
||||||
|
|
||||||
|
Register a menuconfig target with the cmakev2 dispatcher. When exactly one
|
||||||
|
menuconfig is registered (the common case), ``idf.py menuconfig`` behaves
|
||||||
|
identically to today and runs that target directly. When two or more are
|
||||||
|
registered, ``idf.py menuconfig`` presents a small picker so the user can
|
||||||
|
choose which configuration to edit.
|
||||||
|
#]]
|
||||||
|
function(idf_register_menuconfig)
|
||||||
|
set(options)
|
||||||
|
set(one_value NAME TARGET)
|
||||||
|
set(multi_value)
|
||||||
|
cmake_parse_arguments(ARG "${options}" "${one_value}" "${multi_value}" ${ARGN})
|
||||||
|
|
||||||
|
if(NOT DEFINED ARG_NAME)
|
||||||
|
idf_die("idf_register_menuconfig: NAME option is required")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED ARG_TARGET)
|
||||||
|
idf_die("idf_register_menuconfig: TARGET option is required")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
idf_build_get_property(names __MENUCONFIG_NAMES)
|
||||||
|
idf_build_get_property(targets __MENUCONFIG_TARGETS)
|
||||||
|
list(APPEND names "${ARG_NAME}")
|
||||||
|
list(APPEND targets "${ARG_TARGET}")
|
||||||
|
idf_build_set_property(__MENUCONFIG_NAMES "${names}")
|
||||||
|
idf_build_set_property(__MENUCONFIG_TARGETS "${targets}")
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# Create the user-facing `menuconfig` target based on what has been registered
|
||||||
|
# via idf_register_menuconfig(). With a single registration, `menuconfig` is a
|
||||||
|
# thin alias for that target. With two or more, it runs the dispatcher.
|
||||||
|
function(__finalize_menuconfig)
|
||||||
|
idf_build_get_property(names __MENUCONFIG_NAMES)
|
||||||
|
idf_build_get_property(targets __MENUCONFIG_TARGETS)
|
||||||
|
list(LENGTH names num_entries)
|
||||||
|
|
||||||
|
if(num_entries EQUAL 0)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(num_entries EQUAL 1)
|
||||||
|
list(GET targets 0 target)
|
||||||
|
add_custom_target(menuconfig)
|
||||||
|
add_dependencies(menuconfig ${target})
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Two or more registrations: generate entries file and create dispatcher target
|
||||||
|
idf_build_get_property(build_dir BUILD_DIR)
|
||||||
|
idf_build_get_property(python PYTHON)
|
||||||
|
idf_build_get_property(idf_path IDF_PATH)
|
||||||
|
|
||||||
|
set(entries_file "${build_dir}/menuconfig_entries.txt")
|
||||||
|
set(content "")
|
||||||
|
math(EXPR last_idx "${num_entries} - 1")
|
||||||
|
foreach(i RANGE ${last_idx})
|
||||||
|
list(GET names ${i} name)
|
||||||
|
list(GET targets ${i} target)
|
||||||
|
string(APPEND content "${name}|${target}\n")
|
||||||
|
endforeach()
|
||||||
|
file(WRITE "${entries_file}" "${content}")
|
||||||
|
|
||||||
|
add_custom_target(menuconfig
|
||||||
|
COMMAND ${python} "${idf_path}/tools/kconfig_new/menuconfig_dispatcher.py"
|
||||||
|
"${entries_file}" "${build_dir}"
|
||||||
|
USES_TERMINAL
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
#[[api
|
#[[api
|
||||||
.. cmakev2:function:: idf_create_confserver
|
.. cmakev2:function:: idf_create_confserver
|
||||||
|
|
||||||
|
|||||||
@@ -90,6 +90,17 @@ function(__init_project_configuration)
|
|||||||
idf_build_get_property(build_dir BUILD_DIR)
|
idf_build_get_property(build_dir BUILD_DIR)
|
||||||
idf_build_get_property(project_dir PROJECT_DIR)
|
idf_build_get_property(project_dir PROJECT_DIR)
|
||||||
idf_build_get_property(project_name PROJECT_NAME)
|
idf_build_get_property(project_name PROJECT_NAME)
|
||||||
|
get_property(enabled_languages GLOBAL PROPERTY ENABLED_LANGUAGES)
|
||||||
|
|
||||||
|
set(c_enabled OFF)
|
||||||
|
if(C IN_LIST enabled_languages)
|
||||||
|
set(c_enabled ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(cxx_enabled OFF)
|
||||||
|
if(CXX IN_LIST enabled_languages)
|
||||||
|
set(cxx_enabled ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Set the LINKER_TYPE build property. Different linkers may have varying
|
# Set the LINKER_TYPE build property. Different linkers may have varying
|
||||||
# options, so it's important to identify the linker type to configure the
|
# options, so it's important to identify the linker type to configure the
|
||||||
@@ -144,6 +155,7 @@ function(__init_project_configuration)
|
|||||||
if(IDF_TARGET STREQUAL "linux")
|
if(IDF_TARGET STREQUAL "linux")
|
||||||
# Building for Linux target, fall back to an older version of the standard
|
# Building for Linux target, fall back to an older version of the standard
|
||||||
# if the preferred one is not supported by the compiler.
|
# if the preferred one is not supported by the compiler.
|
||||||
|
if(c_enabled)
|
||||||
set(preferred_c_versions gnu23 gnu17 gnu11 gnu99)
|
set(preferred_c_versions gnu23 gnu17 gnu11 gnu99)
|
||||||
set(ver_found FALSE)
|
set(ver_found FALSE)
|
||||||
foreach(c_version ${preferred_c_versions})
|
foreach(c_version ${preferred_c_versions})
|
||||||
@@ -159,6 +171,10 @@ function(__init_project_configuration)
|
|||||||
"${preferred_c_versions}. Please upgrade the host compiler.")
|
"${preferred_c_versions}. Please upgrade the host compiler.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
list(APPEND c_compile_options "-std=${c_std}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(cxx_enabled)
|
||||||
set(preferred_cxx_versions gnu++26 gnu++2b gnu++20 gnu++2a gnu++17 gnu++14)
|
set(preferred_cxx_versions gnu++26 gnu++2b gnu++20 gnu++2a gnu++17 gnu++14)
|
||||||
set(ver_found FALSE)
|
set(ver_found FALSE)
|
||||||
foreach(cxx_version ${preferred_cxx_versions})
|
foreach(cxx_version ${preferred_cxx_versions})
|
||||||
@@ -174,8 +190,8 @@ function(__init_project_configuration)
|
|||||||
"${preferred_cxx_versions}. Please upgrade the host compiler.")
|
"${preferred_cxx_versions}. Please upgrade the host compiler.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
list(APPEND c_compile_options "-std=${c_std}")
|
|
||||||
list(APPEND cxx_compile_options "-std=${cxx_std}")
|
list(APPEND cxx_compile_options "-std=${cxx_std}")
|
||||||
|
endif()
|
||||||
else()
|
else()
|
||||||
# Building for chip targets: we use a known version of the toolchain.
|
# Building for chip targets: we use a known version of the toolchain.
|
||||||
# Use latest supported versions.
|
# Use latest supported versions.
|
||||||
@@ -183,9 +199,13 @@ function(__init_project_configuration)
|
|||||||
# function, which must be called after project().
|
# function, which must be called after project().
|
||||||
# Please update docs/en/api-guides/c.rst, docs/en/api-guides/cplusplus.rst and
|
# Please update docs/en/api-guides/c.rst, docs/en/api-guides/cplusplus.rst and
|
||||||
# tools/test_apps/system/cxx_build_test/main/test_cxx_standard.cpp when changing this.
|
# tools/test_apps/system/cxx_build_test/main/test_cxx_standard.cpp when changing this.
|
||||||
|
if(c_enabled)
|
||||||
list(APPEND c_compile_options "-std=gnu23")
|
list(APPEND c_compile_options "-std=gnu23")
|
||||||
|
endif()
|
||||||
|
if(cxx_enabled)
|
||||||
list(APPEND cxx_compile_options "-std=gnu++26")
|
list(APPEND cxx_compile_options "-std=gnu++26")
|
||||||
endif()
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
# Subprojects that handle their own compiler optimization flags can set the
|
# Subprojects that handle their own compiler optimization flags can set the
|
||||||
# SET_COMPILER_OPTIMIZATION build property to NO before idf_project_init().
|
# SET_COMPILER_OPTIMIZATION build property to NO before idf_project_init().
|
||||||
@@ -215,6 +235,7 @@ function(__init_project_configuration)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(cxx_enabled)
|
||||||
if(CONFIG_COMPILER_CXX_EXCEPTIONS)
|
if(CONFIG_COMPILER_CXX_EXCEPTIONS)
|
||||||
list(APPEND cxx_compile_options "-fexceptions")
|
list(APPEND cxx_compile_options "-fexceptions")
|
||||||
else()
|
else()
|
||||||
@@ -227,6 +248,7 @@ function(__init_project_configuration)
|
|||||||
list(APPEND cxx_compile_options "-fno-rtti")
|
list(APPEND cxx_compile_options "-fno-rtti")
|
||||||
list(APPEND link_options "-fno-rtti") # used to invoke correct multilib variant (no-rtti) during linking
|
list(APPEND link_options "-fno-rtti") # used to invoke correct multilib variant (no-rtti) during linking
|
||||||
endif()
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
if(CONFIG_COMPILER_SAVE_RESTORE_LIBCALLS)
|
if(CONFIG_COMPILER_SAVE_RESTORE_LIBCALLS)
|
||||||
list(APPEND compile_options "-msave-restore")
|
list(APPEND compile_options "-msave-restore")
|
||||||
@@ -236,11 +258,13 @@ function(__init_project_configuration)
|
|||||||
list(APPEND c_compile_options "-Wno-old-style-declaration")
|
list(APPEND c_compile_options "-Wno-old-style-declaration")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(c_enabled)
|
||||||
# TODO IDF-15784: remove in IDF v7.0 ?
|
# TODO IDF-15784: remove in IDF v7.0 ?
|
||||||
check_c_compiler_flag("-Wunused-but-set-variable=1" compiler_supports_wunused_but_set_variable_eq_1)
|
check_c_compiler_flag("-Wunused-but-set-variable=1" compiler_supports_wunused_but_set_variable_eq_1)
|
||||||
if(compiler_supports_wunused_but_set_variable_eq_1)
|
if(compiler_supports_wunused_but_set_variable_eq_1)
|
||||||
list(APPEND compile_options "-Wunused-but-set-variable=1")
|
list(APPEND compile_options "-Wunused-but-set-variable=1")
|
||||||
endif()
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
if(CONFIG_COMPILER_CXX_TRIVIAL_AUTO_VAR_INIT_UNINITIALIZED)
|
if(CONFIG_COMPILER_CXX_TRIVIAL_AUTO_VAR_INIT_UNINITIALIZED)
|
||||||
set(compiler_cxx_trivial_auto_var_init "uninitialized")
|
set(compiler_cxx_trivial_auto_var_init "uninitialized")
|
||||||
@@ -249,7 +273,7 @@ function(__init_project_configuration)
|
|||||||
elseif(CONFIG_COMPILER_CXX_TRIVIAL_AUTO_VAR_INIT_ZERO)
|
elseif(CONFIG_COMPILER_CXX_TRIVIAL_AUTO_VAR_INIT_ZERO)
|
||||||
set(compiler_cxx_trivial_auto_var_init "zero")
|
set(compiler_cxx_trivial_auto_var_init "zero")
|
||||||
endif()
|
endif()
|
||||||
if(compiler_cxx_trivial_auto_var_init)
|
if(NOT IDF_CUSTOM_TOOLCHAIN AND cxx_enabled AND compiler_cxx_trivial_auto_var_init)
|
||||||
idf_toolchain_remove_flags(CXX_COMPILE_OPTIONS "-ftrivial-auto-var-init")
|
idf_toolchain_remove_flags(CXX_COMPILE_OPTIONS "-ftrivial-auto-var-init")
|
||||||
check_cxx_compiler_flag("-ftrivial-auto-var-init=${compiler_cxx_trivial_auto_var_init}"
|
check_cxx_compiler_flag("-ftrivial-auto-var-init=${compiler_cxx_trivial_auto_var_init}"
|
||||||
compiler_supports_ftrivial_auto_var_init)
|
compiler_supports_ftrivial_auto_var_init)
|
||||||
@@ -886,7 +910,10 @@ function(__project_default)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
idf_create_menuconfig("${executable}"
|
idf_create_menuconfig("${executable}"
|
||||||
TARGET menuconfig)
|
TARGET menuconfig-app)
|
||||||
|
idf_register_menuconfig(NAME "Main application"
|
||||||
|
TARGET menuconfig-app)
|
||||||
|
__finalize_menuconfig()
|
||||||
|
|
||||||
idf_create_confserver("${executable}"
|
idf_create_confserver("${executable}"
|
||||||
TARGET confserver)
|
TARGET confserver)
|
||||||
|
|||||||
@@ -1182,7 +1182,30 @@ function(fail_at_build_time target_name message_line0)
|
|||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
#[[
|
#[[
|
||||||
__preprocess_linker_script(<script_in> <script_out>)
|
__linker_script_key(<path> <output>)
|
||||||
|
|
||||||
|
*path[in]*
|
||||||
|
|
||||||
|
Linker script or template path.
|
||||||
|
|
||||||
|
*output[out]*
|
||||||
|
|
||||||
|
Variable set to a stable key derived from the absolute ``path``.
|
||||||
|
|
||||||
|
Compute a collision-resistant key for a linker script. It is used to store
|
||||||
|
per-script metadata such as the generated output path and preprocessor
|
||||||
|
flags as component properties. Both the producer ``target_linker_script``
|
||||||
|
and the consumer ``idf_build_library`` must derive the key identically, so
|
||||||
|
the absolute-path normalization lives here and nowhere else.
|
||||||
|
#]]
|
||||||
|
function(__linker_script_key path output)
|
||||||
|
get_filename_component(path_abs "${path}" ABSOLUTE)
|
||||||
|
string(MD5 hash "${path_abs}")
|
||||||
|
set(${output} "${hash}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
#[[
|
||||||
|
__preprocess_linker_script(<script_in> <script_out> <flags> <component_includes>)
|
||||||
|
|
||||||
*script_in[in]*
|
*script_in[in]*
|
||||||
|
|
||||||
@@ -1192,29 +1215,47 @@ endfunction()
|
|||||||
|
|
||||||
Path where the preprocessed linker script will be saved.
|
Path where the preprocessed linker script will be saved.
|
||||||
|
|
||||||
|
*flags[in]*
|
||||||
|
|
||||||
|
Explicit preprocessor flags from ``target_linker_script``'s ``FLAGS``
|
||||||
|
option, or the literal ``__DEFAULT__`` when no ``FLAGS`` was given.
|
||||||
|
``__DEFAULT__`` keeps comments (``-C``) and selects the parent-dir==target
|
||||||
|
include heuristic; any other value, including an empty string, replaces
|
||||||
|
that whole set, so a caller can drop ``-C``.
|
||||||
|
|
||||||
|
*component_includes[in]*
|
||||||
|
|
||||||
|
Pre-built ``-I`` arguments for the linked component graph, always
|
||||||
|
appended so a template can include any component header.
|
||||||
|
|
||||||
Run the C preprocessor on ``script_in`` and store the result in
|
Run the C preprocessor on ``script_in`` and store the result in
|
||||||
``script_out``.
|
``script_out``. The preprocessor always receives ``-I<config_dir>`` so
|
||||||
|
``sdkconfig.h`` resolves, plus ``component_includes``.
|
||||||
#]]
|
#]]
|
||||||
function(__preprocess_linker_script script_in script_out)
|
function(__preprocess_linker_script script_in script_out flags component_includes)
|
||||||
idf_build_get_property(sdkconfig_header __SDKCONFIG_HEADER)
|
idf_build_get_property(sdkconfig_header __SDKCONFIG_HEADER)
|
||||||
idf_build_get_property(idf_path IDF_PATH)
|
idf_build_get_property(idf_path IDF_PATH)
|
||||||
idf_build_get_property(config_dir CONFIG_DIR)
|
idf_build_get_property(config_dir CONFIG_DIR)
|
||||||
idf_build_get_property(idf_target IDF_TARGET)
|
idf_build_get_property(idf_target IDF_TARGET)
|
||||||
|
|
||||||
# This approach is not ideal, but it is the current method used in cmakev1
|
if(flags STREQUAL "__DEFAULT__")
|
||||||
# for the esp_system component. The linker script files for specific
|
# No FLAGS were given: keep comments (-C, the historical default) and
|
||||||
# targets within the esp_system component include the ld.common file. This
|
# apply the parent-dir==target include heuristic. esp_system's
|
||||||
# adds the ld.common directory to the search path for the C preprocessor.
|
# target-specific scripts live in ld/<target>/ and include the sibling
|
||||||
# This method works for the specific directory layout of esp_common, but if
|
# ld.common file, so add the parent directory to the C preprocessor
|
||||||
# other components with different layouts adopt this approach, adjustments
|
# search path. Works for that layout; a component with a different
|
||||||
# will be necessary. It might be better to include the files using relative
|
# layout, or one that must drop -C, should pass FLAGS instead.
|
||||||
# paths in the linker scripts.
|
set(base_flags "-C")
|
||||||
get_filename_component(script_parent_dir "${script_in}" DIRECTORY)
|
get_filename_component(script_parent_dir "${script_in}" DIRECTORY)
|
||||||
get_filename_component(script_parent_name "${script_parent_dir}" NAME)
|
get_filename_component(script_parent_name "${script_parent_dir}" NAME)
|
||||||
set(extra_cflags "")
|
|
||||||
if(script_parent_name STREQUAL idf_target)
|
if(script_parent_name STREQUAL idf_target)
|
||||||
get_filename_component(dir_to_include "${script_parent_dir}" DIRECTORY)
|
get_filename_component(dir_to_include "${script_parent_dir}" DIRECTORY)
|
||||||
set(extra_cflags "-I\"${dir_to_include}\"")
|
string(APPEND base_flags " -I\"${dir_to_include}\"")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
# Explicit FLAGS replace the whole default set, including -C. config_dir
|
||||||
|
# and the component include dirs are always added regardless.
|
||||||
|
set(base_flags "${flags}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(linker_script_generator "${idf_path}/tools/cmake/linker_script_preprocessor.cmake")
|
set(linker_script_generator "${idf_path}/tools/cmake/linker_script_preprocessor.cmake")
|
||||||
@@ -1225,7 +1266,7 @@ function(__preprocess_linker_script script_in script_out)
|
|||||||
"-DCC=${CMAKE_C_COMPILER}"
|
"-DCC=${CMAKE_C_COMPILER}"
|
||||||
"-DSOURCE=${script_in}"
|
"-DSOURCE=${script_in}"
|
||||||
"-DTARGET=${script_out}"
|
"-DTARGET=${script_out}"
|
||||||
"-DCFLAGS=-I\"${config_dir}\" ${extra_cflags}"
|
"-DCFLAGS=-I\"${config_dir}\" ${base_flags} ${component_includes}"
|
||||||
-P "${linker_script_generator}"
|
-P "${linker_script_generator}"
|
||||||
MAIN_DEPENDENCY "${script_in}"
|
MAIN_DEPENDENCY "${script_in}"
|
||||||
DEPENDS "${sdkconfig_header}"
|
DEPENDS "${sdkconfig_header}"
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def _read_entries(entries_file: Path) -> list[tuple[str, str]]:
|
||||||
|
entries: list[tuple[str, str]] = []
|
||||||
|
for line in entries_file.read_text().splitlines():
|
||||||
|
line = line.strip()
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
name, _, target = line.partition('|')
|
||||||
|
entries.append((name, target))
|
||||||
|
return entries
|
||||||
|
|
||||||
|
|
||||||
|
def _prompt(entries: list[tuple[str, str]]) -> str | None:
|
||||||
|
width = max(len(name) for name, _ in entries)
|
||||||
|
print('\nMultiple menuconfig configurations available:\n')
|
||||||
|
for i, (name, target) in enumerate(entries, 1):
|
||||||
|
print(f' [{i}] {name:<{width}} (idf.py {target})')
|
||||||
|
print()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
choice = input(f'Select [1-{len(entries)}, q to quit]: ').strip().lower()
|
||||||
|
except EOFError:
|
||||||
|
return None
|
||||||
|
if choice in ('q', 'quit', ''):
|
||||||
|
return None
|
||||||
|
if choice.isdigit():
|
||||||
|
idx = int(choice)
|
||||||
|
if 1 <= idx <= len(entries):
|
||||||
|
return entries[idx - 1][1]
|
||||||
|
print('Invalid choice.')
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
if len(sys.argv) != 3:
|
||||||
|
print(f'Usage: {sys.argv[0]} <entries_file> <build_dir>', file=sys.stderr)
|
||||||
|
return 2
|
||||||
|
|
||||||
|
entries_file = Path(sys.argv[1])
|
||||||
|
build_dir = sys.argv[2]
|
||||||
|
|
||||||
|
entries = _read_entries(entries_file)
|
||||||
|
if not entries:
|
||||||
|
print(f'No menuconfig entries registered in {entries_file}', file=sys.stderr)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
target = _prompt(entries)
|
||||||
|
if target is None:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
return subprocess.run(['cmake', '--build', build_dir, '--target', target]).returncode
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(main())
|
||||||
@@ -1,5 +1,17 @@
|
|||||||
# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps
|
# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps
|
||||||
|
|
||||||
|
.ulp_full_subproject_child_project_disable: &ulp_full_subproject_child_project_disable
|
||||||
|
disable:
|
||||||
|
- if: IDF_TARGET in ["esp32", "esp32s2", "esp32s3", "esp32c3", "esp32c2", "esp32c6", "esp32c5", "esp32h2", "esp32p4", "esp32c61", "esp32h21", "esp32h4", "esp32s31"]
|
||||||
|
reason: ULP child project is built by its parent test app
|
||||||
|
|
||||||
|
.ulp_full_subproject_default_depends: &ulp_full_subproject_default_depends
|
||||||
|
depends_components:
|
||||||
|
- ulp
|
||||||
|
- esp_hw_support
|
||||||
|
- esp_hal_pmu
|
||||||
|
|
||||||
|
|
||||||
tools/test_apps/system/bootloader_sections:
|
tools/test_apps/system/bootloader_sections:
|
||||||
disable:
|
disable:
|
||||||
- if: CONFIG_NAME == "rtc_retain" and SOC_RTC_FAST_MEM_SUPPORTED != 1
|
- if: CONFIG_NAME == "rtc_retain" and SOC_RTC_FAST_MEM_SUPPORTED != 1
|
||||||
@@ -182,6 +194,9 @@ tools/test_apps/system/ram_loadable_app:
|
|||||||
reason: cannot pass # TODO: IDF-15525
|
reason: cannot pass # TODO: IDF-15525
|
||||||
|
|
||||||
tools/test_apps/system/rtc_mem_reserve:
|
tools/test_apps/system/rtc_mem_reserve:
|
||||||
|
disable:
|
||||||
|
- if: IDF_BUILD_V2 == "1"
|
||||||
|
reason: Legacy ULP apps are covered by CMake v1; buildv2 covers full_subproject ULP apps.
|
||||||
enable:
|
enable:
|
||||||
- if: IDF_TARGET in ["esp32p4"]
|
- if: IDF_TARGET in ["esp32p4"]
|
||||||
reason: only P4 has a potential conflict due to using rtc mem for lp rom data/stack
|
reason: only P4 has a potential conflict due to using rtc mem for lp rom data/stack
|
||||||
@@ -199,6 +214,48 @@ tools/test_apps/system/test_watchpoint:
|
|||||||
enable:
|
enable:
|
||||||
- if: IDF_TARGET in ["esp32", "esp32c3"] # Just one test per architecture
|
- if: IDF_TARGET in ["esp32", "esp32c3"] # Just one test per architecture
|
||||||
|
|
||||||
|
tools/test_apps/system/ulp/full_subproject/combined:
|
||||||
|
enable:
|
||||||
|
- if: (SOC_ULP_FSM_SUPPORTED == 1) and (SOC_RISCV_COPROC_SUPPORTED == 1)
|
||||||
|
<<: *ulp_full_subproject_default_depends
|
||||||
|
|
||||||
|
tools/test_apps/system/ulp/full_subproject/combined/main/ulp_fsm:
|
||||||
|
<<: *ulp_full_subproject_child_project_disable
|
||||||
|
|
||||||
|
tools/test_apps/system/ulp/full_subproject/combined/main/ulp_riscv:
|
||||||
|
<<: *ulp_full_subproject_child_project_disable
|
||||||
|
|
||||||
|
tools/test_apps/system/ulp/full_subproject/fsm:
|
||||||
|
enable:
|
||||||
|
- if: SOC_ULP_FSM_SUPPORTED == 1
|
||||||
|
<<: *ulp_full_subproject_default_depends
|
||||||
|
|
||||||
|
tools/test_apps/system/ulp/full_subproject/fsm/main/ulp:
|
||||||
|
<<: *ulp_full_subproject_child_project_disable
|
||||||
|
|
||||||
|
tools/test_apps/system/ulp/full_subproject/lp_core:
|
||||||
|
enable:
|
||||||
|
- if: SOC_LP_CORE_SUPPORTED == 1
|
||||||
|
<<: *ulp_full_subproject_default_depends
|
||||||
|
|
||||||
|
tools/test_apps/system/ulp/full_subproject/lp_core/main/ulp:
|
||||||
|
<<: *ulp_full_subproject_child_project_disable
|
||||||
|
|
||||||
|
tools/test_apps/system/ulp/full_subproject/multi_binary:
|
||||||
|
enable:
|
||||||
|
- if: SOC_LP_CORE_SUPPORTED == 1
|
||||||
|
<<: *ulp_full_subproject_default_depends
|
||||||
|
|
||||||
|
tools/test_apps/system/ulp/full_subproject/multi_binary/main/ulp:
|
||||||
|
<<: *ulp_full_subproject_child_project_disable
|
||||||
|
|
||||||
|
tools/test_apps/system/ulp/full_subproject/riscv:
|
||||||
|
enable:
|
||||||
|
- if: SOC_RISCV_COPROC_SUPPORTED == 1
|
||||||
|
<<: *ulp_full_subproject_default_depends
|
||||||
|
|
||||||
|
tools/test_apps/system/ulp/full_subproject/riscv/main/ulp:
|
||||||
|
<<: *ulp_full_subproject_child_project_disable
|
||||||
tools/test_apps/system/unicore_bootloader:
|
tools/test_apps/system/unicore_bootloader:
|
||||||
disable:
|
disable:
|
||||||
- if: SOC_CPU_CORES_NUM == 1
|
- if: SOC_CPU_CORES_NUM == 1
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.22)
|
||||||
|
|
||||||
|
include($ENV{IDF_PATH}/tools/cmakev2/idf.cmake)
|
||||||
|
|
||||||
|
project(combined C CXX ASM)
|
||||||
|
|
||||||
|
idf_project_default()
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
| Supported Targets | ESP32-S2 | ESP32-S3 |
|
||||||
|
| ----------------- | -------- | -------- |
|
||||||
|
|
||||||
|
# ULP FSM and RISC-V Full Subproject Example
|
||||||
|
|
||||||
|
This example demonstrates two separate ULP full subprojects in one application. The main application starts a ULP FSM subproject first, then starts a ULP RISC-V subproject after the FSM counter completes.
|
||||||
|
|
||||||
|
The ULP FSM program is built from `main/ulp_fsm`, and the ULP RISC-V program is built from `main/ulp_riscv`. The parent app registers them independently with `ulp_add_project()`:
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
ulp_add_project("ulp_fsm_main" "${CMAKE_CURRENT_LIST_DIR}/ulp_fsm/" TYPE fsm)
|
||||||
|
ulp_add_project("ulp_riscv_main" "${CMAKE_CURRENT_LIST_DIR}/ulp_riscv/" TYPE riscv)
|
||||||
|
```
|
||||||
|
|
||||||
|
At runtime, the FSM ULP increments `fsm_counter` to 5 and wakes the main CPU from light sleep. The main CPU then loads the RISC-V ULP, initializes `riscv_counter` from the FSM result, and lets the RISC-V ULP continue counting to 10.
|
||||||
|
|
||||||
|
## Example Output
|
||||||
|
|
||||||
|
```
|
||||||
|
ULP FSM and RISC-V full subproject example
|
||||||
|
Starting ULP FSM counter
|
||||||
|
ULP FSM counter: 5
|
||||||
|
Starting ULP RISC-V counter
|
||||||
|
ULP RISC-V counter: 10
|
||||||
|
Example finished
|
||||||
|
```
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
idf_component_register(SRCS "ulp_combined_build_system_example_main.c"
|
||||||
|
REQUIRES ulp)
|
||||||
|
|
||||||
|
ulp_add_project("ulp_fsm_main" "${CMAKE_CURRENT_LIST_DIR}/ulp_fsm/" TYPE fsm)
|
||||||
|
ulp_add_project("ulp_riscv_main" "${CMAKE_CURRENT_LIST_DIR}/ulp_riscv/" TYPE riscv)
|
||||||
+66
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "esp_sleep.h"
|
||||||
|
#include "ulp.h"
|
||||||
|
#include "ulp_riscv.h"
|
||||||
|
#include "ulp_fsm_main.h"
|
||||||
|
#include "ulp_riscv_main.h"
|
||||||
|
|
||||||
|
extern const uint8_t ulp_fsm_main_bin_start[] asm("_binary_ulp_fsm_main_bin_start");
|
||||||
|
extern const uint8_t ulp_fsm_main_bin_end[] asm("_binary_ulp_fsm_main_bin_end");
|
||||||
|
|
||||||
|
extern const uint8_t ulp_riscv_main_bin_start[] asm("_binary_ulp_riscv_main_bin_start");
|
||||||
|
extern const uint8_t ulp_riscv_main_bin_end[] asm("_binary_ulp_riscv_main_bin_end");
|
||||||
|
|
||||||
|
static void init_ulp_fsm_program(void);
|
||||||
|
static void init_ulp_riscv_program(uint32_t initial_count);
|
||||||
|
|
||||||
|
void app_main(void)
|
||||||
|
{
|
||||||
|
printf("ULP FSM and RISC-V full subproject example\n");
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(esp_sleep_enable_ulp_wakeup());
|
||||||
|
|
||||||
|
printf("Starting ULP FSM counter\n");
|
||||||
|
init_ulp_fsm_program();
|
||||||
|
ESP_ERROR_CHECK(esp_light_sleep_start());
|
||||||
|
ulp_timer_stop();
|
||||||
|
|
||||||
|
uint32_t fsm_count = ulp_fsm_counter & UINT16_MAX;
|
||||||
|
printf("ULP FSM counter: %" PRIu32 "\n", fsm_count);
|
||||||
|
|
||||||
|
printf("Starting ULP RISC-V counter\n");
|
||||||
|
init_ulp_riscv_program(fsm_count);
|
||||||
|
ESP_ERROR_CHECK(esp_light_sleep_start());
|
||||||
|
ulp_riscv_timer_stop();
|
||||||
|
|
||||||
|
uint32_t riscv_count = ulp_riscv_counter;
|
||||||
|
printf("ULP RISC-V counter: %" PRIu32 "\n", riscv_count);
|
||||||
|
printf("Example finished\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init_ulp_fsm_program(void)
|
||||||
|
{
|
||||||
|
ESP_ERROR_CHECK(ulp_load_binary(0, ulp_fsm_main_bin_start,
|
||||||
|
(ulp_fsm_main_bin_end - ulp_fsm_main_bin_start) / sizeof(uint32_t)));
|
||||||
|
|
||||||
|
ulp_fsm_counter = 0;
|
||||||
|
ulp_set_wakeup_period(0, 10000);
|
||||||
|
ESP_ERROR_CHECK(ulp_run(&ulp_entry - RTC_SLOW_MEM));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init_ulp_riscv_program(uint32_t initial_count)
|
||||||
|
{
|
||||||
|
ESP_ERROR_CHECK(ulp_riscv_load_binary(ulp_riscv_main_bin_start,
|
||||||
|
ulp_riscv_main_bin_end - ulp_riscv_main_bin_start));
|
||||||
|
|
||||||
|
ulp_riscv_counter = initial_count;
|
||||||
|
ulp_set_wakeup_period(0, 10000);
|
||||||
|
ESP_ERROR_CHECK(ulp_riscv_run());
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.22)
|
||||||
|
|
||||||
|
include(${IDF_PATH}/components/ulp/cmake/ulp_project.cmake)
|
||||||
|
|
||||||
|
project(${IDF_DEFAULT_PROJECT_NAME} ASM)
|
||||||
|
|
||||||
|
ulp_project_default()
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# ULP FSM Subproject
|
||||||
|
|
||||||
|
This ULP FSM subproject is built by the parent combined example. It increments `fsm_counter` on each timer wakeup and wakes the main CPU when the counter reaches 5.
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
idf_component_register(SRCS "main.S"
|
||||||
|
REQUIRES ulp)
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
.bss
|
||||||
|
.global fsm_counter
|
||||||
|
fsm_counter:
|
||||||
|
.long 0
|
||||||
|
|
||||||
|
.text
|
||||||
|
.global entry
|
||||||
|
entry:
|
||||||
|
move r1, fsm_counter
|
||||||
|
ld r0, r1, 0
|
||||||
|
add r0, r0, 1
|
||||||
|
st r0, r1, 0
|
||||||
|
jumpr wake_cpu, 5, ge
|
||||||
|
halt
|
||||||
|
|
||||||
|
wake_cpu:
|
||||||
|
wake
|
||||||
|
halt
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.22)
|
||||||
|
|
||||||
|
include(${IDF_PATH}/components/ulp/cmake/ulp_project.cmake)
|
||||||
|
|
||||||
|
project(${IDF_DEFAULT_PROJECT_NAME} C CXX ASM)
|
||||||
|
|
||||||
|
ulp_project_default()
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# ULP RISC-V Subproject
|
||||||
|
|
||||||
|
This ULP RISC-V subproject is built by the parent combined example. It continues from the FSM counter value and wakes the main CPU when `riscv_counter` reaches 10.
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
idf_component_register(SRCS "main.c"
|
||||||
|
REQUIRES ulp)
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "ulp_riscv_utils.h"
|
||||||
|
|
||||||
|
uint32_t riscv_counter = 0;
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
riscv_counter++;
|
||||||
|
if (riscv_counter >= 10) {
|
||||||
|
ulp_riscv_wakeup_main_processor();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from pytest_embedded import Dut
|
||||||
|
from pytest_embedded_idf.utils import idf_parametrize
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.generic
|
||||||
|
@idf_parametrize('target', ['esp32s2', 'esp32s3'], indirect=['target'])
|
||||||
|
def test_ulp_combined(dut: Dut) -> None:
|
||||||
|
dut.expect_exact('ULP FSM and RISC-V full subproject example')
|
||||||
|
dut.expect_exact('Starting ULP FSM counter')
|
||||||
|
dut.expect_exact('ULP FSM counter: 5', timeout=5)
|
||||||
|
dut.expect_exact('Starting ULP RISC-V counter')
|
||||||
|
dut.expect_exact('ULP RISC-V counter: 10', timeout=5)
|
||||||
|
dut.expect_exact('Example finished')
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
# Enable both ULP types
|
||||||
|
CONFIG_ULP_COPROC_ENABLED=y
|
||||||
|
CONFIG_ULP_COPROC_TYPE_FSM=y
|
||||||
|
CONFIG_ULP_COPROC_TYPE_RISCV=y
|
||||||
|
CONFIG_ULP_COPROC_RESERVE_MEM=4096
|
||||||
|
|
||||||
|
# Set log level to Warning to produce clean output
|
||||||
|
CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y
|
||||||
|
CONFIG_BOOTLOADER_LOG_LEVEL=2
|
||||||
|
CONFIG_LOG_DEFAULT_LEVEL_WARN=y
|
||||||
|
CONFIG_LOG_DEFAULT_LEVEL=2
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.22)
|
||||||
|
|
||||||
|
include($ENV{IDF_PATH}/tools/cmakev2/idf.cmake)
|
||||||
|
|
||||||
|
project(fsm C CXX ASM)
|
||||||
|
|
||||||
|
idf_project_default()
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
| Supported Targets | ESP32 | ESP32-S2 | ESP32-S3 |
|
||||||
|
| ----------------- | ----- | -------- | -------- |
|
||||||
|
|
||||||
|
# ULP FSM Build System Example
|
||||||
|
|
||||||
|
This example demonstrates a separate ULP FSM project built with the CMake v2 ULP project helpers. It programs the ULP FSM coprocessor to increment a counter while the main CPUs are in deep sleep, then wake the main CPU after a fixed number of timer iterations.
|
||||||
|
|
||||||
|
ULP program written in assembly can be found across `main/ulp/main/counter.S` and `main/ulp/main/wake_up.S` (demonstrating multiple ULP source files). The build system assembles and links this program, converts it into binary format, and embeds it into the .rodata section of the ESP-IDF application.
|
||||||
|
|
||||||
|
At runtime, the main code running on the ESP (found in main.c) loads ULP program into the `RTC_SLOW_MEM` memory region using `ulp_load_binary` function. Main code configures the ULP program by setting up values of some variables and then starts it using `ulp_run`. Once the ULP program is started, it runs periodically, with the period set by the main program. The main program enables ULP wakeup source and puts the chip into deep sleep mode.
|
||||||
|
|
||||||
|
On each timer iteration, the ULP program increments `iteration_count`. Once this counter reaches `wakeup_iteration` (set by the main program), the ULP triggers wake up from deep sleep. Upon wakeup, the main program stops the ULP timer, prints the final counter value, and exits the example.
|
||||||
|
|
||||||
|
In this example, the `CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP` Kconfig option is used, which allows you to reduce the boot time of the bootloader during waking up from deep sleep. The bootloader stores in rtc memory the address of a running partition and uses it when it wakes up. This example allows you to skip all image checks and speed up the boot.
|
||||||
|
|
||||||
|
## Example output
|
||||||
|
|
||||||
|
```
|
||||||
|
Not ULP wakeup, initializing ULP
|
||||||
|
Entering deep sleep
|
||||||
|
|
||||||
|
ULP FSM woke up the main CPU
|
||||||
|
ULP FSM iteration count: 5
|
||||||
|
Example finished
|
||||||
|
```
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
idf_component_register(SRCS "ulp_example_main.c"
|
||||||
|
REQUIRES ulp)
|
||||||
|
|
||||||
|
ulp_add_project("ulp_main" "${CMAKE_CURRENT_LIST_DIR}/ulp/" TYPE fsm)
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.22)
|
||||||
|
|
||||||
|
include(${IDF_PATH}/components/ulp/cmake/ulp_project.cmake)
|
||||||
|
|
||||||
|
project(${IDF_DEFAULT_PROJECT_NAME} ASM)
|
||||||
|
|
||||||
|
ulp_project_default()
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
| Supported Targets | ESP32 | ESP32-S2 | ESP32-S3 |
|
||||||
|
| ----------------- | ----- | -------- | -------- |
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
idf_component_register(SRCS "wake_up.S"
|
||||||
|
REQUIRES ulp)
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
/* ULP assembly files are passed through C preprocessor first, so include directives
|
||||||
|
and C macros may be used in these files
|
||||||
|
*/
|
||||||
|
#include "soc/rtc_cntl_reg.h"
|
||||||
|
#include "soc/soc_ulp.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
.global wake_up
|
||||||
|
wake_up:
|
||||||
|
/* Check if the system is in sleep mode */
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
READ_RTC_REG(RTC_CNTL_LOW_POWER_ST_REG, 27, 1)
|
||||||
|
#else
|
||||||
|
READ_RTC_FIELD(RTC_CNTL_LOW_POWER_ST_REG, RTC_CNTL_MAIN_STATE_IN_IDLE)
|
||||||
|
#endif
|
||||||
|
move r1, r0
|
||||||
|
/* Check if the system can be woken up */
|
||||||
|
READ_RTC_FIELD(RTC_CNTL_LOW_POWER_ST_REG, RTC_CNTL_RDY_FOR_WAKEUP)
|
||||||
|
/* If the system is in normal mode or if the system is in sleep mode with ready for wakeup set, we can signal the main CPU to wakeup */
|
||||||
|
or r0, r0, r1
|
||||||
|
jump wake_up, eq
|
||||||
|
|
||||||
|
/* Wake up the SoC, end program */
|
||||||
|
wake
|
||||||
|
halt
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
set(srcs
|
||||||
|
"counter.S")
|
||||||
|
|
||||||
|
idf_component_register(SRCS ${srcs}
|
||||||
|
REQUIRES ulp ulp_wake
|
||||||
|
LDFRAGMENTS "ulp_fsm_sections.lf")
|
||||||
|
|
||||||
|
target_compile_definitions(${COMPONENT_LIB} PRIVATE ULP_BUILD_SYSTEM_FSM_EXAMPLE=1)
|
||||||
|
|
||||||
|
# Supplementary linker script template processed by ldgen. The mapping marker
|
||||||
|
# is resolved using ulp_fsm_sections.lf from this component.
|
||||||
|
target_linker_script(${COMPONENT_NAME} INTERFACE ulp_sections.ld.in
|
||||||
|
PROCESS "${CMAKE_BINARY_DIR}/ulp_sections.ld")
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
/* ULP Example: timer counter
|
||||||
|
|
||||||
|
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, this
|
||||||
|
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
|
||||||
|
This file contains assembly code which runs on the ULP. On each timer wakeup,
|
||||||
|
the program increments a counter in RTC_SLOW_MEM. Once the counter reaches
|
||||||
|
the value set by the main program, the ULP wakes the main CPU from deep sleep.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ULP assembly files are passed through C preprocessor first, so include directives
|
||||||
|
and C macros may be used in these files
|
||||||
|
*/
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
#ifndef ULP_BUILD_SYSTEM_FSM_EXAMPLE
|
||||||
|
#error "ULP FSM compile definitions were not passed to the assembly preprocessor"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define variables, which go into .bss section (zero-initialized data) */
|
||||||
|
.bss
|
||||||
|
.global iteration_count
|
||||||
|
iteration_count:
|
||||||
|
.long 0
|
||||||
|
|
||||||
|
.global wakeup_iteration
|
||||||
|
wakeup_iteration:
|
||||||
|
.long 0
|
||||||
|
|
||||||
|
/* Ldgen-only marker section used by ulp_fsm_sections.lf. Keep it
|
||||||
|
non-allocated so it never becomes part of the ULP FSM load image. */
|
||||||
|
.section .ulp_fsm_extra_data, ""
|
||||||
|
ldgen_section_marker:
|
||||||
|
.long 0x12345678
|
||||||
|
|
||||||
|
/* Code goes into .text section */
|
||||||
|
.text
|
||||||
|
.global entry
|
||||||
|
entry:
|
||||||
|
/* Increment iteration_count. */
|
||||||
|
move r3, iteration_count
|
||||||
|
ld r2, r3, 0
|
||||||
|
add r2, r2, 1
|
||||||
|
st r2, r3, 0
|
||||||
|
|
||||||
|
/* Compare iteration_count to wakeup_iteration. */
|
||||||
|
move r3, wakeup_iteration
|
||||||
|
ld r3, r3, 0
|
||||||
|
sub r3, r3, r2
|
||||||
|
jump wake_up, eq
|
||||||
|
halt
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
|
||||||
|
[sections:ulp_fsm_extra_data]
|
||||||
|
entries:
|
||||||
|
.ulp_fsm_extra_data+
|
||||||
|
|
||||||
|
[scheme:ulp_fsm_extra]
|
||||||
|
entries:
|
||||||
|
ulp_fsm_extra_data -> ulp_fsm_extra_data
|
||||||
|
|
||||||
|
[mapping:main]
|
||||||
|
archive: libmain.a
|
||||||
|
entries:
|
||||||
|
counter (ulp_fsm_extra)
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Supplementary ULP FSM linker script template processed by ldgen.
|
||||||
|
* The mapped marker is non-allocated, so it exercises ldgen without becoming
|
||||||
|
* part of the ULP FSM load image. The FSM loader validates the binary size
|
||||||
|
* against the .text/.data sizes recorded in the default linker-script header.
|
||||||
|
*/
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
.ulp_fsm_extra_data 0 (INFO) :
|
||||||
|
{
|
||||||
|
mapping[ulp_fsm_extra_data]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
/* ULP Example
|
||||||
|
|
||||||
|
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, this
|
||||||
|
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include "esp_sleep.h"
|
||||||
|
#include "ulp.h"
|
||||||
|
#include "ulp_main.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
|
||||||
|
extern const uint8_t ulp_main_bin_start[] asm("_binary_ulp_main_bin_start");
|
||||||
|
extern const uint8_t ulp_main_bin_end[] asm("_binary_ulp_main_bin_end");
|
||||||
|
|
||||||
|
static void init_ulp_program(void);
|
||||||
|
|
||||||
|
void app_main(void)
|
||||||
|
{
|
||||||
|
/* If user is using USB-serial-jtag then idf monitor needs some time to
|
||||||
|
* re-connect to the USB port. We wait 1 sec here to allow for it to make the reconnection
|
||||||
|
* before we print anything. Otherwise the chip will go back to sleep again before the user
|
||||||
|
* has time to monitor any output.
|
||||||
|
*/
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
|
|
||||||
|
uint32_t causes = esp_sleep_get_wakeup_causes();
|
||||||
|
if (!(causes & BIT(ESP_SLEEP_WAKEUP_ULP))) {
|
||||||
|
printf("Not ULP wakeup, initializing ULP\n");
|
||||||
|
init_ulp_program();
|
||||||
|
} else {
|
||||||
|
ulp_timer_stop();
|
||||||
|
printf("ULP FSM woke up the main CPU\n");
|
||||||
|
printf("ULP FSM iteration count: %" PRIu32 "\n", ulp_iteration_count & UINT16_MAX);
|
||||||
|
printf("Example finished\n");
|
||||||
|
vTaskDelay(portMAX_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Entering deep sleep\n\n");
|
||||||
|
ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup() );
|
||||||
|
esp_deep_sleep_start();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init_ulp_program(void)
|
||||||
|
{
|
||||||
|
esp_err_t err = ulp_load_binary(0, ulp_main_bin_start,
|
||||||
|
(ulp_main_bin_end - ulp_main_bin_start) / sizeof(uint32_t));
|
||||||
|
ESP_ERROR_CHECK(err);
|
||||||
|
|
||||||
|
ulp_iteration_count = 0;
|
||||||
|
ulp_wakeup_iteration = 5;
|
||||||
|
|
||||||
|
/* Set ULP wake up period to 20ms. */
|
||||||
|
ulp_set_wakeup_period(0, 20000);
|
||||||
|
|
||||||
|
/* Start the program */
|
||||||
|
err = ulp_run(&ulp_entry - RTC_SLOW_MEM);
|
||||||
|
ESP_ERROR_CHECK(err);
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from pytest_embedded import Dut
|
||||||
|
from pytest_embedded_idf.utils import idf_parametrize
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.generic
|
||||||
|
@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32s3'], indirect=['target'])
|
||||||
|
def test_ulp_full_subproject_fsm(dut: Dut) -> None:
|
||||||
|
dut.expect_exact('Not ULP wakeup, initializing ULP')
|
||||||
|
dut.expect_exact('Entering deep sleep')
|
||||||
|
dut.expect_exact('ULP FSM woke up the main CPU', timeout=5)
|
||||||
|
count = int(dut.expect(r'ULP FSM iteration count:\s+(\d+)', timeout=5).group(1), 10)
|
||||||
|
assert count >= 5
|
||||||
|
dut.expect_exact('Example finished')
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# Enable ULP
|
||||||
|
CONFIG_ULP_COPROC_ENABLED=y
|
||||||
|
CONFIG_ULP_COPROC_TYPE_FSM=y
|
||||||
|
CONFIG_ULP_COPROC_RESERVE_MEM=1024
|
||||||
|
# Set log level to Warning to produce clean output
|
||||||
|
CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y
|
||||||
|
CONFIG_BOOTLOADER_LOG_LEVEL=2
|
||||||
|
CONFIG_LOG_DEFAULT_LEVEL_WARN=y
|
||||||
|
CONFIG_LOG_DEFAULT_LEVEL=2
|
||||||
|
CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP=y
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.22)
|
||||||
|
|
||||||
|
include($ENV{IDF_PATH}/tools/cmakev2/idf.cmake)
|
||||||
|
|
||||||
|
project(lp_core C CXX ASM)
|
||||||
|
|
||||||
|
idf_project_default()
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-P4 | ESP32-S31 |
|
||||||
|
| ----------------- | -------- | -------- | -------- | --------- |
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
idf_component_register(SRCS "lp_core_build_system_example_main.c"
|
||||||
|
REQUIRES ulp)
|
||||||
|
|
||||||
|
ulp_add_project("ulp_build_system_example" "${CMAKE_CURRENT_LIST_DIR}/ulp/")
|
||||||
+50
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include "esp_sleep.h"
|
||||||
|
#include "ulp_lp_core.h"
|
||||||
|
#include "ulp_build_system_example.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
|
||||||
|
extern const uint8_t ulp_build_system_example_bin_start[] asm("_binary_ulp_build_system_example_bin_start");
|
||||||
|
extern const uint8_t ulp_build_system_example_bin_end[] asm("_binary_ulp_build_system_example_bin_end");
|
||||||
|
|
||||||
|
static void init_ulp_program(void);
|
||||||
|
|
||||||
|
void app_main(void)
|
||||||
|
{
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
|
|
||||||
|
init_ulp_program();
|
||||||
|
|
||||||
|
/* Wait for ULP to complete. The ULP variables are in RTC memory and
|
||||||
|
* not declared volatile, so a delay is needed to prevent the compiler
|
||||||
|
* from optimizing the reads into a tight loop. */
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
|
|
||||||
|
printf("Sum calculated by ULP (ulp_sum component): %" PRIi32 "\n", ulp_sum);
|
||||||
|
printf("Product calculated by ULP (ulp_math component): %" PRIi32 "\n", ulp_product);
|
||||||
|
|
||||||
|
printf("Example finished\n");
|
||||||
|
vTaskDelay(portMAX_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init_ulp_program(void)
|
||||||
|
{
|
||||||
|
esp_err_t err = ulp_lp_core_load_binary(ulp_build_system_example_bin_start,
|
||||||
|
(ulp_build_system_example_bin_end - ulp_build_system_example_bin_start));
|
||||||
|
ESP_ERROR_CHECK(err);
|
||||||
|
|
||||||
|
ulp_lp_core_cfg_t cfg = {
|
||||||
|
.wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_HP_CPU,
|
||||||
|
};
|
||||||
|
|
||||||
|
err = ulp_lp_core_run(&cfg);
|
||||||
|
ESP_ERROR_CHECK(err);
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.22)
|
||||||
|
|
||||||
|
include(${IDF_PATH}/components/ulp/cmake/ulp_project.cmake)
|
||||||
|
|
||||||
|
project(${IDF_DEFAULT_PROJECT_NAME} C CXX ASM)
|
||||||
|
|
||||||
|
ulp_project_default()
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
idf_component_register(SRCS "ulp_math.c"
|
||||||
|
INCLUDE_DIRS "include"
|
||||||
|
LDFRAGMENTS "ulp_math.lf")
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
menu "ULP Math Component"
|
||||||
|
|
||||||
|
config ULP_MATH_ENABLED
|
||||||
|
bool "Enable ULP math multiplication"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
When enabled, the ULP program will compute a product using the
|
||||||
|
ulp_math component.
|
||||||
|
|
||||||
|
endmenu
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
int ulp_math_multiply(int a, int b);
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
#include "ulp_math.h"
|
||||||
|
|
||||||
|
/* Place in .ulp_math_fast section via the ldgen fragment (ulp_math.lf) */
|
||||||
|
__attribute__((section(".ulp_math_fast")))
|
||||||
|
int ulp_math_multiply(int a, int b)
|
||||||
|
{
|
||||||
|
return a * b;
|
||||||
|
}
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
|
||||||
|
# Linker fragment file for the ulp_math ULP component.
|
||||||
|
# Demonstrates custom section placement via ldgen for ULP builds.
|
||||||
|
|
||||||
|
[sections:ulp_fast_text]
|
||||||
|
entries:
|
||||||
|
.ulp_math_fast+
|
||||||
|
|
||||||
|
[scheme:ulp_fast]
|
||||||
|
entries:
|
||||||
|
ulp_fast_text -> ulp_math_fast
|
||||||
|
|
||||||
|
[mapping:ulp_math]
|
||||||
|
archive: libulp_math.a
|
||||||
|
entries:
|
||||||
|
ulp_math (ulp_fast)
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
# ulp_clamp is resolved by the component manager via idf_component.yml
|
||||||
|
idf_component_register(SRCS "ulp_sum.c"
|
||||||
|
INCLUDE_DIRS "include"
|
||||||
|
REQUIRES ulp_clamp)
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
menu "ULP Sum Component"
|
||||||
|
|
||||||
|
config ULP_SUM_ENABLED
|
||||||
|
bool "Enable ULP sum function"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
When enabled, the ULP program will compute a sum using the
|
||||||
|
ulp_sum component.
|
||||||
|
|
||||||
|
endmenu
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
dependencies:
|
||||||
|
ulp_clamp:
|
||||||
|
path: ../../extra/ulp_clamp
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
int ulp_sum_func(int a, int b);
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include "ulp_sum.h"
|
||||||
|
#include "ulp_clamp.h"
|
||||||
|
|
||||||
|
int ulp_sum_func(int a, int b)
|
||||||
|
{
|
||||||
|
/* Uses ulp_clamp() from the ulp_clamp managed component.
|
||||||
|
* CONFIG_ULP_CLAMP_MAX_VALUE comes from ulp_clamp's Kconfig. */
|
||||||
|
return ulp_clamp(a + b, 0, CONFIG_ULP_CLAMP_MAX_VALUE);
|
||||||
|
}
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
idf_component_register(SRCS "ulp_clamp.c"
|
||||||
|
INCLUDE_DIRS "include")
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
menu "ULP Clamp Component"
|
||||||
|
|
||||||
|
config ULP_CLAMP_MAX_VALUE
|
||||||
|
int "Maximum clamp value"
|
||||||
|
default 255
|
||||||
|
help
|
||||||
|
The upper bound used by the ulp_clamp() function.
|
||||||
|
|
||||||
|
endmenu
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/* Clamp a value to the range [min, max]. */
|
||||||
|
int ulp_clamp(int value, int min, int max);
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
#include "ulp_clamp.h"
|
||||||
|
|
||||||
|
int ulp_clamp(int value, int min, int max)
|
||||||
|
{
|
||||||
|
if (value < min) {
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
if (value > max) {
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
idf_component_register(SRCS "main.c"
|
||||||
|
REQUIRES ulp ulp_sum ulp_math)
|
||||||
|
|
||||||
|
# Linker script template processed by ldgen. The mapping[ulp_math_fast]
|
||||||
|
# marker is resolved using the .lf fragment from the ulp_math component.
|
||||||
|
target_linker_script(${COMPONENT_NAME} INTERFACE ulp_sections.ld.in
|
||||||
|
PROCESS "${CMAKE_CURRENT_BINARY_DIR}/ulp_sections.ld")
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
#include "ulp_sum.h"
|
||||||
|
#include "ulp_math.h"
|
||||||
|
|
||||||
|
int sum;
|
||||||
|
int product;
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
/* ulp_sum_func internally uses ulp_clamp() from the ulp_clamp
|
||||||
|
* managed component (resolved via ulp_sum/idf_component.yml). */
|
||||||
|
sum = ulp_sum_func(5, 6);
|
||||||
|
product = ulp_math_multiply(3, 7);
|
||||||
|
|
||||||
|
/* ulp_lp_core_halt() is called automatically when main exits */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Supplementary ULP linker script template processed by ldgen.
|
||||||
|
*
|
||||||
|
* ldgen replaces the mapping[ulp_math_fast] marker with explicit symbol
|
||||||
|
* entries derived from the component .lf fragment files. The generated
|
||||||
|
* output is linked via -T alongside the main lp_core_riscv.ld.
|
||||||
|
*/
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = ADDR(.bss) + SIZEOF(.bss);
|
||||||
|
.ulp_math_fast ALIGN(4) :
|
||||||
|
{
|
||||||
|
mapping[ulp_math_fast]
|
||||||
|
*(.ulp_math_fast .ulp_math_fast.*)
|
||||||
|
} > default_app_seg
|
||||||
|
}
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from pytest_embedded import Dut
|
||||||
|
from pytest_embedded_idf.utils import idf_parametrize
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.generic
|
||||||
|
@idf_parametrize('target', ['esp32c5', 'esp32c6', 'esp32p4', 'esp32s31'], indirect=['target'])
|
||||||
|
def test_ulp_full_subproject_lp_core(dut: Dut) -> None:
|
||||||
|
dut.expect_exact('Sum calculated by ULP (ulp_sum component): 11')
|
||||||
|
dut.expect_exact('Product calculated by ULP (ulp_math component): 21')
|
||||||
|
dut.expect_exact('Example finished')
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# Enable ULP
|
||||||
|
CONFIG_ULP_COPROC_ENABLED=y
|
||||||
|
CONFIG_ULP_COPROC_TYPE_LP_CORE=y
|
||||||
|
CONFIG_ULP_COPROC_RESERVE_MEM=4096
|
||||||
|
# Set log level to Warning to produce clean output
|
||||||
|
CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y
|
||||||
|
CONFIG_BOOTLOADER_LOG_LEVEL=2
|
||||||
|
CONFIG_LOG_DEFAULT_LEVEL_WARN=y
|
||||||
|
CONFIG_LOG_DEFAULT_LEVEL=2
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user