RTX RTOS操作实例分析之---邮箱(mailbox)

0 Preface/Foreword

1 邮箱(mailbox)

1.1 mailbox ID定义

 static osMailQId app_mailbox = NULL;

 1.2 定义mailbox结构体变量

#define osMailQDef(name, queue_sz, type) \
static void *os_mail_p_##name[2]; \
const char mail_##name[] = #name; \
const osMailQDef_t os_mailQ_def_##name = \
{ (queue_sz), sizeof(type), (&os_mail_p_##name), \
  { NULL, 0U, NULL, 0U, NULL, 0U }, \
  { mail_##name, 0U, NULL, 0U, NULL, 0U } }

osMailQDef,三个参数

  • name,名字
  • queue_sz,队列中,总共元素个数
  • type,元素大小

实例分析

 osMailQDef (app_mailbox, APP_MAILBOX_MAX, APP_MESSAGE_BLOCK);

#define APP_MAILBOX_MAX (20) 

 APP_MAILBOX_MAX: 20

APP_MESSAGE_BLOCK,为一个结构体类型数据,具体见section 1.3。 

1.3 APP_MESSAGE_BLOCK

 typedef struct {
    uint32_t src_thread;
    uint32_t dest_thread;
    uint32_t system_time;
    uint32_t mod_id;
    enum APP_MOD_LEVEL_E mod_level;
    APP_MESSAGE_BODY msg_body;
} APP_MESSAGE_BLOCK;

 1.3.1 APP_MESSAGE_BODY

typedef struct {
    uint32_t message_id;
    uint32_t message_ptr;
    uint32_t message_Param0;
    uint32_t message_Param1;
    uint32_t message_Param2;
    float    message_Param3;
#if defined(USE_BASIC_THREADS)
    void* p;
#endif
} APP_MESSAGE_BODY;

1.3.2 APP_MOD_LEVEL_E

enum APP_MOD_LEVEL_E {
    APP_MOD_LEVEL_0 = 0,
    APP_MOD_LEVEL_1,
    APP_MOD_LEVEL_2,
}; 

1.3.3 APP_MODULE_ID_T

#ifndef CHIP_SUBSYS_SENS
enum APP_MODUAL_ID_T {
    APP_MODUAL_KEY = 0,
    APP_MODUAL_AUDIO,
    APP_MODUAL_BATTERY,
    APP_MODUAL_BT,
    APP_MODUAL_FM,
    APP_MODUAL_SD,
    APP_MODUAL_LINEIN,
    APP_MODUAL_USBHOST,
    APP_MODUAL_USBDEVICE,
    APP_MODUAL_WATCHDOG,
    APP_MODUAL_ANC,
    APP_MODUAL_VOICE_ASSIST,
    APP_MODUAL_SMART_MIC,
    APP_MODUAL_CAPSENSOR,
#ifdef __PC_CMD_UART__
    APP_MODUAL_CMD,
#endif
#ifdef TILE_DATAPATH
    APP_MODUAL_TILE,
#endif
    APP_MODUAL_MIC,
#ifdef VOICE_DETECTOR_EN
    APP_MODUAL_VOICE_DETECTOR,
#endif
#ifdef AUDIO_HEARING_COMPSATN
    APP_MODUAL_HEAR_COMP,
#endif
    APP_MODUAL_OHTER,
#if defined(USE_BASIC_THREADS)
    APP_MODUAL_AUDIO_MANAGE,
    APP_MODUAL_MEDIA,
    APP_MODUAL_BTSYNC,
    APP_MODUAL_ANC_FADE,
    APP_MODUAL_UX,
    APP_MODUAL_TWSCTRL,
#else
    APP_MODUAL_CUSTOM0,
    APP_MODUAL_CUSTOM1,
    APP_MODUAL_CUSTOM2,
    APP_MODUAL_CUSTOM3,
    APP_MODUAL_CUSTOM4,
    APP_MODUAL_CUSTOM5,
#endif
#if defined (_OSM_HOST_FUNC_)
    APP_MODUAL_P27WLC_II,
#endif
    APP_MODUAL_NUM
};

#else /* defined(CHIP_SUBSYS_SENS) */
enum APP_MODUAL_ID_T {
    APP_MODUAL_KEY = 0,
    APP_MODUAL_AUDIO,
#ifdef VOICE_DETECTOR_EN
    APP_MODUAL_VOICE_DETECTOR,
#endif
    APP_MODUAL_OHTER,

    APP_MODUAL_NUM
};
#endif /* CHIP_SUBSYS_SENS */

CHIP_SUBSYS_SENS :该宏有没有定义呢?通过makefile文件追溯可知,该宏没有定义,详情如下:

 1.4 获取邮箱结构体变量

 osMailQ(app_mailbox)

app_mailbox,该名字和定义时的名字需要相同。

1.5 创建mailbox对象(object) 

 app_mailbox = osMailCreate(osMailQ(app_mailbox), NULL);

有两个参数:

  • 定义的结构体变量地址
  • 线程ID,没有实际作用 

 1.5.1 osMailCreate implementation

osMailQId osMailCreate (const osMailQDef_t *queue_def, osThreadId thread_id) {
  os_mail_queue_t *ptr;
  (void)thread_id;

  if (queue_def == NULL) {
    return (osMailQId)NULL;
  }

  ptr = queue_def->mail;
  if (ptr == NULL) {
    return (osMailQId)NULL;
  }

  ptr->mp_id = osMemoryPoolNew  (queue_def->queue_sz, queue_def->item_sz, &queue_def->mp_attr);
  ptr->mq_id = osMessageQueueNew(queue_def->queue_sz, sizeof(void *), &queue_def->mq_attr);
  if ((ptr->mp_id == (osMemoryPoolId_t)NULL) || (ptr->mq_id == (osMessageQueueId_t)NULL)) {
    if (ptr->mp_id != (osMemoryPoolId_t)NULL) {
      osMemoryPoolDelete(ptr->mp_id);
    }
    if (ptr->mq_id != (osMessageQueueId_t)NULL) {
      osMessageQueueDelete(ptr->mq_id);
    }
    return (osMailQId)NULL;
  }

  return (osMailQId)ptr;
}

主要功能

  • 根据mailbox的大小,动态分配内存池
  • 根据mailbox大小,动态分配消息队列 
  • 返回一个对象指针,该指针原始值为数组。

1.5.2  os_mail_queue_t

 typedef struct os_mail_queue_s {
  osMemoryPoolId_t   mp_id;
  osMessageQueueId_t mq_id;
} os_mail_queue_t;

 作用:保护两个成员,分别用于存放memory pool ID和message queue ID。

1.6 osMailGet 

osEvent osMailGet (osMailQId queue_id, uint32_t millisec) {
  os_mail_queue_t *ptr = (os_mail_queue_t *)queue_id;
  osStatus_t       status;
  osEvent          event;
  void            *mail;

  if (ptr == NULL) {
    event.status = osErrorParameter;
    return event;
  }

  status = osMessageQueueGet(ptr->mq_id, &mail, NULL, millisec);
  switch (status) {
    case osOK:
      event.status = osEventMail;
      event.value.p = mail;
      break;
    case osErrorResource:
      event.status = osOK;
      break;
    case osErrorTimeout:
      event.status = osEventTimeout;
      break;
    default:
      event.status = status;
      break;
  }
  return event;
}

主要功能:

  • 通过osMessageQueueGet获取消息 

1.6.1 osMessageQueueGet

从消息队列中获取消息,或者如果消息队列为空则等待timetout 

/// Get a Message from a Queue or timeout if Queue is empty.
osStatus_t osMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout) {
  osStatus_t status;

  EvrRtxMessageQueueGet(mq_id, msg_ptr, msg_prio, timeout);
  if (IsIrqMode() || IsIrqMasked()) {
    status = isrRtxMessageQueueGet(mq_id, msg_ptr, msg_prio, timeout);
  } else {
    status =  __svcMessageQueueGet(mq_id, msg_ptr, msg_prio, timeout);
  }
  return status;
}

NOTE:

  •  __svcMessageQueueGet在哪里实现?库?内敛函数?宏函数?

验证发现:所有的都是调用__svcMessageQueueGet而不是isrRtxMessageQueueGet。(如下截图所示)

 

1.7 osMailAlloc 

void *osMailAlloc (osMailQId queue_id, uint32_t millisec) {
  os_mail_queue_t *ptr = (os_mail_queue_t *)queue_id;

  if (ptr == NULL) {
    return NULL;
  }
  return osMemoryPoolAlloc(ptr->mp_id, millisec);
}

/// Allocate a memory block from a Memory Pool.
void *osMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout) {
  void *memory;

  EvrRtxMemoryPoolAlloc(mp_id, timeout);
  if (IsIrqMode() || IsIrqMasked()) {
    memory = isrRtxMemoryPoolAlloc(mp_id, timeout);
  } else {
    memory =  __svcMemoryPoolAlloc(mp_id, timeout);
  }
  return memory;
}

NOTE:

  • 从内存池中分配一个内存块

1.8 osMailPut 

osStatus osMailPut (osMailQId queue_id, const void *mail) {
  os_mail_queue_t *ptr = (os_mail_queue_t *)queue_id;

  if (ptr == NULL) {
    return osErrorParameter;
  }
  if (mail == NULL) {
    return osErrorValue;
  }
  return osMessageQueuePut(ptr->mq_id, &mail, 0U, 0U);
}

NOTE:osMessageQueuePut参数中,为什么需要取mail的地址? 如果不取地址,会有什么结果?

验证发现:机器死机,插适配器充电无法恢复,并且无法继续固件升级。(设备变砖) 

/// Put a Message into a Queue or timeout if Queue is full.
osStatus_t osMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout) {
  osStatus_t status;

  EvrRtxMessageQueuePut(mq_id, msg_ptr, msg_prio, timeout);
  if (IsIrqMode() || IsIrqMasked()) {
    status = isrRtxMessageQueuePut(mq_id, msg_ptr, msg_prio, timeout);
  } else {
    status =  __svcMessageQueuePut(mq_id, msg_ptr, msg_prio, timeout);
  }
  return status;
}

