我是靠谱客的博主 勤恳眼神,最近开发中收集的这篇文章主要介绍OSAL处理接收数据包流程,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述



以下为系统处理来自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层规定接收的数据包的类型如下:

typedef struct

{

  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 Profile ID

  epList_t *pList;

  uint8 grpEp;

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

 

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

  {

    // Find the first endpoint for this group

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

    if ( grpEp == APS_GROUPS_EP_NOT_FOUND )

      return;   // No endpoint found,没找到终端

 

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

    if ( epDesc == NULL )

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

 

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

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

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

 

  else if ( aff->DstEndPoint == AF_BROADCAST_ENDPOINT )

  {

    // Set the list

    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 this group

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

      if ( grpEp == APS_GROUPS_EP_NOT_FOUND )

        return;   // No endpoint found

 

      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, byte SecurityUse,

                 uint32 timestamp )

实参——形参

Aff——*aff

epDesc——*epDesc

SrcAddress——*SrcAddress

LinkQuality—— LinkQuality

SecurityUse—— SecurityUse

Timestamp—— timestamp

 

看一下afBuildMSGIncoming()函数

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

//Build the message for the app 

static void afBuildMSGIncoming( aps_FrameFormat_t *aff, endPointDesc_t *epDesc,

                 zAddrType_t *SrcAddress, uint8 LinkQuality, byte SecurityUse,

                 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 as a message.

  if AFCB_CHECK(MSGpkt->endPoint, *(epDesc->task_id), SPI_CB_AF_DATA_IND)

  {

    af_MTCB_IncomingData( (void *)MSGpkt );

    // Release the memory.

    osal_msg_deallocate( (void *)MSGpkt );

  }

  else

#endif

  {

    // Send message through task message.

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

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

  }

}

 

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

 

byte osal_msg_send( byte destination_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 task that a message is waiting

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

 

  return ( ZSUCCESS );

}

 

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

byte osal_set_event( byte task_id, UINT16 event_flag )

{

  if ( task_id < tasksCnt )

  {

  halIntState_t   intState;

    HAL_ENTER_CRITICAL_SECTION(intState);    // Hold off interrupts

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

    HAL_EXIT_CRITICAL_SECTION(intState);     // Release interrupts

  }

   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 is pressed

       

 

 

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

          SampleApp_MessageMSGCB( MSGpkt );

          break;

 

          

        // Received whenever the device changes state in the network

         

        case ZDO_STATE_CHANGE:   //#define ZDO_STATE_CHANGE  0xD1  --ZDO has changed the device'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 a regular interval.

 

 

            osal_start_timerEx( SampleApp_TaskID,

                              SAMPLEAPP_SEND_PERIODIC_MSG_EVT,

                              SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );

          }

          else

          {

            // Device is no longer in the network

          }

          break;

 

        default:

          break;

      }

 

      // Release the memory

      //释放消息占用的内存

      osal_msg_deallocate( (uint8 *)MSGpkt );

 

      // Next - if one is available

 

 

      MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );

    //end while ( MSGpkt )

 

    // return unprocessed events

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

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

   

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

 

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

  //  (setup in SampleApp_Init()).

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

  {

    // Send the periodic message

    SampleApp_SendPeriodicMessage();

 

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

    osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT,

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

 

    // return unprocessed events

    return (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT);

  }

 

  // Discard unknown events

  return 0;

}

 

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

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

void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )

{

  uint16 flashTime;

 

  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;

  }

}

最后

以上就是勤恳眼神为你收集整理的OSAL处理接收数据包流程的全部内容,希望文章能够帮你解决OSAL处理接收数据包流程所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(62)

评论列表共有 0 条评论

立即
投稿
返回
顶部