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:
Renz Christian Bagaporo
2026-07-16 21:00:32 +08:00
126 changed files with 3022 additions and 332 deletions

View File

@@ -1,12 +1,18 @@
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)
else()
set(ldfragments common.lf soc.lf linker.lf)
endif()
set(srcs "src/esp_err_to_name.c")
set(srcs)
if(NOT __ULP_BUILD)
set(srcs "src/esp_err_to_name.c")
endif()
idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS include

View File

@@ -2,6 +2,24 @@ idf_build_get_property(target IDF_TARGET)
set(srcs)
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)
list(APPEND srcs "src/uart.c")

View File

@@ -5,14 +5,27 @@ endif()
set(srcs)
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
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${target}/include")
list(APPEND includes "${target}/include")
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")
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${includes}
REQUIRES soc hal)
REQUIRES ${requires})

View File

@@ -7,19 +7,23 @@ if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${target}/include")
list(APPEND includes "${target}/include")
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")
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")
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")
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")
endif()

View File

@@ -5,6 +5,19 @@ endif()
set(srcs)
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
if(CONFIG_SOC_PMU_SUPPORTED)
@@ -31,5 +44,5 @@ endif()
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${public_include}
REQUIRES soc hal esp_rom
REQUIRES ${requires}
LDFRAGMENTS linker.lf)

View File

@@ -11,6 +11,15 @@ if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${target}/include")
list(APPEND includes "${target}/include")
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)
if(NOT CONFIG_ESP_ROM_HAS_REGI2C_IMPL)
list(APPEND srcs "${target}/regi2c_impl.c")

View File

@@ -8,5 +8,8 @@ components/esp_hal_security/test_apps/crypto:
- esp_security
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:
- if: IDF_TARGET not in ["esp32c6", "esp32h2", "esp32c5", "esp32c61", "esp32p4"]

View File

@@ -12,6 +12,34 @@ if(${target} STREQUAL "linux")
return()
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(priv_requires efuse # only esp_hw_support/adc_share_hw_ctrl.c requires efuse component
spi_flash
@@ -180,18 +208,6 @@ else()
list(APPEND priv_requires "esp_system")
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")
# for mipi_csi_share_hw_ctrl.c
list(APPEND priv_requires esp_hal_cam)

View File

@@ -103,6 +103,8 @@ components/esp_hw_support/test_apps/vad_wakeup:
- ulp
- soc
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
components/esp_hw_support/test_apps/wakeup_tests:

View File

@@ -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_STDATOMIC_S32C1I_SPIRAM_WORKAROUND)
idf_toolchain_add_flags(COMPILE_OPTIONS "-mdisable-hardware-atomics")

View File

@@ -10,4 +10,5 @@ endif()
idf_component_register(SRCS ${sources}
INCLUDE_DIRS "."
PRIV_REQUIRES unity esp_pm ulp esp_timer esp_psram esp_driver_gptimer vfs esp_hal_gpio
esp_driver_gpio
WHOLE_ARCHIVE)

View File

@@ -1,3 +1,7 @@
if(IDF_CUSTOM_TOOLCHAIN)
return()
endif()
if(CONFIG_IDF_TOOLCHAIN_GCC)
# Remove all "-mfix-esp32-psram-cache*" from toolchain flags
# that may have appeared during configuration changes.

View File

@@ -7,6 +7,22 @@ set(include_dirs "include"
"${target_folder}/include/${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(sources "patches/esp_rom_sys.c"

View File

@@ -1,7 +1,7 @@
idf_build_get_property(target IDF_TARGET)
idf_build_get_property(esp_tee_build ESP_TEE_BUILD)
set(srcs "hal_utils.c")
set(srcs)
set(includes "platform_port/include")
set(priv_include)
set(requires)
@@ -12,6 +12,18 @@ list(APPEND includes "${target}/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)
list(APPEND srcs "efuse_hal.c" "${target}/efuse_hal.c")
endif()
@@ -46,11 +58,13 @@ if(NOT esp_tee_build AND NOT BOOTLOADER_BUILD)
endif()
endif()
set(ldfragments linker.lf)
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${includes}
PRIV_INCLUDE_DIRS ${priv_include}
REQUIRES ${requires}
LDFRAGMENTS linker.lf)
LDFRAGMENTS ${ldfragments})
if(CONFIG_HAL_DEFAULT_ASSERTION_LEVEL EQUAL 1)
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u abort")

