摘要:本文是 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.SHAL 负责:寄存器 ↓ 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 / Architecture23 Startup24 Interrupt Controller25 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
企业数字化 ERP 产品动态
相关推荐
【AI智能体工程化实战06】用 TaoToken 统一 Key 打通自动化评测与迭代闭环 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 18:36:52
数据治理第十五篇:五阶段标准实施路径——从制度上墙到长效运营的落地闭环 一、承接前文闭环:从「有规则、有考核」走向「能落地、能运营」在前两篇连载中,我们已经完成数据治理两大核心体系的搭建:第13篇构建了制度规范体系,解决了治理“有据可依”的问题;第14篇落地了KPI考核度量体系&#x… · 2026/9/25 18:36:40
简单聊聊 API 网关是什么:从 Cline 配置 TaoToken 统一 Key 通道说起 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 18:35:50
长假自驾跑长途,除碳这事可以提前排期! 每次长假自驾前,总能见到这么一类车友:头天晚上收拾行李到半夜,临了往油箱里怼一瓶除碳剂,拍着油箱说“兄弟,路上辛苦你了”。结果上了高速跑两百公里进服务区,才后知后觉:这玩意儿刚要起效&… · 2026/9/25 19:11:05
闲鱼超级管家系统源码下载 源码下载:download.csdn.net/download/m0_66047725/93483853
简介:
闲鱼超级管家全面升级新版本,自动滑块、发货、评价、要花、擦亮通通稳定支持,时刻维护!时刻更新!坚决保证使用世界上最强 AI模型(5.6 s… · 2026/9/25 19:10:59
Raven Agent Loop全解:Turn、Iteration、子代理与检查点回滚如何协同工作 Raven Agent Loop全解:Turn、Iteration、子代理与检查点回滚如何协同工作 【免费下载链接】Raven The Harness of Harnesses: a trusted, persistent, self-evolving multi-agent ecosystem for all-domain collaboration. 项目地址: https://gitcode.com/gh_mirr… · 2026/9/25 19:10:28
小白程序员轻松入门AI Agent开发工程师之路 随着大语言模型(LLM)的发展,企业需要的是能可靠完成真实业务任务的AI Agent软件系统,催生了"AI Agent开发工程师"这一新岗位。文章拆解了该岗位所需的8大核心能力域,包括后端工程基础、Python工程能力、LLM API与Prompt、Agent Loop与Tool Use、RAG与知识库、Context… · 2026/9/25 19:10:28
点云预处理与特征计算:任务导向的工业级实践指南 1. 为什么点云预处理不是“清洗一下就完事”的体力活点云数据预处理和特征计算,这两个词在测绘、自动驾驶、工业检测、数字孪生这些领域里天天被提起,但绝大多数人一上手就栽在第一步——误以为它只是“把噪点删掉、把空洞补上、再导出个ply文件”这种标… · 2026/9/25 19:10:04
基于昇腾Atlas 300V 24G推理卡的YOLO模型部署与调优实践 前阵子团队准备把一套基于YOLOv5的检测服务从GPU服务器迁移到昇腾Atlas上,群里讨论最多的一句话就是:“atlas 300v 24g是运算加速卡吗?”我当时也愣了一下。后来翻完产品文档、踩了一周坑,才算把这卡的脾气摸清楚。如果你也是第一… · 2026/9/25 19:09:58
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37