examples: update idf_as_lib example to use new api

This commit is contained in:
Renz Christian Bagaporo 2019-03-24 10:14:49 +08:00
parent c564d1730f
commit 477fa49fc0
24 changed files with 176 additions and 57 deletions

View file

@ -55,8 +55,8 @@ else()
"src/idf/secure_boot_signatures.c")
set(COMPONENT_ADD_INCLUDEDIRS "include")
set(COMPONENT_PRIV_INCLUDEDIRS "include_bootloader")
set(COMPONENT_REQUIRES soc) #unfortunately the header directly uses SOC registers
set(COMPONENT_PRIV_REQUIRES spi_flash mbedtls efuse)
set(COMPONENT_REQUIRES mbedtls soc) #unfortunately the header directly uses SOC registers
set(COMPONENT_PRIV_REQUIRES spi_flash efuse)
endif()
register_component()

View file

@ -34,13 +34,13 @@ else()
"task_wdt.c")
set(COMPONENT_ADD_INCLUDEDIRS "include")
set(COMPONENT_REQUIRES driver esp_event efuse soc) #unfortunately rom/uart uses SOC registers directly
set(COMPONENT_REQUIRES app_update driver esp_event efuse pthread soc) #unfortunately rom/uart uses SOC registers directly
# driver is a public requirement because esp_sleep.h uses gpio_num_t & touch_pad_t
# app_update is added here because cpu_start.c uses esp_ota_get_app_description() function.
set(COMPONENT_PRIV_REQUIRES
app_trace app_update bootloader_support log mbedtls nvs_flash
pthread smartconfig_ack spi_flash vfs wpa_supplicant espcoredump esp_common esp_wifi)
smartconfig_ack spi_flash vfs wpa_supplicant espcoredump esp_common esp_wifi)
set(COMPONENT_ADD_LDFRAGMENTS linker.lf ld/esp32_fragments.lf)

View file

@ -1,4 +1,5 @@
register_config_only_component()
set(COMPONENT_PRIV_REQUIRES bootloader)
register_component()
string(REPLACE ";" " " ESPTOOLPY_FLASH_PROJECT_OPTIONS "${ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS}")
set(ESPTOOLPY_FLASH_PROJECT_OPTIONS

View file

@ -9,7 +9,8 @@ else()
"flash_ops.c"
"partition.c"
"spi_flash_rom_patch.c")
set(COMPONENT_PRIV_REQUIRES bootloader_support app_update soc)
set(COMPONENT_REQUIRES app_update)
set(COMPONENT_PRIV_REQUIRES bootloader_support soc)
endif()
set(COMPONENT_ADD_INCLUDEDIRS include)

View file

