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

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

3天内不再提示

嵌入式软件架构基础设施设计方法

嵌入式开发爱好者 来源:嵌入式开发爱好者 2023-10-12 16:09 次阅读

大家好,今天分享一篇嵌入式软件架构设计相关的文章。

软件架构这东西,众说纷纭,各有观点。在我看来,软件架构是软件系统的基本结构,包含其组件、组件之间的关系、组件设计与演进的规则,以及体现这些规则的基础设施。

软件架构,从来不是一件容易事,它贯穿在产品的整个生命周期,需要所有团队成员遵守并自律,才能将架构思想在软件中体现。新手工程师,由于经历的项目太少,看不到项目全貌,很难从全局理解软件架构。但软件架构真的只是资深工程师的专利吗?这个也不见得。

古人作文,讲究立意为先。今天工程师做项目和产品,也应该先立意。这个意,就是指要有高度。工程师入门能从软件架构的高度出发,看待软件问题,相信对软件的理解,会更加深刻一些。因此,我总结了软件架构的六个步骤,供嵌入式工程师参考。

上次谈到了嵌入式软件架构的第一个步骤,抽象层。建立抽象层(HAL或者DAL)的目的,是为了隔离硬件,让代码与硬件无关。即使整个项目的代码,由某工程师一个人完成,抽象层仍是是有必要的。

但这次我们要聊的是,统一的基础设施,这是针对多人合作一个项目,或者多个项目共享同一个系统架构的情况。

如果说,你手头的项目,没有与他人合作,也不会有后续的相关项目,软件基础设施这一步,可以直接跳过。

基础设施,分为硬件基础设施和软件基础设施。硬件基础设施,包含常用器件库、封装库、原理图库和硬件参考设计等等;而今天我们讨论的重点,主要在于软件基础设施。软件基础设施包含以下内容:

  • •基础数据结构。

  • •底层库。比如C标准库、加密库、校验库、工具库等等。

  • 操作系统/调度机制。包含操作系统以及调度相关服务。

  • •中间件。比如文件系统、协议栈、数据库等。

  • •框架与机制。比如消息通信机制、事件驱动机制、状态机框架、行为树框架。

  • •工具支持。

  • •统一的编程工具链。

  • •统一的代码风格和编程规范。

在一些小公司粗放的开发模式中,并不规定工程师所依赖的软件平台、硬件平台和工具,而是由工程师自己决定。很多工程师,也喜欢这种自由奔放的开发模式,认为只有在这种环境中,才能发挥自身创造力。这种认知是有偏差的,这个我们后续找机会详细讨论。

随着小公司研发能力的提升,对软件基础设施进行约束和规定,几乎是注定的事情。因为软件区别于其他技术的本质,是在于其复用性。

复用程度越高的软件,质量越高,对开发效率和开发质量的提升,就越大。无论从公司的降本增效还是科学管理的角度,都有着强大的动机,去统一软件基础设施。当软件的基础设施统一之后,会产生如下优点:

  • •软件质量提升,风格的高度一致性
  • •软件复用性,会提升至一个新的水平
  • •将可复用的功能,尽量抽象到基础设施层,减少软件冗余,提升开发效率。
  • •为高层模块提供约束和纪律
  • •有利于团队的技术积累和技术传承
  • •有利于团队的技术培训
  • •是团队进行单元测试和测试驱动开发,以及跨平台开发的前提。

因此,是否统一,根本不是一个有争议的问题;如何统一,才是今天我们的重点。

一、基础类型与宏定义

统一的软件基础设施的前提,就是声明统一的基础数据类型和宏,以克服不同的硬件平台和编译器的差异性。

比如下面是我从开源项目EventOS中摘录出来的代码,不见得很完整,只能代表在我在项目里需求。

#include

typedefunsignedinteos_u32_t;
typedefsignedinteos_s32_t;
typedefunsignedshorteos_u16_t;
typedefsignedshorteos_s16_t;
typedefunsignedchareos_u8_t;
typedefsignedchareos_s8_t;
typedefbooleos_bool_t;