View File

@@ -1,6 +1,16 @@
idf_build_get_property(target IDF_TARGET)
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)
set(system_target "noos")
else()

View File

@@ -2,10 +2,20 @@ idf_build_get_property(target IDF_TARGET)
idf_build_get_property(arch IDF_TARGET_ARCH)
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()
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)
set(priv_requires soc hal)

View File

@@ -4,14 +4,6 @@ set(target_folder "${target}")
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}")
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${target_folder}/include")
@@ -39,6 +31,33 @@ else()
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")
list(APPEND srcs "${target_folder}/dport_access.c")
endif()
@@ -55,9 +74,11 @@ if(CONFIG_SOC_BOD_SUPPORTED)
list(APPEND srcs "${target_folder}/power_supply_periph.c")
endif()
set(ldfragments "linker.lf")
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${includes}
LDFRAGMENTS "linker.lf")
LDFRAGMENTS ${ldfragments})
# 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

View File

@@ -1,3 +1,7 @@
if(IDF_CUSTOM_TOOLCHAIN)
return()
endif()
if(CONFIG_IDF_TOOLCHAIN_GCC)
# Common flags
idf_toolchain_add_flags(LINK_OPTIONS "-nostartfiles")

View File

@@ -4,6 +4,11 @@ if(${target} STREQUAL "linux")
return() # This component is not supported by the POSIX/Linux simulator
endif()
if(IDF_BUILD_V2)
include(${CMAKE_CURRENT_LIST_DIR}/CMakeLists_v2.txt)
return()
endif()
set(srcs "")
set(includes "")

View File

@@ -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()

View File

@@ -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(${CMAKE_CURRENT_LIST_DIR}/IDFULPProjectCommon.cmake)
enable_language(C ASM)
set(CMAKE_EXECUTABLE_SUFFIX ".elf")
# 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()
ulp_detect_build_type()
ulp_apply_build_type_options()
# Check the supported assembler version
if(BUILD_FSM)
check_expected_tool_version("esp32ulp-elf" ${CMAKE_ASM_COMPILER})
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)
if(BUILD_RISCV)
target_link_options(${ulp_app_name} PRIVATE "-nostartfiles")
@@ -47,16 +68,6 @@ function(ulp_apply_default_options ulp_app_name)
endfunction()
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}")
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
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)
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)
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()
message(FATAL_ERROR "Unable to determine ULP type. ")
endif()
get_filename_component(ULP_LD_SCRIPT ${ULP_LD_TEMPLATE} NAME)
# Put all arguments to the list
set(preprocessor_args -D__ASSEMBLER__ -E -P -xc -o ${ULP_LD_SCRIPT} ${ULP_PREPRO_ARGS} ${ULP_LD_TEMPLATE})
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})
# Strip the .in suffix so the generated script keeps its .ld name.
get_filename_component(ULP_LD_SCRIPT ${ULP_LD_TEMPLATE} NAME_WLE)
__ulp_add_preprocessed_linker_script(${ulp_app_name} ${ULP_LD_TEMPLATE} ${ULP_LD_SCRIPT}
ld_script ${ULP_PREPRO_ARGS})
# To avoid warning "Manually-specified variables were not used by the project"
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(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.
add_custom_command(OUTPUT ${ulp_ps_output}
@@ -237,59 +235,3 @@ function(ulp_apply_default_sources ulp_app_name)
endif()
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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -9,9 +9,28 @@ set(CMAKE_ASM_COMPILER "esp32ulp-elf-as")
set(CMAKE_OBJCOPY "esp32ulp-elf-objcopy")
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()
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OBJECT "${CMAKE_ASM${ASM_DIALECT}_COMPILER} \
--mcpu=esp32 <DEFINES> <INCLUDES> -o <OBJECT> -c <SOURCE>")
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} \
--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_ASM_LINK_EXECUTABLE "${CMAKE_LINKER} <FLAGS> <CMAKE_ASM_LINK_FLAGS> \
<LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")

