☰
轻松学习Zephyr BSP: 40-公司 BSP 的完整生命周期
2026/9/25 18:36:54 网站建设 项目流程

摘要:本文是 Zephyr BSP 系列(第 20~40 篇)的收束篇,系统梳理一个公司 SoC 从芯片定义到 BSP 可交付的完整生命周期。全文按 18 个阶段展开:从 SoC 规格、Company HAL、Zephyr SoC Port、Startup、中断控制器、时钟/复位,到 Devicetree、Binding、驱动、Kconfig、CMake、Linker、Board、Flash/Debug、Validation、SoC Family、Release 直至 CI 落地。核心观点是:BSP 不是"一个 boards/xxx/ 目录",而是一条从 Silicon 到 Application 的软件供应链。文章最后给出公司 BSP 需要维护的"四条线"(硬件线、软件抽象线、构建线、验证线),帮助读者建立从"学 Zephyr"到"交付可维护 BSP"的工程视角。

公司 BSP 的完整生命周期

到第 39 篇,我们已经把SoC Family Architecture讲清楚了。

现在进入一个非常重要的收束篇:

一个公司 SoC,从"芯片刚出来"到"Zephyr BSP 真正可交付",整个生命周期到底是什么?

这篇不再只讲某一个文件,而是把前面20~39 篇全部串起来。

一、先建立一个总模型

一个真正的公司 BSP,不是:

写几个 driver ↓ 能跑 blinky ↓ 结束

而应该是:

SoC Silicon ↓ Company HAL ↓ Zephyr SoC Port ↓ Devicetree / Binding ↓ Kconfig ↓ Drivers ↓ Board ↓ Build System ↓ Linker / Memory ↓ Flash / Debug / Runner ↓ BSP Validation ↓ Release / Maintenance

再进一步:

┌──────────────────────┐ │ SoC Silicon │ └──────────┬───────────┘ ↓ ┌──────────────────────┐ │ Company HAL │ │ Clock / IRQ / GPIO │ │ UART / SPI / I2C... │ └──────────┬───────────┘ ↓ ┌──────────────────────┐ │ Zephyr SoC Port │ │ startup / soc.c │ │ CMake / Kconfig │ └──────────┬───────────┘ ↓ ┌──────────────────────┐ │ Devicetree + DT │ │ hardware description │ └──────────┬───────────┘ ↓ ┌──────────────────────┐ │ Zephyr Drivers │ │ UART GPIO SPI I2C... │ └──────────┬───────────┘ ↓ ┌──────────────────────┐ │ Board │ │ pins / LEDs / buttons│ └──────────┬───────────┘ ↓ ┌──────────────────────┐ │ Build / Link / Flash │ └──────────┬───────────┘ ↓ ┌──────────────────────┐ │ BSP Validation │ └──────────────────────┘

这就是公司 BSP 的完整生命周期。

二、第一阶段:SoC 还没出来

这是很多 BSP 工程师容易忽略的一个阶段。

芯片甚至还没有回来。

但是 BSP 工作已经可以开始。

例如公司决定做:

Company SoC X1 ├── Cortex-M4 ├──512KB Flash ├──128KB SRAM ├── UART ×3├── SPI ×2├── I2C ×2├── GPIO ├── Timer ├── DMA └── Interrupt Controller

此时首先需要建立:

SoC specification ↓ memory map ↓ interrupt map ↓ peripheral map ↓ clock tree ↓ reset tree ↓ pinmux

也就是说:
BSP 的第一份「代码」往往不是 C 代码,而是硬件规格。

三、第二阶段:Company HAL 出现

芯片团队通常会先提供自己的 HAL。

例如:

company-hal/ ├── include/ │ ├── company_uart.h │ ├── company_gpio.h │ ├── company_clock.h │ └── company_irq.h │ ├── src/ │ ├── company_uart.c │ ├── company_gpio.c │ ├── company_clock.c │ └── company_irq.c │ └── startup/ └── startup_company.S

HAL 负责:

寄存器 ↓ Company API

例如:

company_uart_init();company_uart_write();company_uart_read();

这层通常不应该知道:

struct device DEVICE_DT_DEFINE()DT_INST_FOREACH_STATUS_OKAY()

因为这些是 Zephyr 的概念。
所以我们之前第 37 篇讲的边界非常重要:

┌─────────────────────────┐ │ Zephyr │ │ │ │ struct device │ │ driver API │ │ devicetree │ │ Kconfig │ └────────────┬────────────┘ │ │ adapter ↓ ┌─────────────────────────┐ │ Company HAL │ │ │ │ company_uart_xxx()│ │ company_clock_xxx()│ │ company_gpio_xxx()│ └────────────┬────────────┘ │ ↓ ┌─────────────────────────┐ │ Registers │ └─────────────────────────┘

四、第三阶段:建立 Zephyr SoC Port

接下来正式进入 Zephyr。

目录可能开始变成:

soc/ └── company/ └── cx1/ ├── CMakeLists.txt ├── Kconfig ├── Kconfig.soc ├── soc.c ├── soc.h └──...

