ZigBee协议栈OSAL解析(第三天)

来源:互联网 发布:万能mac地址修改器下载 编辑:程序博客网 时间:2024/04/30 02:25

      今天一天就可以照葫芦画瓢完成点播,广播,组播的实验。但是这样不是太小儿科了嘛。顺着昨天的分析。AF层是

干什么的?

      问题1:各个层之间的关系?

      解决问题:

      1.官方文档:

      ZDO:

The ZigBee Device Objects (ZDO) layer provides functionality for managing a ZigBee device. The ZDO APIprovides the interface for application endpoints to manage functionality for ZigBee Coordinators, Routers, or EndDevices which includes creating, discovering, and joining a ZigBee network; binding application endpoints; andmanaging security.
      AF:

The Application Framework (AF) interface supports an Endpoints (including the ZDO) interface to the underlyingstack. The Z-Stack AF provides the data structures and helper functions that a developer requires to build a devicedescription and is the endpoint multiplexor for incoming messages.

    APS:

The Application Support Sublayer (APS) API provides a general set of support services that are used by both theZDO and the manufacturer-defined application objects.
   后面两个层不提了,ZDO在AF之上,AF为中间层,提供数据收发,和帮助函数,APS和AF的关系,从简短的描述是无法

理清楚关系
   接下来,搜索中文:

    http://blog.csdn.net/accumulating_mocai/article/details/72843761

   英文:

    

    
           这个图倒是很暴力,接下来少许的翻译:

           

The application layer consists of three parts: the Application Sublayer (APS), the Application Framework (AF), and the endpoints. The Application Sublayer interfaces the Zigbee application layer to the Zigbee networking layer and it provides a common set of data transport services to all the endpoints. There are also a couple of other services that the APS provides and we’ll get into that when we discuss the app layer in more detail. 

           应用层包含三个部分:APS,AF和endpoints。APS连接了网络层和应用层,它给所有断点提供了一些公共的数据传输服务。

这里还有一些其他的服务,当我们讨论APP层时再详细分析。

            

The Application Framework is just a glorified multiplexer and container for all of the endpoints. All of the endpoints register themselves with the AF, and when a data frame comes into the application layer, the AF will check its destination endpoint and forward it there. 

             AF仅仅是所有端点的容器和多路复用器,(这里想想NODE连接多个endpoint),所有的endpoint使用AF注册他们自身

当一个数据帧进去应用层时,AF将会检查他的目的端点地址,然后传递过去。

            

The endpoints are what most people associate with Zigbee. Each endpoint houses what’s called an application object which is basically a device profile with whatever extra functionality you decide to add. When the device is started, all the endpoints will register themselves with the application framework and provide descriptions of their device profile and their capabilities. Endpoint 0 is a special endpoint and always contains the Zigbee Device Object (ZDO). This object implements the Zigbee Device Profile which has multiple functions, one of them being the network manager. 

           大多数人会把endpoint和zigbee联系到一块去,每个端点包含被称为应用对象的东西,这种东西就是设备配置文件和

你要添加的额外功能。当一个设备开始运行时,所有的endpoint都会使用AF注册他们自己,并且提供他们的设备配置和功能

的描述符。endpoint0是特殊的端点,一定包含ZDO,这个ZDO会执行ZDP(包含多个功能,其中之一就是网络管理)

           

The user application can manage the network by making requests and handling callbacks to this object, which is why it’s important to know about it. In general, the Zigbee endpoints are going to be the main interface between the user application and the stack.

            用户应用可以通过生产请求和处理回调函数来管理网络,这就是为什么我们必须了解它的原因。总体上,ZigBee 

endpoints将变成主要的用户应用和协议栈沟通的接口。

          

  When I mentioned that the network management deviates slightly from the stack’s layer hierarchy, what I meant was the ZDO’s network manager object bypasses the APS and interfaces directly to the networking layer. Thus, you get a bizarre looking layer stackup like this where you can see the ZDO wraps around the APS and the NWK layers.

            我说网络管理稍微脱离协议栈层次,我的意思是ZDO的网络管理部分绕过APS而直接管理网络层(不好理解参见上图)。

后面一句不翻译了,就是描述上图奇怪的层次关系。

            至此我还是有点不慎理解,因为不是很清楚很多概念。
            

            问题2:AF_DataRequest的使用?

           

                           AF_INCOMING_MSG_CMD到底是哪里置位的呢?

            在解决这个问题之前:

            我要亲自分析下,消息机制!我知道网上很多人分析过了,但是我还是要按照逻辑去推理思考一遍。(大概这是解决

问题的思维培养吧)

            

uint8 * osal_msg_allocate( uint16 len ){  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) );//这里是返回了hdr+1,  }  else    return ( NULL );}
             按照代码来说,分配的空间为 osal_msg_hdr_t、len 而hdr +1已经指向第二个len区域了,而后再看

