FreeRTOS系列第17篇---FreeRTOS队列

本文介绍队列的基本知识,详细源码分析见《FreeRTOS高级篇5---FreeRTOS队列分析

1.FreeRTOS队列

      队列是主要的任务间通信方式。能够在任务与任务间、中断和任务间传送信息。大多数状况下,队列用于具备线程保护的FIFO(先进先出)缓冲区:新数据放在队列的后面。固然,数据也能够放在队列的前面,在下一篇讲队列API函数时,会涉及到数据的存放位置。缓存


图1-1:读写队列网络

      图1-1所示的队列中,最多能保存5个项目,而且假设队列永远不会满。任务A使用API函数xQueueSendToBack()向队列发送数据,每次发送一个数据,新入队的数据置于上一次入队数据的后面。任务B使用API函数xQueueReceive()将数据从队列取出,先入队的数据先出队。函数

2.使用模型:最简单、最灵活

      一般状况下,鱼和熊掌是不可兼得的,但FreeRTOS的队列用户模型管理却兼顾简单和灵活。发送到队列的消息是经过拷贝实现的,这意味着队列存储的数据是原数据,而不是原数据的引用。FreeRTOS队列具备如下特性:源码分析

  • C变量(整形、简单结构体等等)中的简单信息能够直接传送到队列。这样就不须要为信息分配缓存也不须要再进行什么拷贝工做。一样的,信息能够直接从队列读取到C变量中。用直接拷贝的方法入队,能够容许任务当即覆写已经入队的变量或者缓存,实际上队列中已经保存了这些变量或缓冲区携带的信息。由于变量中的数据内容是以拷贝的方式入队的,因此变量自身是容许重复使用的。发送信息的任务和接收信息的任务并不须要就哪一个任务拥有信息、哪一个任务释放信息(当信息再也不使用时)而达成一致。
  • 队列是经过拷贝传递数据的,但这并不妨碍队列经过引用来传递数据。当信息的大小到达一个临界点后,逐字节拷贝整个信息是不实际的,能够定义一个指针队列,只拷贝指向消息的指针来代替整个信息拷贝。FreeRTOS+UDP IP栈例程正是使用这种方法向FreeRTOS协议栈传递大量网络数据的。
  • 队列内存区域分配由内核完成。
  • 变长消息能够经过定义保存一个结构体变量的队列实现,结构体一个成员指向要入队的缓存,另外一个成员保存缓存数据的大小。
  • 单个队列能够接收不一样类型信息,而且信息能够来自不一样的位置。经过定义保存一个结构体变量的队列来实现,结构体的一个成员保存信息类型,另外一个成员保存信息数据(或者指向信息数据的指针)。数据如何解读取决于信息类型。管理FreeRTOS+UDP IP栈的任务正是使用单个队列接收ARP定时器时间通知、以太网硬件传送来的数据包、从应用层传送来的数据包、网络关闭事件等等。
  • 天生适用于那些内存保护(MPU)场合。一个具备内存区域保护的任务能够向另外一个具备内存区域保护的任务传递数据,由于调用队列发送函数会引发RTOS提高微控制器特权级别。只有RTOS(具备全部特权)才能够访问队列存储区域。
  • 在中断函数中使用独立的API。将RTOS任务API和中断服务例程API分来实现意味着能够避免执行时的上下文调用检查开销,还意味着在大多数状况下,与其它RTOS产品相比,用户建立中断服务例程会更简单。
  • API函数很简单。

3.队列阻塞

      API函数容许指定阻塞时间。spa

      每当任务企图从一个空的队列读取数据时,任务会进入阻塞状态(这样任务不会消耗任何CPU时间而且另外一个任务能够运行)直到队列中出现有效数据或者阻塞时间到期。.net

      每当任务企图向一个满的队列写数据时,任务会进入阻塞状态,直到队列中出现有效空间或者阻塞时间到期。线程

      若是多个任务阻塞在一个队列上,那么最高优先级别的任务会第一个解除阻塞。指针

      注:中断程序中毫不能够使用不带“FromISR”结尾的API函数!orm

      总结一下队列的基本用法:blog

  1. 定义一个队列句柄变量,用于保存建立的队列:xQueueHandle xQueue1;
  2. 使用API函数xQueueCreate()建立一个队列。
  3. 若是但愿使用先进先出队列,使用API函数xQueueSend()或xQueueSendToBack()向队列投递队列项。若是但愿使用后进先出队列,使用API函数xQueueSendToFront()向队列投递队列项。若是在中断服务程序中,切记使用它们的带中断保护版本。
  4. 使用API函数xQueueReceive()从队列读取队列项,若是在中断服务程序中,切记使用它们的带中断保护版本。
      以上使用的API函数将在下一篇文章中介绍。