FreeRTOS-如何根据FreeRTOS提供的功能(信号量、任务通知、队列等)设计程序

更新时间:2023-07-01 20:04:50 阅读: 评论:0

FreeRTOS-如何根据FreeRTOS提供的功能(信号量、任务通
知、队列等)设计程序
1、⼆值信号量姓氏王的由来
就像⼀个标志位,事件产⽣置⼀,事件处理后直零
⽤于任务之间的同步,即⼀个任务 give token,另⼀个任务 take token
特别提醒:
命令提示符快捷键V7.X版本中使⽤vSemaphoreCreateBinary函数,使⽤该函数创建的信号量初始值为“满”
V8.X版本以后版本中使⽤xSemaphoreCreateBinary函数,使⽤该函数创建的信号量初始值为“空”
2、计数信号量
事件产⽣加⼀,事件处理减⼀,减到零表⽰事件处理完毕
3、中断推迟处理
中国登记结算
大脸美女
把⼀部分原本放在中断服务函数的程序放在中断外,减少中断服务函数运⾏时间
由于中断服务函数越短越好(处理时间越短越好),把关键处理放中断服务函数,其他放到外⾯,外⾯可以是⼀个任务(灵活性⼤,因为会⽤到⼆值信号量或计数信号量,需要为每个信号量创建⼀个任务,耗⽤资源多),也可以是定时器守护任务的回调函
数xTimerPendFunctionCallFromISR()(定时器守护任务使⽤到⼀个命令队列,只要向队列发送信号就可以执⾏相应代码,所以可以实现“中断推迟处理”功能;只⽤到定时器守护任务这⼀个任务,节省资源,但建议回调函数执⾏时间短⼀些,否则影响其他定时器回调函数的执⾏周期)
4、任务通知
任务通知⼀定程度上可以替代⼆值信号量、计数信号量、事件组或队列。
任务通知优点:更快、占⽤RAM少
任务通知缺点:数据不能从任务发送到ISR(也就是ISR中不能读取任务通知);接收处理任务通知只能在本任务中;任务通知只能通过32位⽆符号整数传递数据;当任务为“pending”,发送任务通知API不会等待任务变为“not-pending”⽽阻塞,也就是数据可能丢失教师评语
任务状态:接收到通知为处理为“pending”,读取通知值状态变为“not-pending”
xTaskNotifyGive() 是xTaskNotify() 的阉割版
ulTaskNotifyTake() 是xTaskNotifyWait() 的阉割版
调⽤发送函数产⽣的影响:
调⽤xTaskNotifyGive()后,通知值加⼀,ucNotifyState变为"pending"
调⽤xTaskNotify()后,通知值可以不变、指定位置⼀、加⼀、强制重写通知值或者ucNotifyState为"not-pending"状态时写通知
值,ucNotifyState变为"pending"。第三个参数如果是eSetBits ,是使 notification value 的某⼀位置⼀,可以同时对notification value 的某⼏位置⼀,然后同时处理⼏件事情;如果第三个参数是eSetValueWithOverwrite ,是设置 notification value 为某个值。
接收函数如何判断是否接收到未读通知:
ulTaskNotifyTake()判断是否有未读通知是根据通知值ulNotifiedValue是否为零,该函数可以实现通知值减⼀或清零。相对来说,该函数实现主要是针对信号量那种类型(xClearCountOnExit 为pdTRUE替代⼆值信号量;为pdFALSE替代计数信号量);
冷淡xTaskNotifyWait()判断是否有通知是依据通知状态ucNotifyState, 该函数可以实现清除指定位。这⾥,通知值才算真正承载了有⽤的通知内容。
5、互斥
当⼀个资源不能被同时使⽤时使⽤互斥,⽐如打印机。⼀般使⽤情况是在某个任务中 take token,并且在这个任务中 give toke
使⽤互斥可能出现的问题:
1、互斥可能会导致⾼优先级任务等待低优先级任务,如下图:
2、也可能导致互锁,两个任务都各⾃持有对⽅想要的互斥信号,导致两个任务都⽆法进⾏,所以建议任务等待互斥信号的时间不要⽆限长,超时可以做⼀些处理,可以发现死锁情况
3、也可能导致⾃锁,⽐如某个函数对任务进⾏递归调⽤;可以通过递归互斥(recursive mutexes)解决
4、也可能某个任务⼀直没执⾏,如下图,但是可以通过调⽤taskYIELD() 解决
我对着镜子哭
6、Gatekeeper Tasks
对资源进⾏保护,使得只有⼀个任务能直接访问资源
蚯蚓的选择互斥量是为了保护“打印机”类型的事件不被破坏,看门⼈任务和队列或者计数信号量配合也可以实现这个功能,具体就是只有看门⼈任务可以直接使⽤“打印机”,看门⼈任务⼤多时间阻塞等待打印数据到来,任何其他任务想使⽤打印机只能向看门⼈任务发送打印数据
7、挂起调度器、关闭中断、进⼊临界区
使某些关键代码段不被打断的进⾏
可以使⽤的API如下:
1、taskDISABLE_INTERRUPTS() 和 taskENABLE_INTERRUPTS()
屏蔽可屏蔽中断,包括调度器也不能⼯作(即不能任务切换,因为调度器也是基于中断),保证某个代码段不被打断的执⾏;但是不⽀持嵌套(即如果调⽤了两个DISABLE,调⽤⼀个ENABLE也可以使中断正常⼯作,嵌套的意思是⼀对DISABLE和ENABLE⾥⾯包含了其他对DISABLE和ENABLE);当调度器挂起,FreeRTOS API不可以被调⽤
2、taskENTER_CRITICAL() 和 taskEXIT_CRITICAL()
和1的区别就是⽀持嵌套,即调⽤了⼏个ENTER,就要调⽤⼏个EXIT才能使能中断;当调度器挂起,FreeRTOS API不可以被调⽤
3、vTaskSuspendAll() 和 xTaskResumeAll()
只是不能进⾏任务切换,但是没有屏蔽中断;1和2不仅不能任务切换,还不能响应中断;当调度器挂起,FreeRTOS API不可以被调⽤
8、队列
携带信息进⾏任务间通信
1、不同于⼆值信号量和计数信号量,队列的原理是FIFO,可以存放数据
2、创建队列时队列的元素个数和元素的类型就已经确定了,只能往队列存放规定的元素类型
3、可以创建队列集合,队列集合⾥⾯可以放队列、计数信号量或⼆值信号量,使⽤队列集合适⽤于多个任务向某个任务发送数据,⽽数据类型不相同,不同数据类型的数据存放在不同的队列集合成员⾥。
4、队列可以实现邮箱功能,即多个任务可以读取长度为1的队列⾥的数据,但不会清除数据,即使队列有数据但没有更新,调⽤xQueuePeek()也不会阻塞;任务往此队列写数据是覆盖⾥⾯的数据。适⽤于向多个任务发送数据,即⼀对多通信,即⼴播。
9、事件组
任务间、任务与中断等多个事件的同步
事件组可以⽤于某个任务等待⼏个条件都满⾜或某个条件满⾜才解除阻塞的情景(多个发送,⼀个接收,即多对⼀通信),或者⼏个任务互相等待条件满⾜才进⼀步执⾏任务,⽐如task A,B,C需要进⼀步执⾏各⾃的任务,需要task A,B,C都满⾜条件(多个发送,多个接收,即多对多通信)。
调⽤这个函数xEventGroupSetBitsFromISR() ,实际是在定时器守护任务中执⾏,说有configUSE_TIMERS
和 INCLUDE_xTimerPendFunctionCall 需要置⼀
10、内存动态申请
如果单⽚机的RAM⽐较⼩,分配给FreeRTOS的heap⽐较少,可以使⽤内存动态申请pvPortMalloc定义⼤数组,从⽽减⼩分配给任务栈的⼤⼩

本文发布于:2023-07-01 20:04:50,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/89/1063578.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:任务   通知   队列   中断   函数   信号量   数据
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图