1.9 osMailFree

osStatus osMailFree (osMailQId queue_id, void *mail) {
  os_mail_queue_t *ptr = (os_mail_queue_t *)queue_id;

  if (ptr == NULL) {
    return osErrorParameter;
  }
  if (mail == NULL) {
    return osErrorValue;
  }
  return osMemoryPoolFree(ptr->mp_id, mail);
}

/// Return an allocated memory block back to a Memory Pool.
osStatus_t osMemoryPoolFree (osMemoryPoolId_t mp_id, void *block) {
  osStatus_t status;

  EvrRtxMemoryPoolFree(mp_id, block);
  if (IsIrqMode() || IsIrqMasked()) {
    status = isrRtxMemoryPoolFree(mp_id, block);
  } else {
    status =  __svcMemoryPoolFree(mp_id, block);
  }
  return status;
}

2 生产者(producer)

2.1 app_mailbox_put

int app_mailbox_put(APP_MESSAGE_BLOCK* msg_src)
{
    osStatus status;
//    osMutexWait(app_mutex_id, osWaitForever);

    APP_MESSAGE_BLOCK *msg_p = NULL;

    msg_p = (APP_MESSAGE_BLOCK*)osMailAlloc(app_mailbox, 0);

    if (!msg_p){
        osEvent evt;
        TRACE_IMM(0,"osMailAlloc error dump");
        for (uint8_t i=0; i<APP_MAILBOX_MAX; i++){
            evt = osMailGet(app_mailbox, 0);
            if (evt.status == osEventMail) {
                TRACE_IMM(9,"cnt:%d mod:%d level:%d src:%08x tim:%d id:%8x ptr:%08x para:%08x/%08x/%08x/%08x",
                            i,
                            ((APP_MESSAGE_BLOCK *)(evt.value.p))->mod_id,
                            ((APP_MESSAGE_BLOCK *)(evt.value.p))->mod_level,
                            ((APP_MESSAGE_BLOCK *)(evt.value.p))->src_thread,
                            ((APP_MESSAGE_BLOCK *)(evt.value.p))->system_time,
                            ((APP_MESSAGE_BLOCK *)(evt.value.p))->msg_body.message_id,
                            ((APP_MESSAGE_BLOCK *)(evt.value.p))->msg_body.message_ptr,
                            ((APP_MESSAGE_BLOCK *)(evt.value.p))->msg_body.message_Param0,
                            ((APP_MESSAGE_BLOCK *)(evt.value.p))->msg_body.message_Param1,
                            ((APP_MESSAGE_BLOCK *)(evt.value.p))->msg_body.message_Param2,
                            (uint32_t)((APP_MESSAGE_BLOCK *)(evt.value.p))->msg_body.message_Param3);
            }else{
                TRACE_IMM(2,"cnt:%d %d", i, evt.status);
                break;
            }
        }
        TRACE_IMM(0,"osMailAlloc error dump end");
    }

    ASSERT(msg_p, "osMailAlloc error");
    msg_p->src_thread = (uint32_t)osThreadGetId();
    msg_p->dest_thread = (uint32_t)NULL;
    msg_p->system_time = hal_sys_timer_get();
    msg_p->mod_id = msg_src->mod_id;
    msg_p->mod_level = msg_src->mod_level;
    msg_p->msg_body.message_id = msg_src->msg_body.message_id;
    msg_p->msg_body.message_ptr = msg_src->msg_body.message_ptr;
    msg_p->msg_body.message_Param0 = msg_src->msg_body.message_Param0;
    msg_p->msg_body.message_Param1 = msg_src->msg_body.message_Param1;
    msg_p->msg_body.message_Param2 = msg_src->msg_body.message_Param2;
    msg_p->msg_body.message_Param3 = msg_src->msg_body.message_Param3;
    msg_p->msg_body.p = msg_src->msg_body.p;

    status = osMailPut(app_mailbox, msg_p);
//    osMutexRelease(app_mutex_id);
    return (int)status;
}

