OSAL处理来自AF的数据包流程

小峰 OSAL处理来自AF的数据包流程

我使用的协议栈版本及例子信息:

ZigBee2006\TexasInstruments\ZStack-1.4.3-1.2.1\Projects\zstack\Samples\SampleApp

 

以下为系统处理来自AF层数据包的大致流程,

afIncomingData() ——afBuildMSGIncoming() ——osal_msg_send() —— osal_set_event()——

根据task_id调用事件处理函(SampleApp_ProcessEvent())——判断具体事件类型调用相应回调函数(SampleApp_MessageMSGCB())——实现具体现象

 

   afIncomingData()函数用来从APS层传递一个ASDUAF;中间调用了afBuildMSGIncoming()函数,这个函数是用来为APS层建立一个特定格式的消息包,然后再调用osal_msg_send()把消息(包含了ASDU)传往AF.

AF层规定接收的数据包的类型如下:

typedefstruct

{

 osal_event_hdr_t hdr;

 uint16 groupId;

 uint16 clusterId;

 afAddrType_t srcAddr;

 byte endPoint;

 byte wasBroadcast;

 byte LinkQuality;

 byte SecurityUse;

 uint32 timestamp;

 afMSGCommandFormat_t cmd;

}afIncomingMSGPacket_t;

 

首先看一下afIncomingData()函数

 

//传输数据:APS---->AF

void afIncomingData(aps_FrameFormat_t *aff, zAddrType_t*SrcAddress,

                    uint8 LinkQuality, byte SecurityUse, uint32 timestamp)

{

  endPointDesc_t*epDesc = NULL;

  uint16 epProfileID =0xFFFF; // Invalid ProfileID

  epList_t*pList;

  uint8grpEp;

//-----------

 

  if (((aff->FrmCtrl &APS_DELIVERYMODE_MASK) == APS_FC_DM_GROUP))

 {

   // Find the first endpoint for thisgroup

   grpEp = aps_FindGroupForEndpoint( aff->GroupID,APS_GROUPS_FIND_FIRST );

   if ( grpEp == APS_GROUPS_EP_NOT_FOUND )

     return;  // No endpointfound,没找到终端

 

   epDesc = afFindEndPointDesc( grpEp);   //找到终端,接着找终端描述符

   if ( epDesc == NULL )

     return;  // Endpoint descriptor notfound,没找到终端描述符

 

   pList = afFindEndPointDescList( epDesc->endPoint);  //找到终端描述符

  //pList指向终端列表中的元素

//-----------

 

  else if (aff->DstEndPoint == AF_BROADCAST_ENDPOINT)

 {

   // Set thelist

   if ( (pList = epList) )

   {

     epDesc = pList->epDesc;

   }

 }

//-----------

 

  else if ( (epDesc =afFindEndPointDesc( aff->DstEndPoint )))

 {

   pList = afFindEndPointDescList( epDesc->endPoint);

 }

//-----------

  while ( epDesc)

 {

   if ( pList->pfnDescCB ) //如果有回叫函数

   {

     uint16 *pID = (uint16*)(pList->pfnDescCB(

                                AF_DESCRIPTOR_PROFILE_ID, epDesc->endPoint));

     if ( pID )

     {

       epProfileID = *pID;

       osal_mem_free( pID );

     }

   }

   

   else if ( epDesc->simpleDesc ) //简单描述符

   {

     epProfileID =epDesc->simpleDesc->AppProfId;

   }

 

   if ( (aff->ProfileID == epProfileID)||

        ((epDesc->endPoint == ZDO_EP)&& (aff->ProfileID== ZDO_PROFILE_ID)) )  //符合各条件

   {

     

       //建立信息传递,注意,这里调用afBuildMSGIncoming()!!

       afBuildMSGIncoming(aff, epDesc, SrcAddress, LinkQuality, SecurityUse, timestamp);

     }

   }

 

   

   if ( ((aff->FrmCtrl &APS_DELIVERYMODE_MASK) == APS_FC_DM_GROUP))

   {

     // Find the next endpoint for thisgroup

     grpEp = aps_FindGroupForEndpoint( aff->GroupID,grpEp );

     if ( grpEp == APS_GROUPS_EP_NOT_FOUND )

       return;  // No endpointfound

 

     epDesc = afFindEndPointDesc( grpEp );

     if ( epDesc == NULL )

       return;   //Endpoint descriptor not found

 

     pList = afFindEndPointDescList( epDesc->endPoint);  //epDesc !=NULL

   }

   

   else if ( aff->DstEndPoint == AF_BROADCAST_ENDPOINT)

   {

     pList = pList->nextDesc;

     if ( pList )

       epDesc = pList->epDesc;

     else

       epDesc = NULL;

   }

   

   else

     epDesc = NULL;

 }

}

