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 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> CMSIS/FreeRTOS中队列(Queue)的使用 -> 正文阅读

[嵌入式]CMSIS/FreeRTOS中队列(Queue)的使用

在有流式数据处理的嵌入式系统中,队列(Queue)是几乎必然被使用的工具,但大多数开发板提供的FreeRTOS例程是不包含队列的,要使用还要自己研究。这次我的样例把串口收到的数据按字节塞入队列,再让另一个线程处理,是一种相对画蛇添足的做法,这么做主要目的是说明队列如何使用。队列更适合用来处理ADC/DAC采样数据、通信模块固定大小的数据包等。

这次我仍是使用自制的STM32F0模块实验,与上次一样,我们还是用STM32CubeMX来生成初始代码,在FreeRTOS中添加队列:
队列设置这里,我设队列的每个项目为uint8_t类型,队列元素最多16个。其实更常见的是设置成某个结构体,这可以等到代码生成后,在代码里修改。这一设置变成了生成代码中的以下代码:

osMessageQueueId_t QueueUartByteHandle;
const osMessageQueueAttr_t QueueUartByte_attributes = {
  .name = "QueueUartByte"
};

QueueUartByteHandle = osMessageQueueNew (16, sizeof(uint8_t), &QueueUartByte_attributes);

FreeRTOS的队列占用空间可以根据以下公式计算:
S p a c e ( B y t e s ) = 92 + E l e m S i z e × n E l e m Space(Bytes) =92 + ElemSize \times nElem Space(Bytes)=92+ElemSize×nElem
比如我这里设置一个元素是1字节,最多16个,那么就会占用92+16=108字节。

我们还是用CMSIS v2的API,而非直接用FreeRTOS的API。参考CMSIS的文档,CMSIS把队列叫做“消息队列”(Message Queue),实现FIFO功能,入队和出队API分别为:

osStatus_t 	osMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout);
osStatus_t 	osMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout);

其中,mq_id是队列的变量名,即我们定义的QueueUartByteHandlemsg_ptr是要入队/出队的数据块指针;msg_prio比较奇怪,入队和出队对应的变量类型不同,表示优先级,但一般都赋NULL;最后的timeout,不等待就为0,永远等待用osWaitForever。这两个函数都可以在中断中运行。

对于FreeRTOS而言,各个API都有普通线程版本和中断版本,CMSIS在编写它的API时,就根据当时状态判断,以CMISIS的osMessageQueuePut为例,通过IS_IRQ()宏进行判断:

// From cmsis_os2.c
osStatus_t osMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout) {
  QueueHandle_t hQueue = (QueueHandle_t)mq_id;
  osStatus_t stat;
  BaseType_t yield;

  (void)msg_prio; /* Message priority is ignored */

  stat = osOK;

  if (IS_IRQ()) {
    if ((hQueue == NULL) || (msg_ptr == NULL) || (timeout != 0U)) {
      stat = osErrorParameter;
    }
    else {
      yield = pdFALSE;

      if (xQueueSendToBackFromISR (hQueue, msg_ptr, &yield) != pdTRUE) {
        stat = osErrorResource;
      } else {
        portYIELD_FROM_ISR (yield);
      }
    }
  }
  else {
    if ((hQueue == NULL) || (msg_ptr == NULL)) {
      stat = osErrorParameter;
    }
    else {
      if (xQueueSendToBack (hQueue, msg_ptr, (TickType_t)timeout) != pdPASS) {
        if (timeout != 0U) {
          stat = osErrorTimeout;
        } else {
          stat = osErrorResource;
        }
      }
    }
  }

  return (stat);
}

我让串口接收中断回调函数把接收到的数据压入队列,让一个任务线程去处理,中断回调通过一个计数信号量通知任务,信号量也在STM32CubeMX中定义:
计数信号量代码生成后,还要把信号量的初始值改为0:

semAddToQueueHandle = osSemaphoreNew(16, 0, &semAddToQueue_attributes);

最后,我把中断回调函数和任务线程函数的代码拍上来,展示如何信号量如何同步、如何向队列存取数据:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	uint8_t recv_char;
	HAL_UART_Receive_IT(huart, &recv_char, 0x01);
	osMessageQueuePut(QueueUartByteHandle, &recv_char, 0U, 0U); // without waiting
	osSemaphoreRelease(semAddToQueueHandle);
	HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13); // just to show uart is working
}
void task1fxn(void *argument)
{
  /* Infinite loop */
	uint8_t  recv_char;
  for(;;)
  {
		osSemaphoreAcquire(semAddToQueueHandle,osWaitForever);
    osDelay(1);
		osMessageQueueGet(QueueUartByteHandle, &recv_char, NULL, 0);
		HAL_UART_Transmit_IT(&huart1, &recv_char, 0x01);
  }
}
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-01-30 19:05:27  更:2022-01-30 19:07:51 
 
开发: 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 10:47:27-

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