嵌入式软件开发与设计基础

1 概述

嵌入式软件主要分为单机软件与带嵌入式操作系统的软件两大类。其中,单机软件又称为裸核软件,裸核软件在实现业务应用的同时需要进行任务调度管理、内存管理与硬件设备管理等。随着嵌入式软件发展,出现实时嵌入式操作系统,将与业务应用无关的任务调度、内存管理及硬件管理管理功能进行抽象,降低嵌入式应用软件的开发难度。下面对嵌入式操作系统与嵌入式软件特点进行简要介绍。

不同于通用操作系统,嵌入式实时操作系统处理过程有严格的时间要求,处理速度必须及时快速,主要用于工业控制;而通用的操作系统大多属于分时操作系统,对处理速度无严格要求,大多用于人机交互场景。

嵌入式应用软件与一般应用程序的区别主要在于控制对象,嵌入式软件的核心控制对象为硬件设备,主要任务是实现设备动作执行或者设备状态采集,需要的硬件资源包括CPU资源、存储资源与硬件设备资源等;而大多桌面服务软件主要用于数据处理与计算,所需要的硬件资源主要为CPU资源与存储资源。

下面就以多任务设计与硬件驱动程序为基础,说明嵌入式应用软件的设计思想。

2 多任务设计

        在介绍多任务设计前,首先了解下嵌入式软件与一般应用软件不同点。一般应用软件的设计遵循日常生活的思考方式,通常按照一定的先后顺序去设计软件,例如先做什么、后做什么,大体是按照一条主线去设计软件功能。对于嵌入式软件,其设计目标为实现多个物理设备的交互控制,并且多个物理设备通常是同时工作运行,不存明显的先后顺序,因此,在软件设计初期时就需要考虑多任务并发设计,即多个任务同时管理多个设备运行控制。那么,嵌入式设备单个cpu处理器是如何实现多个任务同时运行的呢。这就涉及到实时操作系统的多任务调度原理了。

2.1 任务调度

        嵌入式操作系统通常基于调度算法实现多个任务调度运行,常用的调度算法为时间片轮转调度资源独占调度优先级抢占调度等

        间片轮转法的大体思路就是设置单个任务运行每次运行时间的基准值,然后多个任务按一定规则轮流运行,例如时间片设置为10ms,A任务与B任务运行,A任务运行10ms后,B任务运行10ms,接着A再运行10ms依次类推。该方法的关键是设置时间片的大小,如果时间片设置过小,则任务调度过于频繁,由于每次调度时均需要进行调度任务的上下文处理,容易影响系统性能;如果时间片设置过大,任务运行只使用很少的时间片时间,则其余时间存在CPU资源浪费的情况。

图片

        资源独占调度策略较简单,任务一旦获取CPU资源后则独占,直到其主动放弃CPU使用资源,其他任务才可获取CPU资源,例如任务A获取CPU资源,则任务B一直处于等待状态,等到任务A主动挂起或者结束时,任务B可使用CPU资源。该算法的缺点是,当一个任务运行时间较长时,其余任务需要等待较长时间,实时性得不到保证。

图片

优先级抢占调度算法通过设置任务不同的优先级实现,高优先级任务可随时打断低优先级任务,同时只有高优先任务不使用CPU资源时,低优先级任务才可获取CPU资源,例如有任务A、任务B、任务C三个优先级任务,任务A优先级最低,任务C优先级最高,则任务C可打断正在运行的任务A或者任务B,优先使用CPU资源,当其释放CPU资源时,其余两个任务才可获取CPU资源。该算法的缺点是,低优先级任务存在长时间未运行的风险。为了避免这种情况,一般不容许。

图片

综合上上述各调度算法的优缺点,嵌入式操作系统采用组合算法方式实现任务调度。最常使用的调度策略为组合使用时间片轮转调度算法与优先级抢占调度算法,这样的好处有即可以充分应用CPU资源,同时可以降低CPU调度的次数,保证系统的性能。

