This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC2538: Process incoming AF commands through MT

Part Number: CC2538

Hello,

I want to process incoming AF Commands through MT. I know that I have to call MT_AfIncomingMsg() somewhere, but I don't know where.

Can anyone help?

  • Hello Panagiotis,

    For the ZNP example, it is called from znp_app.c -> znpEventLoop for the AF_INCOMING_MSG_CMD case of the SYS_EVENT_MSG event.  You can consider the same for zclGenericApp_event_loop.

    Regards,
    Ryan

  • I have added this in zclGenericApp_event_loop 

      if ( events & SYS_EVENT_MSG )
      {
        while ( (MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( zclGenericApp_TaskID )) || ((pMsg = (osal_event_hdr_t *) osal_msg_receive(zclGenericApp_TaskID)) != NULL) )
        {
          switch ( MSGpkt->hdr.event )
          {
            case AF_INCOMING_MSG_CMD:         
              MT_AfIncomingMsg((afIncomingMSGPacket_t *)pMsg);
              break;

    But it doesn't enter:  case AF_INCOMING_MSG_CMD:

  • I made a capture where I try to discover the basic cluster attributes and use on/off cluster. 

    Sniffer Link

    This is what I see when I execute the commands

    No AF responses, so I don't know for example the attributes of the basic cluster or if the on/off actually worked

  • Did you define both MT_AF_FUNC and MT_AF_CB_FUNC in your project?  Which packet numbers from you sniffer log align with the messages shown in your screenshot?  You can send a separate command to read the on/off attribute, I'm not sure what is contained in your basic attribute discovery message. Also, AF_DATA_CONFIRM should be monitored for AF ACK messages.

    Regards,
    Ryan

  • Both MT_AF_FUNC and MT_AF_CB_FUNC are defined.

    You can see on/off on No. 2312, 3004 and the basic attribute discovery message on 3028. 

    In the screenshots the messages that are shown are MT commands that are being read through the coordinators usb uart.

    In the basic attribute discovery message, it shows what attributes are included in the basic cluster.

    Both messages are af data requests.

  • I changed epDesc->task_id of bdb_RegisterSimpleDescriptor to &MT_TaskID and it somewhat works now.

    Now with every af command I get two responses. One response is the one that I want and the other is af_register_rsp which is being sent from the coordinator to the coordinator. Why is this happening?

    Also now every af command is being sent 2-3 times. 

  • Can you post a screenshot of the behavior you are observing?  I'm guessing that changing epDesc->task_id of bdb_RegisterSimpleDescriptor to &MT_TaskID is most likely causing each incoming message to also enter MT_AfCommandProcessing with a case MT_AF_REGISTER which causes MT_AfRegister to be processed and return a response. The ZNP bdb_RegisterSimpleDescriptor has epDesc->task_id set to &zcl_TaskID, the same as GenericApp, indicating that this is not the correct change to make.  This is a good opportunity to reference the znp_app.c and note what is accomplished in znpEventLoop to handle incoming cases with MT_* APIs.

    Regards,
    Ryan

  • For example I press "Read basic cluster's attributes" and the proccess happens three times

    Also by just enabling MT Commands I get  ZDO_SRC_RTG_IND_RSP with every response.

    I have modified the event loop to include the znp method but it goes straight to return  

    afIncomingMSGPacket_t *MSGpkt;
    osal_event_hdr_t *pMsg;
     
     if ( events & SYS_EVENT_MSG )
      { 
        //while ( (MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( zclGenericApp_TaskID )) || ((pMsg = (osal_event_hdr_t *) osal_msg_receive(zclGenericApp_TaskID)) != NULL)) 
        while ( (MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( zclGenericApp_TaskID )))
        {
          switch ( MSGpkt->hdr.event)
          {          
            case ZCL_INCOMING_MSG:
              // Incoming ZCL Foundation command/response messages
              zclGenericApp_ProcessIncomingMsg( (zclIncomingMsg_t *)MSGpkt );
              break;
    
            case KEY_CHANGE:
              zclGenericApp_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );
              break;
    
            case ZDO_STATE_CHANGE:
              zclGenericApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
    
              // now on the network
              if ( (zclGenericApp_NwkState == DEV_ZB_COORD) ||
                   (zclGenericApp_NwkState == DEV_ROUTER)   ||
                   (zclGenericApp_NwkState == DEV_END_DEVICE) )
              {
                giGenAppScreenMode = GENERIC_MAINMODE;
                zclGenericApp_LcdDisplayUpdate();
              }
              break;
    
            default:
              break;
          }
    
          // Release the memory
          osal_msg_deallocate( (uint8 *)MSGpkt );
        }
    
           while (((pMsg = (osal_event_hdr_t *) osal_msg_receive(zclGenericApp_TaskID)) != NULL)) 
        {
          switch (pMsg->event )
          {
            
            case CMD_SERIAL_MSG:
              MT_ProcessIncoming(((mtOSALSerialData_t *)pMsg)->msg);
              break;
            
            case AF_INCOMING_MSG_CMD:         
              MT_AfIncomingMsg((afIncomingMSGPacket_t *)pMsg);
              break;
              
            case AF_DATA_CONFIRM_CMD:
                MT_AfDataConfirm((afDataConfirm_t *)pMsg);
                break;          
    
            default:
              break;
          }
    
          // Release the memory
          osal_msg_deallocate( (uint8 *)pMsg );
        } 
        
        
        // return unprocessed events
        return (events ^ SYS_EVENT_MSG);
      }

  • All cases should be under the same while loop.

    //...
      if ( events & SYS_EVENT_MSG )
      {
        while ( (MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( zclGenericApp_TaskID )) )
        {
          switch ( MSGpkt->hdr.event )
          {
            case AF_INCOMING_MSG_CMD:
              MT_AfIncomingMsg((afIncomingMSGPacket_t *)MSGpkt);
              break;
              
            case ZCL_INCOMING_MSG:
              // Incoming ZCL Foundation command/response messages
              zclGenericApp_ProcessIncomingMsg( (zclIncomingMsg_t *)MSGpkt );
              break;
    //...

    Regards,
    Ryan

  • I am pretty certain that I have already tried it like this and it didn't work. I'm going to try it again tomorrow just to be sure.

  • Yes it didn't work. It doesn't enter case AF_INCOMING_MSG_CMD, it goes straight to  return (events ^ SYS_EVENT_MSG);

  • Have you defined MT_TASK?

  • Yes I have. This is what I have defined

    ewarm
    CC2538_USE_ALTERNATE_INTERRUPT_MAP=1
    FEATURE_RESET_MACRO
    SECURE=1
    TC_LINKKEY_JOIN
    NV_INIT
    NV_RESTORE
    ZTOOL_P1
    MT_TASK
    MT_UTIL_FUNC
    MT_SYS_FUNC
    MT_AF_FUNC
    MT_ZDO_FUNC
    MT_ZDO_CB_FUNC
    MT_ZDO_MGMT
    MT_ZDO_EXTENSIONS
    MT_GP_CB_FUNC
    MT_APP_FUNC
    MT_APP_CNF_FUNC
    MT_AF_CB_FUNC
    MT_NWK_FUNC
    xLCD_SUPPORTED=DEBUG
    MULTICAST_ENABLED=FALSE
    ZCL_READ
    ZCL_WRITE
    ZCL_BASIC
    ZCL_IDENTIFY
    ZCL_REPORT_DESTINATION_DEVICE
    xLEGACY_LCD_DEBUG
    HAL_UART=TRUE
    xHAL_SPI=TRUE
    USB_SETUP_MAX_NUMBER_OF_INTERFACES=5
    HAL_UART_USB
    xMT_UART_DEFAULT_OVERFLOW=FALSE
    xMT_UART_DEFAULT_PORT

  • Has your application registered for the endpoint and how is afBuildMSGIncoming processed as below?

    #if defined ( MT_AF_CB_FUNC )
      // If ZDO or SAPI have registered for this endpoint, dont intercept it here
      if (AFCB_CHECK(CB_ID_AF_DATA_IND, *(epDesc->task_id)))
      {
        MT_AfIncomingMsg( (void *)MSGpkt );
        // Release the memory.
        osal_msg_deallocate( (void *)MSGpkt );
      }
      else
    #endif
      {
        // Send message through task message.
        osal_msg_send( *(epDesc->task_id), (uint8 *)MSGpkt );
      }

    Regards,
    Ryan

  • I think the endpoint is registered in bdb_RegisterSimpleDescriptor

    void bdb_RegisterSimpleDescriptor( SimpleDescriptionFormat_t *simpleDesc )
    {
      endPointDesc_t *epDesc;
    
      // Register the application's endpoint descriptor
      //  - This memory is allocated and never freed.
      epDesc = osal_mem_alloc( sizeof ( endPointDesc_t ) );
      if ( epDesc )
      {
        // Fill out the endpoint description.
        epDesc->endPoint = simpleDesc->EndPoint;
        //epDesc->task_id = &MT_TaskID;   // all messages get sent to ZCL first
        epDesc->task_id = &zcl_TaskID; 
        epDesc->simpleDesc = simpleDesc;
        epDesc->latencyReq = noLatencyReqs;
    
        // Register the endpoint description with the AF
        afRegister( epDesc );
      }
    }

    afBuildMSGIncoming is processed the same way as the one you sent me.

    Isn't the endpoint registered by default  in the generic app example?

  • Is the endpoint registered the same one which incoming messages are being transmitted, and does afBuildMSGIncoming enter MT_AfIncomingMsg or osal_msg_send?

    Regards,
    Ryan

  • It doesn't enter MT_AfIncomingMsg, it goes straight to osal_msg_send.

    It is the same endpoint since the packet details show that it sends it to the right endpoint and the bdb_RegisterSimpleDescriptor() parameter is zclGenericApp_SimpleDesc 

  • This behavior would confirm that the MT application does not intercept the incoming packet as the endpoint is not reserved to be processed by the MT task (the endpoint was registered by the ZCL task instead).  You can attempt to process MT_AfIncomingMsg anyway and not release the memory with osal_msg_deallocate before entering osal_msg_send as well, or send messages to an endpoint registered by the MT task which also do not have an application attached to them (which causes the behavior observed when bdb_RegisterSimpleDescriptor was modified).

    Regards,
    Ryan

  • I made this changes in afBuildMSGIncoming and now it works.

    #if defined ( MT_AF_CB_FUNC )
      if(epDesc->endPoint != 0){
        MT_AfIncomingMsg( (void *)MSGpkt );
      }
    #endif
        // Send message through task message.
        osal_msg_send( *(epDesc->task_id), (uint8 *)MSGpkt );

    It also works the same if I put MT_AfIncomingMsg in zcl_event_loop

    if ( *msgPtr == AF_INCOMING_MSG_CMD ){
        zcl_ProcessMessageMSG( (afIncomingMSGPacket_t *)msgPtr );
        MT_AfIncomingMsg( (afIncomingMSGPacket_t *)msgPtr );
    }

    Thank you for your help!!!