#defineEOS_NULL((void*)0)

#defineEOS_U32_MAX(0xffffffffU)
#defineEOS_U32_MIN(0U)
#defineEOS_U16_MAX(0xffffU)
#defineEOS_U16_MIN(0U)
#defineEOS_U8_MAX(0xffU)
#defineEOS_U8_MIN(0U)

编译器相关的宏定义。使用宏,屏蔽掉编译器的差异,会

/*CompilerRelatedDefinitions*/
#ifdefined(__ARMCC_VERSION)/*ARMCompiler*/

#defineeos_section(x)__attribute__((section(x)))
#defineeos_used__attribute__((used))
#defineeos_align(n)__attribute__((aligned(n)))
#defineeos_weak__attribute__((weak))
#defineeos_inlinestatic__inline

#elifdefined(__GNUC__)/*GNUGCCCompiler*/

#defineeos_section(x)__attribute__((section(x)))
#defineeos_used__attribute__((used))
#defineeos_align(n)__attribute__((aligned(n)))
#defineeos_weak__attribute__((weak))
#defineeos_inlinestatic__inline

#elifdefined(__IAR_SYSTEMS_ICC__)/*forIARCompiler*/

#defineeos_section(x)@x
#defineeos_used__root
#defineeos_align(n)PRAGMA(data_alignment=n)
#defineeos_weak__weak
#defineeos_inlinestaticinline

#else
#error"Thecurrentcompilerisnotsupported."
#endif

一些常用的数据结构。这些数据结构,与硬件和编译器无关,是在代码中频繁使用,并在多个模块间共享的数据结构,有必要将其提升至基础设施的层面进行支持,以避免各个模块,对同一个数据类型,进行不同的定义带来的数据转换问题。

这些数据结构,与产品紧密相关,不同的产品类型之间,各自是不同的。比如下面的定义。

typedefstructeos_date
{
eos_u32_tyear:16;
eos_u32_tmonth:8;
eos_u32_tday:8;
}eos_date_t;

typedefstructeos_time
{
eos_u32_thour:8;
eos_u32_tminute:8;
eos_u32_tsecond:6;
eos_u32_tms:10;
}eos_time_t;

typedefstructeos_imu_data
{
floatacc[3];
floatgyr[3];
floatmag[3];
}eos_imu_data_t;

二、操作系统

有些芯片的资源太小,是不能运行操作系统的。这些芯片,一般而言,也没有办法建立严谨的嵌入式软件架构,我们会在后续《小资源芯片的软件开发平台》中,单独进行讨论。这里只讨论芯片的。

不同的芯片,所能跑的操作系统是不同的。但如果要建立软件基础设施,应该尽量选取同一个操作系统。

在现存的操作系统中,FreeRTOS和国产RT-Thread对各种不同的硬件架构的芯片,支持比较广泛,可以作为RTOS的首选。

而当产品线异常丰富时,特别是使用了某些小众芯片,或者使用芯片商提供的操作系统时,就没有办法建立统一的软件基础设施。这时,有两个办法解决这一问题:

  • •编写高层模块时,使用宏定义和条件编译,选择对应的RTOS API。这种一般用于所使用的操作系统较少的情况,比如说只有两三种。
staticvoid*task_handler=NULL;

staticvoidtask_func_module_one(void*parameter);

voidmodule_one_init(void)
{
/*Newlycreatingatasktorunthemodule.*/
#if(EOS_RTOS_NAME==EOS_RTOS_NAME_FREERTOS)
xTaskCreate(task_func_module_one,
"TaskModule",2048,NULL,2,
(TaskHandle_t*)&task_handler);
#elif(EOS_RTOS_NAME==EOS_RTOS_NAME_RTTHREAD)
task_handler=rt_thread_create("led1",task_func_module_one,NULL,
2048,2,20);
#else
eos_assert(false);
#endif

eos_assert(task_handler!=NULL);
}