3 消费者(consumer)

3.1 app_mailbox_get 

app_mailbox_get由app_thread调用。 

3.2 app_mailbox_process

 int app_mailbox_process(APP_MESSAGE_BLOCK* msg_p)
{
    if (msg_p->mod_id < APP_MODUAL_NUM){
        if (mod_handler[msg_p->mod_id]){
            int ret = 0 ;
            if(APP_MODUAL_AUDIO_MANAGE == msg_p->mod_id){
                int Priority = osThreadGetPriority(app_thread_tid);
                osThreadSetPriority(app_thread_tid, osPriorityRealtime);
                ret = mod_handler[msg_p->mod_id](&(msg_p->msg_body));
                osThreadSetPriority(app_thread_tid, Priority);
            }else{
                ret = mod_handler[msg_p->mod_id](&(msg_p->msg_body));
            }
            if (ret)
                TRACE(2,"%s, mod_handler[%d] ret=%d", __func__, msg_p->mod_id, ret);
        }
    }
    return 0;
}

NOTE:最终消息处理是在各自模块中实现。(回调函数) 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/530920.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

mysql双机热备

MySQL双机热备&#xff1a;保障数据库高可用性的关键技术 在当今信息化社会中&#xff0c;数据库作为企业信息系统的核心组成部分&#xff0c;其高可用性和数据安全性至关重要。MySQL作为广泛应用的开源关系型数据库管理系统&#xff0c;其双机热备技术成为保障数据库稳定运行…

