9901|15

1381

帖子

2

TA的资源

五彩晶圆(初级)

楼主
 

FreeRTOS学习笔记 (1)应用场景 [复制链接]

 
本帖最后由 cruelfox 于 2018-2-18 12:39 编辑

  去年NXP KW41大赛的时候被迫啃了一口FreeRTOS,我后来打算系统地学习一下它,再尝试应用到自己的DIY项目当中去。FreeRTOS只是众多的 RTOS (字面意思是实时操作系统)中的一种,因为用得广泛有是开源的,作为学习是个不错的选择。我大概地读过了它的文档,现在回头开始梳理,研究下部分的实现细节,一边写这个连载。

什么情况下可以用 FreeRTOS ?

  单片机也要用操作系统?如果以日常用的Windows, Linux, BSD这些,甚至是DOS,来代表操作系统的话,在单片机上运行操作系统时候个很荒诞的想法——因为对大多数单片机,RAM实在太少了。而 FreeRTOS 并不是要提供一个在单片机上运行软件的平台,把软件一个个安装到它上面,供用户选择运行什么,它没有用户界面;它不是一个管家,也不带任何硬件驱动程序,也没有文件系统服务提供。FreeRTOS只是一个操作系统内核,它首先提供了操作系统最重要的特性:任务调度。

  也就是说,有了FreeRTOS,在单片机上实现多任务会容易一些。这里至少有两层含义,一是多任务是否一定要用RTOS才可以实现? 当然不是。对于单片机开发来讲,所有系统资源都是你的,在不同中断服务里面处理不同的任务并不是很困难的事情。第二,是否没有多任务就完全用不着RTOS? 这也得看具体情况,如何界定“任务”的概念了,一件复杂的事情在程序中也有可能划分为几个任务来处理。

  还是举几个例子吧。

1. SD卡MP3音乐播放机
暂且不管用户操作界面,在播放状态下,从数据流上看播放机是这样工作的(作了一定简化):

   I2S接口DMA缓冲区空闲
   用剩余PCM数据填充缓冲区,请求解码下一块MP3数据
   请求读取MP3文件下一段内容
   定位SD卡上要读取扇区位置
   SDIO控制器读命令发送
   SDIO控制器接收数据完成中断
   填充文件数据缓冲区
   解码MP3数据,写PCM数据缓冲区
   填满I2S接口的DMA缓冲区

  这个过程涉及到四个关键的软件部分:

  若按自顶向下的软件设计思路,I2S设备驱动以固定的节拍被唤醒,进行缓冲区PCM数据填充,因此需要定期去调用MP3解码程序。MP3解码器则根据前面一段解码操作的结果来决定是否要访问文件系统(因为MP3解码一块数据产生的PCM音频数据的量并不能刚好是I2S设备驱动请求的大小),以及需要读取多少字节的MP3文件内容,还有解码出来暂时用不到的数据也要保存起来下次用。到了文件系统这里,请求读文件的位置和长度也未必是正好SD卡上的一个扇区,所以也有缓存,而且还需要跟踪文件在SD卡上的索引。SDIO设备驱动则按照文件系统的请求读取SD卡,等待操作完成以后返回,注意它和前面的模块不同的是,有一段什么事情也不干的硬件IO等待时间。
  一层层的嵌套调用关系如这样:

  注意,每一次的函数调用,都代表一个完整的操作:填充一块缓冲区、解码一段MP3数据、读取一段文件,以及读取SD卡一块数据。下层的子程序被调用,完成后返回上一层的程序中继续执行。在没有异常(中断)发生的情况下,程序是不会离开这个调用关系嵌套的。
  又需要注意到,上面几个列举的主要函数,虽然一次调用操作是完整的,但每次操作过后它的内部状态不一定相同。用C语言来说,就是这些函数需要有static型的局部变量,或者是自己用一些全局变量来记住上次调用后状态是怎样了。典型的就是文件系统 read_file() 这样的函数被调用后,它需要记住文件指针的位置,以便下次接着读。
  如上描述实现的音乐播放器实现有一个重要的缺点:在SD卡读操作的等待时间里,CPU的执行只能停留在SD卡访问函数中,不能用来进行MP3解码的运算操作,处理能力被浪费了。在I2S设备的缓冲区填满,到下一次需要再填充这段时间 ,CPU也是处于空闲状态。其实完全可以利用这两段空闲时间,做其它的事情,比如预先解码MP3一部分数据。那么问题是,如何在一个函数执行过程中,跳出去执行其它的函数,然后再跳回来?用中断,对,但是把什么放在中断里面呢?

