摘要:本文是 Zephyr BSP 移植系列的第 31 篇,聚焦 Kconfig 在 Company SoC 平台化中的核心作用。文章首先厘清 Devicetree 与 Kconfig 的分工——前者描述硬件资源,后者决定软件编译与功能配置;随后系统讲解 Kconfig 的生成链路(
.config→autoconf.h→ C 编译)、SoC/Board/Driver 三层的 Kconfig 组织方式,以及depends on、select、default等关键机制的区别。通过 Company UART 驱动实例,串联起 Devicetree、Kconfig、CMake 与 Device Model 的完整协作链路,最终建立「Kconfig(软件配置)— Devicetree(硬件描述)— CMake(编译组织)」的三角模型,帮助读者把 Company SoC 从固定代码升级为可配置的硬件软件平台。
Kconfig:把 Company SoC 变成可配置平台
前面我们已经完成了:
20理解 Zephyr ↓21SoC Port Skeleton ↓22CPU / Architecture ↓23Startup ↓24Interrupt Controller ↓25Clock / Reset ↓26Devicetree ↓27Binding ↓28UART Driver ↓29GPIO / SPI / I2C / Timer ↓30Board Support Package到31 — Kconfig,我们要解决一个非常关键的问题:
Devicetree 描述「硬件是什么」,Kconfig 决定「软件编译什么、启用什么、配置成什么」。
对于公司自己的 SoC,这一步意味着:
Company SoC │ ├── Devicetree │ └── 描述硬件资源 │ └── Kconfig └── 控制软件功能最终形成:
┌────────────────────────────────────────────┐ │ Company Zephyr BSP │ │ │ │ Devicetree Kconfig │ │ ────────── ─────── │ │ UART0 CONFIG_UART │ │ UART1 CONFIG_GPIO │ │ GPIO CONFIG_SPI │ │ SPI0 CONFIG_I2C │ │ Timer CONFIG_TIMER │ │ IRQ CONFIG_SOC_... │ │ │ └────────────────────────────────────────────┘一、先搞清楚:Devicetree 和 Kconfig 为什么都需要?
这是 Zephyr BSP 最容易混淆的地方之一。
假设 Company SoC 有:
UART0 UART1 UART2 GPIO SPI0 SPI1 I2C0 TIMER0 TIMER1Devicetree 可以描述:
uart0: uart@40000000{compatible="company,uart";reg=<0x40000000 0x1000>;interrupts=<5>;status="okay";};它回答:
UART0 在哪里?
但是它不回答:
UART 驱动要不要编译?
这就是 Kconfig 的职责。
例如:
CONFIG_SERIAL=yCONFIG_UART_CONSOLE=yCONFIG_UART_COMPANY=y于是:
Devicetree ↓ UART0 存在 Kconfig ↓ UART 驱动参与编译 ↓ UART Console 开启两者共同决定最终系统。
二、一个非常重要的理解
可以先记住这个模型:
Devicetree=Hardware Description Kconfig=Software Configuration或者更准确一点:
Devicetree → 描述具体硬件实例、资源、连接关系 Kconfig → 决定功能、驱动、编译选项、系统能力例如:
Devicetree
uart0{reg=<...>;interrupts=<...>;clocks=<...>;};描述:
UART0 地址 IRQ ClockKconfig
CONFIG_SERIAL=yCONFIG_UART_INTERRUPT_DRIVEN=yCONFIG_UART_CONSOLE=y描述:
编译 UART 支持 IRQ 把 UART 作为 Console三、Zephyr Kconfig 最终生成什么?
这一点和前面讲 Devicetree 的过程非常类似。
你执行:
west build-bcompany_board appKconfig 会参与:
Kconfig ↓ menuconfig / configuration ↓ .config ↓ autoconf.h ↓ C/C++ 编译最重要的文件之一是:
build/zephyr/.config例如:
CONFIG_SOC_SERIES_COMPANY_X=yCONFIG_SOC_COMPANY_X1=yCONFIG_SERIAL=yCONFIG_UART_CONSOLE=yCONFIG_UART_COMPANY=yCONFIG_GPIO=yCONFIG_GPIO_COMPANY=y然后生成:
build/zephyr/include/generated/zephyr/autoconf.h里面会出现类似:
#defineCONFIG_SERIAL1#defineCONFIG_UART_CONSOLE1#defineCONFIG_UART_COMPANY1#