1、idf的常用基本命令

(1). 查看芯片信息:esptool.py -p COM4 flash_id

1
esptool.py -p COM4 flash_id

(2). 选择芯片命令:idf.py set-target esp32

​ 详细的命令格式为:idf.py set-target [OPTIONS] {esp32|esp32s2|esp32c3|esp32s3|esp32c2|esp32c6|esp32h2|linux}

​ 所以我们如果选择ESP32S3,则可以:

1
idf.py set-target esp32s3

(3). 编译命令:idf.py build

1
idf.py build

(4). 配置命令: idf.py menuconfig

1
idf.py menuconfig

(6). 下载命令: idf.py -p COM3 flash

1
idf.py -p COM3 flash

(7). console调试命令: idf.py -p COM3 monitor

1
idf.py -p COM3 monitor

(8). 退出调试模式: ctrl + ]

(9).更新esptool: pip install --upgrade esptool

1
pip install --upgrade esptool

(10). 关于idf版本相关内容

https://docs.espressif.com/projects/esp-idf/zh_CN/v5.1.3/esp32s3/versions.html

可以通过如下代码来下载idf的源码:

1
2
3
4
cd $IDF_PATH
git fetch
git checkout vX.Y.Z
git submodule update --init --recursive

2、idf和 vscode的一些说明和细节

(1). ESP-IDF CMD和 ESP-IDF PowerShell终端快捷方式

1. 终端快捷方式的解释
  1. cmd的目标内容:C:\WINDOWS\system32\cmd.exe /k ""D:\Espressif\idf_cmd_init.bat" esp-idf-cc72132cd64ef413a5557253e3adc170"
  2. PowerShell的目标内容: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -NoExit -File "D:\Espressif/Initialize-Idf.ps1" -IdfId esp-idf-cc72132cd64ef413a5557253e3adc170
  3. 它们的起始位置:D:\Espressif\frameworks\esp-idf-v5.1\

    本质上idf就是创建了一个Python的虚拟环境,并针对该环境配置了环境变量,配置环境变量的内容可以详解idf安装目录下的idf_cmd_init.bat(针对cmd)和Initialize-Idf.ps1(针对powershell)。

    而/k是cmd的参数,表示”保持命令行窗口打开”,表示在执行完idf_cmd_init.bat保持终端窗口打开,这样可以确保创建的虚拟环境在在终端中有效,也就是关闭了终端,虚拟环境就关闭了,环境变量也随之无效。

    esp-idf-cc72132cd64ef413a5557253e3adc170是idf软件的id,用来表示该idf软件,其在软件安装目录下的esp_idf.json中定义,为idfSelectedId的值。esp_idf.json文件内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"$schema": "http://json-schema.org/schema#",
"$id": "http://dl.espressif.com/dl/schemas/esp_idf",
"_comment": "Configuration file for ESP-IDF Eclipse plugin.",
"_warning": "Use / or \\ when specifying path. Single backslash is not allowed by JSON format.",
"gitPath": "D:/Espressif/tools/idf-git/2.39.2/cmd/git.exe",
"idfToolsPath": "D:\\Espressif",
"idfSelectedId": "esp-idf-cc72132cd64ef413a5557253e3adc170",
"idfInstalled": {
"esp-idf-cc72132cd64ef413a5557253e3adc170": {
"version": "5.1",
"python": "D:/Espressif/python_env/idf5.1_py3.11_env/Scripts/python.exe",
"path": "D:/Espressif/frameworks/esp-idf-v5.1/"
}
}
}

-ExecutionPolicy Bypass目的是关闭powershell的安全策略,这是由于PowerShell有一个安全特性,可以限制未经签名的脚本的执行,所以需要配置Bypass选项,用来允许执行任何脚本,无视这些安全限制,以确保可以运行Initialize-Idf.ps1脚本。