2. USB mass storage设备
  就是利用单片机的USB片上设备,模拟一个U盘。做这样的设备,主要内容就是响应来自USB主机的各种请求。当USB主机向设备发出请求的时候,USB硬件会产生一个IRQ,随后USB的中断服务函数(IRQ handler)被执行。通常,USB驱动程序库会提供一些回调(callback)函数接口,就是由用户写一些函数,供USB IRQ handler在需要的时候调用。
  作为USB mass storage设备,需要提供的回调函数必须要有读存储设备、写存储设备等,以产生实际的磁盘数据给USB,以及接收USB要求写的磁盘数据。这些函数什么时候被调用到,是应用程序无法预见的,因为它在USB中断发生之后的响应过程中。这样一来,回调函数处理U盘模拟的事务,主程序里面不用管,可以处理无关的别的工作,也就实现了多任务么!
  然而,在中断环境下执行用户代码,好像不是太好的选择,因为这时候优先级同级和更低的中断就不能响应了。在实际的USB mass storage设备里面,U盘的数据要从片外存储设备中读取,比如NAND Flash,情况就会糟糕——读取数据需要等待,而这个等待完全发生在USB IRQ handler里面,USB主机的请求暂时也没法再响应了。如果主程序中的任务也需要硬件I/O中断,可能就会受到影响。
  那么,作为只模拟一个U盘,不进行其它任务的应用来说,这样似乎也无关紧要:反正都是等。我亲自做过的USB全速(12Mbps)下U盘设备的表现,传输速度最多到500多kB,比12Mbps差了不少,为什么呢?

  看上面这个图,USB IRQ中断响应期间,是没有数据传输的,所以12Mbps的有效带宽被浪费了一部分,U盘的吞吐率自然就达不到理论值了。回调函数在I/O等待的时候,USB主机也在等待USB设备的应答。而U盘数据准备好之后,USB硬件发送数据,CPU又无事可干直到下一次请求到来。比较合理的设计是利用USB TX的时间进行实际存储设备的I/O预读取,也就是猜测USB会继续请求读上次读了的后面的数据,那就先把数据读到内存中来,一旦猜对了,就可以缩短下次请求的响应时间,模拟U盘的读取吞吐率就提高了。要这么实现,就不能单纯地在回调函数中处理I/O任务。