uint8 osal_msg_send( uint8 destination_task, uint8 *msg_ptr ){  .......................  OSAL_MSG_ID( msg_ptr ) = destination_task;//((osal_msg_hdr_t *) (msg_ptr) - 1)->dest_id和上面对应,强制转换符是必须的  // queue message  osal_msg_enqueue( &osal_qHead, msg_ptr );  // Signal the task that a message is waiting  osal_set_event( destination_task, SYS_EVENT_MSG );  return ( SUCCESS );}
          这个每行代码都要解析
void osal_msg_enqueue( osal_msg_q_t *q_ptr, void *msg_ptr ){  void *list;  halIntState_t intState;  // Hold off interrupts  HAL_ENTER_CRITICAL_SECTION(intState);  OSAL_MSG_NEXT( msg_ptr ) = NULL;//将msg_ptr的前面的header中next设置为null,注意msg_ptr此时为void*  // If first message in queue  if ( *q_ptr == NULL )//*q_ptr为void *类型  {    *q_ptr = msg_ptr;q_ptr为void**  }  else  {    // Find end of queue    for ( list = *q_ptr; OSAL_MSG_NEXT( list ) != NULL; list = OSAL_MSG_NEXT( list ) );    // Add message to end of queue    OSAL_MSG_NEXT( list ) = msg_ptr;  }  // Re-enable interrupts  HAL_EXIT_CRITICAL_SECTION(intState);}
       来看看这个很绕的链表

  
             

       osal_mag_hdr_t很像私有域,这种稍微的技巧处理很特别,也就是说osal_queue为单向链表,大概算是链表里面最

简单的了。上面函数一直给链表尾端添加节点,并且一切明着来的指针都是msg_ptr,通过几个宏来操作链表,我的意思是如果直接

使用msg_ptr可以直接得到消息数据。

       接下来就是接受函数

uint8 *osal_msg_receive( uint8 task_id ){  osal_msg_hdr_t *listHdr;  osal_msg_hdr_t *prevHdr = NULL;  osal_msg_hdr_t *foundHdr = NULL;  halIntState_t   intState;  // Hold off interrupts  HAL_ENTER_CRITICAL_SECTION(intState);  // Point to the top of the queue  listHdr = osal_qHead;  // Look through the queue for a message that belongs to the asking task  while ( listHdr != NULL )  {    if ( (listHdr - 1)->dest_id == task_id )//注意    {      if ( foundHdr == NULL )      {        // Save the first one        foundHdr = listHdr;      }      else      {        // Second msg found, stop looking        break;      }    }    if ( foundHdr == NULL )    {      prevHdr = listHdr;    }    listHdr = OSAL_MSG_NEXT( listHdr );  }   //这个迭代,也说明了msg_list可能存在很多任务的msg,而不是每个任务一个消息队列  // Is there more than one?  if ( listHdr != NULL )  {    // Yes, Signal the task that a message is waiting    osal_set_event( task_id, SYS_EVENT_MSG );//这里的逻辑是while被break的那次。所以还有msg未处理  }  else  {    // No more    osal_clear_event( task_id, SYS_EVENT_MSG );  }  // Did we find a message?  if ( foundHdr != NULL )  {    // Take out of the link list    osal_msg_extract( &osal_qHead, foundHdr, prevHdr );//再看这个函数  }  // Release interrupts  HAL_EXIT_CRITICAL_SECTION(intState);  return ( (uint8*) foundHdr );//返回该节点,注意该指针直接指向msg_data}
         
void osal_msg_extract( osal_msg_q_t *q_ptr, void *msg_ptr, void *prev_ptr ){  halIntState_t intState;  // Hold off interrupts  HAL_ENTER_CRITICAL_SECTION(intState);  if ( msg_ptr == *q_ptr )  {    // remove from first    *q_ptr = OSAL_MSG_NEXT( msg_ptr );//*q_ptr指向链表头,msg_ptr处于链表头,则将*q_ptr指向下一节点  }  else  {    // remove from middle    OSAL_MSG_NEXT( prev_ptr ) = OSAL_MSG_NEXT( msg_ptr );//不然就从中间剔除  }  OSAL_MSG_NEXT( msg_ptr ) = NULL;//设置该剔除的节点next为null  OSAL_MSG_ID( msg_ptr ) = TASK_NO_TASK;//task为no_task  // Re-enable interrupts  HAL_EXIT_CRITICAL_SECTION(intState);}
       之后就看看

uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events ){  afIncomingMSGPacket_t *MSGpkt;  (void)task_id;  // Intentionally unreferenced parameter  if ( events & SYS_EVENT_MSG )  {    MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );//这里强制类型转换    while ( MSGpkt )    {      switch ( MSGpkt->hdr.event )
     OK,到这里消息队列,及怎么处理就很清楚了。现在在回到刚开始的问题
     AF_INCOMING_MSG_CMD到底是哪里置位的呢?

      

     答:该标志实际上是数据包里面的置位的,也就是说发送方定义的。属于event里面的子event。

      SYS_EVENT_MSG到底是哪里置位的呢?

      也就是无线发送和接受的流程是怎么样子呢?

      最后就是AF_DataRequest的使用?

      第四天将围绕这个问题,解析学习,并且做些实验。

            

原创粉丝点击