IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> FreeRtos队列复习 -> 正文阅读

[嵌入式]FreeRtos队列复习

一、基础概念

作用:队列是为了任务与任务、任务与中断之间的通信而准备的,可以在任务与任务、任务与中断之间传递消息,队列中可以存储有限的、大小固定的数据项目。

二、运行机制

在脑海中想像不同任务之间,其需要交互数据的时候,需要的一种通信机制,这种机制在该操作系统就是“消息队列”其特点是任何建立的任务都可以向队列中发送消息和取信息。

1、首先就是创建队列

  • 创建消息队列时 FreeRTOS 会先给消息队列分配一块内存空间,这块内存的大小等于消息队列控制块大小加上(单个消息空间大小与消息队列长度的乘积),接着再初始化消息队列,此时消息队列为空。
  • 初始化消息队列的时候同时会初始内存空间,用于保存消息队列的一些信息如消息的存储位置,头指针 pcHead、尾指针pcTail、消息大小 uxItemSize 以及队列长度 uxLength 等。同时每个消息队列都与消息空间在同一段连续的内存空间中(消息队列是消息空间的别名)。在创建成功的时候,这些内存就被占用了,只有删除了消息队列的时候,这段内存才会被释放掉。其消息队列发送拷贝的数据不能超过其创建时候设置的大小。

2、队列发送消息(入队机制)

- 分三种情况

  • 任务或者中断服务程序立即发送消息。

对应场景: 如果队列未满或者允许覆盖入队,FreeRTOS 会将消息拷贝到消息队列队尾

  • 由用户指定的阻塞超时时间进行阻塞

对应场景①:在设置的阻塞超时时间中,如果队列一直不允许入队,该任务将保持阻塞状态以等待队列允许入队。
对应场景①:当其它任务从其等待的队列中读取入了数据(队列未满),该任务将自动由阻塞态转移为就绪态。
也就是在等待过程中队列会一直按照设定时间入队,但是当队列中提前有消息被读走时候会提前入队。

-超过设置阻塞时间

即使队列中还不允许入队,任务也会自动从阻塞态转移为就绪态,此时发送消息的任务或者中断程序会收到一个错误码 errQUEUE_FULLAPI系统自动发出。

发送紧急消息的过程与发送消息几乎一样,唯一的不同是,当发送紧急消息时,发送的位置是消息队列队头而非队尾,这样,接收者就能够优先接收到紧急消息,从而及时进行消息处理。

3、队列接收消息(出队机制)

  • 读取消息时候,如果队列为空,该任务将保持阻塞状态以等待队列数据有效。
  • 当其它任务或中断服务程序往其等待的队列中写入了数据,该任务将自动由阻塞态转移为就绪态。任务程序继续执行下去。
  • 当等待的时间超过了指定的阻塞时间,即使队列中尚无有效数据,任务也会自动从阻塞态转移为就绪态。继续执行程序。

注意事项:

  • FreeRtos只有在任务中发送消息使用队列,才允许进行阻塞状态,而在中断中发送消息不允许带有阻塞机制的,需要调用在中断中发送消息的API 函数接口,因为发送消息的上下文环境是在中断中,不允许有阻塞的情况。
  • 假如有多个任务阻塞在一个消息队列中,那么这些阻塞的任务将按照任务优先级进行排序优先级高的任务将优先获得队列的访问权。

三、 API函数

使用队列模块的典型流程如下:

  • 创建消息队列
  • 写队列操作
  • 读队列操作
  • 删除队列
    API官网
    https://freertos.org/a00116.html
    send和recive实质上是拷贝消息队列。
    消息队列,发、收、排队的时候三种情况都是叫队列

四、实验代码分析

野火的很简单就任务间的收发,发采用立即发,收阻塞收没有实战使用价值

static void Send_Task(void* parameter)
{	 
  BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */
  uint32_t send_data1 = 1;
  uint32_t send_data2 = 2;
  while (1)
  {
    if( Key_Scan(KEY1_GPIO_PORT,KEY1_GPIO_PIN) == KEY_ON )
    {/* K1 被按下 */
      printf("发送消息send_data1!\n");
      xReturn = xQueueSend( Test_Queue, /* 消息队列的句柄 */
                            &send_data1,/* 发送的消息内容 */
                            0 );        /* 等待时间 0 */
      if(pdPASS == xReturn)
        printf("消息send_data1发送成功!\n\n");
    } 
    if( Key_Scan(KEY2_GPIO_PORT,KEY2_GPIO_PIN) == KEY_ON )
    {/* K2 被按下 */
      printf("发送消息send_data2!\n");
      xReturn = xQueueSend( Test_Queue, /* 消息队列的句柄 */
                            &send_data2,/* 发送的消息内容 */
                            0 );        /* 等待时间 0 */
      if(pdPASS == xReturn)
        printf("消息send_data2发送成功!\n\n");
    }
    vTaskDelay(20);/* 延时20个tick */
  }
}

static void Receive_Task(void* parameter)
{	
  BaseType_t xReturn = pdTRUE;/* 定义一个创建信息返回值,默认为pdTRUE */
  uint32_t r_queue;	/* 定义一个接收消息的变量 */
  while (1)
  {
    xReturn = xQueueReceive( Test_Queue,    /* 消息队列的句柄 */
                             &r_queue,      /* 发送的消息内容 */
                             portMAX_DELAY); /* 等待时间 一直等 */
    if(pdTRUE == xReturn)
      printf("本次接收到的数据是%d\n\n",r_queue);
    else
      printf("数据接收出错,错误代码0x%lx\n",xReturn);
  }
}

在这里插入图片描述
正点的
涉及了中断与任务,任务与任务。

任务与任务之间没什么好分析的就是阻塞时间为10的发送,与创建一个任务阻塞等待接收处理事件。定时器接收队列消息

void TIM2_IRQHandler(void)
{
	u8 *buffer;
	BaseType_t xTaskWokenByReceive=pdFALSE;
	BaseType_t err;
	
	if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET) //溢出中断
	{
		buffer=mymalloc(SRAMIN,USART_REC_LEN);
        if(Message_Queue!=NULL)
        {
			memset(buffer,0,USART_REC_LEN);	//清除缓冲区
			err=xQueueReceiveFromISR(Message_Queue,buffer,&xTaskWokenByReceive);//请求消息Message_Queue
            if(err==pdTRUE)			//接收到消息//其函数xQueueReceiveFromISR返回值为pdTRUE
            {
				disp_str(buffer);	//在LCD上显示接收到的消息
            }
        }
		myfree(SRAMIN,buffer);		//释放内存
		
		portYIELD_FROM_ISR(xTaskWokenByReceive);//如果需要的话进行一次任务切换
	}
	TIM_ClearITPendingBit(TIM2,TIM_IT_Update);  //清除中断标志位
}

队列接收中断函数解释
在这里插入图片描述

	if((USART_RX_STA&0x8000)&&(Message_Queue!=NULL))
	{
		xQueueSendFromISR(Message_Queue,USART_RX_BUF,&xHigherPriorityTaskWoken);//向队列中发送数据
		
		USART_RX_STA=0;	
		memset(USART_RX_BUF,0,USART_REC_LEN);//清除数据接收缓冲区USART_RX_BUF,用于下一次数据接收
	
		portYIELD_FROM_ISR(xHigherPriorityTaskWoken);//如果需要的话进行一次任务切换
	}

待验证:xHigherPriorityTaskWoken这个参数官方解释,估计是返回值的由来,设置好这个参数会自动返回函数值与执行任务切换的选择
在这里插入图片描述

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-03-30 18:41:35  更:2022-03-30 18:43:09 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 6:35:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码