打印
[应用方案]

FreeRTOS队列

[复制链接]
1687|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
643757107|  楼主 | 2017-12-24 13:06 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
1.FreeRTOS队列
      队列是主要的任务间通讯方式。可以在任务与任务间、中断和任务间传送信息。大多数情况下,队列用于具有线程保护的FIFO(先进先出)缓冲区:新数据放在队列的后面。当然,数据也可以放在队列的前面,在下一篇讲队列API函数时,会涉及到数据的存放位置。

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

沙发
643757107|  楼主 | 2017-12-24 13:06 | 只看该作者
2.使用模型:最简单、最灵活
      通常情况下,鱼和熊掌是不可兼得的,但FreeRTOS的队列用户模型管理却兼顾简单和灵活。发送到队列的消息是通过拷贝实现的,这意味着队列存储的数据是原数据,而不是原数据的引用。FreeRTOS队列具有以下特性:

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

使用特权

评论回复
板凳
643757107|  楼主 | 2017-12-24 13:06 | 只看该作者
3.队列阻塞
      API函数允许指定阻塞时间。
      每当任务企图从一个空的队列读取数据时,任务会进入阻塞状态(这样任务不会消耗任何CPU时间并且另一个任务可以运行)直到队列中出现有效数据或者阻塞时间到期。
      每当任务企图向一个满的队列写数据时,任务会进入阻塞状态,直到队列中出现有效空间或者阻塞时间到期。
      如果多个任务阻塞在一个队列上,那么最高优先级别的任务会第一个解除阻塞。
      注:中断程序中绝不可以使用不带“FromISR”结尾的API函数!
      总结一下队列的基本用法:

  • 定义一个队列句柄变量,用于保存创建的队列:xQueueHandle xQueue1;
  • 使用API函数xQueueCreate()创建一个队列。
  • 如果希望使用先进先出队列,使用API函数xQueueSend()或xQueueSendToBack()向队列投递队列项。如果希望使用后进先出队列,使用API函数xQueueSendToFront()向队列投递队列项。如果在中断服务程序中,切记使用它们的带中断保护版本。
  • 使用API函数xQueueReceive()从队列读取队列项,如果在中断服务程序中,切记使用它们的带中断保护版本。

使用特权

评论回复
地板
643757107|  楼主 | 2017-12-24 13:07 | 只看该作者
  FreeRTOS为操作队列提供了非常丰富的API函数,包括队列的创建、删除,灵活的入队和出队方式、带中断保护的入队和出队等等。下面就来详细讲述这些API函数。
1.获取队列入队信息数目1.1函数描述
      UBaseType_t uxQueueMessagesWaiting( QueueHandle_t xQueue );
      返回队列中存储的信息数目。具有中断保护的版本为[url=]uxQueueMessagesWaitingFromISR[/url](),原型为:UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue )。
1.2参数描述
  • xQueue:队列句柄

2.获取队列的空闲数目2.1函数描述
      UBaseType_t uxQueueSpacesAvailable( QueueHandle_t xQueue );
      返回队列的空闲数目。
2.2参数描述
  • xQueue:队列句柄

使用特权

评论回复
5
643757107|  楼主 | 2017-12-24 13:07 | 只看该作者
3.删除队列3.1函数描述
      void vQueueDelete( QueueHandle_t xQueue );
      删除队列并释放所有分配给队列的内存。
3.2参数描述

  • xQueue:队列句柄

4.复位队列4.1函数描述
      BaseType_t xQueueReset( QueueHandle_t xQueue );
      将队列复位到初始状态。
4.2参数描述
  • xQueue:队列句柄

4.3返回值
      FreeRTOSV7.2.0以及以后的版本总是返回pdPASS。
5.创建队列5.1函数描述
     QueueHandle_t xQueueCreate (UBaseType_t uxQueueLength, UBaseType_t uxItemSize);
     创建新队列。为新队列分配指定的存储空间并返回队列句柄。