@ -1,24 +1,38 @@
cmake_minimum_required(VERSION 3.5)
project(idf_as_lib C)
# The source file main.c contains app_main() definition
add_executable(${CMAKE_PROJECT_NAME}.elf main.c)
if("${TARGET}" STREQUAL "esp32")
# Include for ESP-IDF build system functions
include($ENV{IDF_PATH}/tools/cmake/idf.cmake)
# Create idf::esp32 and idf::freertos static libraries
idf_build_process(esp32
# try and trim the build; additional components
# will be included as needed based on dependency tree
#
# although esptool_py does not generate static library,
# processing the component is needed for flashing related
# targets and file generation
COMPONENTS esp32 freertos esptool_py
SDKCONFIG ${CMAKE_BINARY_DIR}/sdkconfig
BUILD_DIR ${CMAKE_BINARY_DIR})
else()
# Create stubs for esp32 and freertos, stub::esp32 and stub::freertos
add_subdirectory(stubs/esp32)
add_subdirectory(stubs/freertos)
add_subdirectory(stubs/spi_flash)
endif()
# Provides idf_import_components() and idf_link_components()
include($ENV{IDF_PATH}/tools/cmake/idf_functions.cmake)
set(elf_file ${CMAKE_PROJECT_NAME}.elf)
add_executable(${elf_file} main.c)
# Create artifacts used for flashing the project to target chip
set(IDF_BUILD_ARTIFACTS ON)
set(IDF_PROJECT_EXECUTABLE ${CMAKE_PROJECT_NAME}.elf)
set(IDF_BUILD_ARTIFACTS_DIR ${CMAKE_BINARY_DIR})
# Link the static libraries to the executable
if("${TARGET}" STREQUAL "esp32")
target_link_libraries(${elf_file} idf::esp32 idf::freertos idf::spi_flash)
# Attach additional targets to the executable file for flashing,
# linker script generation, partition_table generation, etc.
idf_build_executable(${elf_file})
else()
target_link_libraries(${elf_file} stub::esp32 stub::freertos stub::spi_flash)
endif()
# Trim down components included in the build. Although freertos and spi_flash are the ones needed by the application
# itself, the bootloader and esptool_py components are also needed in order to create the artifacts to be used
# for flashing to the target chip
set(IDF_COMPONENTS freertos spi_flash bootloader esptool_py)
# Wraps add_subdirectory() to create library targets for components, and then return them using the specified variable
idf_import_components(components $ENV{IDF_PATH} esp-idf)
# Wraps target_link_libraries() to link processed components by idf_import_components to target
idf_link_components(${CMAKE_PROJECT_NAME}.elf "${components}")
set(CMAKE_EXPORT_COMPILE_COMMANDS 1)

View file

@ -1,13 +1,17 @@
# Using ESP-IDF in Custom CMake Projects
This example illustrates using ESP-IDF components as libraries in custom CMake projects. This builds
an equivalent application to the `hello_world` example under `examples/get-started/hello_world`.
This example illustrates using ESP-IDF components as libraries in custom CMake projects. The application
in this example can run on either host or on an ESP32, and the appropriate libraries are linked
to the executable depending on which target is specified. If the target is an ESP32, the libraries
created from ESP-IDF components are linked. On the other hand, stub libraries are linked if example
is meant to be run on the host to simulate the same application behavior.
The application in this example is equivalent to the `hello_world` example under `examples/get-started/hello_world`.
## Example Flow
Users looking at this example should focus on the [top-level CMakeLists.txt file](./CMakeLists.txt). This builds an
application that can run on targets without relying on the typical ESP-IDF application template. The application itself
follows a similar code flow to the aforementioned `hello_world` example.
application that can run on the target without relying on the typical ESP-IDF application template.
### Output
@ -29,41 +33,38 @@ Restarting in 0 seconds...
## Building this Example
To build this example, run the following commands from this directory:
To build this example, the user can either run [build-esp32.sh](./build-esp32.sh) to build for the ESP32
or run [build.sh](./build.sh) to build for the host:
```bash
# Create a build directory, and change location to that directory.
mkdir build; cd build
# Invoke CMake, specifying the top-level CMakeLists.txt directory and toolchain file to use. This will generate
# the build system files.
cmake .. -DCMAKE_TOOLCHAIN_FILE=$IDF_PATH/tools/cmake/toolchain-esp32.cmake -DIDF_TARGET=esp32
# Build using the generated build system files.
cmake --build .
# Builds the example for ESP32
./build-esp32.sh
```
Or, execute `build.sh` script, which contains the same commands mentioned above.
or
```bash
# Builds the example to run on host
./build.sh
```
## Flashing and Running this Example
To flash this example, we will have to invoke `esptool.py` and `idf_monitor.py` manually. While still in the build directory:
### Flashing to target
To flash and run the example, users can run either [run-esp32.sh](./run-esp32.sh) or [run.sh](./run.sh) depending
on what the example was built for. In the case of ``run-esp32.sh``, the port needs to be specified:
```bash
# Write project binaries to flash.
esptool.py --port /dev/ttyUSB0 write_flash @flash_project_args
# Run the example on device connected to /dev/ttyUSB1
./run-esp32.sh /dev/ttyUSB1
```
### Running on target
or
```bash
# Monitor the output of the flashed firmware.
idf_monitor.py --port /dev/ttyUSB0 idf_as_lib.elf
# Run the example on the host
./run.sh
```
Of course, you should replace the specified ports in the commands specified above to the proper one where your device
is connected.
---
There is a discussion on using ESP-IDF in custom CMake projects in the programming guide under `API Guides` -> `Build System (CMake)` -> `Using ESP-IDF in Custom CMake Projects`