3. 数据记录装置的存储管理
  某个应用需要对远程设备(通过UART连接)进行 ReadChipID, ReadStatus, ReadData, EraseData, WriteData 这几项操作,以实现数据管理。这几个操作在具体的实现上,都是通过UART发送约定好格式的命令数据,然后通过解析UART收到的返回数据内容来判断操作是否成功,并接收有效的数据。
  倘若把注意力放在UART发送命令这里,程序的结构可能是这样的:

  这样的设计假定了远程设备会如期地发送出来应答,对UART交互过程却几乎没有容错能力。一旦交互过程中出现了意外,就无法从错误状态恢复,只能从头再来。
  一旦考虑到UART通信可能出现的异常,程序的编写就变得不那么直截了当了。一种办法是将解析UART收到数据的功能写成状态机,在数据是否合乎预定的格式、对返回数据的辨识的基础上确定程序执行的状态。当到达某些状态时,就从UART发送命令。但如此写法,从读代码的角度很难看出程序执行的意图,把操作流程和通信纠错混在了一起,且不利于代码维护。
  如何在保持程序流程直观的写法下,融进去通信状态识别和错误处理机制呢?按照一般的思维,这是一个单任务(线程)的程序,程序是顺序执行,都不需要借助中断。程序是在按照一个流程进行操作,但还要处理与流程关系不紧密的UART通信异常,这两项工作在时间上是交错的。倘若设想这是两个任务在进行,但是是在可以预见地相互切换着呢?好像这么说把简单事情又复杂化了……

  上面三个例子都有可能借助“任务调度”实现更有效的运行时间分配。在我看来,FreeRTOS提供了一种新的程序组织方式——任务,把复杂的事情划分成独立的小块分开编写;同时又提供一些机制让这些小块功能相互协同,来实现总的目的。FreeRTOS的任务是用C语言函数来编写的,它提供一个特性,可以让几个函数看起来“同时”在执行。当然啰,只有一个CPU的情况下实际上是轮流在执行的,不过这也和普通C语言程序有重大区别。
  我们知道,C语言的函数可以嵌套调用,可以递归调用。比如 funcA() 调用 funcB(),然后 funcB() 又调用 funcC(),甚至 funcC() 再调用 funcA() 都可以。但是 funcA() 必须等到 funcB() 返回之后才能继续执行它后面的内容,funcB() 调用 funcC() 也是等待 funcC() 完成了,控制权才回来。

  对于FreeRTOS的任务则不是这样的了,taskA() 任务可以在执行过程中主动或者被动地交出控制权,taskB() 可以这时候获得控制权,但它并不是从头再开始执行,而是从上次交出控制权的那个地方后面继续执行。又在某个时候,taskB() 交出控制权,系统选择了执行 taskC(),然后再当 taskC() 交出控制权时,taskA() 又恢复了执行。

  上面这个图简化了一点,实际上从一个任务的函数跳出来到另一个任务的函数中继续执行的过程,中间还要执行一段FreeRTOS内核的代码,也就是说是内核在负责调度下一步执行哪个任务,如何暂停当前的任务,如何恢复另一个任务。

  是否多任务的调度一定要用某种RTOS来实现?也并不是,用了RTOS会有所帮助,同时资源开销会多那么一点。比如已经提到过的用中断来切换任务,已可以实现简单的多任务。又比如,把一个任务分解成多个步骤,每个步骤对应一个函数,然后在一个大的循环里面每次选择执行哪个任务的哪一步。这种多任务为非抢占式的,而用中断实现的多任务是抢占式的。
  请注意,不管是否用了某种RTOS来实现,多任务操作的特点是每个任务只要没有执行完,它的状态(包括私有的数据)就必须完整保存。因为代表任务的函数(比如中断服务程序、任务的某一个步骤)一旦返回了,局部变量的作用域就消失,不能用来保存状态,所以任务状态保存要么用全局变量,要么用static的局部变量,要么用动态分配的存储。FreeRTOS的办法是:让任务函数暂停执行不需要返回,可以同时存在多个这种没有返回的函数,然后任选其中一个恢复执行。如何实现这个特性?请听我下篇分析。

此内容由EEWORLD论坛网友cruelfox原创,如需转载或用于商业用途需征得作者同意并注明出处


此帖出自单片机论坛

最新回复

写的真好!给你点赞   详情 回复 发表于 2024-11-13 14:27
点赞(4) 关注(13)
 

回复
举报

1944

帖子

32

TA的资源

纯净的硅(高级)

沙发
 
写的不错,支持一下!!!
此帖出自单片机论坛
 
 

回复

626

帖子

173

TA的资源

一粒金砂(高级)

板凳
 
写的很好啊!!
能转到嵌入式系统版吗?那里很需要这样的精华帖
此帖出自单片机论坛
加EE小助手好友,
入技术交流群
EE服务号
精彩活动e手掌握
EE订阅号
热门资讯e网打尽
聚焦汽车电子软硬件开发
认真关注技术本身

点评

nmg
需要交费。交费后,可获取一定的copy权限。获得的copy权限自发帖日三天后生效,比如本贴是2月16日发表的,需要到2月19日才能copy。  详情 回复 发表于 2018-2-26 09:24
 
 
 

回复

1903

帖子

0

TA的资源

版主

4
 
很好
此帖出自单片机论坛
 
 
 

回复

5263

帖子

239

TA的资源

管理员

5
 
高进 发表于 2018-2-22 18:14
写的很好啊!!
能转到嵌入式系统版吗?那里很需要这样的精华帖

需要交费。交费后,可获取一定的copy权限。获得的copy权限自发帖日三天后生效,比如本贴是2月16日发表的,需要到2月19日才能copy。
此帖出自单片机论坛
加EE小助手好友,
入技术交流群
EE服务号
精彩活动e手掌握
EE订阅号
热门资讯e网打尽
聚焦汽车电子软硬件开发
认真关注技术本身

点评

版面创收了  详情 回复 发表于 2018-2-26 09:28
 
 
 