5.2参数描述
  • usQueueLength:队列项数目
  • uxItemSize:每个队列项大小,单位是字节。队列项通过拷贝入队而不是通过引用入队,因此需要队列项的大小。每个队列项的大小必须相同。

5.3返回值
      成功创建队列返回队列句柄,否自返回0。
5.4用法举例
struct AMessage  
{  
    portCHAR ucMessageID;  
    portCHAR ucData[ 20 ];  
};  
void vATask( void*pvParameters )  
{  
    xQueueHandle xQueue1, xQueue2;  
    // 创建一个队列,队列能包含10个unsigned long类型的值。  
    xQueue1 = xQueueCreate( 10, sizeof( unsigned portLONG ));  
    if( xQueue1 ==0 )  
    {  
        // 队列创建失败,不可以使用  
    }  
    // 创建一个队列,队列能包含10个 Amessage结构体指针类型的值。  
    // 这样可以通过传递指针变量来包含大量数据。  
    xQueue2 =xQueueCreate( 10, sizeof( struct AMessage * ) );  
    if( xQueue2 ==0 )  
    {  
        // 队列创建失败,不可以使用  
    }  
    // ... 任务的其它代码.  
}  



使用特权

评论回复
6
643757107|  楼主 | 2017-12-24 13:08 | 只看该作者
6.向队列投递队列项6.1 函数描述
      BaseType_t [url=]xQueueSend[/url](QueueHandle_t xQueue,  const void * pvItemToQueue,  TickType_t xTicksToWait );
      其实是一个宏,真正被调用的函数是xQueueGenericSend()。定义这个宏是为了向后兼容那些不包含函数xQueueSendToFront()和xQueueSendToBack()宏的FreeRTOS版本。它与xQueueSendToBack()等同。
      这个宏向队列尾部投递一个队列项。项目以拷贝的形式入队,而不是引用形式入队。绝不可以在中断服务例程中调用这个宏,使用带有中断保护的版本xQueueSendFromISR()来完成相同的功能。
6.2参数描述

  • xQueue:队列句柄。
  • pvItemToQueue:指针,指向要入队的项目。要保存到队列中的项目字节数在队列创建时就已确定。因此要从指针pvItemToQueue指向的区域拷贝到队列存储区域的字节数,也已确定。
  • xTicksToWait:如果队列满,任务等待队列空闲的最大时间。如果队列满并且xTicksToWait被设置成0,函数立刻返回。时间单位为系统节拍时钟周期,因此宏portTICK_PERIOD_MS可以用来辅助计算真实延时值。如果INCLUDE_vTaskSuspend设置成1,并且指定延时为portMAX_DELAY将引起任务无限阻塞(没有超时)。

6.3返回值
      队列项入队成功返回pdTRUE,否则返回errQUEUE_FULL。
6.4用法举例
struct AMessage  
{  
      portCHAR ucMessageID;  
      portCHAR ucData[ 20 ];  
}xMessage;  
unsigned portLONG ulVar = 10UL;  
void vATask( voidvoid *pvParameters )  
{  
     xQueueHandle xQueue1, xQueue2;  
     struct AMessage *pxMessage;  
     /*创建一个队列,队列能包含10个unsigned long类型的值。*/  
     xQueue1 = xQueueCreate( 10, sizeof( unsigned portLONG ) );  
     /* 创建一个队列,队列能包含10个 Amessage结构体指针类型的值。
       这样可以通过传递指针变量来包含大量数据。*/  
     xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );  
     // ...  
     if( xQueue1 != 0 )  
     {  
          /*1个unsigned long型数据入队.如果需要等待队列空间变的有效,
         会最多等待10个系统节拍周期*/  
          if( xQueueSend( xQueue1, ( voidvoid * ) &ulVar, ( portTickType ) 10 ) !=pdPASS )  
          {  
               /*消息入队失败*/  
          }  
    }  
    if( xQueue2 != 0 )  
    {  
         /* 发送一个指向结构体Amessage的对象,如果队列满也不等待 */  
         pxMessage = & xMessage;  
         xQueueSend( xQueue2, ( voidvoid * ) &pxMessage, ( portTickType ) 0 );  
    }  
         //... 任务其余代码.  
}



