嵌入式软件架构划分
Posted WangLanguager
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了嵌入式软件架构划分相关的知识,希望对你有一定的参考价值。
1、模块划分
(1)模块划分的“划”是规划的意思,意指怎样合理的将一个很大的软件划分为一系列功能独立的部分,合作完成系统的需求。
(2)C语言作为一种结构化的程序设计语言,在模块的划分上主要依据功能来进行划分。
2、模块划分的方法
(1)模块即是一个.C文件,或者是一个.h文件的接合,头文件(.h)中是对该模块接口的声明。
(2)某模块提供给其他模块调用的外部函数及数据需要在.h文件中冠以extern关键字声明。
(3)仅在模块内部使用的函数和局部变量需要在.C文件中冠以static声明。
(4)永远不要在.h文件中定义变量:定义变量和声明变量的区别在于定义变量会产生内存分配的操作。
在.h文件中定义了变量,其他.C文件引用了该头文件,会使得各个.C文件都将该变量默认为本地变量,使得该变量无法起到全局共享的作用。
一个不好的例子:
/*module1.h*/
int a = 5 ; //在模块1的文件.h文件中定义了int a
/*module1.c*/
#include "module1.h" //在模块1的文件.c文件中包含了模块1的.h文件
/*module2.c*/
#include "module1.h" //在模块2的文件.c文件中包含了模块1的.h文件
/*module3.c*/
#include "module1.h" //在模块3的文件.c文件中包含了模块1的.h文件
一个好的例子:
/*module1.h*/
extern int a; //在模块1的文件.h文件中只是声明了int a
/*module1.c*/
#include "module1.h" //在模块1的文件.c文件中包含了模块1的.h文件
int a = 5; //在模块1的文件.c文件中定义了int a
/*module2.c*/
#include "module1.h" //在模块2的文件.c文件中包含了模块1的.h文件
/*module3.c*/
#include "module1.h" //在模块3的文件.c文件中包含了模块1的.h文件
3、模块的类型
(1)硬件驱动模块:一种特定的硬件对应一个模块
(2)软件功能模块:其模块的划分应满足低耦合、高内聚的要求,一个功能对应一个模块。
4、任务模式:
(1)单任务:微观串行、宏观串行
(2)多任务:微观串行、宏观并行
串行:每一个时刻只运行一个任务。
并行:一个时间段你运行了多个任务。
5、单任务典型架构
(1)从CPU复位时的指定地址开始执行
(2)跳转至汇编代码startup处开始执行、部分初始化操作。
(3)跳转至用户主程序main处执行,在main函数中完成:
①初始化部分硬件设备
②初始化各软件模块
③进入死循环(无限循环),调用各模块的处理函数。
死循环的程序写法:
while(1)
//null
或者写成:
for(;;)
//null
6、中断服务程序
(1)中断是嵌入式系统的重要组成部分,但是在标准C语言中不包含中断,许多编译器开发商在标准C上增加了对中断的支持,提供新的关键字用于标识中断服务程序(ISR),
例如:_ _interrupt
(2)当一个函数被定义为中断函数(ISR)的时候,编译器会自动为该函数增加中断服务程序所需要的中断现场入栈和出栈代码。
7、中断服务程序的特点:
中断服务程序需要满足如下需求:
(1)不能返回值
(2)不能向中断函数(ISR)传递参数
(3)ISR程序应该尽可能的短小精悍;否则会影响程序的性能
(4)printf(char *IpFormatString, ...)函数会带来性能问题,不能在ISR函数中使用,因为变参函数的执行时间比较长。
8、中断服务程序模型
在项目开发中,设计一个队列,在中断服务程序中,只是将中断类型添加进该队列中,在主程序的无限循环中不断扫描中断队列是否有中断产生,有则取出队列中的第一个中断类型,进行相应的处理。
typedef struct tagIntQueue //存放中断的队列
int intType; //中断类型
struct tagIntQueue *next; //队列指针
IntQueue;
IntQueue* IpIntQueueHead;
_ _interrupt ISRexample()
int intType; //中断类型
intType = GetSystemType(); //获取中断类型
QueueAddTail(IpIntQueueHead, intType), //在队列尾中加入新的中断
9、主程序模型
while(1)
if(!IsIntQueueEmpty())
intType = GetFirstInt();
switch(intType)
case xxx: //中断处理函数
....
break;
case xxx:
....
break;
第8期:嵌入式C语言的模块化编程发布
从码农,到软件工程师,再到架构师,是每个工程师的进阶之路,嵌入式工程师也是如此。很多初级工程师,让他实现一个模块,完成一定功能的编程实现,是没有问题的。但是如果你想让他负责整个项目的规划、任务划分可能就比较吃力了。
本期课程,将会带领大家,从C语言的模块化编程思想出发,从零开始,一步一步去分析一个MP3播放器模拟项目,对一个嵌入式软件项目进行需求分析和模块划分、以及对一个模块进行封装和实现。
在实现一个模块封装的过程中,将会对大型项目中经常遇见的各种疑难杂症进行深入分析和探讨:如隐式声明、前向引用、头文件路径、头文件之间的依赖关系及头文件包含顺序等。
接着会继续学习模块的设计原则:高内聚低耦合,以及模块间的通信方式:着重分析回调函数在系统模块之间通信的巧妙运用,以及常用的中断、消息等模块间的异步通信方式。
最后,跟大家一起,对我们的MP3项目软件架构继续重构优化:进行跨平台设计,以及通过不断完善,迭代出一个软件框架的基本流程。
通过本期课程的学习,对于很多初级工程师来说,将会彻底掌握C语言模块化编程的精髓:学会系统分析、系统模块划分的基本方法;掌握系统模块实现过程中经常注意的各种问题;理解系统间通信的各种方式及优劣;对跨平台设计、系统架构、框架的概念有一个更直观的理解,从而具备一个初级架构师的思维和能力。
本期课程中,讲到的相关方法和技术,可以直接应用到以后的开发实战中。
以上是关于嵌入式软件架构划分的主要内容,如果未能解决你的问题,请参考以下文章