0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

固件模块可以分为哪几种类型?

GReq_mcu168 来源:玩转单片机 作者:玩转单片机 2020-07-01 17:05 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

为什么写本文?做公号两月,遇到一些初学单片机的同学,刚刚入手做单片机开发,还没有涉及到使用RTOS,且刚入手直接上RTOS可能会有些难度,有的使用的相对较老单片机资源还有限,也不适合跑RTOS。或者使用RTOS,在整体思路上比较迷茫,不知从何入手,所以本文来聊聊我对单片机程序的整体框架设计的一些思路体会。

为啥要讨论架构单片机系统开发人员的目标之一是在编程环境中创建固件,以实现低成本系统、软件可靠性以及快速的开发迭代时间。实现这种编程环境的最佳方法实践是使用统一的固件架构体系结构,该体系结构在产品开发过程中充当框架并支持“固件模块化”,或称为子系统。

如果不采用统一的设计架构,那么其业务需求耦合关系复杂,不采用先设计-后开发的方法论,想到哪里写到哪里,则程序后期维护将变得异常艰辛,而引入潜在bug/缺陷的风险也将大大增加,且不具备多人协同开发的可能。

可以结合固件模块化、可测试性和兼容性的正确组合的设计体系架构结构应用于任何固件开发项目,以最大程度地提高代码可复用性,加快固件调试速度并提高固件可移植性。

模块化架构设计?模块化编程将程序功能分解为固件模块/子系统,每个模块执行一个功能,并包含完成该功能所需的所有源代码和变量。

固件模块可以分为哪几种类型?

模块化/子系统化有助于协调团队中许多人的并行工作,管理项目各个部分之间的相互依赖关系,并使设计人员、系统集成人员能够以可靠的方式组装复杂的系统。具体来说,它可以帮助设计人员实现和管理复杂性。随着应用程序的大小和功能的增长,需要模块化才能将它们分成单独的部分(无论是作为“组件”,“模块”还是“子系统”)。然后,每个这样分离的部分就成为模块化体系结构的一个元素。这样,可以使用定义明确的界面隔离和访问每个组件。此外,模块化编程可提高固件的可读性,同时简化固件的调试,测试和维护。

即便是一个人独立开发一个项目,这样做依然在代码的调试、可读性、可移植性方面是最佳实践的整体策略。如果代码设计良好,则在其他项目可以轻松应用。而且模块经过上一项目的测试验证,在新的项目中再次应用其缺陷风险将大幅降低。所以每做一个项目,以这种策略不断积累模块“轮子”组件,随着经验的增长,积累的“轮子”就越来越多,也越来越好。所以其优点是显而易见的,否则每做一个项目,都从轮子造起,开发时间长不说,开发水平也得不到提高,重复性工作也很枯燥。比如前文中谈到的非易失存储管理子系统,如设计良好,就变成一个可靠的可移植的轮子。这段话请深入理解,并拿走不谢!

固件模块原理固件开发中模块化编程的基本概念是创建固件模块。从概念上讲,模块代表关注点分离。在计算机科学中,关注点分离是将计算机程序分解为功能很少重叠的独特功能的过程。关注点是程序的任何关注点或功能,并且与功能或行为同义。关注点分离的发展传统上是通过模块化和封装来实现的,其实也就是解耦思想。

固件模块可以分为几种类型:

与很多上层用户模块都有关的代码被实现为单独的固件模块。常见的如底层硬件相关的抽象实现。例如,hal_adc.c 是ADC用户模块的固件模块,而hal_timer.c是Timer用户模块的固件模块。

用于特定纯软件算法的代码被实现为单独的固件模块。 例如,alg_filter.c是执行软件过滤器(例如中值过滤器,均值过滤器或加权均值过滤器、IIR/FIR滤波)的固件模块。

特定应用程序的代码实现为单独的固件模块。 例如,app_battery.c是电池充电器应用程序的固件模块。特定工具的代码实现为单独的固件模块。例如,debug_print.c是用于实现日志打印功能的固件模块。

实施估计模块化设计的一些规则:

所有与模块相关的功能都应集成到单个源文件中,这是高内聚的体现。

模块对外提供一个头文件,该文件声明了该模块的所有资源(硬件依赖/宏/常量/变量/函数)。尽量用struct将紧密相关的变量进行集总封装。