使用特权

评论回复
7
643757107|  楼主 | 2017-12-24 13:09 | 只看该作者
7.向队列投递队列项(带中断保护)7.1函数描述
BaseType_t xQueueSendFromISR (QueueHandle_t xQueue,  
          const voidvoid *pvItemToQueue,  BaseType_t *pxHigherPriorityTaskWoken);  
   其实是一个宏,真正被调用的函数是xQueueGenericSendFromISR()。这个宏是xQueueSend()的中断保护版本,用于中断服务程序,等价于xQueueSendToBackFromISR()。
    在中断服务例程中向队列尾部投递一个队列项。
7.2参数描述
  • xQueue:队列句柄。
  • pvItemToQueue:指针,指向要入队的项目。要保存到队列中的项目字节数在队列创建时就已确定。因此要从指针pvItemToQueue指向的区域拷贝到队列存储区域的字节数,也已确定。
  • pxHigherPriorityTaskWoken:如果入队导致一个任务解锁,并且解锁的任务优先级高于当前运行的任务,则该函数将*pxHigherPriorityTaskWoken设置成pdTRUE。如果xQueueSendFromISR()设置这个值为pdTRUE,则中断退出前需要一次上下文切换。从FreeRTOS V7.3.0起,pxHigherPriorityTaskWoken称为一个可选参数,并可以设置为NULL。

7.3返回值
      列项入队成功返回pdTRUE,否则返回errQUEUE_FULL。
7.4用法举例
void vBufferISR( void )  
{  
    portCHARcIn;  
    portBASE_TYPE xHigherPriorityTaskWoken;  
   
    /* 初始化,没有唤醒任务*/  
    xHigherPriorityTaskWoken = pdFALSE;  
   
    /* 直到缓冲区为空 */  
    do  
    {  
        /* 从缓冲区获得一个字节数据 */  
        cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );                                                        
   
        /* 投递这个数据 */  
        xQueueSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );  
    }while( portINPUT_BYTE( BUFFER_COUNT ) );  
   
    /* 这里缓冲区已空,如果需要进行一个上下文切换*/  
    /*根据不同移植平台,这个函数也不同*/  
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);  
}



使用特权

评论回复
8
643757107|  楼主 | 2017-12-24 13:10 | 只看该作者
8.向队列尾部投递队列项8.1函数描述
BaseType_t xQueueSendToBack(QueueHandle_t xQueue,  
                   const voidvoid * pvItemToQueue, TickType_t xTicksToWait );  
其实是一个宏,真正被调用的函数是xQueueGenericSend()。这个宏等价于xQueueSend()。
      向队列尾投递一个队列项。绝不可以在中断中调用这个宏,可以使用带有中断保护的版本xQueueSendToBackFromISR ()来完成相同功能。
8.2参数描述
      同xQueueSend()。
8.3返回值
      同xQueueSend()。
8.4用法举例
      同xQueueSend()。
9.向队列尾部投递队列项(带中断保护)9.1函数描述
BaseType_t xQueueSendToBackFromISR (QueueHandle_t xQueue,  
      const voidvoid *pvItemToQueue, BaseType_t *pxHigherPriorityTaskWoken );  
其实是一个宏,真正被调用的函数是xQueueGenericSendFromISR()。这个宏是xQueueSendToBack()的中断保护版本,用于中断服务程序,等价于xQueueSendFromISR()。
    在中断服务例程中向队列尾部投递一个队列项。
9.2参数描述
      同QueueSendFromISR()。
9.3返回值
      同QueueSendFromISR()。
9.4用法举例
      同QueueSendFromISR()。


使用特权