2.2 任务通信

      多个任务在调度运行时,不可避免地需要进行数据交互与通信。常用的方式是使用全局变量,即多个任务访问同一块内存地址数据,对数据进行读取修改操作,实现任务间的数据同步。按照任务之间的关系,数据的同步方式可以分为竞争同步有序同步两种。竞争同步指存在多个任务同时发出共享数据访问请求,由任务调度器的决定任务访问的先后顺序,访问的顺序具有随机性;有序同步指多个任务按照一定先后顺序访问共享数据,通常一个任务访问完共享数据后,通知后续任务访问,共享数据访问的顺序通常是固定的,由人为控制实现。

图片

        竞争同步适用多任务资源共享情况,例如两台电脑需要共用一台打印机,当两台电脑同时发起打印请求,一个时刻只允许执行一个电脑的打印任务,另一台电脑必须等候。有序同步主要适用于需要在短时间内处理的任务,即例如中断处理等,获取中断数据后将数据处理计算过程交由另一个任务实现,最终将数据获取与数据处理过程分离。

        嵌入式软件追求高实时性,任务之间通信采用更高效的信号量方式。信号量使用一个整数作为操作对象,通过对整数值进行原子性修改实现从而实现共享资源的保护操作。当多个任务访问共享资源时,通过关闭中断或者硬件原子指令实现只有一个任务可访问共享资源,其他任务进行阻塞等待,当任务完成对共享资源的操作时,开中断并释放信号量,则唤起其他任务获取信号量。

        常用的信号量包括二值信号量、互斥信号量与计数信号量。二值信号量是最简单与高效的信号量,具有0和1两个值;当信号量值为1时,任务可获取信号量;信号量为0时,表示当前信号量不可获取。二值信号量可用于任务竞争同步,也可用于任务有序同步情况。互斥信号量是一种特殊的二值信号量,对复杂的互斥操作进行了优化,只能用于任务竞争同步时的资源互斥访问。计数信号量与二值信号量类似,只不过信号量的值是0到n,同样可以用于n个资源竞争访问或者多个事件信号的有序处理,通常与链表或队列数据结构联合使用。

3 驱动工作特性

        硬件设备是嵌入式软件控制的核心对象,具体的控制则由驱动程序实现。驱动程序与底层硬件直接打交道,一方面接受软件指令并将其转换为硬件动作控制信号,一方面将硬件信息转换为软件所需的数据。作为软件与硬件的沟通桥梁,驱动程序涉及到硬件资源访问与数据通信方式的的控制。

3.1 硬件资源访问

        硬件资源访问通常指硬件寄存器或存储器资源访问,最简单粗暴方式则是驱动程序依据地址直接读取对应存储区域的数据内容。这种方式的缺点是在读取前无法保证地址是有效的,即该地址对应一个实际的存储单元,如读取一个空的地址或错误地址,可能导致CPU产生一个严重的错误,进入中断处理。为了避免无效存储器地址的访问,存储器地址映射必须通过一定方式映射后才可以使用。

        在无操作系统的情况下,驱动程序中使用的地址就是存储器的物理地址,其由存储器地址线的物理连接确定的,是固定不变的。所以,地址映射的任务就是确定实际安装的存储器的起始地址、结束地址、容量等,以便访问时加以注意。

        在具有存储器保护功能的操作系统情况下,驱动程序中使用的地址与存储器实际链接的地址存在差异,前者称为虚拟地址,后者称为物理地址。虚拟地址必须经过存储器控制器的转换,转换为物理地址才能对实际的存储单元进行访问。存储控制器通常是CPU内的MMU模块,地址映射任务就是确定虚拟地址到物理存储器的映射关系,同时具备虚拟地址访问权限的设定。