4.9QT

完善对话框&#xff0c;点击登录对话框&#xff0c;如果账号和密码匹配&#xff0c;则弹出信息对话框&#xff0c;给出提示”登录成功“&#xff0c;提供一个Ok按钮&#xff0c;用户点击Ok后&#xff0c;关闭登录界面&#xff0c;跳转到其他界面 如果账号和密码不匹配&#xf…

苹果商店审核指南:确保Flutter应用顺利通过审核的关键步骤

引言 Flutter是一款由Google推出的跨平台移动应用开发框架&#xff0c;其强大的性能和流畅的用户体验使其备受开发者青睐。然而&#xff0c;开发一款应用只是第一步&#xff0c;将其成功上架到苹果商店才是实现商业目标的关键一步。本文将详细介绍如何使用Flutter将应用程序上…

数字时代电子账单邮件群发:简便、高效、环保

电子账单已经在许多行业得到广泛应用&#xff0c;通过邮件群发发送电子账单简便、高效、环保&#xff0c;以下是一些通常使用电子账单的行业&#xff1a; 1.银行和金融服务&#xff1a;银行、信用合作社、金融科技公司等机构通常通过电子账单向客户提供账户摘要、交易明细、利息…

Python-VBA函数之旅-bool函数

目录 1、bool函数 1-1、Python&#xff1a; 1-2、VBA&#xff1a; 2、相关文章&#xff1a; 个人主页&#xff1a;非风V非雨-CSDN博客 bool函数(Boolean Function)用于将给定的值转换为布尔值(True或False)。常见的应用场景有&#xff1a; 1、条件判断&#xff1a;bool()…

