嵌入式SDK架构设计经验-高级进阶心得

发布时间:2026/7/9 18:49:35
嵌入式SDK架构设计经验-高级进阶心得 今天来分享下工作这些年以来设计嵌入式SDK的一些经验。相信大家在日常工作过程中都或多或少接触过不同的SDK像STM32Cube、MCUXpresso、ESP-IDF、Zephyr、nRF Connect SDK这些都是业内非常知名的SDK设计。我自己这几年工作中也和团队搭建了好几个产品相关的SDK平台今天来聊聊我对SDK设计的理解。记住设计思路SDK 不是把驱动代码打个包而是把配置、构建、调试、交付和长期维护的秩序一起设计出来。在嵌入式、单片机领域SDK的形态其实前后是经历了四次变化的从寄存器的开发包到外设抽象的库方式再到系统级组件化SDK。我们可以来看看每个阶段的设计思路十多年前的SDK设计十多年前我使用的 MCU 的 SDK其实非常简单直接。一个启动文件一个链接脚本一堆寄存器头文件再给几个外设例程。用户把工程导进 Keil 或 IARGPIO 点个灯UART 打个 hello world基本就算入门。这个阶段的SDK设计目标很明确让用户离硬件近一点把寄存器怎么配讲清楚就行。这种方式也不是不好。你做小项目、做单板验证、做课程实验非常方便。问题出在项目变多以后。芯片型号一多开发板一多客户一多麻烦就来了。比如同一个 UART 模块A 客户裸机用B 客户 FreeRTOS 用C 客户要接 RT-Thread。你一开始为了方便把xSemaphoreTake()写进驱动里后来客户说我不用 FreeRTOS你就尴尬了。这个时候你就需要重新添加 OSAL也就是操作系统抽象层这时候就需要彻底重构了改动N多文件才行。还有板级配置。不同板卡有不同的外设、不同芯片型号有不同的配置信息早期大家喜欢把这些东西写到board.h、app_config.h、示例 README甚至直接写进某个 C 文件。项目开始时配置非常快但是两三年后里面的内容越来越臃肿配置非常多这时候就会非常乱。外设抽象SDK设计后来 STM32Cube、MCUXpresso SDK 这类厂商 SDK 慢慢成熟起来SDK 不再只是寄存器资料包而是变成一套芯片软件产品。你会看到 HAL、LL、BSP、Middleware、Examples 这些东西。HAL 给大多数用户一个好用的外设接口LL 给需要性能和细粒度控制的人留更多的驱动方式BSP 负责开发板上的 LED、按键、外部 Flash、传感器中间件再放入 USB、文件系统、TCP/IP、图形库、RTOS 适配。这种设计最大的好处是上手快。很多工程师第一次做 STM32就是靠 CubeMX 把时钟、GPIO、串口先配起来。先跑通再回头看时钟树、外设寄存器、中断优先级。这个路径对入门非常友好。但你真要把 SDK 当平台维护传统厂商 SDK 的历史包袱也会冒出来。目录按芯片系列设计例程按板卡设计IDE 工程一大堆组件依赖藏在工程文件里。一个工程怎么同时支持多个平台如何一键配置不同外设如果在工程中快速剪裁如果支持不同的构建方式虽然厂商也在尽可能的补这部分的配置但是目前来看体验还是比较差。Zephyr 和 ESP-IDF 给了两个很好的参照这几年绕不开两个路线一个是 Zephyr一个是 ESP-IDF。Zephyr 的思路借鉴了Linux框架。它不是把 SDK 当某个芯片的外设包而是把内核、驱动模型、设备树、Kconfig、构建系统、板级描述、测试框架都放进一个 RTOS 平台里。设备树用来描述硬件拓扑和板级连接Kconfig 管功能开关和裁剪驱动通过统一 device model 注册west/manifest 管多仓库和版本。这套架构你可能第一次看起来感觉繁琐、麻烦。像传统 MCU 工程师第一次看到 devicetree经常会有一种感觉我不就是配个 UART 吗怎么多出这么多文件但等你的产品线复杂起来比如 BLE、Matter、Thread、MCUboot、安全启动、OTA、多核通信都要管Zephyr 这种结构的价值就出来了。它牺牲了一点入门爽感换来多板、多芯片、多协议长期演进的秩序。ESP-IDF 则是另一种设计思路。它没有先追求“我要通用到所有 MCU”而是围绕 Espressif 自家芯片把 FreeRTOS、Wi-Fi、BLE、网络协议栈、NVS、分区表、OTA、安全启动、日志、事件循环、组件构建系统、idf.py工具都打包到工作流中。你用 ESP-IDF 做项目会明显感觉到它交付的不是单个驱动而是一套产品开发工作流。这个设计很值得我们学习。相信很多有三五年工作经验的同学在自己工作中也设计过一些大大小小的SDK或者工程架构但是很多同学设计时都是基于怎么交付“代码”进行设计的没有围绕怎么交付“做项目”这个点去做例如构建怎么跑组件怎么加配置怎么改日志怎么看固件怎么打包OTA 包怎么生成版本怎么查出了问题怎么抓现场信息。如何设计一个产品的SDK如果让我设计一个新的嵌入式产品SDK那我们可以参考下方思路首先做好分层处理。1.比如最底下这层放 CMSIS、启动文件、中断向量、链接脚本、寄存器定义。这层尽量别掺业务逻辑。2.再往上是 SoC 支持处理时钟、复位、电源域、pinmux、芯片勘误。这里要非常克制不要把板子上的传感器初始化塞进来。3.然后才是 drivers比如 sensor、display、flash、radio 这类可实例化设备。它们应该依赖抽象过的 I2C/SPI/GPIO而不是某个芯片的寄存器配置。4.再往上是 middlewareUSB、TCP/IP、文件系统、BLE、crypto、GUI 这些。5.services 这一层经常被忽略但我觉得很重要的。日志、事件、配置存储、OTA、shell、diagnostics这些东西不是具体业务但每个产品都会用。我比较喜欢这样的目录sdk/ manifests/ tools/ docs/ scripts/ components/ cmsis/ soc/ ll/ hal/ osal/ drivers/ middleware/ services/ boards/ examples/ tests/ templates/这种设计的好处是soc不能越界到板级器件hal不能偷偷依赖 FreeRTOSdrivers不能直接摸寄存器examples不能只是摆设tools不能变成一堆没人敢删的脚本。然后配置脚本保持一致SDK 维护到后期最折磨人的不是某个驱动 bug而是配置混乱。我倾向于把配置分成三类。芯片能力放soc.yaml比如有几个 UART、几个 SPI、DMA 通道、中断号、时钟源、电源域。板级连接放board.yaml比如 LED 极性、按键引脚、晶振频率、外部 Flash 型号、传感器中断脚。功能裁剪放sdkconfig比如是否启用日志、USB、文件系统、BLE、OTA。你可以用 YAML、JSON、TOML也可以更进一步用 Devicetree。格式不是最重要的最重要的是做好模块分类让每类配置都放置到对应文件中。接着别让 IDE 当唯一入口很多同学设计SDK时会默认把 IDE 当设计的唯一入口。因为用户喜欢图形界面FAE 演示也方便。Keil 点一下IAR 点一下CubeIDE 点一下工程就跑起来了看着挺方便。但你做平台 SDK命令行构建必须优先支持。IDE 可以有但它应该是前端不应该是唯一入口。原因很简单CI 不会帮你点 IDE后期单元测试、自动化构建甚至接入AI编程命令行构建才更灵活。尽可能把构建、烧录、固件打包、签名、OTA 包生成规范起来走一个统一入口。至于这个入口叫sdk.py、idf.py、west都无所谓。这部分就是我对嵌入式SDK设计的一些理解。另外如果你感觉看理论还是差点意思你也可以看看我录制的这套Linux项目课程里面的SDK设计也花了我很多心思这个SDK基于CMake自动化构建支持X86、ARM平台集成交叉编译工具链PC模拟器支持组件化设计模块化编程资源与业务分离前后端分离动态页面加载。复制链接或点击下方阅读原文https://www.bilibili.com/cheese/play/ss147530510通过这类项目带你了解一个企业级的产品软件架构设计学习高级工程师开发思路后期无论是在企业中开发项目、面试谈论架构设计、都能帮助你从容应对凭借扎实架构能力冲击更高薪资。