View File

@@ -9,8 +9,28 @@ set(CMAKE_ASM_COMPILER "esp32ulp-elf-as")
set(CMAKE_OBJCOPY "esp32ulp-elf-objcopy")
set(CMAKE_LINKER "esp32ulp-elf-ld")
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OBJECT "${CMAKE_ASM${ASM_DIALECT}_COMPILER} \
--mcpu=esp32s2 <DEFINES> <INCLUDES> -o <OBJECT> -c <SOURCE>")
# 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} \
--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_ASM_LINK_EXECUTABLE "${CMAKE_LINKER} <FLAGS> <CMAKE_ASM_LINK_FLAGS> \
<LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")

View File

@@ -9,8 +9,28 @@ set(CMAKE_ASM_COMPILER "esp32ulp-elf-as")
set(CMAKE_OBJCOPY "esp32ulp-elf-objcopy")
set(CMAKE_LINKER "esp32ulp-elf-ld")
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OBJECT "${CMAKE_ASM${ASM_DIALECT}_COMPILER} \
--mcpu=esp32s3 <DEFINES> <INCLUDES> -o <OBJECT> -c <SOURCE>")
# 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} \
--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_ASM_LINK_EXECUTABLE "${CMAKE_LINKER} <FLAGS> <CMAKE_ASM_LINK_FLAGS> \
<LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")

View File

@@ -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()

View File

