当前位置: 首页 > news >正文

网站在线留言的用途免费咨询广东律师事务所

网站在线留言的用途,免费咨询广东律师事务所,网站制作手机,电脑网页上的视频怎么保存到本地队列简介 队列是任务到任务、任务到中断、中断到任务数据交流的一种机制(消息传递) 全局变量的弊端:数据无保护,导致数据不安全,当多个任务同时对该变量操作时,数据易受损 使用队列的情况如下:…

队列简介

        队列是任务到任务、任务到中断、中断到任务数据交流的一种机制(消息传递

         全局变量的弊端数据无保护,导致数据不安全,当多个任务同时对该变量操作时,数据易受损

        使用队列的情况如下:

 

        读写队列做好了保护,防止多任务同时访问冲突;我们只需要直接调用API函数即可,简单易用!

        FreeRTOS基于队列, 实现了多种功能,其中包括队列集、互斥信号量、计数型信号量、

二值信号量、 递归互斥信号量,因此很有必要深入了解 FreeRTOS 的队列 。

        在队列中可以存储数量有限、大小固定的数据。队列中的每一个数据叫做“队列项目”,队列能够存储“队列项目”的最大数量称为队列的长度。

        在创建队列时,就要指定队列长度以及队列项目的大小!

FreeRTOS队列特点:

1、数据入队出队方式

        队列通常采用“先进先出”(FIFO)的数据存储缓冲机制,即先入队的数据会先从队列中被读取,FreeRTOS中也可以配置为“后进先出”LIFO方式;

2、数据传递方式

        FreeRTOS中队列采用实际值传递,即将数据拷贝到队列中进行传递, FreeRTOS采用拷贝数据传递,也可以传递指针,所以在传递较大的数据的时候采用指针传递

3、多任务访问

        队列不属于某个任务,任何任务和中断都可以向队列发送/读取消息

4、出队、入队阻塞

        当任务向一个队列发送消息时,可以指定一个阻塞时间,假设此时当队列已满无法入队

若阻塞时间为0  :直接返回不会等待;
若阻塞时间为0~port_MAX_DELAY  :等待设定的阻塞时间,若在该时间内还无法入队,超时后直接返回不再等待;
若阻塞时间为port_MAX_DELAY  :死等,一直等到可以入队为止。出队阻塞与入队阻塞类似;

入队阻塞:

        

队列满了,此时写不进去数据;

 ①将该任务的状态列表项挂载在pxDelayedTaskList

 ②将该任务的事件列表项挂载在xTasksWaitingToSend

出队阻塞:

队列为空,此时读取不了数据;

 ①将该任务的状态列表项挂载在pxDelayedTaskList

 ②将该任务的事件列表项挂载在xTasksWaitingToReceive

问题:当多个任务写入消息给一个满队列时,这些任务都会进入阻塞状态,也就是说有多个任务    在等待同一 个队列的空间。那当队列中有空间时,哪个任务会进入就绪态?

答:

          1、优先级最高的任务

          2、如果大家的优先级相同,那等待时间最久的任务会进入就绪态

队列结构体介绍

typedef struct QueueDefinition 
{int8_t * pcHead					/* 存储区域的起始地址 */int8_t * pcWriteTo;        				/* 下一个写入的位置 */union{QueuePointers_t     xQueue; SemaphoreData_t  xSemaphore; } u ;List_t xTasksWaitingToSend; 			/* 等待发送列表 */List_t xTasksWaitingToReceive;			/* 等待接收列表 */volatile UBaseType_t uxMessagesWaiting; 	/* 非空闲队列项目的数量 */UBaseType_t uxLength;			/* 队列长度 */UBaseType_t uxItemSize;                 		/* 队列项目的大小 */volatile int8_t cRxLock; 				/* 读取上锁计数器 */volatile int8_t cTxLock;			/* 写入上锁计数器 *//* 其他的一些条件编译 */
} xQUEUE;

        当我们锁住队列的时候,你是可以正常读写队列的,只不过操作不了等待发送\接收列表。

当用于队列使用时:

typedef struct QueuePointers
{int8_t * pcTail; 				/* 存储区的结束地址 */int8_t * pcReadFrom;			/* 最后一个读取队列的地址 */
} QueuePointers_t;

当用于互斥信号量和递归互斥信号量时 :

typedef struct SemaphoreData
{TaskHandle_t xMutexHolder;		/* 互斥信号量持有者 */UBaseType_t uxRecursiveCallCount;	/* 递归互斥信号量的获取计数器 */
} SemaphoreData_t;

队列结构体整体示意图:

队列相关API函数介绍

        使用队列的主要流程:创建队列 ---> 写队列 ---> 读队列。

创建队列相关API函数介绍:

函数

描述

xQueueCreate()

动态方式创建队列

xQueueCreateStatic()

静态方式创建队列

         动态和静态创建队列之间的区别:队列所需的内存空间由 FreeRTOS FreeRTOS 管理的堆中分配,而静态创建需要用户自行分配内存。

创建队列函数入口参数解析:

#define xQueueCreate (  uxQueueLength,   uxItemSize  )   			 \					xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), (queueQUEUE_TYPE_BASE )) 

        此函数用于使用动态方式创建队列,队列所需的内存空间由 FreeRTOS FreeRTOS 管理的堆中分配

        前面说 FreeRTOS 基于队列实现了多种功能,每一种功能对应一种队列类型,队列类型的 queue.h 文件中有定义:

#define queueQUEUE_TYPE_BASE                  	( ( uint8_t ) 0U )	/* 队列 */
#define queueQUEUE_TYPE_SET                  	( ( uint8_t ) 0U )	/* 队列集 */
#define queueQUEUE_TYPE_MUTEX                 	( ( uint8_t ) 1U )	/* 互斥信号量 */
#define queueQUEUE_TYPE_COUNTING_SEMAPHORE    	( ( uint8_t ) 2U )	/* 计数型信号量 */
#define queueQUEUE_TYPE_BINARY_SEMAPHORE     	( ( uint8_t ) 3U )	/* 二值信号量 */
#define queueQUEUE_TYPE_RECURSIVE_MUTEX       	( ( uint8_t ) 4U )	/* 递归互斥信号量 */

往队列写入消息API函数:

函数

描述

xQueueSend()

往队列的尾部写入消息

xQueueSendToBack()

xQueueSend()

xQueueSendToFront()

往队列的头部写入消息

xQueueOverwrite()

覆写队列消息(只用于队列长度为 1 的情况)

xQueueSendFromISR()

在中断中往队列的尾部写入消息

xQueueSendToBackFromISR()

xQueueSendFromISR()

xQueueSendToFrontFromISR()

在中断中往队列的头部写入消息

xQueueOverwriteFromISR()

在中断中覆写队列消息(只用于队列长度为 1 的情况)

 队列写入消息:

#define  xQueueSend(  xQueue,   pvItemToQueue,   xTicksToWait  )	 					\    xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
#define  xQueueSendToBack(  xQueue,   pvItemToQueue,   xTicksToWait  )					 \    xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
#define  xQueueSendToFront(  xQueue,   pvItemToQueue,   xTicksToWait  ) 					\   xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT )
#define  xQueueOverwrite(  xQueue,   pvItemToQueue  ) 								\    xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), 0, queueOVERWRITE )

        可以看到这几个写入函数调用的是同一个函数xQueueGenericSend( ),只是指定了不同的写入位置!

        队列一共有 3 种写入位置 :

#define queueSEND_TO_BACK         ( ( BaseType_t ) 0 )		/* 写入队列尾部 */
#define queueSEND_TO_FRONT        ( ( BaseType_t ) 1 )		/* 写入队列头部 */
#define queueOVERWRITE            ( ( BaseType_t ) 2 )		/* 覆写队列*/

        注意:覆写方式写入队列,只有在队列的队列长度为 1 时,才能够使用

往队列写入消息函数入口参数解析:

BaseType_t  xQueueGenericSend(  QueueHandle_t 	    xQueue,const void * const 	pvItemToQueue,TickType_t 		    xTicksToWait,const BaseType_t 	xCopyPosition   );

从队列读取消息API函数:

函数

描述

xQueueReceive()

从队列头部读取消息,并删除消息

xQueuePeek()

从队列头部读取消息

xQueueReceiveFromISR()

在中断中从队列头部读取消息,并删除消息

xQueuePeekFromISR()

在中断中从队列头部读取消息

队列读取消息函数入口参数解析:

BaseType_t    xQueueReceive( QueueHandle_t   xQueue,  void *          const pvBuffer,  TickType_t      xTicksToWait )

        此函数用于在任务中,从队列中读取消息,并且消息读取成功后,会将消息从队列中移除。

BaseType_t   xQueuePeek( QueueHandle_t   xQueue,   void * const    pvBuffer,   TickType_t      xTicksToWait )

        此函数用于在任务中,从队列中读取消息, 但与函数 xQueueReceive()不同,此函数在成功读取消息后,并不会移除已读取的消息

队列相关API函数工作流程具体解析:

创建队列:xQueueCreate( )

        实际执行的是xQueueGenericCreate( )

xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), ( queueQUEUE_TYPE_BASE ) )

        1、计算队列需要多大内存 xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize )

        2、为队列申请内存,申请大小:sizeof( Queue_t ) + xQueueSizeInBytes ,前面部分存放结构体成员,后面就是队列项大小

        3、判断内存是否申请成功,成功即计算出队列项存储区的首地址

        4、调用prvInitialiseNewQueue()初始化新队列pxNewQueue

                (1)、初始化队列结构体成员变量

                (2)、调用xQueueGenericReset()复位队列

                        1)、初始化其他队列结构体成员变量

                        2)、判断要复位的队列是否为新创建的队列

                                不是新创建队列,那就复位它,将列表xTasksWaitingToSend移除,是新创建的队列,那就初始化这两个列表xTasksWaitingToSend和xTasksWaitingToReceive

