嵌入式软件开发常用的三种架构你知道吗?

嵌入式软件开发常用的三种架构你知道吗?,第1张

摘要 :对于单片机程序来说,大家都不陌生,但是真正使用架构,考虑架构的恐怕并不多,随着程序开发的不断增多,架构是非常必要的。

应用程序的架构大致有三种:

1、 简单的前后台顺序执行程序 ,这类写法是大多数人使用的方法,不需用思考程序的具体架构,直接通过执行顺序编写应用程序即可。

2、 时间片轮询法 ,此方法是介于顺序执行与 *** 作系统之间的一种方法。

3、 *** 作系统 ,此法应该是应用程序编写的最高境界。

1、前后台顺序执行法

这是初学者们常用的程序框架设计方案,不用考虑太多东西,代码简单,或者对系统的整体实时性和并发性要求不高;初始化后通过 while(1){} 或 for() {}`循环不断调用自己编写完成的函数,也基本不考虑每个函数执行所需要的时间,大部分情况下函数中或多或少都存在毫秒级别的延时等待。

以下是在校期间做的寝室防盗系统的部分代码(当时也存在部分BUG,没有解决。现在再看,其实很多问题,而且比较严重,比如中断服务函数内竟然有3000ms延时,这太可怕了,还有串口发送等等;由于实时性要求不算太高,因此主函数中的毫秒级别延时对系统运行没有多大影响,当然除BUG外;若是后期需要维护,那就是一个大工程,还不如推翻重写 ):

介于 前后台顺序执行法 *** 作系统 之间的一种程序架构设计方案。该设计方案需能帮助嵌入式软件开发者更上一层楼,在嵌入式软件开发过程中,若遇到以下几点,那么该设计方案可以说是最优选择,适用于程序较复杂的嵌入式系统;

该设计方案需要使用一个定时器,一般情况下定时1ms即可(定时时间可随意定,但中断过于频繁效率就低,中断太长,实时性差),因此需要考虑到每个任务函数的执行时间,建议不能超过1ms(能通过程序优化缩短执行时间则最好优化,如果不能优化的,则必须保证该任务的执行周期必须远大于任务所执行的耗时时间),同时要求主循环或任务函数中不能存在毫秒级别的延时。

以下介绍两种不同的实现方案,分别针对无函数指针概念的朋友和想进一步学习的朋友。

1、无函数指针的设计方式

2、含函数指针的设计方式

嵌入式 *** 作系统EOS( Embedded OperatingSystem )是一种用途广泛的系统软件,过去它主要应用于工业控制和国防系统领域,而对于单片机来说,比较常用的有UCOS、FreeRTOS、 RT-ThreadNano和RTX 等多种抢占式 *** 作系统(其他如Linux等 *** 作系统不适用于单片机)

*** 作系统和“ 时间片论法 ”,在任务执行方面来说, *** 作系统对每个任务的耗时没有过多的要求,需要通过设置每个任务的优先级,在高优先级的任务就绪时,会抢占低优先级的任务; *** 作系统相对复杂,因此这里没有详细介绍了。

关于如何选择合适的 *** 作系统( uCOS 、 FreeRTOS 、 RTThread 、 RTX 等RTOS的对比之特点:

借网上一张对比图:

从上述的对比中可以看出,时间片轮询法的优势还是比较大的,它既有前后台顺序执行法的优点,也有 *** 作系统的优点。结构清晰,简单,非常容易理解,所以这种是比较常用的单片机设计框架。

u C / O S 是一种免费公开源代码、结构小巧、具有可剥夺实时内核的实时 *** 作系统。\x0d\x0a\x0d\x0aμC/OS-II 的前身是μC/OS,最早出自于1992 年美国嵌入式系统专家Jean J.Labrosse 在《嵌入式系统编程》杂志的5 月和6 月刊上刊登的文章连载,并把μC/OS 的源码发布在该杂志的B B S 上。\x0d\x0a\x0d\x0aμC/OS 和μC/OS-II 是专门为计算机的嵌入式应用设计的,绝大部分代码是用C语言编写的。CPU 硬件相关部分是用汇编语言编写的、总量约200行的汇编语言部分被压缩到最低限度,为的是便于移植到任何一种其它的CPU 上。用户只要有标准的ANSI 的C交叉编译器,有汇编器、连接器等软件工具,就可以将μC/OS-II嵌人到开发的产品中。μC/OS-II 具有执行效率高、占用空间小、实时性能优良和可扩展性强等特点, 最小内核可编译至 2KB 。μC/OS-II 已经移植到了几乎所有知名的CPU 上。\x0d\x0a\x0d\x0a严格地说uC/OS-II只是一个实时 *** 作系统内核,它仅仅包含了任务调度,任务管理,时间管理,内存管理和任务间的通信和同步等基本功能。没有提供输入输出管理,文件系统,网络等额外的服务。但由于uC/OS-II良好的可扩展性和源码开放,这些非必须的功能完全可以由用户自己根据需要分别实现。\x0d\x0a\x0d\x0auC/OS-II目标是实现一个基于优先级调度的抢占式的实时内核,并在这个内核之上提供最基本的系统服务,如信号量,邮箱,消息队列,内存管理,中断管理等。\x0d\x0a\x0d\x0a任务管理\x0d\x0a\x0d\x0auC/OS-II 中最多可以支持64 个任务,分别对应优先级0~63,其中0 为最高优先级。63为最低级,系统保留了4个最高优先级的任务和4个最低优先级的任务,所有用户可以使用的任务数有56个。\x0d\x0a\x0d\x0auC/OS-II提供了任务管理的各种函数调用,包括创建任务,删除任务,改变任务的优先级,任务挂起和恢复等。\x0d\x0a\x0d\x0a系统初始化时会自动产生两个任务:一个是空闲任务,它的优先级最低,改任务仅给一个整形变量做累加运算;另一个是系统任务,它的优先级为次低,改任务负责统计当前cpu的利用率。\x0d\x0a\x0d\x0a时间管理\x0d\x0a\x0d\x0auC/OS-II的时间管理是通过定时中断来实现的,该定时中断一般为10毫秒或100毫秒发生一次,时间频率取决于用户对硬件系统的定时器编程来实现。中断发生的时间间隔是固定不变的,该中断也成为一个时钟节拍。\x0d\x0a\x0d\x0auC/OS-II要求用户在定时中断的服务程序中,调用系统提供的与时钟节拍相关的系统函数,例如中断级的任务切换函数,系统时间函数。\x0d\x0a\x0d\x0a内存管理\x0d\x0a\x0d\x0a在ANSI C中是使用malloc和free两个函数来动态分配和释放内存。但在嵌入式实时系统中,多次这样的错作会导致内存碎片,且由于内存管理算法的原因,malloc和free的执行时间也是不确定。\x0d\x0a\x0d\x0auC/OS-II中把连续的大快内存按分区管理。每个分区中包含整数个大小相同的内存块,但不同分区之间的内存快大小可以不同。用户需要动态分配内存时,系统选择一个适当的分区,按块来分配内存。释放内存时将该块放回它以前所属的分区,这样能有效解决碎片问题,同时执行时间也是固定的。\x0d\x0a\x0d\x0a任务间通信与同步\x0d\x0a\x0d\x0a对一个多任务的 *** 作系统来说,任务间的通信和同步是必不可少的。uC/OS-II中提供了4中同步对象,分别是信号量,邮箱,消息队列和事件。所有这些同步对象都有创建,等待,发送,查询的接口用于实现进程间的通信和同步。\x0d\x0a\x0d\x0a任务调度\x0d\x0a\x0d\x0auC/OS-II 采用的是可剥夺型实时多任务内核。可剥夺型的实时内核在任何时候都运行就绪了的最高优先级的任务。\x0d\x0a\x0d\x0auC/os-II的任务调度是完全基于任务优先级的抢占式调度,也就是最高优先级的任务一旦处于就绪状态,则立即抢占正在运行的低优先级任务的处理器资源。为了简化系统设计,uC/OS-II规定所有任务的优先级不同,因为任务的优先级也同时唯一标志了该任务本身。\x0d\x0a\x0d\x0a任务调度将在以下情况下发生:\x0d\x0a\x0d\x0a1) 高优先级的任务因为需要某种临界资源,主动请求挂起,让出处理器,此时将调度就绪状态的低优先级任务获得执行,这种调度也称为任务级的上下文切换。\x0d\x0a\x0d\x0a2) 高优先级的任务因为时钟节拍到来,在时钟中断的处理程序中,内核发现高优先级任务获得了执行条件(如休眠的时钟到时),则在中断态直接切换到高优先级任务执行。这种调度也称为中断级的上下文切换。\x0d\x0a\x0d\x0a这两种调度方式在uC/OS-II的执行过程中非常普遍,一般来说前者发生在系统服务中,后者发生在时钟中断的服务程序中。\x0d\x0a\x0d\x0a调度工作的内容可以分为两部分:最高优先级任务的寻找和任务切换。其最高优先级任务的寻找是通过建立就绪任务表来实现的。u C / O S 中的每一个任务都有独立的堆栈空间,并有一个称为任务控制块TCB(Task Control Block)的数据结构,其中第一个成员变量就是保存的任务堆栈指针。任务调度模块首先用变量OSTCBHighRdy 记录当前最高级就绪任务的TCB 地址,然后调用OS_TASK_SW()函数来进行任务切换。\x0d\x0a\x0d\x0aμC/OS-II的组成部分\x0d\x0a\x0d\x0aμC/OS-II可以大致分成核心、任务处理、时间处理、任务同步与通信,CPU的移植等5个部分。\x0d\x0a\x0d\x0a1) 核心部分(OSCore.c)\x0d\x0a\x0d\x0a是 *** 作系统的处理核心,包括 *** 作系统初始化、 *** 作系统运行、中断进出的前导、时钟节拍、任务调度、事件处理等多部分。能够维持系统基本工作的部分都在这里。\x0d\x0a\x0d\x0a2) 任务处理部分(OSTask.c)\x0d\x0a\x0d\x0a任务处理部分中的内容都是与任务的 *** 作密切相关的。包括任务的建立、删除、挂起、恢复等等。因为μC/OS-II是以任务为基本单位调度的,所以这部分内容也相当重要。\x0d\x0a\x0d\x0a3) 时钟部分(OSTime.c)\x0d\x0a\x0d\x0aμC/OS-II中的最小时钟单位是timetick(时钟节拍)。任务延时等 *** 作是在这里完成的。\x0d\x0a\x0d\x0a4) 任务同步和通信部分\x0d\x0a\x0d\x0a为事件处理部分,包括信号量、邮箱、邮箱队列、事件标志等部分;主要用于任务间的互相联系和对临界资源的访问。\x0d\x0a\x0d\x0a5) 与CPU的接口部分\x0d\x0a\x0d\x0a是指μC/OS-II针对所使用的CPU的移植部分。由于μC/OS-II是一个通用性的 *** 作系统,所以对于关键问题上的实现,还是需要根据具体CPU的具体内容和要求作相应的移植。这部分内容由于牵涉到SP等系统指针,所以通常用汇编语言编写。主要包括中断级任务切换的底层实现、任务级任务切换的底层实现、时钟节拍的产生和处理、中断的相关处理部分等内容。

ucos-ii是一个可剥夺型内核的实时 *** 作系统,以stm32来说,使用系统滴答定时器,定时产生一个时钟节拍,来推动任务的调度,管理,切换等。

关于系统大概的运行原理

2.当产生一个时钟节拍时,如果有比当前运行任务优先级更高的任务就绪,那么优先级(“优先级”为0时优先级最高)高的任务抢占CPU,CPU保存现场环境,放入该任务堆栈中。再将优先级高的任务的堆栈中的现场环境取出来,写入CPU寄存器中。(CPU中的寄存器暂时还没有仔细去研究)。当这个任务执行进入延时,或是要等待某个时间或者信号量。那么它将放弃CPU的使用权,系统会从任务就绪表中,把优先级最高的且就绪状态的任务赋予CPU的使用权。至此来推动整个系统,调度所有的任务。

不发生中断时UCOS系统时间与任务的切换

①.假设当前运行的任务是低优先级的任务,CPU程序寄存器中存在的一些寄存器都是低优先级的任务

②当程序运行到检测到高优先级的任务进入就绪状态的时候,此时CPU发送一些命令,把CPU当前的一些程序寄存器的内容复制到低优先级任务的堆栈中。也就是1过程。

③.此时通过刚刚的就绪表的机制,可以从程序中得到最高优先级的任务,也就是2过程=

④.最后的过程3就是把刚刚的高优先级任务的堆栈指针复制到CPU的程序寄存器当中,实现任务的切换。

当有中断时,UCOS系统的执行原理

当程序正在执行一个中断服务函数时,发生一个系统滴答中断,因为系统滴答定时器的优先级高,所以会中断这个中断服务函数执行任务切换。而有些时候,中断时不能延时的。例如接收数据时,会发生接收错误。造成严重的后果。

这时,就有下图中的 *** 作,可以避免。

PendSV异常(我称它为中断)编程为最低的优先级中断。如果某个中断正在执行,而系统滴答抢占了它,那么这个中断将悬起一个PendSV中断,来缓期执行任务切换。

UCOS的任务切换时间可以在os_cfg.h中去设置OS_TICKS_PER_SEC宏UCOS任务数等配置也可以在该文件中去寻找。

UCOS-II主要提供服务

内存管理

多任务管理

外围资源管理

关于Make 与编译

书中有讲这一块,所以我也记录下我的理解

由于我平时都用keil这样的集成开发环境,之前也有学习过一段时间的linux,但是对编译,makefile这些理解的还是不是很好。

编辑makefile 来将源文件和包含的头文件编译成需要的.obj文件,然后再将这些.obj文件链接成,想要生成的程序。关于makefile好像每一种编译器都有自己的makefile规则和命令,因为以前学习GCC编译器和现在书上看到的BCC编译器写的makefile好像不太一样。我也没有去深究。

所以还是集成开发环境好,工具还是怎么方便怎么来。需要学习的原理的时候再去理解,实际的应用中用自己写的Makefile去编译文件怕是石乐志哦。

UCOS的任务

任务三要素(我理解的)

任务控制块

OSTaskCreate((void()(void))start_task,

//任务函数

(void*)0,

//传递给任务函数的参数

(OS_STK*)&START_TASK_STK[START_STK_SIZE-1],

//任务堆栈的栈顶

(INT8U)START_TASK_PRIO,

//任务的优先级

主要包含了任务的栈顶地址,

如果处理器的堆栈是高地址向下生长的那么栈顶地址


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/11237165.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-14
下一篇 2023-05-14

发表评论

登录后才能评论

评论列表(0条)

保存