-NoExit与cmd终端中的/k作用一样,指示PowerShell在脚本执行完毕后不要关闭窗口,允许用户在同一窗口继续执行更多命令。

-File "D:\Espressif/Initialize-Idf.ps1"表示运行该脚本,用于设置ESP-IDF开发环境,与cmd终端的idf_cmd_init.bat作用相同,详细可以看批处理和脚本的内容
-IdfId esp-idf-cc72132cd64ef413a5557253e3adc170则表示在执行Initialize-Idf.ps1脚本时,给脚本中的IdfId变量复制为esp-idf-cc72132cd64ef413a5557253e3adc170这个值。
​ 通过以上解释,我们大致理解了idf-env工具的作用了。这意味着,实际上,我们可以在任何终端窗口,输入如下内容就可以进行idf的使用:

2. 一种多版本安装方法:

根据前面的终端的解释,所以我这边进行一种多版本idf的安装方法,我首先给电脑安装一个默认版本的idf,这里选择了idf v5.1版本(至于原因,后面有讲),我是安装在D:\Espressif目录下,然后再Espressif目录下又创建了几个其他版本的idf,直接取名版本号如下图:

idf安装

这个时候每安装完成一个版本,可以把该版本的终端快捷方式复制出来,放在桌面的一个文件夹内,这里我取名idf,就可以实现多有版本的终端编译功能。最后所有版本的快捷方式如下:

idf快捷方式

这里需要注意两点:

  1. 安装其他版本的时候,有可能导致,目录下esp_idf.json文件对应的目录内容改变,我记得好像是"gitPath"变量的值会修改,可以修改为对应版本的idf的目录,详细json的值可以参考第一节对快捷方式的解释内容。

  2. 安装可能会再用户环境变量中添加名称为IDF_TOOLS_PATH的环境变量,默认是安装最后一个版本的idf的目录,比如D:\Espressif\v5_1_3,这里可以直接把该环境变量删除掉。否则可能会导致终端快捷方式运行出错(快捷方式运行的时候会首先读取IDF_TOOLS_PATH的值,如果有,则默认定义该值为软件目录,没有则会自动创建批处理文件的目录为IDF_TOOLS_PATH)这里给出idf_cmd_init.bat这部分的定义如下:

    1
    2
    3
    4
    if "%IDF_TOOLS_PATH%" == "" (
    set IDF_TOOLS_PATH=%~dp0
    echo IDF_TOOLS_PATH not set. Setting to %~dp0
    )

此时VScode中默认绑定默认版本的idf。其他版本的编译有两种思路:

一种是直接再vscode中打开终端,然后输入语句来设置对应版本的idf的环境变量和配置,然后用idf的指令进行编译下载和调试;

另外一种方式是,针对每种版本的idf创建一个vscode工作区参数设置文件,直接把该文件复制到需要运行的idf工程中,此时,vscode会自动设置idf的工作区目录,并使用特定版本的idf来编译和下载程序。这个方法参考了B站UP主“第九个下弦月”的一个视频内容提供的 vscode 工作区的概念,详细视频地址为:https://www.bilibili.com/video/BV1bj421Z7z4/?spm_id_from=333.337.search-card.all.click&vd_source=50e88259c3b06cefc86b0480e57ce888

3. 终端环境变量配置语句:

首先是默认版本,我的是v5.1,直接再vscode终端中输入如下语句(一个采用cmd,一个采用powershell),既可再改终端之后,使用针对该版本的idf命令,实现编译和下载等功能:

1
cmd /k ""D:\Espressif\idf_cmd_init.bat" esp-idf-cc72132cd64ef413a5557253e3adc170"

或者

1
powershell -ExecutionPolicy Bypass -NoExit -File "D:\Espressif/Initialize-Idf.ps1" -IdfId esp-idf-cc72132cd64ef413a5557253e3adc170

如果是V5.1.3版本,id号不一样,用改语句:

1
cmd /k ""D:\Espressif\v5_1_3\idf_cmd_init.bat" esp-idf-2f332dae01e5300d41bb5887948c6ac3"

或者

1
powershell -ExecutionPolicy Bypass -NoExit -File "D:\Espressif\v5_1_3/Initialize-Idf.ps1" -IdfId esp-idf-2f332dae01e5300d41bb5887948c6ac3

如果是V5.2.1版本,id号不一样,用改语句:

1
cmd /k ""D:\Espressif\v5_2_1\idf_cmd_init.bat" esp-idf-f2854e5176bb04b11fdfe329dc6d2d14"

或者

1
powershell -ExecutionPolicy Bypass -NoExit -File "D:\Espressif\v5_2_1/Initialize-Idf.ps1" -IdfId esp-idf-f2854e5176bb04b11fdfe329dc6d2d14

注意:安装位置不同,这个生成的码也不同,应该是根据版本号,安装位置等信息生成的唯一识别码。

4. vscode 工作区配置文件

如果不希望再vscode中用终端来编译和下载文件,而是希望直接用vscode下方的快捷键来操作,而且可以实现在一台电脑上随时切换不同版本的idf工程,可以针对每个版本创建一个 vscode 工作区配置文件,把该文件复制到工程目录下,文件后缀需要为:xxx.code-workspace,比如,下面是我针对v5.2.1版本创建的文件,取名为idf_5.2.1.code-workspace内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"folders": [
{
"path": "."
}
],
"settings": {
"idf.espIdfPathWin": "D:\\Espressif\\v5_2_1\\frameworks\\esp-idf-v5.2.1",
"idf.pythonBinPathWin": "D:\\Espressif\\v5_2_1\\python_env\\idf5.2_py3.11_env\\Scripts\\python.exe",
"idf.toolsPathWin": "D:\\Espressif\\v5_2_1",
"idf.customExtraPaths": "D:\\Espressif\\v5_2_1\\tools\\xtensa-esp-elf-gdb\\12.1_20231023\\xtensa-esp-elf-gdb\\bin;D:\\Espressif\\v5_2_1\\tools\\riscv32-esp-elf-gdb\\12.1_20231023\\riscv32-esp-elf-gdb\\bin;D:\\Espressif\\v5_2_1\\tools\\xtensa-esp-elf\\esp-13.2.0_20230928\\xtensa-esp-elf\\bin;D:\\Espressif\\v5_2_1\\tools\\riscv32-esp-elf\\esp-13.2.0_20230928\\riscv32-esp-elf\\bin;D:\\Espressif\\v5_2_1\\tools\\esp32ulp-elf\\2.35_20220830\\esp32ulp-elf\\bin;D:\\Espressif\\v5_2_1\\tools\\cmake\\3.24.0\\bin;D:\\Espressif\\v5_2_1\\tools\\openocd-esp32\\v0.12.0-esp32-20230921\\openocd-esp32\\bin;D:\\Espressif\\v5_2_1\\tools\\ninja\\1.11.1;D:\\Espressif\\v5_2_1\\tools\\idf-exe\\1.0.3;D:\\Espressif\\v5_2_1\\tools\\ccache\\4.8\\ccache-4.8-windows-x86_64;D:\\Espressif\\v5_2_1\\tools\\dfu-util\\0.11\\dfu-util-0.11-win64;D:\\Espressif\\v5_2_1\\tools\\esp-rom-elfs\\20230320",
"idf.customExtraVars": {
"OPENOCD_SCRIPTS": "D:\\Espressif\\v5_2_1\\tools\\openocd-esp32\\v0.12.0-esp32-20230921/openocd-esp32/share/openocd/scripts",
"IDF_CCACHE_ENABLE": "1",
"ESP_ROM_ELF_DIR": "D:\\Espressif\\v5_2_1\\tools\\esp-rom-elfs\\20230320/"
},
"idf.gitPathWin": "D:\\Espressif\\v5_2_1\\tools\\idf-git\\2.43.0\\cmd\\git.exe"
}
}

