Example Analysis
This section will take the program Blink as an example to analyse the
file structure and coding rules of a real project in detail. The Blink
program implements the LED blinking effect, and the project is located
in the directory examples/get-started/blink
, which contains a source
file, configuration files, and several compilation scripts.
The smart light project introduced in this book is based on this example program. Functions will be gradually added in later chapters to finally complete it.
📝 Source code
In order to demonstrate the entire development process, the Blink program has been copied to
esp32c3-iot-projects/device_firmware/1_blink
.
The directory structure of the blink
project files is shown in Figure 4.15.
The blink
project contains only one main
directory, which is a
special component that must be included as described in section 4.3.2.
The main directory is mainly used to store the implementation of the
app_main()
function, which is the entry point to the user program.The
blink
project does not include the components
directory, because
this example only needs to use the components that come with ESP-IDF and
does not require additional components. The CMakeLists.txt
included in
the blink
project is used to guide the compilation process, while
Kconfig.projbuild
is used to add configuration items for this example
program in menuconfig
. Other unnecessary files will not affect the
compilation of the code, so they will not be discussed here. A detailed
introduction to the blink
project files is as follows.
/*blink.c includes the following header files*/
#include <stdio.h> //Standard C library header file
#include "freertos/freeRTOS.h" //FreeRTOS main header file
#include "freertos/task.h" //FreeRTOS Task header file
#include "sdkconfig.h" //Configuration header file generated by kconfig
#include "driver/gpio.h" //GPIO driver header file
The source file blink.c
contains a series of header files
corresponding to function declarations. ESP-IDF generally follows the
order of including standard library header files, FreeRTOS header files,
driver header files, other component header files, and project header
files. The order in which header files are included may affect the final
compilation result, so try to follow the default rules. It should be
noted that sdkconfig.h
is automatically generated by kconfig
and can
only be configured through the command idf.py menuconfig
. Direct
modification of this header file will be overwritten.
/*You can select the GPIO corresponding to the LED in idf.py menuconfig, and the modification result of menuconfig is that the value of CONFIG_BLINK_GPIO will be changed. You can also directly modify the macro definition here, and change CONFIG_BLINK_GPIO to a fixed value.*/
#define BLINK_GPIO CONFIG_BLINK_GPIO
void app_main(void)
{
/*Configure IO as the GPIO default function, enable pull-up mode, and disable input and output modes*/
gpio_reset_pin(BLINK_GPIO);
/*Set GPIO to output mode*/
gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
while(1) {
/*Print log*/
printf("Turning off the LED\n");
/*Turn off the LED (output low level)*/
gpio_set_level(BLINK_GPIO, 0);
/*Delay (1000 ms)*/
vTaskDelay(1000 / portTICK_PERIOD_MS);
printf("Turning on the LED\n");
/*Turn on the LED (output high level)*/
gpio_set_level(BLINK_GPIO, 1);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
The app_main()
function in the Blink example program serves as the
entry point for user programs. It is a simple function with no
parameters and no return value. This function is called after the system
has completed initialisation, which includes tasks such as initialising
the log serial port, configuring single/dual core, and configuring the
watchdog.
The app_main()
function runs in the context of a task named main
.
The stack size and priority of this task can be adjusted in
menuconfig → Componentconfig → Common ESP-related
.
For simple tasks like blinking an LED, all the necessary code can be
implemented directly in the app_main()
function. This typically
involves initialising the GPIO corresponding to the LED and using a
while(1)
loop to toggle the LED on and off. Alternatively, you can use
FreeRTOS API to create a new task that handles the LED blinking. Once
the new task is successfully created, you can exit the app_main()
function.
The content of main/CMakeLists.txt
file, which guides the compilation
process for the main component, is as follows:
idf_component_register(SRCS "blink.c" INCLUDE_DIRS "." )
Among them, main/CMakeLists.txt
only calls one compilation system
function, that is idf_component_register
. Similar to the
CMakeLists.txt
for most other components, blink.c
is added to
SRCS
, and the source files added to SRCS
will be compiled. At the
same time, ".
", which represents the path where CMakeLists.txt
is
located, should be added to INCLUDE_DIRS
as the search directories for
header files. The content of CMakeLists.txt
is as follows:
# Specify v3.5 as the oldest CMake version supported by the current project
# Versions lower than v3.5 must be upgraded before compilation continues
cmake_minimum_required(VERSION 3.5)
# Include the default CMake configuration of the ESP-IDF compilation system
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
# Create a project named "blink"
project(myProject)
Among them, the CMakeLists.txt
in the root directory mainly includes
$ENV{IDF_PATH}/tools/cmake/project.cmake
, which is the main CMake configuration
file provided by ESP-IDF. It is used to configure the default rules of
the ESP-IDF compilation system and define common functions such as
idf_component_register
; project(blink)
creates a project called
blink
, and the final firmware will be named blink.bin
.