View file

@ -0,0 +1,4 @@
#!/bin/bash
rm -rf build && mkdir build && cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=$IDF_PATH/tools/cmake/toolchain-esp32.cmake -DTARGET=esp32 -GNinja
cmake --build .

View file

@ -1,8 +1,4 @@
#!/bin/bash
#
# Build this example, which does not use that standard IDF app template. See README.md for
# more information about the build and how to run this example on the target once built.
mkdir build; cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=$IDF_PATH/tools/cmake/toolchain-esp32.cmake -DIDF_TARGET=esp32
rm -rf build && mkdir build && cd build
cmake ..
cmake --build .

View file

@ -0,0 +1,4 @@
#!/bin/bash
cd build
python $IDF_PATH/components/esptool_py/esptool/esptool.py -p $1 write_flash @flash_project_args
python $IDF_PATH/tools/idf_monitor.py -p $1 idf_as_lib.elf

View file

@ -0,0 +1,3 @@
#!/bin/bash
cd build
./idf_as_lib.elf

View file

@ -0,0 +1,6 @@
add_library(stub_esp32 STATIC system_api.c flash_ops.c cpu_start.c)
target_include_directories(stub_esp32 PUBLIC .)
add_library(stub::esp32 ALIAS stub_esp32)
target_link_libraries(stub_esp32 "-u app_main")
target_link_libraries(stub_esp32 stub::spi_flash)

View file

@ -0,0 +1,11 @@
#include <stdbool.h>
#include <setjmp.h>
extern void app_main();
jmp_buf buf;
int main()
{
setjmp(buf);
app_main();
}

View file

@ -0,0 +1,15 @@
#pragma once
#include <stdint.h>
#define CHIP_FEATURE_EMB_FLASH (1UL << 0)
#define CHIP_FEATURE_BT (1UL << 4)
#define CHIP_FEATURE_BLE (1UL << 5)
typedef struct {
uint32_t features; //!< bit mask of CHIP_FEATURE_x feature flags
uint8_t cores; //!< number of CPU cores
uint8_t revision; //!< chip revision number
} esp_chip_info_t;
void esp_restart(void);
void esp_chip_info(esp_chip_info_t* out_info);

View file

@ -0,0 +1,6 @@
#include "esp_spi_flash.h"
int spi_flash_get_chip_size()
{
return (1024 * 1024 * 1024);
}

View file

@ -0,0 +1,19 @@
#include <stdio.h>
#include <unistd.h>
#include <setjmp.h>
#include "esp_system.h"
extern jmp_buf buf;
void esp_restart(void)
{
printf("\n");
sleep(1); // pause for dramatic effect
longjmp(buf, 0);
}
void esp_chip_info(esp_chip_info_t* out_info)
{
out_info->cores = 8;
out_info->features = (uint32_t) -1;
}

View file

@ -0,0 +1,3 @@
add_library(stub_freertos STATIC task.c)
target_include_directories(stub_freertos PUBLIC .)
add_library(stub::freertos ALIAS stub_freertos)

View file

@ -0,0 +1,7 @@
#pragma once
#include <stdint.h>
#define portTICK_PERIOD_MS 1000
void vTaskDelay( const uint32_t xTicksToDelay );

View file

@ -0,0 +1,7 @@
#include <unistd.h>
#include "freertos/task.h"
void vTaskDelay( const uint32_t xTicksToDelay )
{
sleep(xTicksToDelay);
}

View file

@ -0,0 +1,3 @@
add_library(stub_spi_flash INTERFACE)
target_include_directories(stub_spi_flash INTERFACE .)
add_library(stub::spi_flash ALIAS stub_spi_flash)