往队列写入数据(入队):xQueueSend( )

        实际执行的是:xQueueGenericSend( )

xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )

        1、进入临界区(关中断)

        2、判断队列是否已满?

        3、队列有空闲位置
                (1)、只有在队列有空闲位置或为覆写的情况才能写入消息

                (2)、当有空闲位置或覆写时:将待写入消息按指定写入方式复制到队列中

                (3)、判断是否有因为读不到消息而阻塞的任务,有的话,将解除阻塞态,通过这个函数

                        判断调度器是否被挂起,没有挂起:将移除相应的事件列表项和状态列表项,并且将任务添加到就绪列表中。挂起:将移除事件列表项,将事件列表项添加到等待就绪列表:xPendingReadyList,当调用恢复调度器时xTaskResumeAll( ),xPendingReadyList中多任务就会被处理
                (4)、退出临界区(开中断)

        3、队列已满

                (1)、此时不能写入消息,因此要将任务阻塞

                (2)、如果阻塞时间为0 ,代表不阻塞,直接返回队列满错误

                (3)、如果阻塞时间不为0,任务需要阻塞,记录下此时系统节拍计数器的值和溢出次数,用于下面对阻塞时间进行补偿(补偿就是计算剩余的阻塞时间还有多久)

                (4)、判断阻塞时间补偿后,是否还需要阻塞

                        需要:将任务的事件列表项添加到等待发送列表中,将任务状态列表项添加到阻塞列表中进行阻塞,队列解锁,恢复调度器。不需要:队列解锁,恢复调度器,返回队列满错误。

                        不需要:队列解锁,恢复调度器,返回队列满错误
 

  从队列读取数据(出队):xQueueReceive( )

        1、进入临界区(关中断)

        2、判断队列是否为空

        3、有数据

                (1)、使用函数prvCopyDataFromQueue( )拷贝数据

                (2)、队列项目个数减一

                (3)、因为前面已经减了一个队列项,所以队列已经有空位了,如果xTasksWaitingToSend等待发送列表中,有任务,则解除阻塞态,通过这个函数xTaskRemoveFromEventList( )

                        判断调度器是否被挂起,没有挂起:将移除相应的事件列表项和状态列表项,并且将任务添加到就绪列表中。挂起:将移除事件列表项,将事件列表项添加到等待就绪列表:xPendingReadyList,当调用恢复调度器时xTaskResumeAll( ),xPendingReadyList中多任务就会被处理

                (4)、退出临界区(开中断)

        4、为空

                (1)、此时读取不到消息,因此要将任务阻塞

                (2)、如果阻塞时间为0 ,代表不阻塞,直接返回队列空错误

                (3)、如果阻塞时间不为0,任务需要阻塞,记录下此时系统节拍计数器的值和溢出次数,用于下面对阻塞时间进行补偿

                (4)、判断阻塞时间补偿后,是否还需要阻塞

                        需要:将任务的事件列表项添加到等待接收列表中,将任务状态列表项添加到阻塞列表中进行阻塞,队列解锁,恢复调度器。

                        不需要:队列解锁,恢复调度器,返回队列空错误

