OSAL 消息收发过程 | 学习笔记

简介: 快速学习 OSAL 消息收发过程

开发者学堂课程【嵌入式之 RFID 开发与应用2020版:OSAL 消息收发过程】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址:https://developer.aliyun.com/learning/course/665/detail/11130


OSAL 消息收发过程

知道 OSAL 系统总的调度原理,接下来有一个非常常用的一个手段或者说是一个功能,就是某个进程之间某个任务之间,A 任务要给 B 任务发一个消息,这个消息的收发的过程是怎样的?

首先发送这个消息本质上是通过 osal set 去设置这个事件,提供了 osal msg send message send,仔细去分析这个源代码,想了解的哪个地方可以直接去搜索。

image.png

以这个串口为例,串口在接收到数据的他把接收到的串口的数据,把它放到了 msg里面,PMSG 然后再加一个 msg,这里 OSAL 申请的空间给了 pmsg,之后就调用了 osal send message 去发送,那这个地方有个任务 ID,也就是说要把这个消息发给哪一个任务,这个就是他的 ID 也就是刚才第一个任务,ID;第二个是发的内容。

j++; 〃记录字符数

flag=1; 〃己经从串口接收到信息

}

if(flag==1) 〃已经从串口接收到信息

{

/* Allocate memory for the data */

//分配内存空间,为机构体内容+数据内容+1个记录长度的数据 pMsg = (mtOSALSerialData_t *)osal_msg|_allocate( sizeof

(mtOSALSerialData_t )+j+3);

//事件号用原来的 cmd_serial[msg

pAfsg->hdr.event = CMD_SERIAL_MSG;

pMsg->msg = (uint8*)(pMsg+l); //把数据定位到结构体数据部分

pMsg->msg [θ]= port;//给上层的数据第一个是串口号

pMsg->msg [1]= j;//给上层的数握第二个是长度

buf[j] = 0;

strcpy((char *)&(pMsg->msg[2]),(const char *)buf);

// for(i=θ;i<j;i++) 〃从第二个开始记录数据

// pMsg->msg [i+2]= buf[i];

osal_msg_send( my_TaskID, (byte *)pMsg ); 〃登记任务,发往上层

/* deallocate the msg */

// osal_msg_deallocate ( (uint8 *)pMsg ); 〃释放内存

}

}« end MT_UartProcessZToolData »

#else

msg 消息发送过程:

osal _ msg _ send (uint8 taskID , void msg _ ptr )

msg _ ptr 指向消息内容,不能为空

放入消息队列 osal _ msg _ enqueue (& osal _ qHead , msg _ ptr );

最后通过 osal _ set _ event ( taskID , SYS _ EVENT _ MSG )给任务事件置位

msg 消息接收过程:

msg _ ptr = osal _ msg _ receive ( taskID );>消息队列取出

osal _ msg _ extract (& osal _ qHead , msg _ ptr ,

清除事件 osal _ clear _ event ( taskID , SYS_EVENT-MSG)

具体的发送的过程会把它放到队列当中去。然后通过最后你看。

Osal set event 可以到这个里面去进去看一下。

}

// Check the message header

if ( OSAL_MSG_NEXT( msg_ptr ) != NULL || OSAL_MSG_ID( msg_ptr ) != TASK_NO_TASK ) {

osal_msg_deallocate( msg_ptr ); return

( INVALID_MSG_POINTER );

}

OSAL_MSG_ID( msg_ptr ) = destination_task;

// queue message

osal_msg_enqueue( &osal_qHsad, msg_ptr );

// Signal the task that a message is waiting os[al_set_event ( destination_task, SYS_EVENT_MSG );

return ( SUCCESS );

} « end osal_msg_send »

* @fn osal_msg_receive

*

* @brief

这个事件的类型就是叫做 SYS_EVENT_MSG 然后这个消息发出去了,对方去接收让的第一步,并不是去搜这个消息,而是去搜这个事件。

//任务事件处理函数

uintl6 my_ProcessEvent( uint8 task_id, uintl6 events )

{

afIncomingMSGPacket_t *MSGpkt = NULL;

ifevents & SYS_EVENT_MSG)

