• 正文
  • 相关推荐
申请入驻 产业图谱

ESP32学习:项目的配置菜单,原来可以自己加

10/30 14:36
46
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

打开ESP-IDF的配置编辑器,除了FreeRTOS、Wi-Fi这些SDK选项,还能看到“Xiaozhi Assistant”。点进去,开发板、显示屏等选项都在里面。

第一次碰到,很容易产生一个疑问:这是乐鑫专门给小智做的功能吗?

不是。乐鑫提供的是配置机制,小智提供的是项目自己的配置定义。

我想把ESP32学习系列的第一篇,从这里开始。会点编译、会下载固件以后,再往前走一步,就要弄清楚:界面上的一次选择,到底怎样变成了程序里的一个功能。

菜单是工程提供的,不是编辑器写死的

ESP-IDF使用Kconfig描述配置项。菜单叫什么、选项是什么类型、默认值是多少、需要满足哪些条件,都可以写在配置文件里,由工具读取并展示。

小智项目的main/Kconfig.projbuild里,就能找到Xiaozhi Assistant菜单,以及名为Target Board的开发板单选项。

例如,面包板Wi-Fi版本的配置名是BOARD_TYPE_BREAD_COMPACT_WIFI,并通过depends on IDF_TARGET_ESP32S3限定适用目标。普通ESP32面包板版本,则有自己的配置名和目标依赖。

所以你换了芯片目标,有些板型不再可选,不一定是插件出了问题,也可能只是依赖条件不满足。

编辑器负责呈现,工程负责定义。Kconfig描述的是配置逻辑;终端菜单和图形编辑器怎样画出来,可以不一样。

先把这几个文件分清楚

它们名字相近,但职责并不一样。

文件 负责什么
Kconfig 定义选项与依赖,组件选项通常进入Component config
Kconfig.projbuild 定义在配置界面根层级出现的选项
sdkconfig 保存当前工程的配置值
sdkconfig.defaults 提供项目希望采用的默认配置
build/config/sdkconfig.h 构建系统生成,供C/C++使用

可以把它们理解成:Kconfig定义能选什么,sdkconfig记录选了什么,生成的头文件让代码用上这些选择。

这里有两个容易踩的坑。

一是,不要直接修改生成的sdkconfig.h,下次生成就可能被覆盖。保存配置和构建、重新配置的具体步骤由工具衔接,不是让你手工维护这几份文件。

二是,sdkconfig.defaults不是强制覆盖文件。已有工程里保存的用户选择,不会因为你改了默认值,就必然跟着改变。

自己加一个菜单,没必要写GUI

先别急着修改小智那一大套配置。找一个已经能正常编译的ESP-IDF hello_world副本,做个最小实验。

在main目录新建Kconfig.projbuild:

● ● ●

menu "Xuange Demo"
config XUANGE_STATUS_LOG
bool "Enable status log"
default y

config XUANGE_REPORT_INTERVAL_MS
int "Report interval (ms)"
range 100 5000
default 1000
endmenu

这里定义了一个开关和一个整数配置。range限定输入范围,default提供默认值。它们还没有实现任何日志功能,只是把可配置的规则写了出来。

在已经加载ESP-IDF环境的工程终端里运行:

● ● ●

idf.py menuconfig

找到Xuange Demo,就能修改这两个选项。也可以通过ESP-IDF的VS Code配置编辑器操作。

到这里,没有写一行界面代码,工程却已经有了自己的配置入口。

选项出现了,还要让程序真正使用它

配置名写进输出文件时,会带上CONFIG_前缀。启用日志并把间隔改成500,sdkconfig中就会有类似结果:

● ● ●

CONFIG_XUANGE_STATUS_LOG=y
CONFIG_XUANGE_REPORT_INTERVAL_MS=500

但菜单不会替你实现功能,还要在代码里使用这些配置。

把实验工程的main源文件改成下面的最小版本;如果原来已经有app_main,替换它,不要再定义第二个:

● ● ●

#include "sdkconfig.h"
#include "esp_log.h"

void app_main(void)
{
#ifdef CONFIG_XUANGE_STATUS_LOG
ESP_LOGI("demo", "interval=%d ms",
CONFIG_XUANGE_REPORT_INTERVAL_MS);
#endif
}

这个实验只在启动时打印一次间隔值,还没有实现周期任务。这样更容易看清配置本身的作用。

保存后执行idf.py build,再用实际串口完成烧录和监视,例如idf.py -p PORT flash monitor,其中PORT换成设备的真实端口。

启用开关时,会看到这条应用日志;关闭开关、重新编译并烧录,这段打印代码就不再参与编译。

布尔选项关闭时,对应宏通常不定义,所以这里用#ifdef判断。不要把配置文件里的y,当成C代码中需要比较的字符串。

小智选择开发板,还会影响哪些代码被编进去

配置不只给C/C++使用,CMake也可以读取它。

小智当前的main/CMakeLists.txt里,根据CONFIG_BOARD_TYPE_BREAD_COMPACT_WIFI等配置,选择不同的BOARD_DIR,再组织对应的板级代码。

这才是“选开发板”真正的工程意义:你可能改变的不只是一个变量,而是硬件初始化、引脚定义以及参与构建的源文件。

自己写项目时也一样。Kconfig负责表达选择,CMake负责按选择组织构建,驱动和应用代码负责实现功能。三者不会凭一个菜单自动接通,需要开发者明确关联。

对多硬件版本产品,这套机制比到处手改宏更容易维护。但依赖条件也必须写清楚:没有CAN FD能力的硬件,不会因为多出一个菜单选项,就突然支持CAN FD。

编译期配置,别当成运行期参数

板型、驱动选择、功能裁剪、调试日志开关,都适合放进Kconfig。

用户在设备上修改的音量、联网信息,或者现场调试时频繁调整的控制参数,则通常需要运行期管理;需要断电保存时,再考虑NVS等存储机制。

也不是说PID初值绝对不能写进Kconfig。关键看你想让它在什么时候改变:出厂构建时确定,还是设备运行时调整。两套机制可以配合,但不能混为一谈。

如果要把这套方法用于正式项目,还要保留代码版本、ESP-IDF版本及可复现的配置记录,并检查配置中有没有不该提交的凭证。只记一句“当时在菜单里选过”,下一次交付很难复原。

Kconfig也不是ESP32专属,Linux内核、Zephyr等项目同样使用这套语言。不过,别的MCU工程想拥有类似能力,还需要接上配置生成与构建流程,不是复制一个文件就够了。

学会这套机制,真正的变化是:你不再只是点选别人给你的菜单,而是能把自己的硬件差异、功能选择和依赖关系,变成整个项目都遵守的规则。

相关推荐

多年硬件从业经验,专注分享从研发到供应链,再到精益制造过程中的经验和感悟!