每日一题 — 无重复字符的最长子串

解法一&#xff1a;暴力枚举 先固定一个left&#xff0c;让right向右遍历遇到重复的字符&#xff0c;让left加一然后right返回&#xff0c;重新遍历 解法二&#xff1a; 滑动窗口(在解法一的基础上进行优化) 还是先固定一个left在起始位置&#xff0c;让right从起始位置开始向…

使用docker制作Android镜像(实操可用)

一、安装包准备 1、准备jdk 下载地址&#xff1a;Java Downloads | Oracle 注意版本&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 我下载的jdk17&#xff0c;不然后面构建镜像报错&#xff0c;就是版本不对 2、准备安装的工具包 ttps://dev…

Java多线程实战-从零手搓一个简易线程池(四)线程池生命周期状态流转实现

&#x1f3f7;️个人主页&#xff1a;牵着猫散步的鼠鼠 &#x1f3f7;️系列专栏&#xff1a;Java全栈-专栏 &#x1f3f7;️本系列源码仓库&#xff1a;多线程并发编程学习的多个代码片段(github) &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正…

Playwright安装和基本使用(ui/web自动化)

1.简介 Playwright是2021年微软开源的一个项目「playwright-python」。针对 Python 语言的纯自动化工具&#xff0c;它可以通过单个API自动执行 Chromium&#xff0c;Firefox 和 WebKit 浏览器&#xff0c;同时支持以无头模式、有头模式运行。 Playwright&#xff08;Git&…

【Machine Learning系列】带你快速学习十大机器学习算法

前言 机器学习算法是一类用于从数据中学习模式和规律的算法。这些算法可以通过训练样本的输入和输出来推断出模型的参数&#xff0c;然后用于预测新的未知数据。 文章目录 前言机器学习算法1. 线性回归算法 Linear Regression2. 支持向量机算法(Support Vector Machine,SVM)3. …

Centos7.9部署Harbor详细教程