View file

@ -0,0 +1,5 @@
#pragma once
#include <stddef.h>
int spi_flash_get_chip_size();

View file

@ -66,7 +66,7 @@ LOG_SUSPECTED=${LOG_PATH}/common_log.txt
touch ${LOG_SUSPECTED}
SDKCONFIG_DEFAULTS_CI=sdkconfig.ci
EXAMPLE_PATHS=$( find ${IDF_PATH}/examples/ -type f -name CMakeLists.txt | grep -v "/components/" | grep -v "/common_components/" | grep -v "/main/" | sort )
EXAMPLE_PATHS=$( find ${IDF_PATH}/examples/ -type f -name CMakeLists.txt | grep -v "/components/" | grep -v "/common_components/" | grep -v "/main/" | grep -v "/idf_as_lib/stubs/" | sort )
if [ $# -eq 0 ]
then
@ -142,7 +142,7 @@ build_example () {
idf.py build >>${BUILDLOG} 2>&1
else
rm -rf build &&
./build.sh >>${BUILDLOG} 2>&1
./build-esp32.sh >>${BUILDLOG} 2>&1
fi ||
{
RESULT=$?; FAILED_EXAMPLES+=" ${EXAMPLE_NAME}" ;

View file

@ -73,7 +73,10 @@ components/espcoredump/test/test_espcoredump.sh
tools/ldgen/ldgen.py
tools/ldgen/test/test_fragments.py
tools/ldgen/test/test_generation.py
examples/build_system/cmake/idf_as_lib/build-esp32.sh
examples/build_system/cmake/idf_as_lib/build.sh
examples/build_system/cmake/idf_as_lib/run-esp32.sh
examples/build_system/cmake/idf_as_lib/run.sh
examples/storage/parttool/parttool_example.py
examples/system/ota/otatool/otatool_example.py
tools/check_kconfigs.py

View file

@ -342,6 +342,7 @@ function run_tests()
rm sdkconfig.defaults;
print_status "Building a project with CMake library imported and PSRAM workaround, all files compile with workaround"
# Test for libraries compiled within ESP-IDF
rm -rf build
echo "CONFIG_SPIRAM_SUPPORT=y" >> sdkconfig.defaults
echo "CONFIG_SPIRAM_CACHE_WORKAROUND=y" >> sdkconfig.defaults
@ -349,7 +350,16 @@ function run_tests()
idf.py -C $IDF_PATH/examples/build_system/cmake/import_lib -B `pwd`/build reconfigure -D SDKCONFIG_DEFAULTS="`pwd`/sdkconfig.defaults"
grep -q '"command"' build/compile_commands.json || failure "compile_commands.json missing or has no no 'commands' in it"
(grep '"command"' build/compile_commands.json | grep -v mfix-esp32-psram-cache-issue) && failure "All commands in compile_commands.json should use PSRAM cache workaround"
rm sdkconfig.defaults
rm -r sdkconfig.defaults build
# Test for external libraries in custom CMake projects with ESP-IDF components linked
mkdir build && touch build/sdkconfig
echo "CONFIG_SPIRAM_SUPPORT=y" >> build/sdkconfig
echo "CONFIG_SPIRAM_CACHE_WORKAROUND=y" >> build/sdkconfig
# note: we just need to run cmake
(cd build && cmake $IDF_PATH/examples/build_system/cmake/idf_as_lib -DCMAKE_TOOLCHAIN_FILE=$IDF_PATH/tools/cmake/toolchain-esp32.cmake -DTARGET=esp32)
grep -q '"command"' build/compile_commands.json || failure "compile_commands.json missing or has no no 'commands' in it"
(grep '"command"' build/compile_commands.json | grep -v mfix-esp32-psram-cache-issue) && failure "All commands in compile_commands.json should use PSRAM cache workaround"
rm -r build
print_status "Make sure a full build never runs '/usr/bin/env python' or similar"
OLDPATH="$PATH"