3.2 轮询与中断

      对驱动程序访问硬件资源的方式有了大致了解后,接着考虑驱动程序访问的目的。简单来说分为三类,一类是将控制信号发送硬件控制寄存器,实现硬件设备控制,一类是读写设备的数据区,实现设备数据交互;另一类则是获取设备状态数据,判断设备是否处于正常运状态。

        对于控制类信号或设置数据,通常由应用软件主动发送至硬件,在设备工作周期属于低频事件。对于设备状态与数据获取,则需要依据具体情况考虑,一种为应用软件固定周期轮询获取设备数据,从而判断设备状态是否正常;另一种则是当设备状态发生变化时,由硬件设备向应用程序发送中断信号,通知应用程序获取设备当前状态。

        那么这两种方式有什么差异呢。轮询方式通常采用定时器或者任务延时实现轮询周期设置,每一周期CPU都会访问获取一次设备数据,优点是可以获取设备状态数据的变化历程,监控设备状态,缺点是设备状态长时间未变化时,需要消耗CPU资源获取设备状态数据。中断方式,需要预先设置中断触发条件,当设备状态满足中断触发条件时,会立即上报应用软件,优点是设备状态变化时,通过中断信号可让CPU立即获取其变化状态,无需消耗资源定时轮巡查看处理,缺点是CPU收到中断信号后必须立即快速处理数据,否则会影响其他中断的接受。

        了解了轮询与中断特点后,两类方式适用于不同情况。轮询方式适用于变化规律平稳、对处理时限要求不高的设备状态数据,例如空调采集我的温度数据。中断方式则适用于突发的、实时处理要求较高的设备状态数据,例如烧水壶的温度监测处理。

3 应用软件设计

       对多任务设计与驱动程序工作特性有了一定认识后,考虑如何设计一个嵌入式应用程序。这里先给出总体的原则,纵向分层定架构、横向模块化定功能、任务划分定优先、数据流向定关联

      纵向分层定框架是依据物理实体的组成进行软件调用层级关系的设计。嵌入式软件设计包含业务应用、操作系统、驱动程序、硬件设备,从运行依赖与抽象程序,硬件设备属于最底层,其次驱动层规范硬件接口,往上是操作系统提供的驱动管理模块、任务调度模块,业务应用软件属于最顶层。层次关系一目了然,分层最终的目标是调用关系规范化,即任意一层只能被上一层调用,不容许跨层调用

      横向模块化主要实现业务功能的划分,主要剥离功能模块之间的耦合度,将业务集中的模块封装为独立的模块,功能模块划分适用于各个层内的功能划分。

       任务划分定优先主要实现任务合理的调度,依据任务特性主要分为中断任务、周期任务与事件驱动任务。中断任务主要处理设备中断事件,必须分配高优先级,特点是任务必须处理耗时短,否则影响调度。事件驱动任务主要适用处理具有较强随机性的数据,处理过程应较短,分配较高的优先级。周期任务则适用于循环重复数据处理过程,数据处理时限无特殊要求,可分配较低优先级。

       数据流向定关联主要实现多任务的数据交互,对于周期任务,通常采用全局变量与互斥信号量与硬件采集任务进行数据交互,事件驱动任务则通过队列、计数信号量与采集任务进行有序关联。

       下面的图则将分层、任务划分与数据流统一表达了。

图片

参考文章

[1] 张扬,于银涛.VxWorks内核、设备驱动与BSP开发详解(第2版)[M].北京.人民邮电初版社,2011.3[第10章-第17章]

[2] 王利涛.嵌入式C语言自我修养-从芯片、编译器到操作系统[M].中国工信初版社.2021.4[第18章-第10章]

[3]宋宝华.Linux设备驱动开发详解:基于最新的Linux4.0内核[M].机械工业出版社.2015.08[第1章、第6章]

[4]https://blog.csdn.net/weixin_42155195/article/details/80940611;

[5]温煜.嵌入式软件重构课程。

  • 22
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值