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.

CCS/LAUNCHXL-CC1310: Polling and tracking stops after reset of sensor and collector

Part Number: LAUNCHXL-CC1310
Other Parts Discussed in Thread: CC1310

Tool/software: Code Composer Studio

Hey guys,

I finally tracked down an old error I noticed before but never was able to reproduce. We use the sensor collector 15.4stack example in non-beacon mode. We have two cc1310 launchpads for testing. I will now try to elaborate the scenario and hopefully, you can tell me why this error happens and how to solve it.

  1. After flashing sensor/collector everything works fine, polling works and the sensor is tracked periodically
  2. Factory resetting the collector causes the sensor to disconnect and rejoin the collector. Still, everything works fine.
  3. I do now reset or unplug/replug the cc1310 sensor launchpad. Still, everything seems fine.
  4. I do now factory reset or flash the collector board. The sensor disconnects and rejoins the network.
  5. From now on, the sensor never gets configured during polling again and no tracking message is send to the collector. Other functions still work (sending other data messages or rejoining network after another disconnect from the collector)

In the sniffer I see the following when the polling timer expires.

The message from the collector after the "data request" is not answered. I noticed during debugging, that the sensor is not entering dataIndCB() anymore after step 5 is reached. Like the sensor is acknowledging the message, but the message is not passing some security stuff or whatever.

When I flash the sensor again, everything works fine.

So any idea whats happening here? I assume it has something to do with the power cycle of the sensor during reset.

Btw. I noticed that in the function disassoCnfCb() the case-loop if(pData->status == ApiMac_status_success) is never entered if the collector is not present or not acknowledging the message, what is always the case in my scenarios, because I only disconnect if the collector does not acknowledge the sensor messages. Not sure if that makes so much sens.

kind regards