1、前置准备 系统需要已经安装docker、docker-compose… 2、下载Harbor wget https://github.com/goharbor/harbor/releases/download/v2.10.1/harbor-online-installer-v2.10.1.tgztar xvf harbor-offline-installer-v2.10.1.tgzcd harbor3、修改配置文件 cp harbor.yml.t…

CSS滚动条样式修改

前言 目前我们可以通过 CSS伪类 来实现滚动条的样式修改&#xff0c;以下为修改滚动条样式用到的CSS伪类&#xff1a; ::-webkit-scrollbar — 整个滚动条 ::-webkit-scrollbar-button — 滚动条上的按钮 (上下箭头) ::-webkit-scrollbar-thumb — 滚动条上的滚动滑块 ::-web…

CUDA 12.4文档2 内核线程架构

本博客参考官方文档进行介绍&#xff0c;全网仅此一家进行中文翻译&#xff0c;走过路过不要错过。 官方网址&#xff1a;https://docs.nvidia.com/cuda/cuda-c-programming-guide/ 本文档分成多个博客进行介绍&#xff0c;在本人专栏中含有所有内容&#xff1a; https://bl…

网络学习学习笔记

NETEBASE学习笔记 一.VRP系统1.四种视图模式2.基础命令 二.TCP/IP1.五层模型 一.VRP系统 1.四种视图模式 (1)< Huawei > 用户视图 【查看运行状态】 (2)[Huawei] 系统视图 【配置设备的系统参数】 system-view /sys 进入系统视图 CtrlZ/return 直接返回用户视图 (3)[Hua…

AR远程空间标注Vuforia+WebRTC音视频通话和空间标注功能

AR远程空间标注VuforiaWebRTC音视频通话和空间标注功能 视频学习地址&#xff1a;https://www.bilibili.com/video/BV1ZT4y187mG/?vd_sourcefc4b6cdd80b58c93a280fd74c37aadbf

李沐23_LeNet——自学笔记

手写的数字识别 知名度最高的数据集&#xff1a;MNIST 1.训练数据&#xff1a;50000 2.测试数据&#xff1a;50000 3.图像大小&#xff1a;28✖28 4.10类 总结 1.LeNet是早期成功的神经网络 2.先使用卷积层来学习图片空间信息 3.使用全连接层来转换到类别空间 代码实现…

学习记录:bazel和cmake运行终端指令

Bazel和CMake都是用于构建软件项目的工具&#xff0c;但它们之间有一些重要的区别和特点&#xff1a; Bazel&#xff1a; Bazel是由Google开发的构建和测试工具&#xff0c;用于构建大规模的软件项目。它采用一种称为“基于规则”的构建系统&#xff0c;它利用构建规则和依赖关…

Android 属性动画及自定义3D旋转动画

Android 动画框架 其中包括&#xff0c;帧动画、视图动画&#xff08;补间动画&#xff09;、属性动画。 在Android3.0之前&#xff0c;视图动画一家独大&#xff0c;之后属性动画框架被推出。属性动画框架&#xff0c;基本可以实现所有的视图动画效果。 视图动画的效率较高…

第十届蓝桥杯大赛个人赛省赛(软件类) CC++ 研究生组-RSA解密

先把p&#xff0c;q求出来 #include<iostream> #include<cmath> using namespace std; typedef long long ll; int main(){ll n 1001733993063167141LL, sqr sqrt(n);for(ll i 2; i < sqr; i){if(n % i 0){printf("%lld ", i);if(i * i ! n) pri…

关于VMware安装win系统的磁盘扩容与缩减

使用VMware虚拟机安装虚拟windows系统时&#xff0c;如果创建虚拟磁盘的空间预留不足&#xff08;特别是C判空间&#xff09;&#xff0c;安装win系统后&#xff0c;由于默认win系统在安装时分配的healthy健康盘位于系统C盘临近区域&#xff0c;此时如果需要增加C盘虚拟空间&am…