• freeRTOS中文实用教程2--队列


    1.前言

    freeRTOS中所有任务的通信和同步机制都是基于队列来实现。

    2.队列的特点

    图 队列的读写操作

    • 队列的数据存储

    (1)队列可以保存有限个具有确定长度的数据单元,队列可以保存的最大单元数目称为队列的深度;

    (2)队列创建时需要设定队列深度和每个单元的大小;

    (3)队列先进先出

    • 多任务存取

    队列是内核中具有独立权限的对象,不属于任何任务,可以有多个任务进行读写

    • 读队列阻塞

    (1)任务读取队列数据时可以指定一个阻塞超时时间;

    (2)未超过阻塞超时时间,队列为空,任务将保持阻塞状态;

    (3)队列中写入数据,任务将由阻塞态转为就绪态;或者阻塞时间超过了阻塞超时时间,任务也将由阻塞态转为就绪态;

    (4)可能会有多个任务处于阻塞态等待读取队列中的数据;

    (5)队列数据有效,优先级最高的任务会解除阻塞,相同优先级则等待时间最长的任务会解除阻塞

    • 写队列阻塞

    (1)任务写入队列数据时可以指定一个阻塞超时时间;

    (2)未超过阻塞超时时间,队列满,任务将保持阻塞状态;

    (3)队列有空闲,任务将由阻塞态转为就绪态;或者阻塞时间超过了阻塞超时时间,任务也将由阻塞态转为就绪态;

    (4)可能会有多个任务处于阻塞态等待向队列中的写入数据;

    (5)队列有空闲,优先级最高的任务会解除阻塞,相同优先级则等待时间最长的任务会解除阻塞

    3. 使用队列传递复合数据类型

    图 结构体用于队列传递举例

    一般是通过传递复合数据类型的指针来实现

    4.使用队列传递指针

    • 如果队列存储的数据单元尺寸较大,那最好是利用队列来传递数据的指针
    • 利用队列传递指针时,一定要十分小心地做到以下两点

    (1)指针指向的内存空间的所有权必须明确

    不会有任意两个任务同时修改共享内存中的数据 .原则上,共享内存在其指针发送到队列之前,其内容只允许被发送任务访问;

    共享内存指针从队列中被读出之后,其内容亦只允许被接收任务访问 

    (2)指针指向的内存空间必须有效 

    如果指针指向的内存空间是动态分配的,只应该有一个任务负责对其进行内存释放。当这段内存空间被释放之后,就不应该有任何一个任务再访问这段空间

     注:切忌用指针访问任务栈上分配的空间。因为当栈帧发生改变后,栈上的数据将不再有效

    5.队列操作API

    API原型 函数说明 参数说明 返回值
    xQueueCreate( uxQueueLength, uxItemSize ) 用于创建一个队列,并返回一个 xQueueHandle 句柄以便于对其创建的队列进行引用 。当创建队列时, FreeRTOS 从堆空间中分配内存空间。分配的空间用于存储队列数据结构本身以及队列中包含的数据单元。如果内存堆中没有足够的空间来创建队列,xQueueCreate()将返回 NULL

    • uxQueueLength

    队列能够存储的最大单元数目,即队列深度。

    • uxItemSize

    队列中数据单元的长度,以字节为单位

    NULL 表示没有足够的堆空间分配给队列而导致创建失败。
    NULL 值表示队列创建成功。此返回值应当保存下来,以作为
    操作此队列的句柄
    xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueSendToBack()用于将数据发送到队列尾
    • xQueue

    目标队列的句柄

    • pvItemToQueue

    发送数据的指针

    • xTicksToWait

    阻塞超时时间。如果在发送时队列已满,这个时间即是任务处于阻塞态等待队列空间有效的最长等待时间

     
    xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait ) 用于将数据发送到队列首
     

    pdPASS
    返回 pdPASS 只会有一种情况,那就是数据被成功发送到队列

    errQUEUE_FULL
    如 果 由 于 队 列 已 满 而 无 法 将 数 据 写 入 , 则 将 返 回
    errQUEUE_FULL

    xQueueSendToFrontFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) 用于在中断服务中实现相同的功能
       
    xQueueSendToBackFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) 用于在中断服务中实现相同的功能     

    xQueueReceive

    xQueuePeek 

    用于从队列中接收(读取)数据单元。接收到的单元同时会从队列中删除

    也是从从队列中接收数据单元,不同的是并不从队列中删出接收到的单元 

    注:切记不要在中断服务例程中调用 xQueueRceive()xQueuePeek()

       
    xQueueReceiveFromISR
         
     uxQueueMessagesWaiting

     用于查询队列中当前有效数据单元个数

    切记不要在中断服务例程中调用 uxQueueMessagesWaiting()

       
     uxQueueMessagesWaitingFromISR
         

    6. 执行流程举例

    send1和sender2负责写队列,receiver负责读队列:

  • 相关阅读:
    动态二维码
    二维码
    购物车
    logback学习与配置使用
    UML类图几种关系的总结
    java.lang.Excetion,java.lang.RuntimeException,java.lang.Error有什么区别?
    Java编程最差实践
    Hibernate利用@DynamicInsert和@DynamicUpdate生成动态SQL语句
    从 Java 代码到 Java 堆
    Project configuration is not up-to-date with pom.xml
  • 原文地址:https://www.cnblogs.com/smartjourneys/p/7077365.html
Copyright © 2020-2023  润新知