http://www.yayakq.cn/news/759930/

相关文章:

  • 网站的后台是怎么做的新冠最新消息实时动态
  • 工信部网站备案系统登录网站搭建服务平台
  • 河北互联思维网站建设张家界seo优化首选
  • 网站开发定制公司鞍山微信小程序定制开发
  • 专业制作网站 地摊惠民建设局网站
  • 网站建设的方法个人网站网站建设方案书
  • 长沙优化网站排名做家居的网站
  • 云南网是什么性质的单位网络优化软件
  • 专门做外贸的的网站有哪些京东网上购物官方网站
  • 网站推广话术与技巧网站运营托管咨询
  • 网站提交百度收录中国中建设计网站
  • 做网站必须会宁波百度seo代理
  • 外贸建站代理开发一个网上商城
  • 网站插件开发外加工平台
  • 网站建设要准备什么资料wordpress 允许函数
  • 做网站设计都需要什么软件商店网站在线设计
  • 网站备案拍照淘宝指数查询工具
  • seo网站概述学计算机的出路
  • 只做女性的网站软件培训机构排行榜
  • h5互动的网站深圳网站改版公司
  • 网站如何做谷歌优化seo搜索引擎优化平台
  • 怎么更改网站关键词wordpress首页文章列表丰富多样
  • 网站提取规则怎么设置建设网站以什么为导向
  • 和县建设局网站团队拓展游戏项目大全
  • wordpress网站音乐播放器网络服务单位招标
  • 东莞网站推广衣裙iis 发布网站内部服务器错误
  • 北京网站建设模板案例网页小游戏玩不了怎么办
  • php mysql开发网站开发上位机软件开发教程
  • 普通企业网站营销广元市建设局网站首页
  • 网站跳出率一般多少浏览国外网站dns