这时候还不是 Board。
而是:
告诉 Zephyr:「这个 CPU + SoC 是什么。」

例如:

Company CX1 ↓ Cortex-M4 ↓ clock ↓ interrupt controller ↓ memory ↓ SoC peripherals

这里对应我们之前:

21SoC Port Skeleton 下面是一个完整的`soc.c`示例,它把 SoC 初始化、时钟配置和中断控制器初始化串在一起: ```c /* * soc.c - Company CX1 SoC 初始化 * * 该文件是 Zephyr SoC Port 的核心,负责在 Zephyr 内核启动前 * 完成最基本的硬件初始化,让 CPU 具备运行内核的条件。 */#include <zephyr/kernel.h>#include <zephyr/init.h>#include <soc.h>/* 引入 Company HAL 提供的底层接口 */#include <company_clock.h>#include <company_irq.h>/* ------------------------------------------------------------------ *1. 时钟配置 * * 目标:把 SoC 的时钟树配置到稳定状态。 * 顺序很重要:先配 PLL,再配总线分频,最后使能外设时钟。 * 如果时钟没配好,后面所有外设(UART/SPI/I2C)都无法工作。 * ------------------------------------------------------------------ */ static void soc_clock_init(void){/*1.1配置系统 PLL:输入8MHz 晶振,倍频到96MHz 主频 */ company_clock_pll_config(COMPANY_PLL_SRC_HSE,8,96);/*1.2配置总线分频:HCLK=96MHz,PCLK1=48MHz,PCLK2=96MHz */ company_clock_bus_config(COMPANY_BUS_HCLK,96);company_clock_bus_config(COMPANY_BUS_PCLK1,48);company_clock_bus_config(COMPANY_BUS_PCLK2,96);/*1.3使能基础外设时钟:GPIO、UART0、SPI0 */ company_clock_enable(COMPANY_CLOCK_GPIO);company_clock_enable(COMPANY_CLOCK_UART0);company_clock_enable(COMPANY_CLOCK_SPI0);}/* ------------------------------------------------------------------ *2. 中断控制器初始化 * * 目标:让 Zephyr 能够正确接收并分发 SoC 的中断。 * 这里只做最基础的 NVIC 配置,具体外设的 IRQ 由各 driver 自行注册。 * ------------------------------------------------------------------ */ static void soc_irq_init(void){/*2.1关闭所有外设中断,保证启动阶段处于干净状态 */ company_irq_disable_all();/*2.2设置中断优先级分组:4 位抢占优先级 +0位子优先级 */ company_irq_set_priority_group(COMPANY_IRQ_PRIO_GROUP_4);/*2.3使能全局中断(由 Zephyr 内核在启动后期统一打开, * 这里只做控制器层面的准备) */ company_irq_global_enable();}/* ------------------------------------------------------------------ *3. SoC 总初始化入口 * * 这是 Zephyr 在启动早期(PRE_KERNEL_1)调用的函数, * 必须在内核调度器运行之前完成所有基础硬件配置。 * ------------------------------------------------------------------ */ static int soc_init(void){/*3.1先配时钟:一切外设工作的前提 */ soc_clock_init();/*3.2再配中断控制器:保证后续 driver 能注册 ISR */ soc_irq_init();/*3.3最后做 SoC 级杂项初始化(如 memory protection 等) */ company_soc_lowlevel_init();return0;}/* 注册为 PRE_KERNEL_1 阶段初始化,优先级0(最早执行) */ SYS_INIT(soc_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);

关键点说明:

  • soc_clock_init():先配 PLL 再配分频,最后使能外设时钟,顺序不能颠倒;
  • soc_irq_init():先关中断、再设优先级分组,保证启动阶段干净;
  • SYS_INIT(..., PRE_KERNEL_1, ...):让 Zephyr 在内核启动前自动调用soc_init(),这是 SoC Port 与内核的正式接缝。

22 CPU / Architecture
23 Startup
24 Interrupt Controller
25 Clock / Reset

下面是一个完整的 Devicetree 节点示例,它把 uart0、gpio0、spi0 等外设统一描述出来: ```dts / { soc { /* UART0:串口控制器,基地址 0x40000000,IRQ 5 */ uart0: uart@40000000 { compatible = "company,cx1-uart"; reg = <0x40000000 0x1000>; interrupts = <5>; clocks = <&clk 0>; status = "okay"; }; /* GPIO0:通用输入输出控制器,基地址 0x40020000,IRQ 6 */ gpio0: gpio@40020000 { compatible = "company,cx1-gpio"; reg = <0x40020000 0x1000>; interrupts = <6>; clocks = <&clk 1>; status = "okay"; }; /* SPI0:串行外设接口,基地址 0x40040000,IRQ 7 */ spi0: spi@40040000 { compatible = "company,cx1-spi"; reg = <0x40040000 0x1000>; interrupts = <7>; clocks = <&clk 2>; status = "okay"; }; }; };

对应的 binding YAML 文件内容如下:

# dts/bindings/serial/company,cx1-uart.yamldescription:Company

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询