/*Thetaskfunctionofthemoduleone.*/
staticvoidtask_func_module_one(void*parameter)
{
(void)parameter;

/*Initialization.*/

while(1)
{
/*Addthetaskfunction.*/
}
}
  • •建立操作系统抽象层(OSAL,Operating System Abstraction Layer),以屏蔽操作系统的差异,使高层模块依赖于OSAL。这种情况适合于资源丰富的情况。
  • 著名的POSIX标准,就是为了建立OSAL的,FreeRTOS和RT-Thread都在不同程度上对POSIX标准进行了支持;在 v嵌入式领域,CMSIS_OS也是为了建立操作系统的统一接口;但无论是POSIX和CMSIS_OS,被各RTOS支持的力度是不同,因此如果我们产品中需要建立严谨的嵌入式软件架构,还是要建立属于自己的OSAL,以便屏蔽掉操作系统的不同带来的差异。

三、中间件

中间件有很多类型,文件系统、各种协议栈、数据库、日志模块、Shell模块,都属于中间件的范畴。但在大部分情况下,这些也都属于软件基础设施的范畴。

因为我们一旦选择某个中间件,一般来说,是没有必要更换的,正是由于这种稳定性,中间件也可以纳入软件基础设施的范畴。以下是我经常使用的开源中间件:

  • •FatFS

  • •LwIP

  • •FlashDB

  • •uC/Modbus

  • CAN Festival

  • •letter-shell

开源中间件,只占据了一小部分。实际产品中,中间件的大部分,都是产品或者项目私有的代码。我日常所使用的主要有:日志模块数据采集模块通讯传输层协议通讯应用层协议文件传输协议OTA功能 * 时间同步

中间件,占据了软件基础设施的大部分内容。在产品开发中,之所以软件复用性能够做到越来越高,中间件的积累,是一个很重要的原因。

四、框架与机制

在不同的产品上,开发嵌入式软件,除了RTOS之外,很多产品还需要一些框架的支持。常见的框架包括:外设与驱动框架设备框架消息框架状态机框架行为树框架事件驱动框架

这些框架的使用,与产品的特性相关,由产品和需求所决定。比如家庭服务机器人中,需要应用状态机框架和行为树框架,来应对复杂的应用层逻辑。而某些应用层逻辑比较简单的产品,就不需要使用状态机和行为树。

软件基础设施与硬件的关系

嵌入式软件有一个区别于其他软件领域的重要特性,那就是直接依赖于硬件。软件基础设施,有很多也是需要硬件去体现和承载。比如文件系统,在规定某个源代码比如FatFS作为其文件系统解决方案的同时,所伴随的硬件驱动程序和硬件推荐设计,也往往被固化,以便在下一个项目中进行复用,并节约时间。

对于一些重要的且复杂的软件基础设施,如文件系统、网络等,由于调试和测试都比较耗时,一般推荐固化硬件设计的方式。硬件工程师,应优先对这些重要且复杂的软件基础设置,分配硬件资源,而硬件的其他工程,比如IO、ADC等,再行分配。

结论

嵌入式软件基础设施,非常重要,根据项目与产品的不同,它所包含的内容也不尽相同。一般在项目启动时,就会初步选定一些软件基础设施的内容,比如RTOS、协议栈、文件系统等等。

需要指出的是,软件基础设施,也不是不变的,而是随着产品开发发展,不断会有新的组件和元素,加入到软件基础设施中去,也有可能会剥离掉旧的组件,就像生物的新陈代谢。

软件基础设施的新陈代谢,要温和,要相对稳定,添加和删除,都要执行谨慎原则。


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

    关注

    7

    文章

    3761

    浏览量

    64272
  • 嵌入式软件
    +关注

    关注

    4

    文章

    240

    浏览量

    26613
  • 系统架构
    +关注

    关注

    1

    文章

    68

    浏览量

    23520

原文标题:嵌入式软件架构基础设施设计方法