可以看到,其实它操作和终端配置环境变量差不多,就是设置idf工具的目录地址而已。其他版本可以参考这个来设置,这里不多赘述。需要做好的配置文件,可以直接到如下地址下载:https://gitee.com/SenySunny/picture/tree/master/idf_code-workspace

另外,经部分电脑xxx.code-workspace文件并不会生效,针对这种情况,请直接把"settings"的内容(即所有的idf.xxx相关的软件目录选项)复制到.vscode目录下的settings.json文件中,然后重新打开工程目录。

(2). vscode中的idf工程代码跳转问题

在vscode中建立idf工程,或者直接从idf中复制example例程创建工程修改时,默认情况下我们点击使用的idf中的api函数是无法跳转到idf目录下,可以通过如下手段,实现代码的跳转(默认是按下Ctrl+鼠标左击实现跳转)——注意需要vscode已经安装idf插件和C/C++插件。

默认打开一个工程内的C文件,会在vscode的右下方出现win32的按钮图标(注意如下没有出现,可以尝试最大化vscode窗口),点击按钮,在弹出的选项栏中选择”编辑配置(JSON)”(也可以直接按住Ctrl+P按钮,在弹出的输入框输入> 编辑配置(JSON),效果一样),此时,会自动为工程添加c_cpp_properties.json文件(在.vscode目录下)。

在c_cpp_properties.json文件文件中的”configurations”属性添加一行代:码"compileCommands": "${workspaceFolder}/build/compile_commands.json", 注意json格式,需要在前面一行添加逗号,在正常添加之后的c_cpp_properties.json文件内容如下(不同环境下可能有所不同,只需要注意添加compileCommands属性即可):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE"
],
"windowsSdkVersion": "10.0.22621.0",
"compilerPath": "cl.exe",
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "windows-msvc-x64",
"compileCommands": "${workspaceFolder}/build/compile_commands.json"
}
],
"version": 4
}

此时在进行编译之后,会在build目录下产生一个compile_commands.json文件,此时,便可以按住ctrl键,鼠标点击特定函数,即使函数是在idf的内部,也可以实现跳转。

(3). 在下载或者其他使用串口的时候,出现无法打开串口的情况解决办法(被占用)

由于idf的操作都是在终端中进行的操作,如果它把串口占用了,可能会导致再次使用串口,出现无法打开串口的情况,此时可能会不清楚是哪个进程占用了串口的情况,导致无法使用串口(很多时候,即使把掉USB线,再插入也没有用,因为线程本身支持断线再插入的时候自动重新打开),可以通过如下方法来解除串口的占用。

  1. 打开注册表,在系统的左下角软件搜索栏输入“regedit”,或者右击右下角windows图标选择“运行”, 输入regedit,都可以打开注册表

  2. 打开如下注册表选项“计算机\HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM”,在里面找到无法打开的注册表,如下图,我电脑是COM4

regedit_COMM

  1. 复制它的名称,我的电脑为\Device\USBSER000.打开电脑资源管理器,选择“性能”选项卡, 点击下方的“打开资源监视器”,选择“CPU”,在关联的句柄中输入串口设备的名称,点击刷新,就可以看到占用串口的应用程序,选中右击,选择“结束进程”即可,此时,串口就又可以使用了,按照下图顺序操作即可。

regedit_COMM2

(4). 关于USB-Serial-JTAG的一些问题(目前发现在v5.1中可以正常打印,其他版本可以用于log打印,但是直接用于stdin和stdout貌似有bug)