评论回复
9
643757107|  楼主 | 2017-12-24 13:21 | 只看该作者
10.向队列首部投递队列项10.1函数描述
BaseType_t xQueueSendToFront(QueueHandle_t xQueue,     
const voidvoid * pvItemToQueue,TickType_t xTicksToWait);  




      其实是一个宏,真正被调用的函数是xQueueGenericSend()。
      这个宏向队列首部投递一个队列项。绝不可以在中断服务例程中调用这个宏,可以使用带有中断保护的版本xQueueSendToFrontFromISR ()来完成相同功能。
10.2参数描述
  • xQueue:队列句柄。
  • pvItemToQueue:指针,指向要入队的项目。要保存到队列中的项目字节数在队列创建时就已确定。因此要从指针pvItemToQueue指向的区域拷贝到队列存储区域的字节数,也已确定。
  • xTicksToWait:如果队列满,任务等待队列空闲的最大时间。如果队列满并且xTicksToWait被设置成0,函数立刻返回。时间单位为系统节拍时钟周期,因此宏portTICK_PERIOD_MS可以用来辅助计算真实延时值。如果INCLUDE_vTaskSuspend设置成1,并且指定延时为portMAX_DELAY将引起任务无限阻塞(没有超时)。

10.3返回值
      队列项入队成功返回pdTRUE,否则返回errQUEUE_FULL。


使用特权

评论回复
10
643757107|  楼主 | 2017-12-24 13:24 | 只看该作者
11.向队列首部投递队列项(带中断保护)11.1函数描述
BaseType_t xQueueSendToFrontFromISR (QueueHandle_t xQueue,  
        const voidvoid *pvItemToQueue,BaseType_t *pxHigherPriorityTaskWoken);  
其实是一个宏,真正被调用的函数是xQueueGenericSendFromISR()。这个宏是xQueueSendToFront ()的中断保护版本,用于中断服务程序。
11.2参数描述
  • xQueue:队列句柄。
  • pvItemToQueue:指针,指向要入队的项目。要保存到队列中的项目字节数在队列创建时就已确定。因此要从指针pvItemToQueue指向的区域拷贝到队列存储区域的字节数,也已确定。
  • pxHigherPriorityTaskWoken:如果入队导致一个任务解锁,并且解锁的任务优先级高于当前运行的任务,则该函数将*pxHigherPriorityTaskWoken设置成pdTRUE。如果xQueueSendFromISR()设置这个值为pdTRUE,则中断退出前需要一次上下文切换。从FreeRTOS V7.3.0起,pxHigherPriorityTaskWoken称为一个可选参数,并可以设置为NULL。

11.3返回值
      列项入队成功返回pdTRUE,否则返回errQUEUE_FULL。
12.读取并移除队列项12.1函数描述
BaseType_t xQueueReceive(QueueHandle_t xQueue,  
                     voidvoid *pvBuffer,TickType_t xTicksToWait);  
其实是一个宏,真正被调用的函数是xQueueGenericReceive()。
      这个宏从队列中读取一个队列项并把该队列项从队列中删除。读取队列项是以拷贝的形式完成,而不是以引用的形式,因此必须提供足够大的缓冲区以便容纳队列项。参数pvBuffer指向这个缓冲区。
      绝不可以在中断服务例程中调用这个宏,可以使用使用带有中断保护的版本xQueueReceiveFromISR来完成相同功能。


使用特权

评论回复
11
643757107|  楼主 | 2017-12-24 13:26 | 只看该作者
12.2参数描述
  • pxQueue:队列句柄。
  • pvBuffer:指向一个缓冲区,用于拷贝接收到的列表项。
  • xTicksToWait:要接收的项目队列为空时,允许任务最大阻塞时间。如果设置该参数为0,则表示即队列为空也立即返回。阻塞时间的单位是系统节拍周期,宏portTICK_RATE_MS可辅助计算真实阻塞时间。如果INCLUDE_vTaskSuspend设置成1,并且阻塞时间设置成portMAX_DELAY,将会引起任务无限阻塞(不会有超时)。

