摘要:本文深入剖析 Zephyr 中
west build -b my_board到CONFIG_SOC_xxx=y的完整链路。核心结论是:-b选择的是 Board 而非 SoC,SoC 由 Board 的 Kconfig 体系(select/default y)进一步选择。全文从 Board 的board.yml、Kconfig.board、Kconfig.defconfig、my_board_defconfig等文件出发,逐层拆解 Board → SoC Family → SoC Variant → Kconfig symbol → CMake source selection 的完整流程,并厘清soc.yml(SoC 目录/metadata)与Kconfig.soc(Kconfig symbol)的区别、select与default y的差异、Kconfig 与 Devicetree 的分工,最后给出基于build/zephyr/.config的 SoC 选择诊断方法,帮助 BSP 开发者快速定位「SoC 代码未被编译」的问题。
接入 Zephyr 中断控制器
下面接着你的Zephyr BSP 系列。这一篇建议把重点放在一个非常关键的问题上:
用户只写了 west build -b my_board,Zephyr 为什么最后会得到 CONFIG_SOC_xxx=y?
真正的答案不是「Board 配置了 SoC」这么简单,而是一条完整的Board → SoC family → SoC variant → Kconfig symbol → CMake source selection链路。
从 -b my_board 到 CONFIG_SOC_xxx:Zephyr 是怎么选中你的 SoC 的?
前面我们已经建立了:
soc.yml + Kconfig.soc:让 Zephyr **认识 SoC** soc/:提供 SoC 的代码 board/:描述具体开发板 DEVICE_DT_DEFINE():把硬件设备最终变成 struct device这一篇继续向前追:
west build-bmy_board │ ▼ Board │ ▼ Board Kconfig │ ▼ SoC family / variant │ ▼CONFIG_SOC_xxx=y │ ▼ SoC Kconfig │ ▼ SoC CMakeLists.txt │ ▼ 编译对应 SoC 源码1. 先回答最核心的问题
假设我们有自己的板子:
boards/ └── my_vendor/ └── my_board/执行:
west build-bmy_board samples/hello_world你可能会自然地认为:
\-b my_board ↓ my_board ↓ my_soc但实际上不是一个简单的字符串映射。
更准确地说:
-bmy_board │ ▼ Board definition │ ├── board.yml ├── Kconfig.board ├── Kconfig.defconfig ├── my_board_defconfig └── my_board.dts │ ▼ Kconfig system │ ▼ CONFIG_SOC_... │ ▼ SoC selection也就是说:
-b 选择的是 Board,而不是直接选择 SoC。
SoC 是 Board 的配置体系进一步选择出来的。
2. -b 到底是什么?
执行:
west build-bmy_board-b 的含义是:
buildforboard=my_board也就是:
Board=my_board它首先告诉 Zephyr:
“我要针对这个 Board 建立一个 build configuration。”
这一步本身并没有直接执行:
CONFIG_SOC_MY_SOC=y3. Board 在哪里?
一个典型 Zephyr Board:
boards/ └── my_vendor/ └── my_board/ ├── board.yml ├── Kconfig.board ├── Kconfig.defconfig ├── my_board_defconfig ├── my_board.dts └── CMakeLists.txt其中最重要的几个文件:
board.yml Kconfig.board Kconfig.defconfig my_board_defconfig my_board.dts它们分别解决不同的问题。
4. board.yml:告诉 Zephyr「我是谁」
例如:
board: name: my_board full_name: My Board vendor: my_vendor它主要属于 Board metadata。
它可以让 Zephyr 知道:
my_board ↓ My Board ↓ my_vendor但是:
不要把 board.yml 理解成「选择 SoC 的地方」。
SoC 选择主要发生在 Kconfig。
5. 真正关键的是 Board Kconfig
例如:
boards/my_vendor/my_board/Kconfig.board可能包含:
config BOARD_MY_BOARDselectSOC_MY_SOC于是:
BOARD_MY_BOARD │ │select▼ SOC_MY_SOC最终:
CONFIG_BOARD_MY_BOARD=yCONFIG_SOC_MY_SOC=y这就是最核心的一层。
6. 所以 -b 并不是直接变成 CONFIG_SOC_xxx
真正的关系更像:
-bmy_board │ ▼ BOARD_MY_BOARD │ │select▼ SOC_MY_SOC │ ▼CONFIG_SOC_MY_SOC=y因此可以记住:
-b 选择 Board,Board 的 Kconfig 负责选择 SoC。
7. 但实际 Zephyr 里还会多一层
真实的 SoC 往往不是:
SOC_MY_SOC这么简单。
例如一个 MCU 家族:
MyVendor MCU Family下面可能有:
my_soc_a my_soc_b my_soc_c因此 Zephyr 通常会形成:
Board │ ▼ SoC Family │ ▼ SoC Series │ ▼ SoC Variant例如:
my_board │ ▼ my_vendor_m4 │ ▼ my_vendor_m4_series │ ▼ my_vendor_m4_123最终才落到具体:
CONFIG_SOC_MY_VENDOR_M4_123=y8. 为什么需要这种层次?
因为 SoC 通常存在大量共性。
例如:
MY_VENDOR_M4 │ ├── my_m4_101 ├── my_m4_102 ├── my_m4_201 └── my_m4_202它们可能共享:
startup code clock driver interrupt controller GPIO UART timer power management所以 Zephyr 不希望每个 SoC 都复制一份:
Kconfig CMakeLists.txt startup.c soc.c而是:
SoC Family │ ├── common code │ ├── common Kconfig │ └── common CMake │ ▼ specific variant9. Kconfig.defconfig 又是什么?
Board 通常还有:
Kconfig.defconfig例如:
ifBOARD_MY_BOARD config SOC_MY_SOC default y endif这里就出现了一个非常重要的区别:
select和:
default y不是同一回事。
10. select 和 default y 的区别
假设:
config BOARD_MY_BOARDselectSOC_MY_SOC这是:
Board → 强制选择 SoC而:
config SOC_MY_SOC default y表示:
如果当前配置环境允许, 那么默认打开 SOC_MY_SOC所以理解 Kconfig 时必须区分:
select和:
default11. Board defconfig 是另外一层
Board 还有:
my_board_defconfig里面可能有:
CONFIG_SERIAL=yCONFIG_UART_CONSOLE=yCONFIG_CONSOLE=y它表达的是:
“这个 Board 默认需要哪些功能。”
例如:
my_board │ ├──CONFIG_SERIAL=y