课程简介
本课程不教基础的“单片机点灯”或“如何调用 RTOS API”,而是致力于完成嵌入式软件工程师在架构设计与工程能力上的双重蜕变。学完本课程,学员将达成以下四大目标。
认知跃迁:建立顶层架构思维。跳出面向过程的作坊式编程习惯,全面建立“接口标准化、业务可插拔、模块高内聚低耦合”的现代软件工程架构思维。
核心突围:精通 C 语言极限解耦技法。熟练掌握在资源受限的 MCU 上,利用 C 语言(结构体+函数指针)实现面向对象设计、依赖倒置(DIP)与依赖注入(DI),彻底斩断老旧项目中的“大泥球”代码依赖。
资产沉淀:掌握一套工业级已落地的轻量级软件平台的设计与实现。深度理解并能复用诸如 TaskPump(无锁事件驱动泵)、多级软件 Timer、HFSM(层次状态机)、双存储 File 抽象层等企业级核心组件,打造一套不绑定特定硬件与 OS 的跨项目复用底座。
效能破局:掌握平滑重构与质量保驾护航。学会“数据驱动+配置化”的多型号适配方法;掌握脱离硬件环境的 PC 端纯代码编译与 cmocka 自动化单元测试技术,建立重构历史烂代码的绝对信心。
目标收益
培训对象
本课程专为在嵌入式软件泥潭中挣扎、渴望突破能力瓶颈的工程师及技术管理者量身打造。
遇到能力提升瓶颈的一线嵌入式软件开发工程师。只会调库写业务,面对复杂的祖传代码不敢改、改不动,渴望掌握底层核心组件编写能力与高级架构设计能力,向高级开发或架构师迈进的工程师。
面临交付压力的技术主管、项目经理。团队深陷多型号适配、国产化替代的泥潭,饱受分支代码合并之苦,急需一套组件化、平台化的破局方案来降低研发成本、提升团队效能的管理者。
高可靠领域的嵌入式开发者(军工、医疗、汽车、工控等)。受限于严苛的可靠性要求,无法使用臃肿的开源系统,需要学习如何设计轻量化、无锁化、静态内存分配的高可靠自研框架的开发者
课程大纲
|
模块一:从作坊到正规军——破局与重塑 本模块直击军工、民品企业多产品线开发面临的“代码泥潭”痛点,确立平台化演进的目标与顶层架构思想。 |
1.困境诊断:熟悉的代码坏味道 a)散乱的 #ifdef 宏开关是如何毁掉整个软件资产的? b)多型号(甚至国产替代)并行开发时的合并地狱。 c)高可靠规范铁律与杂乱现实代码的复杂度反噬。 2.心智重塑:跨越软件开发的认知鸿沟 a)“好懂”的代码为何一步步沦为“灾难”? b)从“读故事”到“画地图”的脑回路重构:fMRI 脑功能成像原理解密。 c)7±2 工作记忆极限与代码结构的物理映射(米勒定律与组块理论)。 3.顶层设计:软件架构的终极蓝图 a)行业架构定义(Wikipedia/IEEE)的本质精炼——概念、关系与约束,及软件设计的终极目标(简单性)。 b)深度解析App/View/Controller/Service分层,与底层基座(HAL/ CAL)的单向依赖铁律。 c)软件设计有效性检验公式(∑局部复杂度 < 整体复杂度)、避开 5 大研发错觉,以及个人“模仿 ➔ 重构 ➔ 驾驭”的进化之路。 4.思想落地:模块设计语法学与C语言ADT a)以 mbadge(内存门禁卡)授权模块为例,解密“以人为本”的设计品味。 b)当面临灵活性与简单性的冲突时,如何进行取舍? c)以Timer模块为例,剖析阿博特(Verfahren von Abbott)需求分析法建模(名词定义空间,动词塑造接口)与C语言高内聚ADT封装范式。 |
|
模块二:软件解耦的心法与技法——核心武器库 软件的腐化往往从模块间的强耦合开始。本模块教授如何利用 C 语言的特性斩断依赖,实现真正的组件化。 |
1.软件解耦的黄金法则:维勒(David Wheeler)法则 a)回顾 mbadge 模块的实现加深理解,进一步交叉理解阿博特需求分析法。 2.接口与实现彻底分离的方法 a)消除头文件的“交叉依赖”与“循环依赖”技巧(前置声明、不透明指针)。 b)使用 C 语言的“结构体+函数指针”实现虚表(VTable)。 c)实战:如何用 VTable 将千差万别的底层硬件统一为标准的读写接口?(Device 模块的抽象) 3.依赖注入(DI)与依赖倒置(DIP)实战 a)通过“注册-回调”依赖注入机制实现控制反转(IoC)。 b)引入 TaskPump 实现系统调度(高层策略)对物理外设、中断任务(底层细节)的依赖倒置。 4.组件的“六边形”规范:接口标准化与可拔插设计 a)如何设计一个高度自治、不挑硬件的通用组件? b)如何实现变更硬件器件的情形下,业务逻辑不改一行代码? 5.组件化环境下的静态内存架构 a)嵌入式系统内存分配的三大尴尬。 b)应对三大尴尬的两大黄金策略: i.去中心化自治:谁使用资源谁提供(静态)内存。 ii.中央集权控制:用 enum 绑定数组大小。 |
|
模块三:打造已工业落地的轻量级平台底座——塑造编程新范式 现场剖析并实战演练基础设施层(CAL/HAL)的构建,让业务逻辑像搭乐高那样规范化、机制化。 |
1.平台化终极方法论 a)彻底分离策略与机制。 b)尽量将机制原子化。 2.硬件抽象:统一设备抽象(Device)实战(device.c/.h共 224 行代码) a)源码剖析:拆解 device.c,领略 POSIX 风格在嵌入式系统中的极简实现。 b)驱动与设备分离:探索基于 “/device/uart/com0” 字符串路径的设备寻址机制。 c)依赖倒置落地:底层驱动的动态注册机制与 VTable 虚表的应用。 d)规避接口膨胀:巧用 DeviceControl(ioctl思想)兼顾统一接口与底层定制化。 e)跨硬件平台代码组织:以 DeviceTick 为例的编译期多态落地实践。 f)课堂作业:基于 Device 模型徒手实现并挂载虚拟 LED 驱动。 3.异步编程:任务泵(TaskPump)实战(task_pump.c/.h共 184 行代码) a)源码剖析:拆解 task_pump.c/.h,彻底告别“大循环 + Delay”的低效模式。 b)多优先级泵治理:在裸机或 RTOS 上实现高实时性业务流转。 c)抛弃 RTOS 线程同步:基于无锁队列的单线程并发与大任务 LIFO 异步时序拆解。 d)课堂作业:完成传感器的异步标定编程。 4.时间管理:多粒度软定时器(Timer)设计与实战(timer.c/.h共 203 行代码) a)源码剖析:解析 timer.c/.h,如何用一个硬件定时器衍生出成百上千的软 Timer。 b)链表管理、相对时间差分算法的精妙实现。 c)定时器与 TaskPump 的无缝联动:超时事件的优雅抛出。 |
|
模块四:层次状态机——业务逻辑的大基建 业务逻辑复杂时,满篇的 switch/case 和 if/else 是难以维护的,也容易导致动辄几百行代码的函数实现。通过引入层次状态机(HFSM)就能很好地解决这些问题,实现代码简洁的同时让代码好读、好改。 |
1.层次状态机的起源、软件设计本质、概念与状态建模方法 a)为什么要引入状态机? b)状态机的软件设计本质。 c)传统平面状态机的痛点。 d)层次状态机的核心概念与状态建模四步法。 2.源码剖析:企业级 HFSM 框架深度剖析(hfsm.c/.h共 613 行代码) a)HFSM运行状态(HfsmInstance)、状态机行为(HfsmState)和业务数据(p_user_data)的分离设计。 b)LCA(Lowest Common Ancestor,最近公共祖先)算法在状态转换中的应用。 c)浅历史(Shallow History)与深历史(Deep History)状态的恢复机制。 d)防呆与快速失败(Fail-Fast)设计的落地。 e)课堂作业:基于 HFSM 的智能微波炉控制软件状态建模。 3.策略与机制的分离:防腐层(Anti-Corruption Layer)设计与状态机防污染 4.HFSM 与 TaskPump 的化学反应 a)构建中断和线程安全的状态机:TaskPump + HFSM 异步架构。 b)将复杂的通讯协议解析、UI 流转等装入状态机,实现业务逻辑的纯粹化。 |
|
模块五:数据驱动与插件化架构——同一套代码服务多型号、多项目 解决多型号、定制化带来的噩梦,做到新增项目、型号或变更硬件时,核心主干代码零改动,仅需增加独立驱动、插件并修改配置文件。 |
1.“一套代码”战略:破解多型号、多项目独立代码分支维护的困境 a)行业普遍痛点:每出一个新型号、新项目就拷贝一份代码或拉一个新分支维护,结果遭受一个 Bug 出现后得在多个分支上同时修复的麻烦,并增加了各分支代码同步的长期麻烦。“一套代码” 战略是根治这一痛点的解药,不过还得翻越后面的“三座大山”才行。 b)检验同一套代码落地的终极标准:开闭原则(OCP)——面对新需求,只加代码而不改老代码。以 Hood 真实源码为例,阐明 OCP 是针对模块边界而非整个系统的局部闭合理念;并将 OCP 具象化为代码级(插件化)与数据级(数据驱动)两大落地方法。 c)“一库多型”代码树规划与构建范式。物理代码库只有一份,在目录拓扑上将核心基座(闭合区)与型号插件、配置(装配区)彻底物理隔离;通过编译期宏与运行期配置,实现单一 Git 主干稳定产出全型号定制固件。 2.可选功能与选配硬件的插件化抽象(多型号装配与优雅降级) a)插件化维度跃迁:从底层 Device 驱动到高层 Service 业务服务。将可选业务功能(如网络通信、数据同步、算法引擎)标准化为 Service 插件契约。 业务逻辑仅面向 Service 契约编程,实现业务层对具体功能实现的彻底解耦。 b)消灭业务层宏的一种技巧:空对象模式与优雅降级。通过注入空实现提供安全默认行为,或利用统一状态码让业务流静默降级,保持业务主逻辑全型号 100% 纯净统一。 c)乐高式装配实战:基于构建矩阵的链接期多态装配。以 Makefile 作为变体装配接线板,根据 TARGET 目标按需编入对应插件;全产品线共享同一个纯净的 main.c 入口,插件通过 static 实现私有化绑定,达成零全局变量暴露与 ROM 体积的极致精简。 3.数据驱动与表驱动配置 a)变体收敛与隔离:构建 Config/Preference 配置防腐层,将硬件差异(GPIO管脚、采样率)、业务差异(参数、通信协议)统一收敛,避免硬件变更侵蚀业务逻辑。 b)编译期裁剪与运行时配置:结合编译宏(镜像体积最小化)与运行时配置表(表驱动),兼顾灵活性与资源极致使用。 c)C 语言高级实战:巧用 X-Macro(宏展开)维护变体矩阵,实现修改一处,全局(枚举、配置、字符串)自动对齐。 4.案例实战与跨型号质量保障 a)实战演练:为同一套代码配置出基础版、进阶版(带选配传感器)和旗舰版(带双路通信)三个型号的编译产物。 b)跨型号 CI/CD 自动化构建防线:如何确保修改一个通用 Bug 时,通过自动化编译矩阵一键验证所有型号,杜绝“改好型号 A,带崩型号 B”问题。 |
|
模块六:卸下历史包袱,建立质量自信——稳妥落地与工程化 再好的架构,如果无法在真实的老项目中落地,也是空中楼阁。本模块聚焦转型过程与质量保证。 |
1.破除硬件诅咒:将 PC 打造为嵌入式的“第一开发板” a)摆脱仿真器与烧录器:业务与硬件解耦后的跨平台秒级原生编译(GCC、Clang)。 b)嵌入式纯软件工程流:在 PC 端复现时序、边界与异常分支。 2.面向接口的测试架构:接缝理论与 cmocka 实战 a)接缝(Seam)本质:为什么没有测试保护的老代码就是定时炸弹? b)对付老代码:链接接缝与 GCC --wrap 魔法(不改一行老代码,强行拦截底层调用)。 c)对付新架构:对象接缝与架构级 Mock(利用 VTable + 依赖注入模拟传感器、异常)。 3.“绞杀者模式”:老旧项目的渐进式平滑重构 a)决不能“推倒重来”!在老系统与新架构之间筑起防腐层。 b)动刀策略:老项目重构的 ROI 决策矩阵(低风险、高频变更模块先行)。 c)新老共存期的数据同步、状态迁移与平滑退役方案。 4.质量防线固化:将不退化作为工程铁律 a)本地 Git Hook + CI/CD 自动化测试流建设。 b)架构看护:如何防止后续迭代再次退化为“大泥球”。 |
|
模块一:从作坊到正规军——破局与重塑 本模块直击军工、民品企业多产品线开发面临的“代码泥潭”痛点,确立平台化演进的目标与顶层架构思想。 1.困境诊断:熟悉的代码坏味道 a)散乱的 #ifdef 宏开关是如何毁掉整个软件资产的? b)多型号(甚至国产替代)并行开发时的合并地狱。 c)高可靠规范铁律与杂乱现实代码的复杂度反噬。 2.心智重塑:跨越软件开发的认知鸿沟 a)“好懂”的代码为何一步步沦为“灾难”? b)从“读故事”到“画地图”的脑回路重构:fMRI 脑功能成像原理解密。 c)7±2 工作记忆极限与代码结构的物理映射(米勒定律与组块理论)。 3.顶层设计:软件架构的终极蓝图 a)行业架构定义(Wikipedia/IEEE)的本质精炼——概念、关系与约束,及软件设计的终极目标(简单性)。 b)深度解析App/View/Controller/Service分层,与底层基座(HAL/ CAL)的单向依赖铁律。 c)软件设计有效性检验公式(∑局部复杂度 < 整体复杂度)、避开 5 大研发错觉,以及个人“模仿 ➔ 重构 ➔ 驾驭”的进化之路。 4.思想落地:模块设计语法学与C语言ADT a)以 mbadge(内存门禁卡)授权模块为例,解密“以人为本”的设计品味。 b)当面临灵活性与简单性的冲突时,如何进行取舍? c)以Timer模块为例,剖析阿博特(Verfahren von Abbott)需求分析法建模(名词定义空间,动词塑造接口)与C语言高内聚ADT封装范式。 |
|
模块二:软件解耦的心法与技法——核心武器库 软件的腐化往往从模块间的强耦合开始。本模块教授如何利用 C 语言的特性斩断依赖,实现真正的组件化。 1.软件解耦的黄金法则:维勒(David Wheeler)法则 a)回顾 mbadge 模块的实现加深理解,进一步交叉理解阿博特需求分析法。 2.接口与实现彻底分离的方法 a)消除头文件的“交叉依赖”与“循环依赖”技巧(前置声明、不透明指针)。 b)使用 C 语言的“结构体+函数指针”实现虚表(VTable)。 c)实战:如何用 VTable 将千差万别的底层硬件统一为标准的读写接口?(Device 模块的抽象) 3.依赖注入(DI)与依赖倒置(DIP)实战 a)通过“注册-回调”依赖注入机制实现控制反转(IoC)。 b)引入 TaskPump 实现系统调度(高层策略)对物理外设、中断任务(底层细节)的依赖倒置。 4.组件的“六边形”规范:接口标准化与可拔插设计 a)如何设计一个高度自治、不挑硬件的通用组件? b)如何实现变更硬件器件的情形下,业务逻辑不改一行代码? 5.组件化环境下的静态内存架构 a)嵌入式系统内存分配的三大尴尬。 b)应对三大尴尬的两大黄金策略: i.去中心化自治:谁使用资源谁提供(静态)内存。 ii.中央集权控制:用 enum 绑定数组大小。 |
|
模块三:打造已工业落地的轻量级平台底座——塑造编程新范式 现场剖析并实战演练基础设施层(CAL/HAL)的构建,让业务逻辑像搭乐高那样规范化、机制化。 1.平台化终极方法论 a)彻底分离策略与机制。 b)尽量将机制原子化。 2.硬件抽象:统一设备抽象(Device)实战(device.c/.h共 224 行代码) a)源码剖析:拆解 device.c,领略 POSIX 风格在嵌入式系统中的极简实现。 b)驱动与设备分离:探索基于 “/device/uart/com0” 字符串路径的设备寻址机制。 c)依赖倒置落地:底层驱动的动态注册机制与 VTable 虚表的应用。 d)规避接口膨胀:巧用 DeviceControl(ioctl思想)兼顾统一接口与底层定制化。 e)跨硬件平台代码组织:以 DeviceTick 为例的编译期多态落地实践。 f)课堂作业:基于 Device 模型徒手实现并挂载虚拟 LED 驱动。 3.异步编程:任务泵(TaskPump)实战(task_pump.c/.h共 184 行代码) a)源码剖析:拆解 task_pump.c/.h,彻底告别“大循环 + Delay”的低效模式。 b)多优先级泵治理:在裸机或 RTOS 上实现高实时性业务流转。 c)抛弃 RTOS 线程同步:基于无锁队列的单线程并发与大任务 LIFO 异步时序拆解。 d)课堂作业:完成传感器的异步标定编程。 4.时间管理:多粒度软定时器(Timer)设计与实战(timer.c/.h共 203 行代码) a)源码剖析:解析 timer.c/.h,如何用一个硬件定时器衍生出成百上千的软 Timer。 b)链表管理、相对时间差分算法的精妙实现。 c)定时器与 TaskPump 的无缝联动:超时事件的优雅抛出。 |
|
模块四:层次状态机——业务逻辑的大基建 业务逻辑复杂时,满篇的 switch/case 和 if/else 是难以维护的,也容易导致动辄几百行代码的函数实现。通过引入层次状态机(HFSM)就能很好地解决这些问题,实现代码简洁的同时让代码好读、好改。 1.层次状态机的起源、软件设计本质、概念与状态建模方法 a)为什么要引入状态机? b)状态机的软件设计本质。 c)传统平面状态机的痛点。 d)层次状态机的核心概念与状态建模四步法。 2.源码剖析:企业级 HFSM 框架深度剖析(hfsm.c/.h共 613 行代码) a)HFSM运行状态(HfsmInstance)、状态机行为(HfsmState)和业务数据(p_user_data)的分离设计。 b)LCA(Lowest Common Ancestor,最近公共祖先)算法在状态转换中的应用。 c)浅历史(Shallow History)与深历史(Deep History)状态的恢复机制。 d)防呆与快速失败(Fail-Fast)设计的落地。 e)课堂作业:基于 HFSM 的智能微波炉控制软件状态建模。 3.策略与机制的分离:防腐层(Anti-Corruption Layer)设计与状态机防污染 4.HFSM 与 TaskPump 的化学反应 a)构建中断和线程安全的状态机:TaskPump + HFSM 异步架构。 b)将复杂的通讯协议解析、UI 流转等装入状态机,实现业务逻辑的纯粹化。 |
|
模块五:数据驱动与插件化架构——同一套代码服务多型号、多项目 解决多型号、定制化带来的噩梦,做到新增项目、型号或变更硬件时,核心主干代码零改动,仅需增加独立驱动、插件并修改配置文件。 1.“一套代码”战略:破解多型号、多项目独立代码分支维护的困境 a)行业普遍痛点:每出一个新型号、新项目就拷贝一份代码或拉一个新分支维护,结果遭受一个 Bug 出现后得在多个分支上同时修复的麻烦,并增加了各分支代码同步的长期麻烦。“一套代码” 战略是根治这一痛点的解药,不过还得翻越后面的“三座大山”才行。 b)检验同一套代码落地的终极标准:开闭原则(OCP)——面对新需求,只加代码而不改老代码。以 Hood 真实源码为例,阐明 OCP 是针对模块边界而非整个系统的局部闭合理念;并将 OCP 具象化为代码级(插件化)与数据级(数据驱动)两大落地方法。 c)“一库多型”代码树规划与构建范式。物理代码库只有一份,在目录拓扑上将核心基座(闭合区)与型号插件、配置(装配区)彻底物理隔离;通过编译期宏与运行期配置,实现单一 Git 主干稳定产出全型号定制固件。 2.可选功能与选配硬件的插件化抽象(多型号装配与优雅降级) a)插件化维度跃迁:从底层 Device 驱动到高层 Service 业务服务。将可选业务功能(如网络通信、数据同步、算法引擎)标准化为 Service 插件契约。 业务逻辑仅面向 Service 契约编程,实现业务层对具体功能实现的彻底解耦。 b)消灭业务层宏的一种技巧:空对象模式与优雅降级。通过注入空实现提供安全默认行为,或利用统一状态码让业务流静默降级,保持业务主逻辑全型号 100% 纯净统一。 c)乐高式装配实战:基于构建矩阵的链接期多态装配。以 Makefile 作为变体装配接线板,根据 TARGET 目标按需编入对应插件;全产品线共享同一个纯净的 main.c 入口,插件通过 static 实现私有化绑定,达成零全局变量暴露与 ROM 体积的极致精简。 3.数据驱动与表驱动配置 a)变体收敛与隔离:构建 Config/Preference 配置防腐层,将硬件差异(GPIO管脚、采样率)、业务差异(参数、通信协议)统一收敛,避免硬件变更侵蚀业务逻辑。 b)编译期裁剪与运行时配置:结合编译宏(镜像体积最小化)与运行时配置表(表驱动),兼顾灵活性与资源极致使用。 c)C 语言高级实战:巧用 X-Macro(宏展开)维护变体矩阵,实现修改一处,全局(枚举、配置、字符串)自动对齐。 4.案例实战与跨型号质量保障 a)实战演练:为同一套代码配置出基础版、进阶版(带选配传感器)和旗舰版(带双路通信)三个型号的编译产物。 b)跨型号 CI/CD 自动化构建防线:如何确保修改一个通用 Bug 时,通过自动化编译矩阵一键验证所有型号,杜绝“改好型号 A,带崩型号 B”问题。 |
|
模块六:卸下历史包袱,建立质量自信——稳妥落地与工程化 再好的架构,如果无法在真实的老项目中落地,也是空中楼阁。本模块聚焦转型过程与质量保证。 1.破除硬件诅咒:将 PC 打造为嵌入式的“第一开发板” a)摆脱仿真器与烧录器:业务与硬件解耦后的跨平台秒级原生编译(GCC、Clang)。 b)嵌入式纯软件工程流:在 PC 端复现时序、边界与异常分支。 2.面向接口的测试架构:接缝理论与 cmocka 实战 a)接缝(Seam)本质:为什么没有测试保护的老代码就是定时炸弹? b)对付老代码:链接接缝与 GCC --wrap 魔法(不改一行老代码,强行拦截底层调用)。 c)对付新架构:对象接缝与架构级 Mock(利用 VTable + 依赖注入模拟传感器、异常)。 3.“绞杀者模式”:老旧项目的渐进式平滑重构 a)决不能“推倒重来”!在老系统与新架构之间筑起防腐层。 b)动刀策略:老项目重构的 ROI 决策矩阵(低风险、高频变更模块先行)。 c)新老共存期的数据同步、状态迁移与平滑退役方案。 4.质量防线固化:将不退化作为工程铁律 a)本地 Git Hook + CI/CD 自动化测试流建设。 b)架构看护:如何防止后续迭代再次退化为“大泥球”。 |
近期公开课推荐