@@ -1,10 +1,16 @@
if(IDF_BUILD_V2 AND __ULP_BUILD)
return()
endif()
# ulp_embed_binary
#
# 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)
set(ulp_cmake_dir "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/cmake")
set(sources "")
spaces2list(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})
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})
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})
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
${ulp_artifacts_prefix}.ld
${ulp_artifacts_prefix}.h)
# 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})
set(ulp_artifacts_extras ${ulp_artifacts_prefix}.map
${ulp_artifacts_prefix}.sym
${CMAKE_CURRENT_BINARY_DIR}/${app_name}/esp32.ulp.ld)
list(APPEND ulp_artifacts
${ulp_artifacts_prefix}.bin
${ulp_artifacts_prefix}.ld
${ulp_artifacts_prefix}.h)
list(APPEND ulp_artifacts_extras
${ulp_artifacts_prefix}.map
${ulp_artifacts_prefix}.sym
${ulp_binary_dir}/${binary_name}.elf)
endforeach()
# 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.
string(REPLACE ";" "|" ulp_s_sources "${ulp_s_sources}")
idf_build_get_property(sdkconfig_header SDKCONFIG_HEADER)
idf_build_get_property(sdkconfig_cmake SDKCONFIG_CMAKE)
idf_build_get_property(sdkconfig SDKCONFIG)
idf_build_get_property(idf_path IDF_PATH)
idf_build_get_property(idf_target IDF_TARGET)
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.")
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)
elseif(IDF_TARGET STREQUAL "esp32s2" OR IDF_TARGET STREQUAL "esp32s3")
# 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.")
string(TOLOWER "${type}" type_lower)
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")
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()
message(FATAL_ERROR "Invalid ULP_TYPE '${type}'; expected 'fsm' or 'riscv'.")
endif()
else()
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()
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()
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()
externalproject_add(${app_name}
SOURCE_DIR ${project_path}
BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${app_name}
INSTALL_COMMAND ""
CMAKE_ARGS -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
-DCMAKE_GENERATOR=${CMAKE_GENERATOR}
-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}
-DULP_VAR_PREFIX=${prefix}
-DULP_TYPE=${type}
-DCOMPONENT_DIR=${COMPONENT_DIR}
-DCOMPONENT_INCLUDES=$<TARGET_PROPERTY:${COMPONENT_TARGET},INTERFACE_INCLUDE_DIRECTORIES>
-DIDF_TARGET=${idf_target}
-DIDF_PATH=${idf_path}
-DSDKCONFIG_HEADER=${SDKCONFIG_HEADER}
-DSDKCONFIG_CMAKE=${SDKCONFIG_CMAKE}
-DPYTHON=${python}
-DCMAKE_MODULE_PATH=${idf_path}/components/ulp/cmake/
${extra_cmake_args}
BUILD_COMMAND ${CMAKE_COMMAND} --build ${CMAKE_CURRENT_BINARY_DIR}/${app_name} --target build
BUILD_BYPRODUCTS ${ulp_artifacts} ${ulp_artifacts_extras} ${ulp_ps_sources}
${CMAKE_CURRENT_BINARY_DIR}/${app_name}/${app_name}
BUILD_ALWAYS 1
)
SOURCE_DIR ${project_path}
BINARY_DIR ${ulp_binary_dir}
INSTALL_COMMAND ""
CMAKE_ARGS -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
-DCMAKE_GENERATOR=${CMAKE_GENERATOR}
-DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FLAG}
-DADD_PICOLIBC_SPECS=${CONFIG_LIBC_PICOLIBC}
-DULP_VAR_PREFIX=${prefix}
-DULP_TYPE=${type}
${ulp_project_args}
-DIDF_TARGET=${idf_target}
-DIDF_PATH=${idf_path}
-DPYTHON=${python}
${extra_cmake_args}
BUILD_COMMAND ${CMAKE_COMMAND} --build ${ulp_binary_dir} --target build
BUILD_BYPRODUCTS ${ulp_artifacts} ${ulp_artifacts_extras} ${ulp_ps_sources}
${ulp_binary_dir}/${app_name}
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}")
spaces2list(exp_dep_srcs)
set_source_files_properties(${exp_dep_srcs} PROPERTIES OBJECT_DEPENDS ${ulp_artifacts})
if(exp_dep_srcs)
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_dependencies(${COMPONENT_LIB} ${app_name}_artifacts)
target_linker_script(${COMPONENT_LIB} INTERFACE ${CMAKE_CURRENT_BINARY_DIR}/${app_name}/${app_name}.ld)
target_add_binary_data(${COMPONENT_LIB} ${CMAKE_CURRENT_BINARY_DIR}/${app_name}/${app_name}.bin BINARY)
foreach(binary_name IN LISTS binary_names)
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()
endfunction()
@@ -139,6 +241,23 @@ function(validate_ulp_type ULP_TYPE)
endif()
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)
cmake_parse_arguments(ULP "" "PREFIX;TYPE" "" ${ARGN})
if(NOT ULP_PREFIX)
@@ -146,18 +265,38 @@ function(ulp_embed_binary app_name s_sources exp_dep_srcs)
endif()
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"
"${ULP_PREFIX}" "${ULP_TYPE}" "${s_sources}" "${exp_dep_srcs}")
__setup_ulp_project("${app_name}" "${ulp_cmake_dir}"
"${ULP_PREFIX}" FALSE "${ULP_TYPE}"
"${app_name}"
"${s_sources}" "${exp_dep_srcs}")
endfunction()
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)
set(ULP_PREFIX "ulp_")
endif()
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()

View File

@@ -1,6 +1,12 @@
# 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:
disable+:
- *ulp_legacy_buildv2_disable
disable:
- if: SOC_LP_CORE_SUPPORTED != 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:
disable:
- *ulp_legacy_buildv2_disable
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)
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:
disable+:
- *ulp_legacy_buildv2_disable
disable:
- if: SOC_LP_CORE_SUPPORTED != 1
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:
disable+:
- *ulp_legacy_buildv2_disable
disable:
- if: SOC_LP_CORE_SUPPORTED != 1
depends_components:
@@ -51,6 +63,8 @@ components/ulp/test_apps/lp_core/lp_core_hp_uart:
components/ulp/test_apps/ulp_fsm:
disable:
- *ulp_legacy_buildv2_disable
enable:
- if: SOC_ULP_FSM_SUPPORTED == 1
depends_components:
@@ -61,6 +75,8 @@ components/ulp/test_apps/ulp_fsm:
components/ulp/test_apps/ulp_riscv:
disable+:
- *ulp_legacy_buildv2_disable
disable:
- if: SOC_RISCV_COPROC_SUPPORTED != 1
depends_components:

View File

@@ -21,6 +21,12 @@ endif()
message(STATUS "Compiler supported targets: ${dump_machine}")
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 "
"(or an invalid CMakeCache.txt file has been generated somehow)")
endif()