HI3861学习笔记(10)——LiteOS(CMSIS-RTOS2)消息队列

一、简介

1.1 消息队列

消息队列,是一种常用于任务间通信的数据结构,实现了接收来自任务或中断的不固定长度的消息,并根据不同的接口选择传递消息是否存放在自己空间。任务能够从队列里面读取消息,当队列中的消息是空时,挂起读取任务;当队列中有新消息,挂起的读取任务被唤醒并处理新消息。

用户在处理业务时,消息队列提供了异步处理机制,允许将一个消息放入队列,但并不立即处理它,同时队列还能起到缓冲消息作用。

LiteOS中使用队列数据结构实现任务异步通信工作,具有如下特性:

  • 消息以先进先出方式排队,支持异步读写工作方式。
  • 读队列和写队列都支持超时机制。
  • 发送消息类型由通信双方约定,可以允许不同长度(不超过队列节点最大值)消息。
  • 一个任务能够从任意一个消息队列接收和发送消息。
  • 多个任务能够从同一消息队列接收和发送消息。
  • 当队列使用结束后,如果是动态申请的内存,需要通过释放内存函数回收。

1.2 消息队列的运作机制

创建队列时,根据用户传入队列长度和消息节点大小来开辟相应的内存空间以供该队列使用,返回队列ID。

在队列控制块中维护一个消息头节点位置Head和一个消息尾节点位置Tail来表示当前队列中消息存储情况。Head表示队列中被占用消息的起始位置。Tail表示队列中被空闲消息的起始位置。刚创建时Head和Tail均指向队列起始位置。

写队列时,根据Tail找到被占用消息节点末尾的空闲节点作为数据写入对象。

读队列时,根据Head找到最先写入队列中的消息节点进行读取。

删除队列时,根据传入的队列ID寻找到对应的队列,把队列状态置为未使用,释放原队列所占的空间,对应的队列控制头置为初始状态。

二、API说明

以下任务管理接口位于 kernel/liteos_m/components/cmsis/2.0/cmsis_os2.h

业务BUILD.gn中包含路径

include_dirs = [
        "//utils/native/lite/include",
        "//kernel/liteos_m/components/cmsis/2.0",
    ]

2.1 osMessageQueueNew

功能 创建消息队列,不能在中断服务调用该函数
函数定义 osMessageQueueId_t osMessageQueueNew (uint32_t msg_count,uint32_t msg_size,const osMessageQueueAttr_t *attr)
参数 msg_count:队列中的最大消息数
msg_size:最大消息大小(以字节为单位)
attr:消息队列属性;空:默认值
返回 消息队列ID

2.2 osMessageQueuePut

功能 发送消息,如果参数timeout设置为0,可以从中断服务例程调用
函数定义 osStatus_t osMessageQueuePut (osMessageQueueId_t mq_id,const void *msg_ptr,uint8_t msg_prio,uint32_t timeout)
参数 mq_id:由osMessageQueueNew获得的消息队列ID
msg_ptr:要发送的消息
msg_prio:指优先级
timeout:超时值
返回 0 - 成功,非0 - 失败

2.3 osMessageQueueGet

功能 获取消息,如果参数timeout设置为0,可以从中断服务例程调用
函数定义 osStatus_t osMessageQueueGet (osMessageQueueId_t mq_id,void *msg_ptr,uint8_t *msg_prio,uint32_t timeout)
参数 mq_id:由osMessageQueueNew获得的消息队列ID
msg_ptr:指针指向队列中获取消息的缓冲区指针
msg_prio:指优先级
timeout:超时值
返回 0 - 成功,非0 - 失败

2.4 osMessageQueueDelete

功能 删除消息队列
函数定义 osStatus_t osMessageQueueDelete (osMessageQueueId_t mq_id)
参数 mq_id:消息队列ID
返回 0 - 成功,非0 - 失败

三、通过消息队列进行线程之间交换消息

编译时在业务BUILD.gn中包含路径

include_dirs = [
        "//utils/native/lite/include",
        "//kernel/liteos_m/components/cmsis/2.0",
    ]

在Message_example函数中,通过osMessageQueueNew()函数创建了消息队列ID,Thread_MsgQueue1()函数中通过osMessageQueuePut()函数向消息队列中发送消息。在Thread_MsgQueue2()函数中通过osMessageQueueGet()函数读取消息队列中的消息比打印出来。

void Thread_MsgQueue1 (void *argument) 
{
  (void)argument; 

  msg.Buf = "Hello BearPi-HM_Nano!";                                         // do some work...
  msg.Idx    = 0U;
  while (1)
  {
    osMessageQueuePut(mid_MsgQueue, &msg, 0U, 0U);
    osThreadYield();                                            // suspend thread   
    osDelay(100);
  }
}
 
void Thread_MsgQueue2 (void *argument) 
{
  (void)argument;
  osStatus_t status;

  while (1) {
    // Insert thread code here...
    status = osMessageQueueGet(mid_MsgQueue, &msg, NULL, 0U);   // wait for message
    if (status == osOK) {
      printf("Message Queue Get msg:%s\n",msg.Buf);
    }
  }
}

static void Message_example (void) {
 
  mid_MsgQueue = osMessageQueueNew(MSGQUEUE_OBJECTS, 100, NULL);
  if (mid_MsgQueue == NULL) {
    printf("Falied to create Message Queue!\n");
  } 
  osThreadAttr_t attr;
  
  attr.attr_bits = 0U;
  attr.cb_mem = NULL;
  attr.cb_size = 0U;
  attr.stack_mem = NULL;
  attr.stack_size = 1024*10;
  attr.priority = 25;

  attr.name = "Thread_MsgQueue1";
  if (osThreadNew(Thread_MsgQueue1, NULL, &attr) == NULL) {
      printf("Falied to create Thread_MsgQueue1!\n");
  }
  attr.name = "Thread_MsgQueue2";
  if (osThreadNew(Thread_MsgQueue2, NULL, &attr) == NULL) {
      printf("Falied to create Thread_MsgQueue2!\n");
  }
}

示例代码编译烧录代码后,按下开发板的RESET按键,通过串口助手查看日志,会打印从消息队列中获取的消息。

Message Queue Get msg:Hello BearPi-HM_Nano!
Message Queue Get msg:Hello BearPi-HM_Nano!
Message Queue Get msg:Hello BearPi-HM_Nano!
Message Queue Get msg:Hello BearPi-HM_Nano!
Message Queue Get msg:Hello BearPi-HM_Nano!

• 由 Leung 写于 2021 年 7 月 18 日

• 参考:【鸿蒙2.0设备开发教程】小熊派HarmonyOS 鸿蒙·季 开发教程

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,591评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,448评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,823评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,204评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,228评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,190评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,078评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,923评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,334评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,550评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,727评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,428评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,022评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,672评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,826评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,734评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,619评论 2 354

推荐阅读更多精彩内容