1.消息队列
顾名思义,他的数据结构是队列,而队列是遵循先入先出的原则 。而这个队列中的每个成员是消息,这个消息在代码中其实指的就是程序运行中的数据以队列的形式保存。他的作用就好像全局变量,每个任务都有访问这个消息队列的权限。同时也有向队列中保存元素的权力。但是我们知道代码中最好不要使用全局变量,因为写代码时往往写的都是部分API函数,使用全局变量很容易与其他人函数中的局部变量产生冲突,造成不可预料的错误。而这个消息队列的使用机制就有点像函数中的指针参数。让每个任务可以知道其它任务产生的数据。联系起每个任务。
首先我们在应用是先应该应用创建队列函数,创建队列函数参数我们应该表明我们队列中的数据最大要多大的空间。其此指明我们队列的数据个数,函数返回的是队列句柄,其实通俗意义上我的理解就是队列地址。
在使用读取队列函数时我们只要在任务定义一个临时变量利用API函数读取出来。注意这个时候数据读出来的同时数据在队列中出队,如果队列中没有数据,在函数参数中设置可以选择不同的·等待时间,等待时间就是处于阻塞态
同理,写数据,如果队列中没有多余空间,也可以选择等待写入时间·。
2.各种信号的应用
Freertos中的信号也是以队列的形式保存,只不过不同的信号,大小空间机制应用不一样。
一.二值信号
二值信号其实我个人感觉和我们在裸机中断中使用的置标志位的操作有点像。在裸机中,我们常常在中断时在中断函数里面改变某个变量,然后主函数中判断这个变量从而判断某个函数要不要执行。这样做的好处是不让中断函数执行太长时间。而Freertos中的这个二值信号只有两个值,0,1.如果一个任务你想让他在特定条件成立后再运行,你就在条件成立后将这个二值信号置1。然后在任务中使用读取二至信号的函数,这样在二值信号为0的情况下将任务进入阻塞态。一旦二值信号在某个任务中被置1,任务便会立即进入就绪态。这个时候依据优先级决定下一个任务。
二.计数信号量
计数信号量其实和我们定义数组最大长度比较像,我们在定义数组时经常会用一个宏定义把数组长度记录例如Max-number这类的标识数组长度,也就是记录最大数组长度,其实这也就是为了避免我们使用了过多的空间,而计数信号量也类似,我们可以想象一个场景,我们希望在停车场停车,但我们不知道停车场有多少停车位,我们肯定希望有一个数据可以表明停车场有多少停车位,而计数信号就可以类似指明资源数,而二值信号就两位信息,可以标识是否有停车位。是否有资源数。这就是二者的区别。我们在创建计数信号时要指明最多的资源数与初始化时有多少资源数。函数返回计数信号句柄。我们在应用时可以在某个操作后计数加一,表明这个操作执行次数。后面任务在没有资源时会进入阻塞态。其实和二值信号量应用比较像,计数信号量非零即一。
三.互斥信号量
互斥信号量与二值信号量相辅相成。它的产生就是为了解决二值信号量优先级反转的问题。
这个情景其实有点特殊,二值信号量初始值为1。从上倒下优先级依次降低。最高与最低优先级任务内容都是先获取二值信号量,然后释放信号量,M任务则是简单任务与信号量无关。但是一开始HM任务都在阻塞态(delay中),所以说L任务在执行。L任务在获取二值信号量后,HM任务恢复就绪态,但是由于信号量被最低优先级任务获取了,所以说最高优先级任务依然处于阻塞态,这个时候中优先级任务执行后一小段阻塞(delay)回到低优先级执行,这个时候释放信号量最高优先级才会回到就绪态得到执行。在这个过程中,高优先级任务由于被最低优先级抢走了资源所以说没得到响应,反而让中优先级的任务在高优先级之前执行。这个过程就叫优先级反转。为了避免这个情况。产生了互斥信号量。它可以在这种情况下把高优先级任务优先级继承给最低优先级,于是变成了下面这个过程
低优先级执行完回到高优先级,最后回到中等优先级。避免了优先级反转。
我个人是在学习后对知识的总结,所以很多地方的函数操作,函数介绍都一笔带过,但是在学习相关内容后应该不成问题。