​ 目前发现USB-Serial-JTAG,在打印的时候,会有缓冲机制,也就是只有当收到\n字符(或者超时相关)的时候才会进行打印和输入,而且不管是绑定esp_vfs虚拟文件系统还是通过fflush(stdout);强制刷新输出缓冲流都没有用,这部分的内容可以参考: https://docs.espressif.com/projects/esp-idf/zh_CN/v5.2.1/esp32s3/api-guides/usb-serial-jtag-console.html (无关版本问题,在5.1版本也一样)和 https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32s3/api-guides/usb-serial-jtag-console.html ,在文章中是这样说明的:

​ 对于从 ESP32-S3 发送到 PC 终端的数据(例如 stdout、日志),ESP32-S3 会先写入一个小型内部缓冲区。如果该缓冲区达到最大容量(例如没有连接 PC 终端),ESP32-S3 会进行一次等待,时长约 50 ms。在此期间,PC 终端可以请求数据,但可能会导致应用程序出现非常短暂的暂停。

​ 对于从 PC 终端发送到 ESP32-S3 的数据(如控制台命令),许多 PC 终端会等待 ESP32-S3 接收字节后,再允许发送更多数据。这与使用 USB 转串口 (URAT) 桥接芯片不同,URAT 桥接芯片始终接收字节,并将其发送到(可能未在监听)的 ESP32-S3。

​ 在极少数情况下,从 ESP32-S3 发送到主机的数据可能会“阻塞”在主机内存中。继续发送数据即可“取消阻塞”,但如果应用程序未继续发送数据,则需要手动将这些数据刷新到主机。能否继续发送数据取决于驱动程序,默认配置的非阻塞驱动程序和 VFS 实现会在换行后自动刷新,而基于中断的阻塞驱动程序会在发送缓冲区变空时自动刷新。

​ 目前发现在5.1版本中通过设置usb_serial_jtag缓冲区,然后绑定esp_vfs。然后用usb_serial_jtag_read_bytesusb_serial_jtag_write_bytes来替代getcharputchar貌似在部分环境下有效(也可以使用putchar+fflush(stdout)),但是我测试在5.1.3版本中无效。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//初始化usb_serial_jtag缓冲区,并绑定esp_vfs
usb_serial_jtag_driver_config_t usb_serial_jtag_config = {
.rx_buffer_size = 1024 * 8, .tx_buffer_size = 1024 * 2};
usb_serial_jtag_driver_install(&usb_serial_jtag_config);
esp_vfs_usb_serial_jtag_use_driver();

//输入采用如下形式
char platform_getchar() {
while (1) {
char buff[1] = {0};
if (usb_serial_jtag_read_bytes(buff, 1, 100) > 0) {
return buff[0];
}
vTaskDelay(1);
}
}
//输出采用如下形式
int platform_putchar(char ch) {
usb_serial_jtag_write_bytes(&ch, 1, 0);
//也可以使用如下两条语句替代代码
//putchar(ch);
//fflush(stdout);
return 0;
}

​ 如果直接绑定console做标准输入输出,printf或者putchar都会直接进行usb的缓冲区,直到接收到\n字符(部分版本超时之后也会)之后才会一并通过usb_serial_jtag输出。

​ 所以目前发现如果希望使用USB-Serial-JTAG即作为下载程序,又充当一个标准串口来使用,目前最好用v5.1版本,如果不是充当标准串口,而支持用作log打印或者不介意数据缓冲问题的情况下,可以采用任意版本的idf。

3、idf的工程和工具补充

(1). 一些常见的menuconfig配置问题

​ idf的工程 配置是通过menuconfig来实现的,menuconfig是一种工程代码管理工具,可以通过图形化配置界面,对工程的信息进行配置,这里对一些经常使用的menuconfig配置做一个说明

1. Flash大小和CPU频率

​ 比如ESP32-S3默认的flash大小是2M,CPU工作频率为160MHz这个可以修改成你的flash大小和频率如下:

menuconfig_flash

menuconfig_cpu

2. 修改主线程app_main的栈大小

​ 当程序比较大时,可能会导致主线程堆栈太小,可以设置高一些。否则可能会给出***ERROR*** A stack overflow in task main has been detected.的报错信息。