12.3返回值
      成功接收到列表项返回pdTRUE,否则返回pdFALSE。
12.4用法举例
struct AMessage  
{  
    portCHAR ucMessageID;  
    portCHAR ucData[ 20 ];  
} xMessage;  
   
xQueueHandle xQueue;  
   
// 创建一个队列并投递一个值  
void vATask( voidvoid *pvParameters )  
{  
     struct AMessage *pxMessage;  
   
     // 创建一个队列,队列能包含10个 Amessage结构体指针类型的值。  
     // 这样可以通过传递指针变量来包含大量数据。  
     xQueue =xQueueCreate( 10, sizeof( struct AMessage * ) );  
     if( xQueue == 0)  
     {  
          // 创建队列失败  
    }  
    // ...  
    // 向队列发送一个指向结构体对象Amessage的指针,如果队列满不等待  
    pxMessage = & xMessage;  
    xQueueSend(xQueue, ( voidvoid * ) &pxMessage, ( portTickType ) 0 );  
    // ... 其它代码  
}  
   
// 该任务从队列中接收一个队列项  
voidvADifferentTask( voidvoid *pvParameters )  
{  
    struct AMessage *pxRxedMessage;  
   
    if( xQueue != 0)  
    {  
        // 从创建的队列中接收一个消息,如果消息无效,最多阻塞10个系统节拍周期  
        if(xQueueReceive( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) )  
        {  
            // 现在pcRxedMessage 指向由vATask任务投递进来的结构体Amessage变量  
        }  
    }  
   // ... 其它代码  
}  
13读取并移除队列项(带中断保护)13.1函数描述
BaseType_t xQueueReceiveFromISR (QueueHandle_t xQueue,  
        voidvoid *pvBuffer, BaseType_t *pxHigherPriorityTaskWoken);  
从队列中读取一个队列项并把该队列项从队列中删除。功能与xQueueReceive()相同,用于中断服务函数。
13.2参数描述
  • pxQueue:队列句柄。
  • pvBuffer:指向一个缓冲区,用于拷贝接收到的列表项。
  • pxHigherPriorityTaskWoken:如果入队导致一个任务解锁,并且解锁的任务优先级高于当前运行的任务,则该函数将*pxHigherPriorityTaskWoken设置成pdTRUE。如果xQueueSendFromISR()设置这个值为pdTRUE,则中断退出前需要一次上下文切换。从FreeRTOS V7.3.0起,pxHigherPriorityTaskWoken称为一个可选参数,并可以设置为NULL。

13.3返回值
      成功接收到列表项返回pdTRUE,否则返回pdFALSE。
13.4用法举例
xQueueHandle xQueue;  
   
/* 该函数创建一个队列并投递一些值 */  
voidvAFunction( voidvoid *pvParameters )  
{  
     portCHAR cValueToPost;  
     const portTickType xBlockTime = (portTickType )0xff;  
   
     /*创建一个队列,可以容纳10个portCHAR型变量 */  
     xQueue = xQueueCreate( 10, sizeof( portCHAR ) );  
     if( xQueue == 0 )  
     {  
          /* 队列创建失败 */  
     }  
    /*…... */  
    /* 投递一些字符,在ISR中使用。如果队列满,任务将会阻塞xBlockTime 个系统节拍周期 */  
    cValueToPost = 'a';  
    xQueueSend( xQueue, ( voidvoid * ) &cValueToPost, xBlockTime );  
    cValueToPost = 'b';  
    xQueueSend( xQueue, ( voidvoid * ) &cValueToPost, xBlockTime );  
    /*... 继续投递字符 ... 当队列满时,这个任务会阻塞*/  
    cValueToPost = 'c';  
    xQueueSend( xQueue, ( voidvoid * ) &cValueToPost, xBlockTime );  
}  
   
