如何用一个实例来探讨嵌入式软件架构设计?

一、感慨

近公司新招了一个做嵌入式软件开发开发的童鞋,该童鞋是从上海的某一个上市公司出来的,因为我们这边人手不够,因此把他安排了去负责一个新产品的研发,前期让他负责加速度计、NB-IOT、舵机、外置Flash的功能测试,测试完成之后,准备让他做一个该产品的概要设计。然后他花了2个星期的时间,给我们写出来一个概要设计,说实话,我看到这个概要设计,我就觉得是刚毕业的大学生写的。

版本一的架构设计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2.1系统体系结构
系统分为两层:硬件驱动层、应用层。
2.1.1硬件驱动层
硬件驱动层包含板载硬件资源正常运行所需的所有驱动程序。
1)MCU初始化
2)I2C数据存取
3)SPI数据读取
4)加速度计初始化
5)蓝牙模块启动
6)BC95模块启动
7)485通讯模块启动
2.2.2应用层
1)Mcu运行模式切换
2)震动及倾斜
3)数据解析
4)开/关锁
5)数据发送
6)历史数据保存
看到版本一的架构设计之后,说实话,我还是第一次见到这样来写架构设计的,居然是以序号来写的,这个让别人读起来,特别的别扭。  

版本二的架构设计

看到版本二的架构设计之后,虽然颇感欣慰,但是想到达到我们所要求的,还要很大的一段距离,该架构设计,主要有以下几点问题:

1.对架构的理解还不是很清晰,既然是做架构设计,那就应该从整体来看,而不是仅仅只是局限于一个模块,或者功能里面。

2.还是每个层次的理解也还不是很清晰,比如讲MCU的初始化,归于硬件驱动层里面。MCU的初始化,严格意义上来说,是属于流程的一部分了,而不是驱动。比如电脑的开启启动,把这个归于硬件的驱动里面,肯定是属于牛头不对马嘴的。

3.还有就是各个模块的启动,也是不能属于硬件驱动层的,也都是业务流程的一部分了,都不应该属于驱动层的一部分。

4.还有就是总线数据的读写,虽然驱动的作用也就是读写,但是数据总线的读写不能写成硬件驱动。

5.应用层的系统参数初始化,也还是属于流程。

6.数据的解析和数据的发生,都是属于通信功能里面的,不应该单独独立出来,属于单个的应用。

 

看到这里之后,说实话,我真的很惊讶,难倒从大企业出来的童鞋,能力都是这样的吗?从大企业出来的童鞋们,工资也是要的老高老高的,难倒他们不知道,在昆明的工资,都是以K来计算的吗?在昆明能拿到8K的工资做开发的人就已经很少了。然后再到1W

以上的,童鞋们就更少了。

说实话,我们的这位童鞋,上班的时候,还经常看电子书,在实习期间还经常看电子书,我不知道,他哪来的实力,心可以放的这么宽,交代的活没有完成,还有时间来看电子书。当然托他的福,我的工资也终于涨到6K了,因为新人的工资,比老人高,

做的活还是一样的(结果一不一样我就知道了),为了考虑到老人的心里面不平衡,所以才给我加的工资的。领导们在批加工资的申请的时候,还专门把我叫去办公室,让我表决心啥的。。

 

然后,我让他去改,把我说的这些改改,然后再看一下,还有什么问题没?结果我看他在那抓耳挠腮,还有各种叹气,然后和我说,改不了。

既然改不了,那我就只能亲自操刀上阵了,毕竟同事一场。

 

 二、基本框架图

(1)架构设计的目的

1、应用的代码逻辑清晰,且避免重复的造轮子。

2、如果没有好的架构,移植将会是一件很痛苦的事情,因此一个好的架构设计,方便软件的移植。

3、最大限度的复用。

4、高耦合低内聚。 

 

(2)设计思路

如何把硬件的驱动和一个功能封装成一个个的模块,然后可以像小朋友搭积木一个,一个个模块可以快速的拼接起来,组成一个个不同的模型。

我们的嵌入式架构思路也是来源于此,即功能模块化设计、分层设计。

这个设计和WEB开发的MVC模式类似,都是注重分层设计。

 

模块化设计:将收集到的需求,进行归类,总结和分析,将这些需求概括为一个个单独的功能,每一个功能,做成一个单独的功能模块。

分层设计一句话不好直接表达,其主要体现在一下几方面:

1、功能模块对外调用的模块封装成一个个API,将底层驱动做个API以供功能模块调用。(各个功能模块可以独立编译(如通信模块纯ANSI C,可在任意平台复用),或者调用驱动层接口(日志库模块调用了驱动读写Flash),总而言之,言而总之,封装出各个功能独立的可复用的功能模块。)

2、API分为驱动层API和应用层API,而不是所有程序都调用驱动层API。(整个应用中都调用驱动层API会导致应用中驱动调用随处可见,无法移植和最大限度的复用)

 

总体分 硬件驱动层-->功能模块层-->业务逻辑层-->应用层

总体结构示意框图:

说明:

1.层与层之间不能跨层调用。

2.模块与模块各自独立,无依赖关系。

3.模块提供统一的接口供上层调用,模块的内外接口分明。

4.模块的功能只能增,不能改。

5.各个功能模块层也还可以进行继续分层,比如接口层、驱动层、硬件层。

 

(3)模块层次说明

硬件驱动层

硬件驱动层包含板载硬件资源正常运行所需的所有驱动程序并提供API给功能模块调用。

功能模块层

功能模块层包括实现具体功能的函数,通过调用驱动层API实现相应功能,同时提供可调用的API给业务逻辑层。

业务逻辑层

业务逻辑层包括产品整体功能的各个业务流程,通过调用功能模块层的API实现。