menuconfig_main_stack

3. flash分区表

​ esp-idf默认分区表如下,只占用了系统1M+64K的空间:

1
2
3
4
5
# Name,   Type, SubType, Offset,  Size, Flags
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
nvs, data, nvs, 0x9000, 0x6000,
phy_init, data, phy, 0xf000, 0x1000,
factory, app, factory, 0x10000, 1M,

​ 而程序稍微大一些,空间就可能不够,所以一般项目大一些情况,我们会自定义分区表,可以直接在工程下创建partitions.csv文件,然后再menuconfig中选择自己创建的分区表信息,如下:

menuconfig_partition

​ 具体分区表partitions.csv的内容可以参考

4. PSRAM的开启和使用
5. 指定默认console输出通道

​ 这里面有几个值可以选择:

1
2
3
4
5
6
Default:UART0: 		选择系统默认底串口0作为log是输出。
USB CDC: 选择USB CDC设备作为输出,基于TinyUSB
USB serial/JTAG: 选择系统底USB转串口/JTAG接口作为输出。
Custom:UART: 选择系统指定串口作为输出,可以选择UART0/UART1
None: 关闭输出通道,注意,如果这里关闭,但是实际有prinf,可能会报错,
如果只是希望关闭log,可以参考6,关闭log

menuconfig_console

6. 设置log输出模式

​ log输出包括两个部分底输出,一个式Bootloader config底log输出,也就是系统启动底时候Bootloader代码底log输出,一个代码的log输出,一般情况下我们只需要设置代码底log输出即可,Bootloader的log输出对我们代码几乎没有影响,还可以方便看到一些代码的配置信息,所以一般不需要设置,保持默认就好。这里把两个都给出来

​ Bootloader的log输出设置:

boot_log

​ 代码的log输出设置:

app_log

(2). 关于Kconfig.projbuild和sdkconfig.defaults

​ Kconfig.projbuild本质上是一个配置menuconfig的配置文件,可以同来配置和增加menuconfig相关的配置信息。

​ 关于Kconfig更多的信息可以参考如下图片:

Kconfig_i

​ 而sdkconfig.defaults可以定义一些默认的配置选项,即给menuconfig配置中的一些参数进行设定,这样可以使得我们不需要通过menuconfig交互式界面对设备信息进行配置,直接通过文本的形式进行配置(前提是我们已经知道了配置的名称和内容)。

​ 实际上,我们在执行idf.py menuconfig的时候,会自动根据menuconfig中的定义,加载sdkconfig.defaults的内容,进行配置。所以如果sdkconfig.defaults中的定义已经存在,则会自动进行menuconfig的配置。

(3). 组件管理(managed_componentscomponents)与官方组件管理工具: https://components.espressif.com/

​ idf的组件分为三种:idf官方组件, 第三方组件, 自定义组件,它们分别在“idf的frameworks库的components目录”, 工程的managed_components目录, 工程的components目录下,这里对这三个组件做个简单介绍

​ 第一种为:idf官方组件,它跟随idf的发布而更新,在idf的frameworks库的components目录下,比如5.1版本的官方组件都在如下目录中

1
frameworks\esp-idf-v5.1\components

​ 第二种为:第三方组件:一般指的是在官方组件管理工具: https://components.espressif.com/ 中可以搜索到的组件库,乐鑫有一个网络组件管理工具网站,在idf中也构建了组件管理工具。官方和某些第三方发布的组件可以在这里搜索到。它可以通过idf_component.yml来管理,一般情况下,在组件库的界面中会提供下载组件的方法如下图:

components

​ 更新完成之后组件库会自动添加到工程的managed_components目录下方。该组件在每次编译的时候会自动同步,以确保组件内容没有被修改,所以一般不允许修改组件的内容。