/* ISR:输出从队列接收到的所有字符 */  
voidvISR_Routine( void )  
{  
     portBASE_TYPE xTaskWokenByReceive = pdFALSE;  
     portCHAR cRxedChar;  
   
     while( xQueueReceiveFromISR( xQueue, ( voidvoid *) &cRxedChar, &xTaskWokenByReceive) )  
    {  
       /* 接收到一个字符串,输出.*/  
       vOutputCharacter( cRxedChar );  
       /* 如果从队列移除一个字符串后唤醒了向此队列投递字符的任务,那么参数xTaskWokenByReceive将会设置成pdTRUE,这个循环无论重复多少次,仅会
          有一个任务被唤醒。*/  
    }  
    /*这里缓冲区已空,如果需要进行一个上下文切换根据不同移植平台,这个函数也不同 */  
    portYIELD_FROM_ISR(xTaskWokenByReceive);  
}  
14.读取但不移除队列项14.1函数描述
BaseType_t xQueuePeek(QueueHandle_t xQueue,  
        voidvoid *pvBuffer, TickType_t xTicksToWait);  
其实是一个宏,真正被调用的函数是xQueueGenericReceive()。
      这个宏从队列中读取一个队列项,但不会把该队列项从队列中移除。这个宏绝不可以用在中断服务例程中,可以使用使用带有中断保护的版本xQueuePeekFromIS()来完成相同功能。
14.2参数描述
      同xQueueReceive()。
14.3返回值
      同xQueueReceive()。
14.4用法举例
      同xQueueReceive()。


使用特权

评论回复
12
643757107|  楼主 | 2017-12-24 13:33 | 只看该作者
15.读取但不移除队列项(带中断保护)15.1函数描述
      BaseType_t xQueuePeekFromISR(QueueHandle_t xQueue, void *pvBuffer,);
      功能与xQueuePeek()相同,用于中断服务程序。
15.2参数描述
  • pxQueue:队列句柄。
  • pvBuffer:指向一个缓冲区,用于拷贝接收到的列表项。

15.3返回值
      成功接收到列表项返回pdTRUE,否则返回pdFALSE。
16.队列注册16.1函数描述
      void vQueueAddToRegistry(QueueHandle_t xQueue, char *pcQueueName,);
      为队列分配名字并进行注册。
16.2参数描述
  • l  xQueue:队列句柄
  • l  pcQueueName:分配给队列的名字。这仅是一个有助于调试的字符串。队列注册仅存储指向队列名字符串的指针,因此这个字符串必须是静态的(全局变量活着存储在ROM/Flash中),不可以定义到堆栈中。

      队列注册有两个目的,这两个目的都是为了调试RTOS内核:

  • 它允许队列具有一个相关的文本名字,在GUI调试中可以容易的标识队列;
  • 包含调试器用于定位每一个已经注册的队列和信号量时所需的信息。

       队列注册仅用于调试器。
       宏configQUEUE_REGISTRY_SIZE定义了可以注册的队列和信号量的最大数量。仅当你想使用可视化调试内核时,才进行队列和信号量注册。
16.3用法举例
void vAFunction( void )  
{  
    xQueueHandle xQueue;  
   
   /*创建一个队列,可以容纳10个char类型数值 */  
   xQueue = xQueueCreate( 10, sizeof( portCHAR ) );  
   
   /* 我们想可视化调试,所以注册它*/  
   vQueueAddToRegistry( xQueue, "AMeaningfulName" );  
}  
17.解除注册17.1函数描述
      void vQueueUnregisterQueue(QueueHandle_t xQueue);
      从队列注册表中移除指定的队列。
17.2参数描述

  • xQueue:队列句柄

18.查询队列是否为空(仅用于中断服务程序)18.1函数描述
      BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue );
      查询队列是否为空。这个函数仅用于ISR。
18.2参数描述
  • xQueue:队列句柄

18.3返回值
      队列非空返回pdFALSE,其它值表示队列为空。
19.查询队列是否满(仅用于中断服务程序)19.1函数描述
      BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue );
      查询队列是否满,仅用于ISR。