文章出处:【微信号:嵌入式开发爱好者,微信公众号:嵌入式开发爱好者】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    诚聘嵌入式软件架构

    猎头职位:嵌入式软件架构师【厦门】岗位职责:1、负责软件系统总体方案设计和详细设计,负责核心代码编写;2、负责技术方案评审,负责制定系统测试方案;3、负责新技术和关键技术的跟踪、研究和
    发表于 03-01 10:20

    嵌入式软件开发中的程序架构

    嵌入式软件开发,包括单片机开发中,软件架构对于开发人员是一个必须认真考虑的问题。软件架构对于系
    发表于 02-02 06:58

    嵌入式架构有多重要

    原有的代码。接下来嵌入式ARM便和大家分享一下,嵌入式架构那些事儿……01嵌入式系统的基本架构嵌入式
    发表于 10-27 08:15

    为何要进行嵌入式软件架构设计?如何设计?

    为何要进行嵌入式软件架构设计?如何进行嵌入式软件架构设计?
    发表于 11-01 06:31

    决定嵌入式系统软件架构的因素和架构的影响

    嵌入式系统软件架构设计目录1.前言42.决定架构的因素和架构的影响42.1.常见的误解52.1.1.小型的系统不需要
    发表于 11-08 06:54

    嵌入式软件基础的四层架构分别是哪些

    嵌入式软件分层架构基本原则有哪些?嵌入式软件基础的四层架构分别是哪些?
    发表于 12-24 07:57

    基于模块化设计的嵌入式软件测试方法

    分析嵌入式软件的特点,综述传统的软件测试方法;针对嵌入式软件的特点,提出
    发表于 05-18 13:26 23次下载

    基于模块化设计的嵌入式软件测试方法

    摘要:分析嵌入式软件的特点,综述传统的软件测试方法;针对嵌入式软件的特点,提出
    发表于 04-07 00:32 2023次阅读
    基于模块化设计的<b class='flag-5'>嵌入式</b><b class='flag-5'>软件</b>测试<b class='flag-5'>方法</b>

    嵌入式软件架构设计

    嵌入式软件架构的设计,帮助我们建立合理,有效的软件架构
    发表于 11-09 17:34 19次下载

    嵌入式软件是什么意思_嵌入式软件的分类有哪些

    本文首先阐述了嵌入式软件的概念,其次介绍了嵌入式软件的特征,最后介绍了嵌入式软件的分类。
    发表于 08-31 15:54 1.6w次阅读

    嵌入式开发中常用的软件架构

    嵌入式软件开发,包括单片机开发中,软件架构对于开发人员是一个必须认真考虑的问题。软件架构对于系
    的头像 发表于 01-01 10:16 5531次阅读
    <b class='flag-5'>嵌入式</b>开发中常用的<b class='flag-5'>软件</b><b class='flag-5'>架构</b>

    嵌入式软件架构

    嵌入式软件架构
    发表于 10-20 20:51 20次下载
    <b class='flag-5'>嵌入式</b>系<b class='flag-5'>软件</b><b class='flag-5'>架构</b>

    嵌入式系统软件架构设计

    嵌入式系统软件架构设计目录1.前言42.决定架构的因素和架构的影响42.1.常见的误解52.1.1.小型的系统不需要
    发表于 11-03 18:21 30次下载
    <b class='flag-5'>嵌入式</b>系统<b class='flag-5'>软件</b><b class='flag-5'>架构</b>设计

    详解FreeRTOS:嵌入式软件系统架构

    目前常见的嵌入式软件系统架构有三种可以分为:轮询系统架构、前后台系统架构和多任务系统架构
    的头像 发表于 05-04 16:40 2423次阅读
    详解FreeRTOS:<b class='flag-5'>嵌入式</b><b class='flag-5'>软件</b>系统<b class='flag-5'>架构</b>

    通信基础设施设备的电流检测应用

    电子发烧友网站提供《通信基础设施设备的电流检测应用.pdf》资料免费下载
    发表于 09-03 10:03 0次下载
    通信<b class='flag-5'>基础设施设</b>备的电流检测应用