​ 第三种为:自定义组件,自定义组件库,我们一般放在工程目录的components目录下,用户可以自行修改,另外如果我们要对一些第三方组件进行修改定制,可以线同步到``managed_components目录,然后我们在剪贴到components```目录下,再进行编辑使用。

(4). 组件配置文件idf_component.yml 和组件信息文件dependencies.lock

idf_component.yml文件是一个YAML格式的文件,用于定义组件的元数据和依赖关系。这个文件通常位于组件的根目录下,作用包括:

  • 定义依赖项:它列出了当前组件依赖的其他组件或库,包括这些依赖的版本信息。这有助于确保项目中使用的是兼容的组件版本。
  • 指定组件属性:比如组件的描述、维护者信息、许可证信息等。
  • 配置选项:提供对组件内部设置的配置,如使能或禁用特定的功能。

dependencies.lock文件是一个自动生成的文件,通常在执行项目配置过程(如运行idf.py reconfigure或首次构建项目时)生成。它的主要作用是:

  • 锁定依赖版本:文件中详细记录了项目解析依赖时所确定的具体版本号。这确保了项目的再现性,即不同的开发者或在不同的环境中构建项目时,都将使用相同版本的依赖,避免由于依赖版本变化导致的问题。
  • 依赖解析的结果:这个文件是项目依赖解析过程的直接产物,它包含了所有必需的、已解析的依赖组件及其版本,确保了构建系统能够获取和使用正确的组件版本。

idf_component.ymldependencies.lock的区别

  • 用途差异idf_component.yml用于声明依赖和组件配置,而dependencies.lock用于锁定这些依赖的具体版本,确保构建的一致性。
  • 更新机制idf_component.yml由开发者手动更新,以匹配组件需求和属性;dependencies.lock通常在依赖关系有变化或首次解析依赖时自动更新。
  • 目标用户idf_component.yml面向项目和组件开发者,他们需要在这个文件中指定和管理组件的依赖关系;而dependencies.lock主要是给构建系统使用,以保证项目的构建环境和条件的一致性。

idf_component.yml文件内容大致如下:

1
2
3
4
5
6
dependencies:
espressif/esp_lcd_touch_ft5x06: "^1.0.6"
idf: ">=4.4"
lvgl/lvgl: "~8.3.0"
espressif/zlib: "^1.3.0"
espressif/es8311: "^1.0.0"

dependencies.lock文件内容大致如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
dependencies:
espressif/es8311:
component_hash: eacbe7cb7f6993eb0f439121a56663cdfbf95925e7ddf5d2ed5aa640bed476fd
source:
service_url: https://api.components.espressif.com/
type: service
version: 1.0.0
espressif/esp_lcd_touch:
component_hash: d4d8f2dc33205797169a97a02e0d89a8982f59fe0509129b54422052b8522f59
source:
service_url: https://api.components.espressif.com/
type: service
version: 1.1.1
espressif/esp_lcd_touch_ft5x06:
component_hash: 97759953d9436a365e9427078c5b04ecce4e6a50f50cf62c68cd6bfa229b812c
source:
service_url: https://api.components.espressif.com/
type: service
version: 1.0.6
espressif/zlib:
component_hash: 999ec50086ac1c82b8321d8f540dc9fd10f5622948b935558aa16b4b66e95d9d
source:
service_url: https://api.components.espressif.com/
type: service
version: 1.3.0
idf:
component_hash: null
source:
type: idf
version: 5.1.0
lvgl/lvgl:
component_hash: 948bff879a345149b83065535bbc4a026ce9f47498a22881e432a264b9098015
source:
service_url: https://api.components.espressif.com/
type: service
version: 8.3.11
manifest_hash: b2c9ad493b01235aaa12d62f4d6922fb1ee3203b34b14257305de16c9838f577
target: esp32c3
version: 1.0.0

​ 下面是几个常用的针对idf_component.yml组件描述符

1. ^ (Caret): 允许版本在当前主版本号范围内更新。

​ 例如,^1.0.6允许使用1.0.6以上到2.0.0以下的版本。

2. ~ (Tilde): 允许次要版本的更新,如果指定了次版本,则只更新补丁版本。

​ 例如,~8.3.0可以更新到8.3.x的任何版本,但不超过8.4.0。

3. >= (Greater Than or Equal To): 指定版本必须大于或等于特定版本。

​ 例如,>=4.4表示版本必须是4.4或更高。

(5). idf中Cmake配置的一些关键词

1. 屏蔽一些不必要的警告
1
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-char-subscripts -Wno-maybe-uninitialized")
  1. set: 这是CMake的命令,用于设置或修改变量的值。
  2. CMAKE_C_FLAGS: 这是一个CMake变量,代表用于C语言编译器的编译选项。
  3. "${CMAKE_C_FLAGS}": 这部分是变量替换,意思是取出CMAKE_C_FLAGS变量当前的值。
  4. -Wno-char-subscripts-Wno-maybe-uninitialized 是具体添加到CMAKE_C_FLAGS变量中的编译器选项:
    • -Wno-char-subscripts:这个选项用来禁止编译器发出警告,当数组下标是char类型时。通常这种情况下,char类型的下标会被隐式转换为整型,某些情况下可能会引发问题或警告。
    • -Wno-maybe-uninitialized:这个选项用来禁止编译器发出警告,当变量可能未初始化时。这可以防止编译器对可能未初始化的使用发出警告,尽管这样做有时可能隐藏实际的编程错误。
2. 自动扫描文件夹下的C文件自动添加(循环扫描目录以及子目录下的所有c文件)
1
2
file(GLOB_RECURSE SOURCES *.c)
idf_component_register(SRCS ${SOURCES})

注意,这可能导致增加或者删除文件,但是cmake并没有发现,导致其没有被编译仅二进制文件的可能性,所以这种情况下,建议增加或者删除文件的时候,可以先clean一下项目,然后再重新编译。

​ 另一个常用的实践是尽量避免在配置文件中使用GLOB来指定源文件。可以考虑明确列出所有源文件,虽然这增加了维护成本,但可以提高项目的可预测性。

3. 静态库编译到二进制系统中关键字:WHOLE_ARCHIVE
1
2
3
4
file(GLOB_RECURSE SOURCES *.c)
idf_component_register(SRCS ${SOURCES}
WHOLE_ARCHIVE
INCLUDE_DIRS ".")

这个意思是,有些函数,即使没有被系统调用(比如被main函数,或者中断函数,或者其他函数调用),这些函数仍然需要被编译到二进制文件中,这样做的目的是,一些脚本解析器,本身系统不会调用该函数,但是系统会执行来自外部的命令,或者文件系统中的脚本代码,根据脚本代码的执行情况会产生调用函数的可能性,如果不包含此关键字可能导致,该函数并未被编译到二进制文件中,而导致系统执行失败。

4. 组件依赖关键字:REQUIRES
1
2
3
4
5
6
7
file(GLOB_RECURSE SOURCES *.c)
idf_component_register(SRCS ${SOURCES}
WHOLE_ARCHIVE
INCLUDE_DIRS "."
REQUIRES
driver
fatfs)

REQUIRES关键字描述的是代码对一些其他组件库的依赖关系,也就是说,这部分代码可能需要依赖一些其他组件库一起运行(包括官方组件,第三方组件,自定义组件)如果没有相关的组件,可能会导致编译失败,加上这个组件库之后,系统会把需要的组件库一起添加到系统的编译选项里面进行编译。

5. 添加预处理器定义
1
2
3
# add macro
idf_build_set_property(
COMPILE_DEFINITIONS "-DPIKA_CONFIG_ENABLE" APPEND)

这会将PIKA_CONFIG_ENABLE定义添加到当前目标的编译定义中。