19.2参数描述
  • xQueue:队列句柄

19.3返回值
      队列没有满返回pdFALSE,其它值表示队列满。
20.向队列尾部覆盖式投递队列项20.1函数描述
      BaseType_t xQueueOverwrite(QueueHandle_t xQueue, const void * pvItemToQueue);
      其实是个宏,真正被调用的函数是xQueueGenericSend()。这个宏是xQueueSendToBack()的另一个版本,向队列尾投递一个队列项,如果队列已满,则覆盖之前的队列项。一般用于只有一个队列项的队列中,如果队列的队列项超过1个,使用这个宏会触发一个断言(已经正确定义configASSERT()的情况下)。这个宏绝不可以在中断服务程序中调用,可以使用使用带有中断保护的版本xQueueOverwriteFromISR()来完成相同功能。
20.2参数描述
  • xQueue:队列句柄。
  • pvItemToQueue:指针,指向要入队的项目。要保存到队列中的项目字节数在队列创建时就已确定。因此要从指针pvItemToQueue指向的区域拷贝到队列存储区域的字节数,也已确定。

20.3返回值
      总是返回pdPASS。
20.4用法举例
void vFunction( voidvoid *pvParameters )  
{  
    QueueHandle_t xQueue;  
    unsigned long ulVarToSend, ulValReceived;  
   
    /*创建队列,保存一个unsignedlong值。如果一个队列的队列项超过1个,强烈建议不要使用xQueueOverwrite(),如果使用xQueueOverwrite()会触发一个断言(已经正确定义configASSERT()的情况下)。*/  
    xQueue = xQueueCreate( 1, sizeof( unsigned long ) );  
   
    /*使用 xQueueOverwrite().向队列写入10*/  
    ulVarToSend = 10;  
    xQueueOverwrite( xQueue, &ulVarToSend );  
   
    /*从队列读取值,但是不把这个值从队列中删除。*/  
    ulValReceived = 0;  
    xQueuePeek( xQueue, &ulValReceived, 0 );  
   
    if( ulValReceived != 10 )  
     {  
          /* 处理错误*/  
     }  
   
     /*到这里队列仍是满的。使用xQueueOverwrite()覆写队列,写入值100 */  
     ulVarToSend = 100;  
     xQueueOverwrite( xQueue, &ulVarToSend );  
   
     /* 从队列中读取值*/  
     xQueueReceive( xQueue, &ulValReceived, 0 );  
   
     if( ulValReceived != 100 )  
     {  
          /*处理错误 */  
     }  
   
      /* ... */  
}  
21向队列尾部覆盖式投递队列项(带中断保护)21.1函数描述
BaseType_t xQueueOverwriteFromISR (QueueHandle_t xQueue, const voidvoid * pvItemToQueue,  
                       BaseType_t *pxHigherPriorityTaskWoken);  
其实是个宏,真正被调用的函数是xQueueGenericSendFromISR()。这个宏的功能与xQueueOverwrite()相同,用在中断服务程序中。
21.2参数描述
  • xQueue:队列句柄。
  • pvItemToQueue:指针,指向要入队的项目。要保存到队列中的项目字节数在队列创建时就已确定。因此要从指针pvItemToQueue指向的区域拷贝到队列存储区域的字节数,也已确定。
  • pxHigherPriorityTaskWoken:如果入队导致一个任务解锁,并且解锁的任务优先级高于当前运行的任务,则该函数将*pxHigherPriorityTaskWoken设置成pdTRUE。如果xQueueSendFromISR()设置这个值为pdTRUE,则中断退出前需要一次上下文切换。从FreeRTOS V7.3.0起,pxHigherPriorityTaskWoken称为一个可选参数,并可以设置为NULL。

21.3返回值      总是返回pdPASS。



使用特权

评论回复
13
huangcunxiake| | 2017-12-24 22:25 | 只看该作者
理解这个过程了,就容易做了。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

199

主题

3697

帖子

11

粉丝