{

MSGpkt = (aflncomingMSGPacket t *)osal msg receive( my TaskID );

while(MSGpkt != NULL){

switch ( MSGpkt->hdr.event )

{

case ZDO_STATE_CHANGE:

identity_nwk = (devStates_t)(MSGpkt->hdr.status);

if(identity_nwk == DEV_END_DEVICE){

debug("入'网成功\n");

debug("获得地址=0x%x\n",NLME_GetShortAddr());

#if CTRL_0R GATHER // 控制节点/采集节点入网成功后尧发一个数据给协调器以确认自己是谁,

send_coord_affirm(SAMPLEAPP_CTRL_CLUSTERID);//这是不同终端要改

#else

send_coord_affirm(SAMPLEAPP_SENSOR_CLUSTERID);//这是不同终端要改

只要被调度,就要去判断有没有发生这个事件,被调度的是因为有人给他调用了osal set event 他才会被调用。他被调用的第一步就检测有没有收到这个消息,如果if是成立的就表示收到这个消息之后再调用 osal msg receive 这个函数去接收消息。可以看到它首先调用这个函数从消息队列里面把消息提取出来,最后清除这个任务。

消息收发操作流程:

申请消息空间(消息开头都会有 osal _ msg _ hdr _ t 结构): msgstr = osal _ m $ g _ allocate (1en)

消息内容的初始化: strcpy ( msgstr ,” helloln ");>发送消息: osal _ msg _ send ( xxTaskID , msgstr )- osal _ msg _ enqueue (在链表结尾添加节点

接收消息(根据任务 ID 进行接收): msg = osal _ msg _ receive ( xx _ TaskID )

对得到的消息进行处理

释放消息: osal _ msg _ deallocate O()

这里也有他的详细过程,申请,空间,拷贝,接收完了以后还要释放,这个地方接收是在这个里面。这个消息调用了操作系统,这个 osal_ msg_ ollocate, 释放必须要调的 deallocate,这就有点像 C 语言里面的那个 Malloc 和 Free,但他释放的对象是谁得去看它在发送的时候 Allocation 给了谁,他给的 pmsg。相当于他的这个返回值。

再去找有没有地方调用 deallocate 也就是前面这些接收到消息之后,这里都是使用。当使用完不再使用的时候,就必须要调用这个就把

把它释放掉。这个就是整个消息的收发流程,在操作系统里面这个任务之间通信也是时常发生的,所以这个过程一定要搞清楚,而且一定要理解消息收发的本质是什么。

本质其实就是往消息队列里面放了一块申请的空间,并且通过之前那个事件的机制去把某个事件给置位,让操作系统在轮询调度的过程当中能够发现这个事件从而去调度相应的任务去处理这个消息。

相关文章
|
测试技术
CRC-16 MODBUS原理,附实测可用源码
之前做串口解析,CRC校验一直用和校验,就是吧各个位加在一起,新来一个串口协议,是CRC-16 MODBUS的形式校验,不会呀,从网上找了找资源,没有找到源码,都要下载,分享出来。
CRC-16 MODBUS原理,附实测可用源码
|
传感器 物联网 Linux
Python:蓝牙心率广播设备监测(BLE 心率监测器)技术解析与实现
本文探讨了如何使用 Python 脚本与支持蓝牙低功耗(BLE)心率广播的设备交互以获取实时心率数据。重点分析了 BLE 协议、GATT 服务模型,以及具体方法。此外,还讨论了华为手表等设备的兼容性问题。
2552 19
|
存储 安全 数据安全/隐私保护
STM32 Customer BootLoader 刷新项目 (一) STM32CubeMX UART串口通信工程搭建
本文介绍了基于STM32的Customer BootLoader刷新项目的第一部分:使用STM32CubeMX搭建UART串口通信工程。项目采用正点原子探索者v2开发板,通过USB串口与上位机通信,实现固件刷新功能。主要内容包括: 1. 硬件原理图介绍:详细描述了开发板的串口连接方式及电路图。 2. STM32CubeMX工程搭建:从创建新工程、配置系统时钟、USART串口设置到生成代码,一步步详细说明。 3. 代码编写:展示了如何使用HAL库实现串口接收和发送数据,并提供了main.c的完整代码。 4. 工程下载和调试:编译并下载工程到开发板,通过串口调试助手验证通信功能。
STM32 Customer BootLoader 刷新项目 (一) STM32CubeMX UART串口通信工程搭建
|
移动开发 JavaScript 前端开发
UniApp低代码-颜色选择器diy-color-picker-代码生成器
UniApp低代码-颜色选择器diy-color-picker-代码生成器
754 5
|
C语言
【数据结构】双向带头循环链表(c语言)(附源码)
本文介绍了双向带头循环链表的概念和实现。双向带头循环链表具有三个关键点:双向、带头和循环。与单链表相比,它的头插、尾插、头删、尾删等操作的时间复杂度均为O(1),提高了运行效率。文章详细讲解了链表的结构定义、方法声明和实现,包括创建新节点、初始化、打印、判断是否为空、插入和删除节点等操作。最后提供了完整的代码示例。
627 0
|
iOS开发 MacOS Python
Electron Mac 打包报 Error: Exit code: ENOENT. spawn /usr/bin/python ENOENT 解决方法
Electron Mac 打包报 Error: Exit code: ENOENT. spawn /usr/bin/python ENOENT 解决方法
|
存储 C语言
C语言中向函数传递二维数组的技术详解
C语言中向函数传递二维数组的技术详解
1170 0
|
物联网 Java Linux
事件驱动型OSAL系统原理分析|学习笔记
快速学习事件驱动型OSAL系统原理分析
事件驱动型OSAL系统原理分析|学习笔记
|
安全 物联网 网络架构
Zigbee—网络层地址分配机制
Zigbee—网络层地址分配机制
|
Linux C语言
嵌入式软件调试中的打印开关及打印等级
嵌入式软件调试中的打印开关及打印等级