在源文件中包括自检代码部分,以实现该模块模块的所有自检功能。

固件模块的接口应经过精心设计和定义。

由于固件取决于硬件,因此需要在源文件头中明确提及硬件的相关性。比如利用宏将硬件依赖转定义,或者利用函数将基本操作进行封装。则在新的架构体系,仅仅需要移植这部分实现即可使用。

通常,固件模块可供其他团队成员在其他项目中使用。可能涉及到管理更改,缺陷修复、所有者应维护模块。源文件头应包含“作者”和“版本”信息。

固件在某种程度上取决于编译器。源文件头中应声明基于什么开发环境进行过验证,以指定编译器或与IDE相关的信息。

需要注意的是,模块化设计会引入一些调用开销,也可能增加固件尺寸大小。在实际实现时,折中考量。不要过度模块化,所以建议采用高内聚、低耦合的实现策略。在前面文章中有谈到过的呼吸机PB560的设计,看过其代码,本打算解读一下其代码设计,但读下来发现,其设计过度模块化了,没有实现高内聚的思想。其源代码很多源文件仅仅实现了一个函数,而不是把一类问题集中抽象实现,后来就放弃了其代码解读。

如何拆分模块?做工程开发,一定是需求驱动的。第一件事需要对需求有比较清晰的认知,然后才能设计一个比较合理的框架。我们需要实现什么?大致总体设计过程策略我的基本采用如下图所示思路(我比较喜欢绘图,图会让人比较直观)

固件模块可以分为哪几种类型?

问自己第一个问题是:这个项目要实现什么主要功能?这个来自哪里?如果是实际产品开发,则可能来自市场的需求,如果是自己的DIY项目,也一定会YY出一个大致的想法?总之不管源自何方,需求总要先梳理清楚。那么需求一般意义上包含哪些呢?

哪些是硬件IO接口需求,比如开关量输入,ADC采样,I2C/SPI通信等等

哪些是业务逻辑需求,比如要采集一个传感器量数据,控制一个加热装置,那么这是高内聚的需求。

哪些是算法相关的技术需求,比如产品中哪些信号需要滤波处理,哪些需要做频域分析等等。

是否有对外的通信协议需求。

是否有业务数据需要历史存储,或者设备参数需要掉电保存

是否需要有日志打印需求。

不一而足。

结合固件模块原理以及相关指导原则,那么将相关性高的需求,抽象实现在一系列的模块中,在由这一系列模块配合实现某个相关性高的业务需求,再进一步这些模块就变成一个子系统。多个子系统在main.c的调度下,协调完成产品的整体功能。

如何集成调度对于某些不使用RTOS的应用而言,可以使用如下的框架进行:

void main(void)

/*各模块初始化*/

init_module_1();

init_module_2();

while(1)

/*实现一个定时调度策略*/

if(timer50ms)

timer50ms = 0;

app_module_1();

if(timer100ms)

timer100ms = 0;

app_module_2();

/*异步请求处理,如中断后台处理*/

if(flag1)

communication_handler();

对于基于RTOS的集成实现举例:

void task1(void)

/*处理子系统相关的初始化*/

init_task1();

while(1)

/*应用相关调用*/

task1_mainbody();

void taskn(void)

/*处理子系统相关的初始化*/

init_taskn();

while(1)

/*应用相关调用*/

taskn_mainbody();

void main(void)

/*一些基本硬件相关初始化,比如IO,时钟,OS tick定时器等*/

init_hal();

/*一些基本RTOS初始化*/

init_os();

/*任务创建*/

os_creat(“task1”,task1,栈设置,优先级,。..);

os_creat(“taskn”,taskn,栈设置,优先级,。..);

/*启动OS调度器,交由OS调度管理应用任务*/

os_start();

具体不同的RTOS,其函数名各有不同,但大致思路一般都差不多。

总结一下本文从为什么需要模块化设计整体架构,到这样做的好处,以及具体做的一些指导原则,再到实际中如何实现,怎么做到高内聚低耦合,提供了一些个人工作中的体会以及思路。同时对于裸机程序整体框架、基于RTOS的集成框架做了两个demo,基本能解决大部分的框架思路问题。将前文中的一些个人推崇的原则,在加粗总结下:

所有与模块相关的功能都应集成到单个源文件中,这是高内聚的体现。