Slev1n

  • Hey Slev1n,

    I'm slightly confused by your description given the expected behavior of the orphan procedure: http://dev.ti.com/tirex/content/simplelink_cc13x2_26x2_sdk_3_20_00_68/docs/ti154stack/html/ti154stack/non-beacon-mode.html#maintaining-a-connection-for-end-nodes 

    If the collector factory resets then it loses the sensor device record stored in NV and will not send a coordinator realignment while the sensor sends orphan notifications.  Therefore the sensor would need to exit orphan and perform a new join, or reset NV memory (you may accomplish this by re-flashing the device).  Rejoins and network communication is successful so long as the NV memory is not erased by re-programming or FN resets.  I do not observe the collector allowing an orphaned sensor to join its network after a factory reset which clears NV.

    Regards,
    Ryan

  • Hey Ryan,

    I did not provide enough resources for you to understand my disconnect behavior. See below the functions handleMaxDataFail() and disassoCnfCb().

    static void handleMaxDataFail(void)
    {
        if(!CONFIG_RX_ON_IDLE)
        {
            /* stop polling */
            Ssf_setPollClock(0);
        }
    
        ApiMac_mlmeSetReqBool(ApiMac_attribute_RxOnWhenIdle, true);
        /* Initialize counter for re-join delay calculation */
        interimDelayTicks = Clock_getTicks();
        /* non beacon network or fh mode - update stats */
        Sensor_msgStats.syncLossIndications++;
    
        if(CONFIG_FH_ENABLE)
        {
            updateState(Jdllc_states_orphan);
            parentFound = false;
            /* start trickle timer for PCS */
            Ssf_setTrickleClock(fhPanConfigInterval,
                                ApiMac_wisunAsyncFrame_configSolicit);
        }
        else
        {
    //__________________MY CHANGE START___________________
    #ifndef POWER_MEAS
            // For debug purpose only
            System_printf("Entered handleMaxDataFail \r\n");
    #endif
            if (auto_orphan_dis)
            {
            	Jdllc_sendDisassociationRequest();
            	auto_orphan_dis = false;
            }
    //_________________MY CHANGE END____________________
        }
    
        devInfoBlock.dataFailures = 0;
    }
    

    AND

    static void disassoCnfCb(ApiMac_mlmeDisassociateCnf_t *pData)
    {
    //____________________MY CHANGE START_______________________
    #ifndef POWER_MEAS
                // For debug purpose only
                System_printf("Disc entered!\r\n");
    #endif
    //____________________MY CHANGE END_____________________________
    
        if(pData->status == ApiMac_status_success)
        {
            /* stop polling */
            if(!CONFIG_RX_ON_IDLE)
            {
                Ssf_setPollClock(0);
            }
            /* enable looking for new parent */
            parentFound = false;
    
            /* set devInfoBlock back to defaults */
            devInfoBlock.panID = CONFIG_PAN_ID;
            devInfoBlock.channel = JDLLC_INVALID_CHANNEL;
            devInfoBlock.coordShortAddr = 0xFFFF;
            memset(&devInfoBlock.coordExtAddr[0], 0x00, APIMAC_SADDR_EXT_LEN);
            devInfoBlock.devShortAddr = 0xFFFF;
            memset(&devInfoBlock.devExtAddr[0], 0x00, APIMAC_SADDR_EXT_LEN);
            devInfoBlock.beaconOrder = CONFIG_BEACON_ORDER;
            devInfoBlock.superframeOrder = CONFIG_SUPERFRAME_ORDER;
            /* Below two commented lines will be set by updateState()*/
            /*devInfoBlock.currentJdllcState = Jdllc_states_initWaiting;*/
            /*devInfoBlock.prevJdllcState = Jdllc_states_initWaiting;*/
            devInfoBlock.currentDevState = Jdllc_deviceStates_scanActive;
            devInfoBlock.prevDevState = Jdllc_deviceStates_scanActive;
            devInfoBlock.dataFailures = 0;
            devInfoBlock.pollInterval = CONFIG_POLLING_INTERVAL;
    
            /* change state back to initWaiting and print on UART */
            updateState(Jdllc_states_initWaiting);
        }
    
        if(pJdllcCallbacksCopy && pJdllcCallbacksCopy->pDisassocCnfCb)
        {
            pJdllcCallbacksCopy->pDisassocCnfCb(&pData->deviceAddress.addr.extAddr,
                                                pData->status);
        }
    
        if(macCallbacksCopy.pDisassociateCnfCb != NULL)
        {
            macCallbacksCopy.pDisassociateCnfCb(pData);
        }
    //_____________MY CHANGE START____________
    #ifdef AUTO_RESTART // Since SDK 3 this might be all obsolete
        parentFound = false;
        devInfoBlock.panID = JDLLC_INVALID_PAN;
        ApiMac_secDeleteDevice(&devInfoBlock.coordExtAddr);
        Jdllc_join();
    #endif
    //_____________MY CHANGE END____________
    }

    So in my scenario, orphan phase is skipped and the sensor immediately disconnects from the network after 2 failed transmissions. This works all fine as described in my first post as long as the sensor is not reset or a power cycles occurs and then disconnects and rejoins the network.

    Any idea what can be the reason the sensor does not answer the collector message?

  • Remove the following lines:

        parentFound = false;
        devInfoBlock.panID = JDLLC_INVALID_PAN;
        ApiMac_secDeleteDevice(&devInfoBlock.coordExtAddr);

    And replace Jdllc_join(); with Util_setEvent(&Sensor_events, SENSOR_START_EVT); to see if this affects behavior.

    Regards,
    Ryan

  • Ok, I tried your changes.

    1. Removing "parentFound = false" causes the sensor to never rejoin. Because during disconnection, the case if(pData->status == ApiMac_status_success) is never true, because the sensor only disconnects if there is no answering collector anymore. So all the code within this case loop is never executed in my scenario, thus I have to set parentFound = false by myself.
    2. Replacing Jdllc_join(); with Util_setEvetn... works the same as before unfortunately no improvement.

    I still got no clue why the sensor is not responding to the collector messages anymore...what can be a reason for the sensor to acknowledge the collector reply but not enter dataIndCB() in sensor.c??

    kind regards

    Slev1n

  • Are you able to replicate this behavior with the default example and minimal changes?  If so then please provide clear replication steps.  Are only the configuration and tracking messages affected?  Does MAC_CbackEvent send a message to the application for the case MAC_MCPS_DATA_IND which then gets further processed in processIncomingICallMsg?

    Regards,
    Ryan

  • Yes, I can replicate this behavior with the default example.

    Changes:

    1. Channel set to 0 and PHY_ID to ETSI long range mode
    2. Skip orphan mode and directly disassociate using Jdllc_sendDisassociationRequest(); in the "else" loop in handleMaxDataFail();
    3. To enable automatic rejoin after disassociation I added the following at the end of dissasocCnfCb()
    parentFound = false;
    devInfoBlock.panID = JDLLC_INVALID_PAN;
    ApiMac_secDeleteDevice(&devInfoBlock.coordExtAddr);
    Jdllc_join();
    
    That are basically all changes (except for different reporting, polling, tracking intervals and some printouts)

    How to proceed
    • Establish a working network like described here
    http://dev.ti.com/tirex/content/simplelink_academy_cc13x0sdk_1_14_02_04/modules/154-stack_01_sensor_collector/154-stack_01_sensor_collector.html
    • Press reset button on sensor board
    • perform factory reset on collector board and unplug the board so the sensor will eventually disconnect
    • Replug the collector board...the sensor will join and send data messages, but will not respond to config request or tracking requests anymore

    Ryan Brown1 said:
    Are only the configuration and tracking messages affected?

    I think yes. But there are no other messages coming from the collector as far as I know...As you can see in the sniffer log from my first post. The sensor requests data, the collector sends data which is acknowledged by the sensor. Now, the sensor should actually perform the configuration request or tracking request and respond to the collector. But the sensor is doing nothing, in the applications it looks like no message from the collector has ever been arrived.

    Ryan Brown1 said:
    Does MAC_CbackEvent send a message to the application for the case MAC_MCPS_DATA_IND which then gets further processed in processIncomingICallMsg?

    I am not completely sure what you mean, but I put a print statement into processIncomingICallMSG but only in the case for MAC_MCPS_DATA_IND. This works at the beginning, but after performing the steps I mentioned this case is not entered anymore since no messages are printed anymore. So it looks like the sensor is somekind of rejecting/ignoring the messages from the collector at this point.

    So, I dont think this issue has something to do with my disassociation procedure. Only if the sensor was reset or unplugged and then disconnects and rejoins this issue occurs.

    I can send you my project files from the only slightly changed project_zero example if you want. Are you not able to reproduce the error I am facing?

    kind regards

    Slev1n

  • I have tested this setup and behavior is exactly as expected with Jdllc_sendDisassociationRequest(); replacing switchState(Jdllc_deviceStates_scanOrphan); and updateState(Jdllc_states_orphan); inside handleMaxDataFail and Util_setEvent(&Sensor_events, SENSOR_START_EVT); at the end of disassoCnfCb.

    Regards,
    Ryan

  • It looks like that it is now working with the basic example, though I have to add parentFound = false at the end of dissasocCnfCb, too.. So maybe it has something to do what I am doing in dissasocCnfCb in my actual code. I will test this with my actual code and report back.

    But one question remains. If there is no collector, when the sensor is sending its disassociation request this if loop if(pData->status == ApiMac_status_success) is not entered in dissasocCnfCb() right? I tested it with a print command...it is not in my case. So all the /* set devInfoBlock back to defaults */ is not happening, right? And parentFound is not set to false...Any comment on that pls.

  • Without a coordinator to provide an ACK the disassoCnfCb status will be ApiMac_status_noAck.  To force these actions to take place you can remove the if statement but the coordinator won't realize that the sensor has been disassociated when it powers back on.  You can also take action in jdllcDisassocCnfCb from sensor.c which is called by pJdllcCallbacksCopy->pDisassocCnfCb(&pData->deviceAddress.addr.extAddr, pData->status); as this function already uses Ssf_clearNetworkInfo to clear NV information and prepare the sensor to associate again.

    Regards,
    Ryan

  • I am aware, that the collector wont realize that. However, there are two scenarios, where the sensors will disassociate due to HandleMaxDataFail

    1. The collector is replaced, factory reset or flashed so in either of these options the collector does not know the sensor anymore and is not interested in receiving/processing the disassoc message from the sensor.

    2. The collector was just too busy or for whatever reason did not answer a few subsequent messages and HandleMaxDataFail() is called. Now the collector might notice the disassoc message but maybe not. E.g. the collector has no power for some time and after the disconnection of the sensor gets powered on again. The sensor will now rejoin and the collector detects a "rejoin" instead of a "new device join".

    I have to test the second scenario, but hopefully polling/tracking will still work. Though I still dont know what exactly was wrong with my code I mark your answer as "This resolved my issue" because it must have something to do with my code. I will post updates here or create a new thread if I was able to track the issue further down.

    Regards

    Slev1n

  • So I have tried your approach with my actual code unfortunately it did not work. I did then remove the if statement in dissasocCnfCb, but this did not help.

    I was then startled by the UART print "Restarted: 0x1" by the sensor when it joined the network again. But I thought since it is a new network (collector was factory reset and has a new short address) it should be "Started: 0x1". Going through sensor_process() I noticed, that if network config is available, the boolean rejoining is set to true. This variable is never set to false (except if you reset/flash the board) so even if the sensor disconnects and Sensor_Start_EVT is set again, this variable is still true...I was too lazy/did not have the time to completely track down the implications, however, I added a rejoining = false if NO network info is available when Sensor_Start_EVT is processed. This solves the issue...

    Two questions:

    1. Any idea why this solved the issue?

    2. Do the two changes, removing the if statement in disassocCnfCb() AND/OR setting rejoining = false have any implications you can think of? I will perform further tests, but maybe you have something crucial in mind.

    kind regards

    Slev1n

  • Glad to hear that you resolved your issue.  Inside of jdllcJoinedCb, Jdllc_addSecDevice is only called if rejoining is false so you were correct in resetting this variable.  This is the only location in which that value is actually used so I do not foresee any negative implications.

    Regards,
    Ryan