//----------------------------------------------------------------------------------------

afBuildMSGIncoming( aff, epDesc, SrcAddress,LinkQuality, SecurityUse, timestamp )

afBuildMSGIncoming( aps_FrameFormat_t *aff,endPointDesc_t *epDesc,

                zAddrType_t *SrcAddress, uint8 LinkQuality, byteSecurityUse,

                uint32 timestamp )

实参——形参

Aff——*aff

epDesc——*epDesc

SrcAddress——*SrcAddress

LinkQuality—— LinkQuality

SecurityUse—— SecurityUse

Timestamp—— timestamp

 

看一下afBuildMSGIncoming()函数

*********************************************************************

//Buildthe message for the app 

static voidafBuildMSGIncoming( aps_FrameFormat_t *aff, endPointDesc_t*epDesc,

                zAddrType_t*SrcAddress, uint8 LinkQuality, byteSecurityUse,

                uint32 timestamp )

{

 afIncomingMSGPacket_t*MSGpkt;   //AF层需要接收这种结构体类型的信息包

                                                                         //下面就通过本函数来为接收到的信息构造这种类型

                                                                          //信息包,从而可以发送到AF层去

  const byte len =sizeof( afIncomingMSGPacket_t ) +aff->asduLength;  //长度

  byte *asdu =aff->asdu;

  MSGpkt =(afIncomingMSGPacket_t *)osal_msg_allocate( len);  //分配内存

 

  if ( MSGpkt == NULL)

 {

   return;

 }

 

 MSGpkt->hdr.event = AF_INCOMING_MSG_CMD//事件类型

 MSGpkt->groupId =aff->GroupID;        //ID

 MSGpkt->clusterId =aff->ClusterID;    //ID

  afCopyAddress(&MSGpkt->srcAddr, SrcAddress);  //源地址

 MSGpkt->srcAddr.endPoint =aff->SrcEndPoint; 

 MSGpkt->endPoint =epDesc->endPoint;

 MSGpkt->wasBroadcast =aff->wasBroadcast; //广播

 MSGpkt->LinkQuality = LinkQuality;       //链路质量

 MSGpkt->SecurityUse = SecurityUse;       //安全使能

 MSGpkt->timestamp = timestamp;           //时间

 

 MSGpkt->cmd.TransSeqNumber = 0;          //传送序号

 MSGpkt->cmd.DataLength =aff->asduLength; //长度

 

  if (MSGpkt->cmd.DataLength )  //aff->asduLength

 {

   MSGpkt->cmd.Data = (byte *)(MSGpkt +1);  //空间

              //把长为MSGpkt->cmd.DataLength数据从asdu赋给MSGpkt->cmd.Data

   osal_memcpy( MSGpkt->cmd.Data, asdu,MSGpkt->cmd.DataLength );

 }

 else  //无数据

 {

   MSGpkt->cmd.Data = NULL;

 }

 

#if defined ( MT_AF_CB_FUNC)

  // If MT has subscribed for this callback, don't send asa message.

  ifAFCB_CHECK(MSGpkt->endPoint,*(epDesc->task_id),SPI_CB_AF_DATA_IND)

 {

   af_MTCB_IncomingData( (void *)MSGpkt );

   // Release thememory.

   osal_msg_deallocate( (void *)MSGpkt );

 }

 else

#endif

 {

   // Send message through taskmessage.

//数据包构造好后,就要发送到AF层,这里调用osal_msg_send()

osal_msg_send( *(epDesc->task_id),(uint8 *)MSGpkt );

 }

}

 

*********************************************************************

 

byte osal_msg_send( bytedestination_task, byte *msg_ptr )