模块对外提供一个头文件,该文件声明了该模块的所有资源(硬件依赖/宏/常量/变量/函数)。尽量用struct将紧密相关的变量进行集总封装。

在源文件中包括自检代码部分,以实现该模块模块的所有自检功能。

固件模块的接口应经过精心设计和定义。

由于固件取决于硬件,因此需要在源文件头中明确提及硬件的相关性。比如利用宏将硬件依赖转定义,或者利用函数将基本操作进行封装。则在新的架构体系,仅仅需要移植这部分实现即可使用。

通常,固件模块可供其他团队成员在其他项目中使用。可能涉及到管理更改,缺陷修复、所有者应维护模块。源文件头应包含“作者”和“版本”信息。

固件在某种程度上取决于编译器。源文件头中应声明基于什么开发环境进行过验证,以指定编译器或与IDE相关的信息。
责任编辑:pj

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 单片机
    +关注

    关注

    6078

    文章

    45577

    浏览量

    673537
  • 编程
    +关注

    关注

    90

    文章

    3723

    浏览量

    97434
  • RTOS
    +关注

    关注

    25

    文章

    869

    浏览量

    123210
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    电阻试验可以检测哪些项目?有哪些类型和设备?

    电阻试验是电气工程领域中的一项基础且重要的测试,也是一种常见的电气测试,涉及对电阻元件的阻值进行测量和评估,用于测量导体或电气设备的电阻值。电阻试验可以分为种类型,包括直流电阻试验、绝缘电阻测试等
    的头像 发表于 04-17 16:05 69次阅读
    电阻试验<b class='flag-5'>可以</b>检测哪些项目?有哪些<b class='flag-5'>类型</b>和设备?

    单相电机可以分为哪几种类型

    单相电机是家用电器和小型工业设备中应用最广泛的动力装置之一,其结构简单、成本低廉的特点使其在220V交流电环境下具有不可替代的优势。根据工作原理和启动方式的不同,单相电机主要可分为以下几种类型
    的头像 发表于 03-03 17:12 836次阅读

    探针电池座安装方式的差异与类型

    探针,也称作弹簧针连接器,常用于手机这种小型电子产品中。探针的主体结构由针头、弹簧、针管三部分构成。依据安装方式的差异,探针可划分为以下几种类型
    的头像 发表于 02-26 14:24 261次阅读
    探针电池座安装方式的差异与<b class='flag-5'>类型</b>

    CW32单片机支持哪几种开发环境,比较常用的MDK支持吗?

    CW32单片机支持哪几种开发环境,比较常用的MDK支持吗。 若使用MDK开发,是否也需要下载芯片包,导入到MDK中?xxx32的库可以用吗。
    发表于 01-26 06:14

    请问单片机开发的程序设计语言主要有哪几种

    单片机开发的程序设计语言主要有哪几种
    发表于 01-14 08:29

    电能质量在线监测装置的采样模块有哪些类型

    电能质量在线监测装置采样模块按 测量对象 分为 电压采样模块 和 电流采样模块 两大类,按 接入方式 分为 直接接入式 和 间接接入式 ,按
    的头像 发表于 12-17 15:48 1303次阅读
    电能质量在线监测装置的采样<b class='flag-5'>模块</b>有哪些<b class='flag-5'>类型</b>?

    MCU固件几种Flash(闪存)划分方式

    你通过U盘、OTA远程等方式下载的程序,其实你还是需要提前下载BootLoader程序,才能进一步下载APP程序。     今天就来说说通过OTA方式升级固件时,几种Flash(闪存)划分方式
    的头像 发表于 11-27 18:20 1386次阅读

    单模光纤线有几种类型

    单模光纤线根据ITU-T国际标准(G.65x系列)主要分为以下六种类型,每种类型在传输性能、应用场景和成本上存在差异: G.652(常规单模光纤): 核心特性:零色散波长在1310nm附近
    的头像 发表于 09-11 10:00 2779次阅读

    工业相机的类型及不同类型的应用

    工业相机根据不同的分类标准,可分为种类型,每种类型都有其独特的应用场景。
    的头像 发表于 08-29 17:07 939次阅读
    工业相机的<b class='flag-5'>类型</b>及不同<b class='flag-5'>类型</b>的应用

    水晶头主要有哪几种型号

    环境中,是网络连接的标准接口。 特点:支持高速网络通信,具有自动防止脱落的功能,适用于连接计算机、路由器、交换机等网络设备。 分类:根据网线类型(如五类、六类等)的不同,RJ-45水晶头还有不同规格,如超五类水晶头(孔径一般是1.0mm)、六类水晶头(孔径一般是1.08mm
    的头像 发表于 08-05 09:41 5193次阅读

    变压器常见类型及特点详解

    变压器在电力系统中起着重要的作用,根据不同的标准,变压器可以分为种类型。以下是对变压器主要类型及其特点的详细阐述:
    的头像 发表于 08-02 13:37 2360次阅读

    固态电容按照介质种类分为哪几种

    固态电容按照介质种类主要分为 钽介质固态电容、铝介质固态电容、陶瓷介质固态电容(MLCC虽属陶瓷电容,但部分特殊结构可视为固态电容变种)以及聚合物介质固态电容(如导电高分子型) 。以下为具体分类
    的头像 发表于 07-25 16:10 1316次阅读
    固态电容按照介质<b class='flag-5'>种类</b>来<b class='flag-5'>分为</b><b class='flag-5'>哪几种</b>?

    声音传感器有哪几种

    声音传感器作为将声波信号转换为电信号的装置,在工业自动化、智能家居、医疗诊断等领域应用广泛。根据工作原理和检测目标的不同,声音传感器主要分为以下几类: 一、基于压电效应的传感器 压电式声音传感器利用
    的头像 发表于 06-23 10:10 2334次阅读

    门铃语音芯片有哪几种型号可以选择?

    门铃语音芯片的选择可以很广泛!因为简单的OTP语音芯片也可以用,高级一点的FLASH语音芯片,或者在高端一点的语音识别芯片,或者集成蓝牙又或者红外等等,有非常多的方案,具体可以看自己详细的需求。 以
    的头像 发表于 06-09 15:58 821次阅读

    电容分为哪几种,各有什么用途呢?

    一、电容的分类‌ ‌按介质材料分类‌ ‌陶瓷电容‌:钛酸钡/钛酸锶介质,高频特性优,体积小(耐压10V~100V),适用于高频去耦和RF匹配电路。 ‌电解电容‌:氧化铝/钽氧化物介质,容量大(μF~F级),有极性,用于电源滤波和储能。 ‌薄膜电容‌:聚酯/聚丙烯介质,耐压高(kV级),低损耗,适用于交流滤波和电机驱动。 ‌超级电容‌:活性炭/石墨烯介质,容量达法拉级,用于能量回收和备用电源。 ‌云母电容‌:云母片介质,精度高(±1%),用于高频谐振和精密仪器。 ‌按结构分类‌ ‌固定电容‌:容量不可变,如瓷介电容、电解电容。 ‌可变电容‌:容量可手动调节,用于调谐电路。 ‌微调电容‌:小范围调节容量,用于电路校准。 ‌按功能用途分类‌ ‌滤波电容‌:平滑电源纹波(如电解电容+陶瓷电容组合)。 ‌耦合电容‌:隔直通交,连接信号源与放大电路。 ‌旁路电容‌:为高频信号提供低阻抗通路(如0.1μF陶瓷电容)。 ‌调谐电容‌:用于射频电路频率调整(如可变陶瓷电容)。 ‌二、核心用途‌ ‌能量存储与释放‌ 电解电容和超级电容用于电源储能、瞬时大电流放电。 ‌信号处理‌ 耦合电容传输交流信号,隔断直流分量。 旁路电容抑制高频噪声,提升信号完整性。 ‌电路保护‌ 安规电容(X/Y电容)抑制EMI,保护电源输入端。 ‌三、典型应用场景‌ ‌消费电子‌ 手机/平板:多层陶瓷电容(MLCC)用于高频去耦。 快充设备:电解电容滤波,超级电容快速充放电。 ‌工业设备‌ 电机驱动:薄膜电容耐高压,用于逆变器滤波。 电力系统:直流干式电容器用于STATCOM补偿无功功率。 ‌通信与射频‌ 调谐电容选择振荡频率,云母电容稳定高频电路。 ‌四、选型要点‌ ‌高频电路‌:优选低ESR的陶瓷电容或云母电。 ‌高精度场景‌:云母电容或CBB电容(误差±1%)。
    发表于 06-05 15:29