应用层

应用层将各个业务逻辑进行整合调用,完成整个产品的功能。

 

(4)优势

如果驱动变动了,或者换不同平台,只需更改驱动层,应用层不受影响。

如果功能模块变动了,只需升级相应的功能模块,其他的模块不受影响,应用层也不受影响。

按照这种逻辑设计好之后,主要的工作就是在业务逻辑层。应用层则为程序的总体流程和框架,主要调用业务逻辑层实现不同的功能。
--------------------- 
作者:dwx1005526886 
来源:CSDN 
原文:https://blog.csdn.net/dwx1005526886/article/details/80877338 
版权声明:本文为博主原创文章,转载请附上博文链接!

《ARM嵌入式系统软件开发实例(一) 周立功 北京航天航空大学出版社》(PDF) 目录第1章 ZLG/FS原理与应用 1.1 概述 1.1.1 ZLG/FS简介 1.1.2 ZLG/FS的特点 1.1.3 已实现的特性 1.1.4 暂时未实现的特性 1.2 使用 1.2.1 使用示例 1.2.2 Config.h和fat.h 1.2.3 与编译器无关的数据类型 1.2.4 初始化ZLG/FS 1.2.5 目录相关操作 1.2.6 文件相关操作 1.2.7 关闭ZLG/FS 1.2.8 在多任务环境下使用ZLG/FS 1.3 ZLG/FS的结构视图 1.3.1 概述 1.3.2 应用程序 1.3.3 文件管理与目录管理 1.3.4 文件分配表管理与文件目录表管理 1.3.5 逻辑盘管理模块 1.3.6 高速缓存管理模块 1.3.7 底层驱动程序 1.3.8 实用程序 1.3.9 源代码文件说明 1.4 驱动程序设计指南 1.4.1 一个驱动程序的例子 1.4.2 参数 1.4.3 逻辑盘初始化 1.4.4 卸载逻辑盘 1.4.5 读/写扇区 1.5 FAT文件系统基础知识 1.5.1 简介 1.5.2 本节的约定 1.5.3 概述(适用于各类型的FAT文件系统) 1.5.4 引导扇区和BPB 1.5.5 FAT数据结构 1.5.6 FAT类型的确定 1.5.7 FAT卷的初始化 1.5.8 FAT32 FSInfo扇区结构和备份引导扇区 1.5.9 FAT的目录结构(FDT表) 1.5.10 FAT的长目录项 1.5.11 命名限制和字符集 1.5.12 短文件名和长文件名的名字映射 1.5.13 命名惯例和长文件名 1.5.14 长目录项对旧版FAT的影响 1.5.15 验证目录的内容 1.5.16 与FAT目录项相关的其他注意事项 1.6 逻辑盘信息管理 1.6.1 用户接口函数 1.6.2 内部使用函数 1.6.3 逻辑盘和卷的区别 1.6.4 逻辑盘信息登录项 1.6.5 初始化 1.6.6 加载底层驱动程序 1.6.7 卸载底层驱动程序 1.6.8 获取逻辑盘信息 1.6.9 获取空闲登录项 1.7 Cache管理 1.7.1 用户接口函数 1.7.2 内部使用函数 1.7.3 原理 1.7.4 初始化 1.7.5 通过Cache读/写逻辑扇区 1.7.6 把Cache数据写回逻辑盘 1.8 文件分配表管理 1.8.1 FAT简介 1.8.2 接口函数 1.8.3 获取簇的下一个簇号 1.8.4 设置下一个簇号 1.8.5 为簇链增加一个簇 1.8.6 删除一个簇链 1.9 文件目录表管理 1.9.1 FDT简介 1.9.2 用户接口函数 1.9.3 内部接口函数 1.9.4 数据结构 1.9.5 读取FDT信息 1.9.6 保存FDT信息 1.9.7 获取指定目录指定FDT信息 1.9.8 设置指定目录指定FDT信息 1.9.9 在指定目录查找指定FDT 1.9.10 指定目录查增加FDT 1.9.11 在指定目录删除指定FDT 1.9.12 改变指定目录指定FDT属性 1.9.13 察看指定目录是否为空 1.9.14 在指定目录查看指定FDT是否存在 1.10 目录操作 1.10.1 用户接口函数 1.10.2 内部接口函数 1.10.3 获取指定目录的逻辑盘号 1.10.4 改变当前逻辑盘 1.10.5 建立目录 1.10.6 删除目录 1.10.7 改变当前目录 1.10.8 用户文件/目录名转换为系统名 1.10.9 获取指定文件/目录所在的目录的开始簇号及系统内名称 1.10.10 获取指定目录开始簇号 1.11 文件操作 1.11.1 用户接口函数 1.11.2 数据结构 1.11.3 初始化 1.11.4 删除文件 1.11.5 打开文件 1.11.6 查看指定的文件是否处于打开状态 1.11.7 关闭文件 1.11.8 从文件中读数据 1.11.9 把数据写入文件 1.11.10 判断文件是否读/写到文件尾 1.11.11 移动文件读/写位置 1.12 实用程序 第2章 USB驱动程序开发 2.1 USB1.1协议简介 2.1.1 USB系统构成 2.1.2 USB设备的枚举过程 2.1.3 USB的分组标识 2.1.4 USB标准设备请求 2.1.5 USB设备描述符 2.2 PDIUSBD12器件简介 2.3 硬件电路设计 2.4 软件设计总体思想 2.5 USB设备控制层 2.6 USB接口控制驱动 2.7 应用层 2.7.1 初始化PDIUSBD12 2.7.2 控制传输处理 2.7.3 端点1和端点2数据接收与发送设计思想 2.7.4 从端点接收数据 2.7.5 往端点发送数据 2.8
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值