本文共 3895 字,大约阅读时间需要 12 分钟。
本章简单的介绍一下ZigBee的消息机制,如果说的有问题还请多多指正。
通俗的说,ZigBee的消息机制就好比这有一排抽屉,当我要向某个任务或者事件发送消息时,就把该消息和对应的数据放到抽屉中,在任务轮训时,某个任务轮训按个查看抽屉中是否有自己需要的消息,有就取出并且处理,没有就结束,等待下一次轮训。
ZigBee消息链表如下图所示:(注:消息机制实现代码在osal.c中)
图1 ZigBee消息队列
值得注意的是,消息队列中每条消息都有一个系统消息头,结构体为osal_msg_hdr_t,包括三个数据类型,包括下一条消息的指针、消息长度和任务ID。消息头下有一个事件消息头,结构体为osal_event_hdr_t,该消息头包括事件的掩码和状态。使用过程中特别注意,通过系统函数获取的消息指针为事件消息头(osal_event_hdr_t)对应的地址,具体可看图1。
下面以串口接收到数据解包后将数据发到应用层为例,来介绍一下ZigBee的消息机制是怎么实现的。
【MT_UART.c】串口接收到数据后,首先要申请该消息对应的空间内存,申请多少要看数据有多少。
App_pMsg = (mtOSALSerialData_t *)osal_msg_allocate( sizeof (mtOSALSerialData_t) + MT_RPC_FRAME_HDR_SZ + App_LEN_Token );
其中 [MT_RPC_FRAME_HDR_SZ + App_LEN_Token]为串口数据长度,MT_RPC_FRAME_HDR_SZ包括数据长度、命令码0、命令码1三个数据,App_LEN_Token表示应用层数据,在此不再赘述。申请的该指针返回的为mtOSALSerialData_t,对应的图2中event的地址。
再看osal_msg_allocate( uint16 len )这个函数。
<span style="font-family: Arial, Helvetica, sans-serif;">uint8 * osal_msg_allocate( uint16 len )</span>
{ osal_msg_hdr_t *hdr; if ( len == 0 ) return ( NULL ); hdr = (osal_msg_hdr_t *) osal_mem_alloc( (short)(len + sizeof( osal_msg_hdr_t )) ); if ( hdr ) { hdr->next = NULL; hdr->len = len; hdr->dest_id = TASK_NO_TASK; return ( (uint8 *) (hdr + 1) ); } else return ( NULL );}
该函数在申请内存时,添加了sizeof( osal_msg_hdr_t )长度,该长度及图1中消息时间头,并且赋予了该消息头的next指针,长度len和dest_id任务ID。函数返回的指针为hdr+1,从我们正常的角度看,即申请了一片内存,返回内存指针,在内存指针前加上了任务消息头。因此这就是在处理任务消息头时都要-1的原因。
图3 任务消息处理函数
这样就生成一条消息。但是该工作并没有完成,需要将该消息放入消息对垒并且通知对应的任务ID取出该消息。
通过查看串口代码,可发现当数据校验正确后,要调用该函数。
osal_msg_send( App_TaskID, (byte *)App_pMsg );
该函数代码如下:
uint8 osal_msg_send( uint8 destination_task, uint8 *msg_ptr ){ if (