嵌入式操作系统FreeRTOS
FreeRTOS是一个专门为轻量级嵌入式应用设计的迷你操作系统,它的主要功能由IPC、时钟管理、内存管理、任务通知以及任务调度等部分构成。
FreeRTOS的代码可以分解为三个主要区块:任务调度、通讯、硬件库。
- 任务调度:FreeRTOS用任务控制块(Task Control Block,TCB)以及双向链表来维护任务队列,同优先级通过TCB句柄移动完成时间片轮转,用可剥夺式多任务内核保证高优先级任务的优先运行。
- 通信:任务很重要,不过任务间可以互相通讯则更为重要。FreeRTOS使用消息队列来完成进程通讯。
- 硬件接口:基础的FreeRTOS核心只有接近9000行代码,是与硬件无关的,不论FreeRTOS是运行在ARM的芯片还是Intel芯片上,都能够保证运行的逻辑正确。
进程通信IPC
在内核较大的操作系统中,例如Windows和Linux中,作为系统资源分配的最小单元,进程在进行资源分配的过程中需要达到同步。
因此,操作系统作为进程的调度管理系统,需要为进程间提供通信手段以达到进程同步的目的。
在嵌入式实时操作系统RTOS中,出于通过裁剪内核以达到精简目的的考核,通常采用一种或少数几种方式完成进程通信机制。
FreeRTOS中采用了信号量、消息队列和事件组来完成进程通信,事件组用来对需要多资源同步的任务进行标记管理。
信号量
二值信号量、计数信号量、互斥信号量、递归互斥信号量,用来控制多任务对同一资源的访问。
消息队列
任务或中断服务子程序可以将一个消息放入到队列。同样,任务可以从队列中得到消息。
支持FIFO和LIFO两种数据存取方式。
事件组
事件组被用来记录事件状态。当消息被传递完毕,该事件位标记为1,当队列中没有消息需要传递,该事件位标记为0。
事件标志组中所有事件位都存储在一个无符号的EventBits_t类型的变量中,对于STM32来说,一个事件标志组最多可以存储24个事件位。
内存管理
FreeRTOS使用C语言标准库实现,如果系统中的对象是动态创建的,则有时可以使用标准库中的malloc()和free()函数实现内存分配。但因为平台的差异性和mallocz()自身的特性,通过标准库进行内存分配存在以下问题:
- 兼容性,并不总是在系统中可用。
- 安全性,标准库的分配算法不是线程安全的。
- 确定性,执行性能根据执行条件不同具有差异。
由于不同芯片的时序和内存架构并不总是相同的,因此,标准库中的分配算法并不能适用于所有驱动及应用。
为了解决这个问题,FreeRTOS将内存分配封装成五个管理方案,几乎可以覆盖所有内存使用情况,并且这些方案是可以根据具体需求进行移植,具有更高的灵活性和适用性。
NB-IoT关键技术
本文基于环境监测项目进行终端设备的软件功能设计,因此,除OTA模块之外的环境监测功能所需传输数据仅包含环境参数和部分“读”、“写”、“执行”的控制参数,数据量小,并且环境监测所需的覆盖面积对终端设备的数量有一定要求,结合上述项目需求,本文选择NB-IoT技术作为终端的底层通信技术。
NB-IoT是一种用于蜂窝通信的物联网(IoT)技术,聚焦大连接、广覆盖、低功耗和低成本,因此,在某些方面,NB-IoT相较于3G、4G等通信网络提供更好的性能。
- 覆盖广,相比传统GSM,一个基站可以提供10倍的面积覆盖。将面积覆盖范围增加到1千米,以及对于具有弱信号的区域更好的室内和室外覆盖。
- 海量连接。2000KHz的频率可以提供10万个连接。
- 低功耗。NB-IoT具有两种省电模式,其特点是不连续接受和睡眠工作,再加上NB-IoT不提供任何的Qos,因此,NB-IoT设备通常具有超长的工作时长。
- 低成本。由于是选取授权频段上的蜂窝网络,NB-IoT无须重新建网,射频和天线等硬件设备也能复用。再加上NB-IoT的低功耗、低带宽、低速率的特性,芯片和模组的制作难度和成本都大幅下降。
DRX模式保证设备在非必要状态进入睡眠状态,否则设备即使在完全无须进行通信的状态下也需要时时刻刻对数据传送源进行监听,这产生了相当大的能源浪费。
而DRX模式只在需要的时候,终端从睡眠状态中唤醒进入wake up state 后才监听网络,以达到省电的目的,eDRX即扩展DRX周期,将周期睡眠时间延长,以达到更加省电的效果。
PSM,即省电模式,由于物联网中有些设备几乎是处于长期无上下行数据的状态,因此设计出PSM模式设定休眠周期,在该模式下几乎与网络失联。
OTA的关键技术分析
为了使设备拥有远程更新功能,本文在架构设计之初,将OTA功能设计放进了软件功能框架。
在OTA升级中,根据OTA依靠整包或增量文件进行升级的方式被分为整包升级(Full OTA)和差分升级。
- 整包升级的优势在于可以忽略任何用户在终端设备上的修改,即使设备是完全“砖头”的状态,都可以进行恢复和更新。
- 但整包传输的传输量是整个固件版本的大小。
- 差分升级的优势在于传输量很小,仅传输更新版本与原版固件之间的差别描述,使得传输量达到极大减小。
字节差分技术
差分算法的基本原则是经过一些操作使旧版本能直接省纪委新版本,这些操作是针对软件程序字节流进行的,包括添加操作,删除操作,变更操作和复制操作。
基于编辑距离
编辑距离是新旧版本文件替换所需要的最小操作数。
差分文件主要由新旧版本文件的差异描述信息组成。
差分文件的四个部分:
- 操作信息(Operation):添加操作I(Insertion),删除操作D(Deletion),变更操作R(Repacement)和复制操作M(Match),每个操作占用1字节空间。
- 地址偏移大小(Offset):新旧版本相似片段所有的地址偏移量。
- 附加数据信息(Extra):对操作信息进行补充说明,例如操作信息的长度。
- 数据区(Data):无法通过操作描述还原出的数据被追加卸载文件尾部形成额外数据区。
T(mn) = O(mn) + T(mn/2)
基于LCS问题
除此之外,在因特网中经常被使用作为差分文件生成的算法还有Bsdiff、Xdelta等,其中又以Bsdiff的应用最为广泛,Bsdiff最初用于Unix系统,现代软件(例如Google Chrome浏览器)也使用此算法来减少升级包的大小,但与编辑距离的算法不同,Bsdiff是基于后缀子串的最长公共子序列(longest common sequence, LCS)问题的一种差分算法。
最长公共子序列问题是指寻找两个字符串中相匹配的最长顺序子串。子串并不要求相邻,但公共部分必须在原序列中保持相同顺序。
LCS问题可以被分解成最小子问题。
因此,LCS问题的最优解可利用子问题的最优解来构建。基于这样的思路,LCS问题是典型的动态规划问题。
假设存在序列A,序列B,其中元素分别为ai和bj。
A = {a1,a2,…,an}
B = {b1,b2,…,bm}
序列A,B组成dp矩阵C,该问题的递推公式为:
通过LCS问题的求解,能够对比文件之间的相似度,对不同字符序列中的相似子序列进行选取,从而进行对应的差分处理。
压缩编码技术
通常,在差分更新中,新旧版文件在进行差分后会将生成的差分文件进行压缩,以进一步减小固件包。
例如,在文件压缩领域,最为熟知并广泛运用在互联网中的LZ族算法,在改论文中描述了一种基于字典结构的编码算法。
严格来说,LZ77本身并不能称作算法,与Huffman编码相似,只定义了编码方式,而没有严格定义如何实现这样的编码方式或者在什么样的场景下实现。
还有基于文件预处理的压缩算法,例如bzip2算法,对文件进行预处理,使得文件相同字符集中,提高数据内容的局部相关性,以达到更高的压缩率。同时,在文件解压缩后,可以通过相应算法的逆变换对打乱的序列进行还原。
总的来说,差分算法包括文件差分的压缩两个过程,压缩通常可以基于文件的差分形式进行相应的选择,以达到最好的性能。