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:最终消息处理是在各自模块中实现。(回调函数) 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

conda创建虚拟环境太慢,Collecting package metadata (current_repodata.json): failed

(省流版&#xff1a;只看加粗红色&#xff0c;末尾也有哦) 平时不怎么用conda&#xff0c;在前公司用服务器的时候用的是公司的conda源&#xff0c;在自己电脑上直接用python创建虚拟环境完事儿&#xff0c;所以对conda的配置并不熟悉~~【狗头】。但是python虚拟环境的最大缺点…

U盘属性0字节,数据恢复全攻略

U盘&#xff0c;这个我们日常生活中常用的数据存储工具&#xff0c;有时却会突然显示出“属性0字节”的诡异状况。面对这种突如其来的故障&#xff0c;许多用户都感到束手无策&#xff0c;甚至误以为数据已经彻底丢失。那么&#xff0c;U盘属性0字节究竟是怎么回事&#xff1f;…

OpenCV 使用freetype在图像上写中文

​​​​​​ #include "opencv2/opencv.hpp" #include "opencv2/freetype.hpp"static cv::Ptr<cv::freetype::FreeType2> getFreeType() {static cv::Ptr<cv::freetype::FreeType2> ft2;if (ft2.empty()){ft2 cv::freetype::createFreeType…

小红书商业IP变现策略与实操经验分享

一、个人介绍与背景 1. 创业者背景 作为连续创业者&#xff0c;我创立了树叶有光品牌&#xff0c;并在多个领域有所涉猎&#xff0c;如人生陪跑师、财富卡点爆破师等。这些多重身份让我在创业过程中积累了丰富的经验和独特的视角。 二、小红书账号运营经验 1. 运营成果 经…

Ubuntu 22.04安装新硬盘并启动时自动挂载

方法一 要在Ubuntu 22.04系统中安装一个新硬盘、对其进行格式化并实现启动时自动挂载&#xff0c;需要按以下步骤操作&#xff1a; 1. 安装硬盘 - 确保你的硬盘正确连接到计算机上&#xff08;涉及硬件安装&#xff09;。 2. 发现新硬盘 - 在系统启动后&#xff0c;打开终端…

30天拿下Rust之实战Web Server

概述 随着互联网技术的飞速发展&#xff0c;Web服务器作为承载网站与应用的核心组件&#xff0c;其性能、稳定性和安全性都显得至关重要。Rust语言凭借其独特的内存安全保证、高效的性能以及丰富的生态系统&#xff0c;成为了构建现代Web服务器的理想选择。 新建项目 首先&…

适合户外运动的开放式耳机选哪款?五款开放式耳机推荐

开放式蓝牙耳机由于其开放式设计&#xff0c;适合在户外运动、工作场所等需要保持警觉的场合使用。在户外活动中&#xff0c;能够听到周围环境的声音对于安全和警惕性非常重要。同时&#xff0c;这种耳机在运动或工作时不容易产生不适感&#xff0c;也不会阻碍佩戴者与他人的交…

高等数学基础篇(数二)之二重积分(解析版)

二重积分&#xff1a; 一、二重积分的概念及性质 1.二重积分的概念 2.二重积分的性质 二、二重积分的计算 1.利用直角坐标计算 2.利用极坐标计算 3.利用函数的奇偶性计算 4.利用变量的轮换对称性计算 目录 一、二重积分的概念及性质 1.二重积分的概念 2.二重积分的性…

ubuntu 23 安装maven

要在 Ubuntu 23 系统上安装 Maven&#xff0c;请遵循以下步骤&#xff1a; **1. ** 确保已安装 Java Development Kit (JDK): Maven 需要 Java 环境才能运行。确认您的系统已经安装了 JDK 8 或更高版本。如果尚未安装&#xff0c;可以通过以下命令安装 OpenJDK&#xff1a; s…

活动图高阶讲解-15

1 00:00:00,000 --> 00:00:07,200 目前来说&#xff0c;这个菱形到底是分还是合 2 00:00:07,200 --> 00:00:13,600 这个是靠入边出边的数量来判断的 3 00:00:13,600 --> 00:00:22,560 有的方法学&#xff0c;它可能会这样搞一些花样 4 00:00:22,560 --> 00:00:2…

Transformer架构的核心公式类似于数学期望并不复杂,但为什么这个模型这么强呢?

Transformer是一个利用注意力机制来提高模型训练速度的模型&#xff0c;因其适用于并行化计算以及本身模型的复杂程度使其在精度和性能上都要高于之前流行的循环神经网络。 一、Transformer模型整体结构 标准的Transformer结构如下图所示&#xff0c;是一个编码器-解码器架构…

免费SSL通配符证书/SSL泛域名证书获取教程

我们先基本了解什么是SSL证书以及其作用。SSL证书是一种数字证书&#xff0c;它通过为网站提供身份验证和数据加密服务&#xff0c;从而保护网站的用户信息安全。当我们在浏览器的地址栏看到“https”和绿色锁标志时&#xff0c;就表示该网站使用了SSL证书。 那么什么又是通配…

idea 开发serlvet汽车租赁管理系统idea开发sqlserver数据库web结构计算机java编程layUI框架开发

一、源码特点 idea开发 java servlet 汽车租赁管理系统是一套完善的web设计系统sqlserver数据库 系统采用serlvetdaobean mvc 模式开发&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。 java se…

34470A是德科技34470A数字万用表

181/2461/8938产品概述&#xff1a; Truevolt数字万用表&#xff08;34460A、34461A、34465A、34470A&#xff09;利用是德科技的新专利技术&#xff0c;使您能够快速获得见解、测量低功耗设备并保持校准的测量结果。Truevolt提供全方位的测量能力&#xff0c;具有更高的精度、…

C++【组合模式】

简单介绍 组合模式是一种结构型设计模式&#xff0c; 只有在可以将对象拆分为【树状结构】的情况下使用。并且像使用独立对象一样使用它们。 常用于表示与图形打交道的用户界面组件或代码的层次结构。 基础理解 Q&#xff1a;为什么要用组合模式 &#xff1f; A&#xff1a;在…

蓝桥杯刷题day14——盖印章【算法赛】

一、问题描述 小 Z 喜欢盖印章。 有一天,小 Z 得到了一个 nm 的网格图,与此同时,他的手上有两种印章(分别称为 A,B),如下图所示。 他想将这两种印章盖在这个网格图上。 由于小 Z 是一个有原则的人,他将按照以下规则进行操作。 每个印章所形成的图案的边必须和网格图…

plasmo浏览器插件框架使用react和ant.design框架创建页面内容脚本UI样式注入

使用plasmo开发浏览器插件的时候&#xff0c;想要使用内容脚本UI注入自定义的UI组件&#xff0c;官方文档&#xff1a;Content Scripts UI – Plasmo&#xff0c;最好是搭配上好看的UI样式&#xff0c;所以可以集成ant.design的UI组件库&#xff0c;但是只集成组件还不行&#…

[C语言]——动态内存经典笔试题分析

目录 一.题目1 1.运行结果 2.分析 3.问题所在 4.更正 二.题目2 1.运行结果 2.分析 3.问题所在 4.更正 三.题目3 1.问题所在 2.更正&#xff1a; 四.题目4 一.题目1 void GetMemory(char *p){p (char *)malloc(100);}void Test(void){char *str NULL;GetMemory…

2024春算法训练4——函数与递归题解

一、前言 感觉这次的题目都很好&#xff0c;但是E题....&#xff08;我太菜了想不到&#xff09;&#xff0c;别人的题解都上百行了&#xff0c;晕&#xff1b; 二、题解 A-[NOIP2010]数字统计_2024春算法训练4——函数与递归 (nowcoder.com) 这种题目有两种做法&#xff1a;…

泛微OA 自定义多选浏览框

1、建模引擎-》应用建模-》表单 2、建模引擎-》应用建模-》模块 3、建模引擎-》应用建模-》查询 4、把查询页面挂到前端页面。 效果展示&#xff1a; 5、建模引擎-》应用建模-》浏览框 6、流程表单中字段应用