freertos2

1、多任务系统中互斥的引入

为什么裸机程序就不用考虑互斥问题呢?

假设有一个变量,因为裸机程序都是一个函数一个函数轮流执行的,因此变量不会在某个时刻被多个函数同时访问。而多任务系统可以看作是同时运行的,一个变量可能会被多个任务同时访问。

没有引入freertos时,a的值经过两个函数后变为2。

 引入FREERTOS后,

 

假设任务a和任务b都需要在自己的任务里面访问a变量,将a变量加1,那么会遇到什么问题呢?

执行a++的操作分为3步,第一步:从存储器中读出a的值赋给寄存器R0;第二步:寄存器R0自加1;第三步:将寄存器的值放入存储器当中。假设任务a在取出a的值给寄存器R0,还没来得及自加1的操作,TICK中断就触发,触发瞬间R0的值会被保存起来;任务2就开始执行,假设任务b比较幸运,能够执行完全部程序,a的值此时为1,切换任务a时,任务a恢复上次的现场,即R0=0,进行自加1,然后把寄存器的值写入到存储器中的a变量,则a的值此时为1。

可见,实现各任务对变量的互斥访问尤为重要。

 

2、队列怎么实现互斥访问?

 任务A只要把变量a成功写入到存储器里边,任务b就可以读取a变量的值。任务a写数据,任务b读数据,就不会产生互斥问题。那么,如何能保证不会产生互斥问题呢?

假设任务a和任务c都要访问变量a,那么就需要把两个任务的程序进入到队列里面,队列里面有一个QueueSend函数,这个函数可以保证一个任务对变量进行访问(也就是写数据到内存的某个变量)之前,可以关掉tick中断,就可以防止进行任务的切换了,写完后立马打开中断就可以了。接着下一个任务要对这个变量进行访问(也就是写数据到内存的这个变量)之前,也是关掉中断,访问完再打开中断即可。 

3、使用队列的第二个好处——休眠唤醒——提高CPU的利用率

 在裸机系统中

 A_fun()函数中执行达到某个条件时flag就为1,B_fun()函数每次进来都需要一直判断flag是不是为1,浪费了CPU资源。在Freertos操作系统中是怎么样的呢?

 当A_fun()函数满足某个条件时就可以写队列,B_fun()函数就读队列,如果队列里面没有数据就进入休眠态,直到A_fun()函数有写队列才唤醒。当读取到队列有数据就放回数据。

 任务A在执行过程发现不满足条件于是不写队列,接着切换到任务B时读队列发现没有数据,于是就进入休眠状态,切换到任务A时开始全速运行,即使tick中断触发时也不切换任务,直到自身条件满足了,也就是可以写入队列了,那么就会唤醒任务B,就可以切换到任务B上次读取队列的位置,任务B就能读取队列的值并返回。

 休眠其实就是把当前任务从就绪链表移到阻塞链表当中。

  1. 队列的核心--关中断--环形缓冲区--链表

 

 

写队列就是执行两个操作步骤:1)写Data;2)唤醒。

唤醒时怎么就能够在队列里找到B的任务呢?

读队列发现无Data后执行两个操作步骤:1)将当前任务从就绪态转到阻塞态;2)把自己的任务通过链表记录到等待队列中。这样当任务A唤醒时,就知道需要唤醒的是B任务了。

环形缓冲区 

 

 环形缓冲区其实就是一个数组,为什么是环形的呢?因为当要访问到第len个数组元素时就需要从头开始。数组内容一开始都是空的,长度假设为4,一开始R和W指针都是指向第0个数组元素。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值