Build ULP full subprojects through a dedicated entry file,
components/ulp/cmake/ulp_project.cmake, that wraps tools/cmakev2/idf.cmake
and layers a small ULP API on top, mirroring the cmakev2 layering:
ulp_project_init like idf_project_init (init, detect the ULP type,
reset the compile/link options inherited from the app)
ulp_build_executable like idf_build_executable, plus the embeddable
.bin/.h/.ld artifacts
ulp_project_default like idf_project_default (single-executable case)
A child project now includes this one file instead of idf.cmake and calls
these helpers directly, so idf_build_executable is used as-is for the
multi-binary case and the module-path indirection (include(IDFULPProject)
resolved via -DCMAKE_MODULE_PATH) is gone.
As a result:
- IDFULPProjectv2.cmake is removed; its setup moves into the wrapper.
- IDFULPProject.cmake becomes the CMake v1-only entry point.
- The ULP component no longer registers a POST_ELF callback; the binary
artifacts are produced by ulp_build_executable.
- The v2 full-subproject examples (lp_core, riscv, fsm, multi_binary,
combined) are updated to the new API.
- The ULP subproject API is documented in build-system-v2.rst.
Also fix a latent bug this exercises: idf_build_library emitted linker
scripts as "-T <name>" relying on a following "-L" search directory. GNU
ld only searches -L directories that precede -T, so the direct
esp32ulp-elf-ld link used for ULP FSM failed to open the script. Emit the
absolute path instead, matching what the CMake v1 ULP build already does.
Finally, replace the parent-argument bypass loop that used to live in
IDFULPProjectv2.cmake with --no-warn-unused-cli on the child configure,
and stop passing the unused IDF_PARENT_BUILD_DIR.
Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
Rename the ULP memory-layout linker scripts to .ld.in and let the
standard build system preprocess them, instead of the ULP build doing
its own C-preprocessor pass.
CMake v2 (full subproject): register each memory-layout template with
target_linker_script using the new FLAGS (the include dirs its #include
lines need) and MEMORY (emit before section-placement scripts) options.
soc/soc.h and the esp_common headers now resolve from the linked
component graph automatically, so the POST_ELF callback no longer
harvests include directories or preprocesses the template; it only
produces the .bin and the symbol header/linker exports from the ELF.
CMake v1 (legacy): the templates are now .ld.in, so strip the suffix
with NAME_WLE when deriving the generated script name. The v1-only
preprocessing helpers (__ulp_add_preprocessed_linker_script and
__ulp_create_arg_file) move from the shared IDFULPProjectCommon.cmake
to IDFULPProject.cmake next to their only caller, since CMake v2 no
longer references them.
Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
Register ULP memory linker scripts with target_linker_script so CMake v2 handles preprocessing and attachment through the component graph.
Keep the generated legacy outputs named .ld by stripping only the .in suffix, and pass full linker script paths to support direct ld invocation.
Add cmakev2 support for the ULP sub-project, allowing it to be built
using the standard idf_project_init() flow when the main project uses
cmakev2. The existing cmakev1 path is preserved — the ULP
CMakeLists.txt checks IDF_BUILD_V2 and delegates to CMakeLists_v2.txt,
following the same pattern used by the bootloader sub-project.
The parent's project_include.cmake now has separate externalproject_add
blocks for cmakev1 and cmakev2, making the different requirements of
each build system explicit:
cmakev1 path:
Passes -DSDKCONFIG_HEADER and -DSDKCONFIG_CMAKE from the parent.
The ULP sub-project includes the parent's sdkconfig.cmake directly
(no kconfgen). This is the existing behavior.
cmakev2 path:
Passes -DSDKCONFIG_DEFAULTS pointing to the parent's sdkconfig.
The ULP sub-project runs its own kconfgen with its own component
set, generating separate sdkconfig.h and sdkconfig.cmake outputs.
The parent's sdkconfig serves as defaults, so the ULP inherits
the parent's IDF configuration while adding ULP-specific options
from its own components. A menuconfig-<app_name> proxy target is
registered in the parent build for ULP-specific configuration.
The proxy target depends on the ULP configure step to ensure the
cmake cache exists before menuconfig runs.
Passes -DIDF_CUSTOM_TOOLCHAIN=1 so that __init_toolchain() skips
IDF_TARGET-based toolchain resolution and component
project_include.cmake files skip IDF toolchain flag manipulation.
IDFULPProject.cmake is updated to skip the direct
include(${SDKCONFIG_CMAKE}) when running under cmakev2, as
idf_project_init() handles sdkconfig loading.
Verified with identical ULP artifacts (bin, ld, h) across all three
ULP types:
- LP Core (esp32c6, lp_core/lp_uart/lp_uart_print example)
- RISC-V (esp32s3, ulp_riscv/adc example)
- FSM (esp32, ulp_fsm/ulp example)
Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
Updated kconfig option type and other supporting changes in build system
to allow enabling both ULP FSM and ULP RISCV simultaneously. Users can
choose at run time which one to initialize and use.
NOTE: Both ULP FSM and ULP RISCV can't be used simultaneously at run
time because they share some common hardware like RTC slow memory space.
Closes https://github.com/espressif/esp-idf/issues/12999
The ULP sources include sdkconfig.h for compile-time configuration
values. The sdkconfig directory was previously available to the ULP
target indirectly through the COMPONENT_INCLUDES variable, which is
populated from the parent component's INTERFACE_INCLUDE_DIRECTORIES.
In cmake v1, idf_component_register() adds the config_dir as PUBLIC
include directory to every component (component.cmake:498), so it
ends up in INTERFACE_INCLUDE_DIRECTORIES and gets passed to the ULP
subproject via COMPONENT_INCLUDES.
In cmakev2, the config_dir is added as a build-level property and
applied to components as PRIVATE (component.cmake:1053), so it no
longer appears in INTERFACE_INCLUDE_DIRECTORIES. As a result, the
sdkconfig directory is missing from the ULP target's include paths.
Add the sdkconfig directory explicitly to the ULP target's include
directories. Note that SDKCONFIG_HEADER is already passed to the ULP
subproject and its directory is already extracted into sdkconfig_dir
for linker script preprocessing (IDFULPProject.cmake:40).
Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
This commit:
- Removes the link time symbol name clash detection.
- Extracts symbols of type NOTYPE for global identifiers defined in
assembly files.
- Makes the prefix argument optional for ulp_add_build_binary_targets().
- Adds a unit test for the ulp binary embed with a prefix feature.
This commit adds APIs to initialize and configure the LP ADC from the HP
core and also adds APIs to read the raw and converted ADC values from the LP core.
This commit adds the ability to use LP ROM functions from the LP core.
This allows the LP core code to utilize standard functions such as those
for printing from the LP ROM and therefore help reduce the code size on
the LP core.
There are redefinition compilation warnings for the register operation
macros when a ULP program was compiled which included soc.h before
ulp_riscv_register_ops.h. This commit fixes the issues by delegating the
exclusion macro to the CMakeLists.txt file.
Closes: https://github.com/espressif/esp-idf/issues/12116
This commit adds a minimal logging driver for the LP core. The logging
driver provides a printf function which is built on top of the LP UART
driver. The commit also adds an example to demonstrate how to use print
statements in an LP core program.
This commit adds a UART driver for the LP core to interact with the LP
UART. The commit also adds an example to demonstrate the usage of the LP
UART driver.
This commit adds a driver for reading the touch sensor from the ULP
RISC-V core during sleep. The commit also adds an example to demonstrate
this feature.
Closes https://github.com/espressif/esp-idf/issues/10480
This commit adds support for the LP I2C peripheral driver to be used by
the LP core. An example is also added to demonstrate the usage of the LP
I2C peripheral from the LP core.