{

//--------------------------------

  if ( msg_ptr == NULL) //无消息

   return (INVALID_MSG_POINTER );

//--------------------------------

  if ( destination_task>= tasksCnt )  //不在任务条目范围内???任务不合法

 {

   osal_msg_deallocate( msg_ptr );

   return ( INVALID_TASK );

 }

//--------------------------------

 // 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;  //检查到含有合法任务的消息,

                           //则把目的任务的ID赋给消息结构体的dest_id

  //OSAL_MSG_ID()参见前面          

                                            

//--------------------------------

  // queue message 把当前消息(msg_ptr所指)加入到系统消息列表中

  osal_msg_enqueue(&osal_qHead, msg_ptr );

//--------------------------------

  // Signal the taskthat a message is waiting

  osal_set_event(destination_task, SYS_EVENT_MSG );  //设置事件发生标志函数!!

 

  return ( ZSUCCESS);

}

 

*********************************************************************/

byte osal_set_event( byte task_id, UINT16event_flag )

{

  if ( task_id< tasksCnt )

 {

 halIntState_t  intState;

   HAL_ENTER_CRITICAL_SECTION(intState);   // Hold offinterrupts

   tasksEvents[task_id] |= event_flag;  // Stuff the event bit(s) 相应任务有事件发生

   HAL_EXIT_CRITICAL_SECTION(intState);    // Releaseinterrupts

 }

  else

   return ( INVALID_TASK );

 

  return ( ZSUCCESS);

}

 

//判断OSAL层的消息类型

  if ( events& SYS_EVENT_MSG )

 {

   MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive(SampleApp_TaskID );  //接收属于本用户应用SampleApp

                                                      消息(SampleApp_TaskID来标志

   while ( MSGpkt //接收到着                                            

                                                                       //属于这个应用的消息osal_msg_receive( MApp_TaskID);

     switch ( MSGpkt->hdr.event //判断数据包事件类型

     {

       

       // Received when a key ispressed

       

 

 

       case AF_INCOMING_MSG_CMD: // #define AF_INCOMING_MSG_CMD  0x 1A  --Incoming MSG typemessage

         SampleApp_MessageMSGCB( MSGpkt );

         break;

 

         

       // Received whenever the device changes statein the network

         

       case ZDO_STATE_CHANGE:  //#define ZDO_STATE_CHANGE  0xD1  --ZDO has changed thedevice's network state

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

         if ( (SampleApp_NwkState ==DEV_ZB_COORD)

             || (SampleApp_NwkState == DEV_ROUTER)

             || (SampleApp_NwkState == DEV_END_DEVICE))

         {

           // Start sending the periodic message in aregular interval.

 

 

           osal_start_timerEx( SampleApp_TaskID,

                             SAMPLEAPP_SEND_PERIODIC_MSG_EVT,

                             SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );

         }

         else

         {

           // Device is no longer in thenetwork

         }

         break;

 

       default:

         break;

     }

 

     // Release thememory

     //释放消息占用的内存

     osal_msg_deallocate( (uint8 *)MSGpkt );

 

     // Next - if one isavailable

 

 

     MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive(SampleApp_TaskID );

    //endwhile (MSGpkt )

 

   // return unprocessed events

   // 判断是否有未处理的系统消息,有则接收返回没有处理的事件

   return (events ^ SYS_EVENT_MSG);  //注意!这里returnosal_start_system()下

   

//--------------------------

 

 // Send a message out - This event is generated by atimer

 //  (setupin SampleApp_Init()).

 if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT)   //发送周期消息

 {

   // Send the periodicmessage

   SampleApp_SendPeriodicMessage();

 

   // Setup to send message again innormal period (+ a little jitter)

   osal_start_timerEx( SampleApp_TaskID,SAMPLEAPP_SEND_PERIODIC_MSG_EVT,

       (SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand()& 0x00FF)) );

 

   // return unprocessedevents

   return (events ^SAMPLEAPP_SEND_PERIODIC_MSG_EVT);

 }

 

  // Discard unknownevents

  return0;

}

 

//SampleApp_MessageMSGCB()功能是处理接收数据,函数

//的输入为接收到的数据,而输出为小灯闪烁的时间。

void SampleApp_MessageMSGCB(afIncomingMSGPacket_t *pkt )

{

  uint16flashTime;

 

 switch ( pkt->clusterId )//判断簇ID

 {

   case SAMPLEAPP_PERIODIC_CLUSTERID //periodic

     break;

 

   case SAMPLEAPP_FLASH_CLUSTERID //flash

     flashTime = BUILD_UINT16(pkt->cmd.Data[1],pkt->cmd.Data[2] );

     HalLedBlink( HAL_LED_4, 4, 50, (flashTime / 4) ); //小灯闪烁四次

     break;

 }

}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值