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.

Simplelink stuck in _SlNonOsSemGet()

Other Parts Discussed in Thread: CC3100MOD, CC3100, CC3100BOOST

I have a CC3100MOD on our prototype board and Simplelink ported to our MCU operating in a non-OS mode using SPI.

After Simplelink starts a few initial messages are sent and responses are received. The sync codes appear correct.   Simplelink gets to  sl_DevGet() then _SlNonOsSemGet() with an infinite timeout and then calls _SlNonOsMainLoopTask(). The SpawnEntries list is null.  Simplelilnk is stuck in this loop. 

Is this the normal sequence of events?

Thanks.

  • Hi Paul,

    _SlNonOsMainLoopTask() check for whether host got response from NWP or not. if not, it will stuck at this point till it get response from NWP.

    Regards,

    Aashish

  • What response am I expecting?
    In configureSimpleLinkToDefaultState() sl_Start() returns 0 indicating it is in station mode. The return value from sl_Start is actually SL_RET_CODE_OK;
    I get the hardware interrupt.
    In _SlDrvRxHdrRead() the response from NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[0], 4) is BC-DC-CD-AB.
    Another NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[0], 4) which sends BC-DC-CD-AB and receives 08-00-08-00.
    I get the InitializationComplete() callback which is an empty method at this time. ​
    It hangs in _SlNonOsSemGet() called from the sl_DevGet() method.
    Is the InitializationComplete callback suppose to do something?
    In method _SlDrvMsgReadCmdCtx(), the source  of the hang up is this
            else
            {
                /* CmdSyncObj will be signaled by IRQ */
                 _SlDrvSyncObjWaitForever(&g_pCB->CmdSyncObj);
            }
    I don't get the second IRQ from the 3100MOD.  ​The first IRQ gets cleared back to a low. ​
    Paul
  • Aashish,

    Apparently this has been a common problem. I located this post describing a similar problem, e2e.ti.com/.../1455676.

    I follow the procedure in the post and end by writing the CNYS pattern on the SPI lines and read back SYNC pattern correctly.

    I find that when the IRQ occurs g_pCB->IsCmdRespWaited = true. That is the only interrupt I get from the module. The IRQ line does not activate a second time. If I delay the IRQ ( by hiting a breakpoint) then sl_Spawn((_SlSpawnEntryFunc_t)_SlDrvMsgReadSpawnCtx, NULL, 0); gets executed.

    void _SlDrvRxIrqHandler(void *pValue)
    {
    sl_IfMaskIntHdlr();
    RxIrqCnt++;
    if (TRUE == g_pCB->IsCmdRespWaited)
    {
    OSI_RET_OK_CHECK( sl_SyncObjSignalFromIRQ(&g_pCB->CmdSyncObj) );
    }
    else
    {
    sl_Spawn((_SlSpawnEntryFunc_t)_SlDrvMsgReadSpawnCtx, NULL, 0);
    }
    }
  • Hi Paul,


    Please share LA capture for SPI line. Also try spi_debug_tool example from SDK. This example verify porting of CC3100 host-driver to a new MCU platform. For more details refer processors.wiki.ti.com/.../CC31xx_SPI_Debug_Tool



    Regards,
    Aashish
  • Aashish,

    I don't have LA to show capture but I do have scope with SPI debug module. I believe the SPI is working. Here is the sequence of events until hangup occurs. Is it possible to verify these values?  IRQ never goes high a second time.

    IRQ = 0

    MOSI [ 21 43 34 12]   [66 84 08 00]   [00 00 01 00 0C 00 01 08]

    MISO [ 00 00 00 00]   [00 00 00 00]   [00 00 00 00 00 00 00 00]

    IRQ = 1

    MOSI [65 87 78 56]   [22 00 00 00]   [11 00 00 00]   [00 00 00 00]   [00 00 00 00]

    MISO [00 00 00 00]   [00 00 00 00]   [00 00 00 00]   [00 00 00 00]   [00 00 00 00] 

    IRQ = 0

    MOSI [00  00  00  00 ]  [BC DC CD AB]  [00 00 00 00]   [00 00 00 00]

    MISO [BC DC CD AB]  [08  00  08  00 ]  [00 00 00 00]   [11  11 11 11]

    at this point we end up in 

    _SlNonOsMainLoopTask(), the call stack is

    _SlNonOsSemGet()

    _SlDrvSyncObjWaitForever()

    _SlDrvMsgReadCmdCtx()

    // here is code from _SlDrvMsgReadCmdCtx()

    else
    {
    /* CmdSyncObj will be signaled by IRQ */
    _SlDrvSyncObjWaitForever(&g_pCB->CmdSyncObj);
    }

    IRQ never goes high.

    Regards,

    Paul

  • Aashish,

    I incorporated the SPI Debug Tool into my existing application. I removed the UartWrite commands since I don't have that capability right now. Running in the debugger and stepping through the TestSpi() method or letting it run to completion it exits with SUCCESS. My porting is correct.
  • Paul,

    I see a problem in the SPI trace you shared above: When 'SL_OPCODE_DEVICE_DEVICEGET' is sent to the device ([66 84 08 00] on MOSI line), CC3100 is expected to send the response 'SL_OPCODE_DEVICE_DEVICEGETRESPONSE' [0x66 0x04 0x38 0x00], after of course the exchange of H2N/N2H SYNC patterns. But what I instead see on the line is an 'SL_OPCODE_DEVICE_INITCOMPLETE' response. This message is expected from the device after the initial initialization sequence, and not as a response to any command. Can you please check if your application is asserting the nHIB line to enable the device again during this sequence?

    I'm attaching the SPI logs that I've captured on my setup for 'sl_start' and 'sl_DevGet' calls - Please use the same for your reference.

    -/Praneet

    SPI_Capture_May03.csv

  • Praneet,

    After HIB goes high it stays high at 2.8 volts.

    I looked through your log file.  Some differences I  noticed:

    My first SPI packet is your 10th packet, at line 46 of your file.  

    Your 12th packet MOSI data differs from my correspondig 3rd packet.

    Your MOSI data is FF when not sending command, and mine is 0.

    Does the SL_OPCODE_DEVICE_INITCOMPLETE response arrive before the InitComplete callback?

    Paul

  • Paul,

    Are you calling 'sl_Start' asynchronously (.i..e. sl_Start(0. 0. <init_complete_cb>))? If yes, the application should wait till the driver calls the 'InitComplete' callback before sending any commands to the device. The driver calls this callback after receiving 'SL_OPCODE_DEVICE_INITCOMPLETE'.

    For quick reference:

    _u8 gInitStatus = 0;
    _u8 gDeviceRole  = 0;
    void SimpleLinkInitCallback(_u32 status)
    {
        if(gDeviceRole == status)
        {
            UART_PRINT("Device started in %s role\n\r",\
                                    (0 == status) ? "Station" :\
                                    ((2 == status) ? "AP" : "P2P"));
            gInitStatus = 1; //APP_EVENT_STARTED;
        }
        else
        {
            gInitStatus = 2; //APP_EVENT_ERROR;
        }
    }
    
    _i32 InitSimplelink(_u8 role)
    {
        _i32 retVal = -1;
    
        gDeviceRole = role;
        
        /* Assumption: The device is configured to start as station */
        retVal = sl_Start(0, 0, SimpleLinkInitCallback);
        ASSERT_ON_ERROR(retVal);
        
        gInitStatus = 0;
        while(!gInitStatus)    
        {
        	sl_Task();
        }
    
        return (gInitStatus == 1) ? 0 /* Success */ : -1 /* Failure */;
    }
    
    int main()
    {
        SlVersionFull   ver = {0};
        
        _i32 retVal = -1;
        _u8  configOpt = 0;
        _u8  configLen = 0;
        
        retVal = InitSimplelink(ROLE_STA);
        ASSERT_ON_ERROR(retVal);
        
        configOpt = SL_DEVICE_GENERAL_VERSION;
        configLen = sizeof(ver);
        retVal = sl_DevGet(SL_DEVICE_GENERAL_CONFIGURATION, &configOpt, &configLen, (_u8 *)(&ver));
        ASSERT_ON_ERROR(retVal);
        
        ...
        ...
        ...
        
    }
    

    -/Praneet

  • Praneet,

    Having the call to sl_Task() in InitSimplelink()  allowed the initialization to continue.

    Does sl_Task() have to be called from other areas of the program?  

    Code now hangs in sl_WlanConnect() at VERIFY_RET_OK ( _SlDrvCmdOp(&CmdCtrl, &Msg, NULL));

    There is no interrupt at this point.  Should there be?  I see that our FORCE_AP pin is floating.

    Your reply was great help.

    Thanks,

    Paul

  • Paul,

    Yes - A Non-OS application is required to continuously call this (or '_SlNonOsMainLoopTask') function to receive asynchronous events from the device.

    Specific to your query, the application should expect a 'SL_WLAN_CONNECT_EVENT' and/or 'SL_NETAPP_IPV4_IPACQUIRED_EVENT' asynchronous events on a successful connection after a call to 'sl_WlanConnect'.

    I suggest you take references from the 'getting_stated_with_*' sample applications of the SDK

    -/Praneet

  • Praneet,

    Initialization is successful. UDP messages are transmitted.

    Question on sl_RecvFrom(). Whether or not there are incoming messages, sl_RecvFrom will hang in _SlNonOsMainLoopTask(). IRQ is usually low when the hangup occurs. Occasionally it will be high.

    Any ideas on why the IRQ would not occur?

    Thanks for the help.
    Paul
  • Paul, The application needn't have to loop on '_SlNonOsMainLoopTask' after a call to 'sl_RecvFrom' - Please take references from the 'udp_socket' sample application of the SDK.

    -/Praneet
  • Praneet,

    I have been referencing the udp socket sample project.  I used that when I started working with slstudio using the EMUBoost board with the CC3100Boost.

    The current problem is that the code will hang in the _SlDrvMsgReadSpawnCtx() or  _SlNonOsMainLoopTask() called from sl_RecvFrom().  I've been using non blocking mode but have tried the blocking mode also.

    For example, in non blocking mode at 50 mSec intervals I call BsdUdpServer() which calls sl_RecvFrom() .  The CC3100 has no data so it returns -11. When the process exits normally I see that it takes about three milliseconds for this process to  complete.

    After a random amount of time ( a few seconds to a few minutes ) the above described conditions will occur.

    _SlNonOsMainLoopTask() is called from the loop.

    Separate client and server sockets are opened after connecting to the access point.  The sockets are not closed.

    I can send packets out to a host application via BsdUdpClient() ( without calling  BsdUdpServer() )  without the code hanging up.

    Any assistance will be appreciated. 

    Thanks,

    Paul

  • Paul,

    Are you able to reproduce the issue on the 'slstudio' setup (just to make sure there's no platform/port specific issue)?
    Would it be possible for you to share your application code? If it's consistently (and easily) reproducible, I'd want to recreate it on my setup to investigate further.

    -/Praneet
  • Praneet,

    Is there a plan for adding a recovery mechanism in the driver to handle when the code hangs?

    I'm looking into a potential problem on our end. I will update you when I know more.

    Thanks,
    Paul
  • Paul,

    The application could define 'sl_GeneralEvtHdlr' to receive and handle fatal error events which occur in the device/host-driver. The below events will require restarting the device to continue:
    SL_DEVICE_ABORT_ERROR_EVENT
    SL_DEVICE_DRIVER_ASSERT_ERROR_EVENT
    SL_DEVICE_DRIVER_TIMEOUT_CMD_COMPLETE
    SL_DEVICE_DRIVER_TIMEOUT_SYNC_PATTERN
    SL_DEVICE_DRIVER_TIMEOUT_ASYNC_EVENT

    For receiving some of these timeout events (for ex: SL_DEVICE_DRIVER_TIMEOUT_SYNC_PATTERN), the application is expected to define 'sl_GetTimestamp' - The implementation of this functions should return the timer counter value in ticks unit.

    -/Praneet
  • Praneet,

    I have implemented a handler for the general events​. I am able to recover and restart the device most of the time.

    I do get a code hang up occasionally when restarting the device in ​_SlDrvRxHdrRead() at this point

    /* read while first 4 bytes are different than last 4 bytes */
    while ( *(_u32 *)&pBuf[0] == *(_u32 *)&pBuf[4])
    {
    NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[4], 4);
    }

    when called from sl_WlanPolicySet(SL_POLICY_CONNECTION, SL_CONNECTION_POLICY(1, 0, 0, 0, 1), NULL, 0);


    Currently in the driver a timeout is started shortly before the while loop. I added ​a timeout check within the while loop as shown below. It seems like this while loop should have a timeout.​

    ​ /* read while first 4 bytes are different than last 4 bytes */
    while ( *(_u32 *)&pBuf[0] == *(_u32 *)&pBuf[4])
    {
    NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[4], 4);
    #if (defined (sl_GetTimestamp)) && (!defined (SL_TINY))
    if (_SlDrvIsTimeoutExpired(&TimeoutInfo))
    {
    TimeoutState = TIMEOUT_ONE_MORE_SHOT;
    break;
    }
    #endif
    }

    I'm forcing connection errors so I can test this recovery method.​

    The original problem of the code stuck in SlNonOsSemGet() has been determined and resolved.

    Paul
  • Paul,

    A timeout (check to exit) is indeed required for this loop - We will add it in our next host-driver release. Thanks for the feedback.
    Let me know if you have additional queries on the topic.

    -/Praneet
  • Paul, I'm closing this thread - For additional queries on the topic, please start a new thread w/ references to the current one for us to track it better.

    -/Praneet