回复

626

帖子

173

TA的资源

一粒金砂(高级)

6
 
nmg 发表于 2018-2-26 09:24
需要交费。交费后,可获取一定的copy权限。获得的copy权限自发帖日三天后生效,比如本贴是2月16日发表的 ...

版面创收了
此帖出自单片机论坛
加EE小助手好友,
入技术交流群
EE服务号
精彩活动e手掌握
EE订阅号
热门资讯e网打尽
聚焦汽车电子软硬件开发
认真关注技术本身
 
 
 

回复

4

帖子

0

TA的资源

一粒金砂(初级)

7
 
不错,最近正在学习实时操作系统
此帖出自单片机论坛
 
 
 

回复

1万

帖子

16

TA的资源

版主

8
 
不错,等待下文
此帖出自单片机论坛
 
个人签名http://shop34182318.taobao.com/
https://shop436095304.taobao.com/?spm=a230r.7195193.1997079397.37.69fe60dfT705yr
 
 

回复

2939

帖子

4

TA的资源

五彩晶圆(中级)

9
 
很透彻,明晰的文章
此帖出自单片机论坛
 
 
 

回复

295

帖子

1

TA的资源

版主

10
 
写的很好啊,不知道什么时候,发帖子可以支持一下markdown的格式呢
此帖出自单片机论坛

点评

目前发帖就能用支持markdown拉,有专门的markdown编辑器,在编辑器页面右上角有个markdown字样,点击可切换到markdown编辑器  详情 回复 发表于 2019-11-13 13:44
 
 
 

回复

1万

帖子

203

TA的资源

管理员

11
 
hotsauce1861 发表于 2019-11-13 08:20 写的很好啊,不知道什么时候,发帖子可以支持一下markdown的格式呢

目前发帖就能用支持markdown拉,有专门的markdown编辑器,在编辑器页面右上角有个markdown字样,点击可切换到markdown编辑器

此帖出自单片机论坛
加EE小助手好友,
入技术交流群
EE服务号
精彩活动e手掌握
EE订阅号
热门资讯e网打尽
聚焦汽车电子软硬件开发
认真关注技术本身
 
个人签名玩板看这里:
https://bbs.eeworld.com.cn/elecplay.html
EEWorld测评频道众多好板等你来玩,还可以来频道许愿树许愿说说你想要玩的板子,我们都在努力为大家实现!
 
 

回复

493

帖子

1

TA的资源

一粒金砂(高级)

12
 

由于毕业刚工作时使用的就是RTOS,所以对RTOS一直有种特殊的感觉。

工作中一直使用的是Itron,现在接触一下其他的,也很不错哦。

 

楼主总结的很到位呢。跟着楼主,学习下去。

最近有个打算,要给娃做个玩具。大致的想法就是故事机+遥控车的结合体。

MCU肯定是用RTOS,正好可以用FreeRTOS练练手。

有必要的话,再上SOC吧。

此帖出自单片机论坛

点评

nmg
欢迎加入到打卡、交流哇 https://bbs.eeworld.com.cn/thread-1136649-1-1.html    详情 回复 发表于 2020-8-12 18:45
 
 
 

回复

5263

帖子

239

TA的资源

管理员

13
 
Bingqi23 发表于 2020-8-12 09:47 由于毕业刚工作时使用的就是RTOS,所以对RTOS一直有种特殊的感觉。 工作中一直使用的是Itron,现在接触 ...

欢迎加入到打卡、交流哇

https://bbs.eeworld.com.cn/thread-1136649-1-1.html

 

此帖出自单片机论坛
加EE小助手好友,
入技术交流群
EE服务号
精彩活动e手掌握
EE订阅号
热门资讯e网打尽
聚焦汽车电子软硬件开发
认真关注技术本身
 
 
 

回复

5

帖子

0

TA的资源

一粒金砂(初级)

14
 

学习学习

此帖出自单片机论坛
 
 
 

回复

2

帖子

0

TA的资源

一粒金砂(初级)

15
 

rtos并不是必须的,好多场景不使用rtos,也可以使用别的办法实现同样的效果,但是代价就是代码的复杂度增加和可维护性减少,因此rtos可以代码更友好的代码开发体验

此帖出自单片机论坛
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

16
 

写的真好!给你点赞

此帖出自单片机论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表