小智自定义开发板怎么加:Kconfig、CMakeLists、config.json 三处都要改
- 知道自定义一块开发板要建什么目录、改哪三个文件
- 看懂 config.json 里 type / target / sdkconfig_append 各是什么用
- 避开「只改了 Kconfig 没改 CMakeLists」这个最高频失误
- 知道命名限制和参考实现从哪找
本文讲解原理与流程、引用关键片段并注明出处,版权归原作者,遵循其开源协议;一切以上游仓库最新版本为准。
如果你用的是市面上常见的小智开发板,main/boards/ 下大概率已经有现成目录,选中板型直接编译就行。
但只要你干了下面任何一件事,就得自己加板型:自己画了 PCB、买了块冷门板子、拿通用开发板自己接了麦克风和屏、或者在别人的板子上改了接线。
这件事本身不难,难在它要改三个地方,漏一个就失败,而且失败信息不会告诉你漏了哪个。
本篇依据上游 custom-board_zh.md 整理思路与要点,具体字段和写法以上游文档最新版为准。代码版权归原作者 78 及社区贡献者,遵循 MIT 协议。本文写于 2026 年 7 月底,上游更新频繁。
一块板子由四个文件组成
先建目录:
mkdir main/boards/my-custom-board
按上游文档,一个开发板目录下包含这几样:
| 文件 | 作用 |
|---|---|
xxx_board.cc |
板级初始化代码 |
config.h |
硬件配置 |
config.json |
开发板类型和构建配置 |
README.md |
说明文档 |
先说命名限制,因为它是个隐形雷:名称只能包含小写字母、数字、点(.)和连字符(-)。习惯用下划线或者驼峰命名的人,在这里会栽跟头,而且报错信息不会直说是命名问题。
最省事的起步方式不是从零写,是抄一个最像的。 上游文档里就是拿 lichuang-c3-dev 作为参考实现来讲的。找一块和你硬件最接近的板子——同芯片、同类 codec、屏幕接口相近——把它整个目录复制过来改,比对着文档一行行写快得多,也不容易漏。
config.h:硬件长什么样
这个文件描述的是你这块板子的物理事实:麦克风、喇叭、按键、屏幕分别接在哪、用什么参数。
上游文档给出的参考片段是这类:
#define AUDIO_INPUT_SAMPLE_RATE 24000
#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR
#define DISPLAY_WIDTH 320
#define DISPLAY_HEIGHT 240
可以看出它覆盖三类:音频(采样率、codec 型号与地址)、按键、显示(分辨率等)。
这里最容易出问题的是音频部分,原因是它最依赖硬件细节:codec 型号不对、I2C 地址不对、采样率和硬件对不上,症状都是"能开机但听不见/没声音"——看起来像软件 bug,其实是这个文件里某一行数字不对。
引脚定义同样在这一层。如果你的接线和参考板不同,就得在这里改成你实际接的引脚。这部分内容较多,单独讲会更清楚。
xxx_board.cc:把这块板"装配"起来
config.h 描述的是参数,板级初始化代码干的是动作:按这些参数把外设真正建起来,交给上层用。
理解它的关键是抓住一个设计:应用启动时拿到一个 board 对象,之后所有跟板子相关的资源——灯、屏幕、音频 codec 等等——都从这个对象上取。 上层逻辑(对话、唤醒、MCP)不关心你的喇叭接在哪个引脚,它只管找 board 要。
这个抽象带来的好处,正是自定义板型能成立的原因:换一块板子,只换这一层,上面所有功能原样能跑。 你不需要去改对话流程或者协议代码,只要把"我这块板的外设长这样"讲清楚。
所以写这个文件时,你实际要回答的就是几个问题:音频 codec 是哪颗、怎么初始化;有没有屏幕、什么驱动;按键怎么读;灯怎么控。参考板里这些都是现成的,你的工作主要是改成自己的型号和引脚,而不是从零设计。
这也解释了前面那条建议为什么重要:复制一个最像的参考板来改。从零写这个文件,你得先搞懂整套板级抽象;复制着改,你只需要认出哪几行是硬件相关的。
config.json:告诉构建系统怎么编
三个关键字段,按上游文档的说明:
type—— 固件上报的开发板系列类型,发布后应保持稳定。这句"保持稳定"是有分量的:它是设备向服务端报身份用的,随便改会影响已经发出去的设备的识别。做产品的人尤其要早想清楚,别上线后再改。target—— 目标芯片型号,必须与硬件匹配。这是最直接的错误来源,填错后面全错。sdkconfig_append—— 额外的 sdkconfig 配置项数组。需要开某些特性、调某些参数时写在这,比让用户自己去 menuconfig 点更可靠。
sdkconfig_append 这个设计值得多说一句:它把"这块板子必须打开的开关"固化进了板子的定义里。这样别人拿到你的板型目录,编译出来就是对的,不需要额外口头交代"记得去 menuconfig 里打开某某"。做板子分发时,能写进这里的就别写进 README。
Kconfig 与 CMakeLists:必须成对改 ⭐
这是全篇最重要的一节,因为漏改这两个中的一个,是自定义板型最高频的失败原因。
第一处,main/Kconfig.projbuild 里加声明:
config BOARD_TYPE_MY_CUSTOM_BOARD
bool "My Custom Board (我的自定义开发板)"
depends on IDF_TARGET_ESP32S3
depends on 那行是按目标芯片限定的——写了 IDF_TARGET_ESP32S3,这个板型就只在目标芯片是 S3 时才出现在选项里。如果你在配置界面里死活找不到自己加的板型,先查这一行:多半是你的目标芯片和这里写的对不上,选项被条件隐藏了。这个现象很迷惑人,因为它不报错,只是"看不见"。
第二处,main/CMakeLists.txt 里加对应分支:
elseif(CONFIG_BOARD_TYPE_MY_CUSTOM_BOARD)
set(BOARD_DIR "my-custom-board")
set(BUILTIN_TEXT_FONT font_puhui_basic_20_4)
endif()
注意 BOARD_DIR 要和你建的目录名一致。这里还要设置内置字体(BUILTIN_TEXT_FONT),图标字体和默认表情集也在这一层配置——有屏幕的板子如果字体没配,会出现能点亮但显示不正常的情况。
为什么必须成对: Kconfig 管的是"这个选项在配置界面里存在、能被选中",CMakeLists 管的是"选中之后去哪个目录找代码"。只改前者,你能在界面里选到它,但构建时找不到目录;只改后者,你压根选不到它。两个文件的两处改动,缺一不可——这就是为什么建议你复制一个现成板子来改,复制不容易漏,从零写容易漏。
编译
配好之后用脚本编译:
python scripts/build.py my-custom-board
上游推荐脚本方式而不是手工 idf.py set-target 加 menuconfig,道理在这里体现得最明显:你板子的目标芯片、字体、sdkconfig 追加项都已经写在 config.json 里了,脚本读它一次配齐,比人手工点一遍可靠得多。
加完之后先验哪里
板型加完第一次编译通过,别急着高兴,按这个顺序验:
先验能不能开机。 串口有日志、能启动,说明目录、Kconfig、CMakeLists 这条链是通的。
再验音频。 麦克风能不能拾音、喇叭有没有声音——这是 config.h 里 codec 配置和引脚定义对不对的直接体现,也是自定义板最容易出问题的地方。
最后验显示。 屏幕亮不亮、内容正不正常,对应分辨率参数和字体配置。
按这个顺序的好处是每一步失败都能指向一小段配置,不用满地找。倒过来查会痛苦得多。
相关:小智编译失败怎么查讲编译不过的通用排查,小智固件现在要 ESP-IDF 6.0 了讲版本变动对板级代码的影响(I2S、LCD 这些正是自定义板会碰的),小智怎么选硬件与配 BOM讲硬件本身怎么定。