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.

CC3200 UDP Packet rate

Other Parts Discussed in Thread: CC3200

Hello,

We are working on a wireless sensor application where we read a sensor via the CC3200 SPI and then relay the reading back to our computer DAQ software via a UDP packet. We'd like to achieve an overall sample rate of the sensor of 5kS/s. We're able to achieve 80kS/s via SPI only. I modified the UDP example such that a timer is enabled for a specific sampling frequency. The timer ISR then samples the sensor via SPI and sends a UDP packet consisting of a counter and the sensor reading. The code functions correctly at low sample (timer) frequencies and low packet counts, but inconsistently hangs with increasing packet counts and timer frequencies. Anything above 1kHz hangs quickly and the code sometimes hangs with frequencies as low as 200Hz. I know the UDP packets aren't very efficient since we only have 6 bytes of data with a 48 byte header; however, our DAQ software plugin recognizes a single sample per packet, so this is the easiest for us to implement. 

Questions:

1) Any help establishing the maximum UDP packet rate would be appreciated. We're seeing the application hang at moderate speeds of 200Hz.

2) Any recommendations for achieving a higher throughput are appreciated.

Application information:

CC3200MODLAUNCHXL

DeweSoft 7.1 DAQ software with ethernet receiver plugin

  • Hi Nicholas,

    Please investigate or describe how the application is organized and where exactly it is getting stuck. I also recommend testing the throughput with the communication to the sensor removed from the system. For example, by using predefined data to test with. That way you can isolate any issues caused by performing the actions together.

    Best Regards,
    Ben
  • Hi,

    You are sending udp packets using sl_ API directly from timer interrupt? I think this way can't work properly.

    You need save samples achieved from timer interrupt into buffer and outside ISR read values from buffer and send it via UDP.

    Jan
  • Hello Ben,

    We did try sending a fixed angle value and are seeing similar results (sometimes we are able to acheive a slightly higher frequency). I've pasted the code snippets below. As you can see the program flow is very similar to the UDP demo application. Instead of filling a buffer in the BsdUdpClient function, we create the UDP socket and enable a timer. The BsdUdpClient function then enters a while loop until the required number of packets have been sent. The timer ISR then sends each UDP packet and increments the packet timer. Once the while loop exits, the timer is disabled and the socket is closed.

    When the program hangs, it never finishes sending all of the required packets. When we click pause on the CCS debugger, the carrat points to functions within nonos.c (picture attached).

    Timer ISR Code:

     else
        {
         //fixed angle value
         AMSReadData = 0x3fff;
        }
        //fill UDP buffer
        UDPMessage[0] = g_ulLoopCount++;
        UDPMessage[1] = (uint32_t)AMSReadData;
        //transmit via UDP
        // sending packet
        //_i16 sl_SendTo(_i16 sd, const void *buf, _i16 Len, _i16 flags, const SlSockAddr_t *to, SlSocklen_t tolen);
        iStatus = sl_SendTo(g_iSockID, UDPMessage, 8, 0,(SlSockAddr_t *)&g_sAddr, g_iAddrSize);
        if( iStatus <= 0 )
        {
         // error
         sl_Close(g_iSockID);
         //ASSERT_ON_ERROR(SEND_ERROR);
        }

    Modified BsdUdpClient Code:

    // creating a UDP socket
        g_iSockID = sl_Socket(SL_AF_INET,SL_SOCK_DGRAM, 0);
        if( g_iSockID < 0 )
        {
            // error
            ASSERT_ON_ERROR(SOCKET_CREATE_ERROR);
        }


        // Enable the GPT
        //
        MAP_TimerEnable(g_ulBase,TIMER_A);

        // for a UDP connection connect is not required
        // sending 1000 packets to the UDP server
        while (g_ulLoopCount < g_ulPacketCount)
        {
            // UDP transmit moved to timer
        }
        // Disable timer
        MAP_TimerDisable(g_ulBase,TIMER_A);

        UART_PRINT("Sent %u packets successfully\n\r",g_ulPacketCount);

        //closing the socket after sending 1000 packets
        sl_Close(g_iSockID);

    Terminal output when code hangs...

  • Hi Jan,

    Thank you for your reply. My understanding is that if the timer frequency is set too high, then the next ISR won't fire until the first one has finished processing. Prior to sending UDP packets, we did a similar test with only SPI angle sampling via timer ISR. We steadily increased the timer interrupt frequency until we saw the events fired at an irregular rate which was slower than the timer frequency.

    Note, we are toggling an LED and a GPIO pin in addition to sampling the sensor via SPI. We toggle the GPIO pin so we can measure the event frequency using a scope.
  • Hi,

    Using sl_ API calls in ISR will not work properly. If you not want issue, don't try do that.

    Jan
  • Hello Jan,

    Removing the sl_API call from the timer ISR seems to have prevented the program from hanging. However, the timing between UDP packets is highly irregular. Frequencies vary from 20kHz to 125Hz (see attached plot).

    Any idea why the packet timing is so irregular? 

    Updated BsdUdpClient code:

    while (g_ulLoopCount < g_ulPacketCount)
    {
    // UDP transmit moved to timer
    //fixed angle value
    AMSReadData = 0x3fff;

    // toggle LED and pin
    g_ucLEDStatus ^= (1 << (GPIO_LED3 % 8));
    g_ucGPIOValue ^= (1 << (22 % 8));
    GPIOPinWrite(g_uiLED3Port,g_ucLED3Pin,g_ucLEDStatus);
    GPIOPinWrite(g_uiGP22Port,g_ucGP22Pin,g_ucGPIOValue);

    //fill UDP buffer
    UDPMessage[0] = g_ulLoopCount++;
    UDPMessage[1] = (uint32_t)AMSReadData;
    //transmit via UDP
    // sending packet
    //_i16 sl_SendTo(_i16 sd, const void *buf, _i16 Len, _i16 flags, const SlSockAddr_t *to, SlSocklen_t tolen);
    iStatus = sl_SendTo(g_iSockID, UDPMessage, 8, 0,(SlSockAddr_t *)&g_sAddr, g_iAddrSize);
    if( iStatus <= 0 )
    {
    // error
    sl_Close(g_iSockID);
    Message("Socket Error!");
    //ASSERT_ON_ERROR(SEND_ERROR);
    }
    }

  • I found this post regarding the SL_POLICY_PM setting.

    I tried both the SL_LOW_LATENCY_POLICY as well as the SL_ALWAYS_ON_POLICY. Neither were very consistent. I saw 27 packets with a frequency of 20kHz (excellent rate!) followed by a delay of 171Hz and more packets/delays.

    Any ideas on how to obtain consistently higher packet rates (approximately 20kHz)?

    Thanks,

  • Hi,

    I expect that small sleep in sending loop can slightly decrease sending rate, but it will be more constant. Also will be good to serve asynchronous events by calling _SlNonOsMainLoopTask(); in case of using non OS code. Also check RSSI. Poor signal can have dramatic impact to transmit rate.

    Jan
  • Hi Nicholas,

    I'm glad you were able to move past the problem with the program hanging.

    Be aware that there are factors in a wireless network, outside of device settings, that can impact the transmission rate. You should also note that the maximum transfer rate would require ideal conditions.

    Can you describe how you are setting the GPIO to try to keep track of data transfer?

    Best Regards,

    Ben

  • Hello Ben,

    As far as I'm aware the wireless network should be close to optimum. The router is inches away from the demo board and shows 99% signal quality. I'd be happy to describe the modifications we made. We've also done some additional testing as follows:

    TCP demo application:

    1) Updated pinmux and main.c to toggle green LED and another GPIO pin during while{} loop used to send packets (loop in BsdTCP/UdpClient)
    2) Adjusted packet size to 8 bytes. We were able to send 1,000 TCP packets with a time period corresponding to roughly 2 Hz (so average of 2kHz frequency per packet). 
    We performed the same test using UDP, which resulted in an overall average packet frequency of 2.5 kHz. These are both far below the  stated application throughput of 13Mbps and 16Mbps accounting for packet header / minimum size.
    3) Increased packet size to 80 bytes with UDP. We saw a similar average packet frequency of 2.3kHz (see image, 1,000 packets in 2.30Hz- notice the large delay).
    Thoughts:
    1) Ideally we’d like to see a more uniform packet spacing / timing for our specific application, but I believe we can accommodate the irregularities we’re seeing.
    2) The stated application throughputs of 13Mbps and 16Mbps should apply to both small and large packets. We may be able to develop a workaround by transmitting larger packets to achieve our desired throughput, but the preferred solution would be to have smaller packets with a faster packet rate.
    3) Can you clarify what happens if an ISR is triggered while a previous ISR is running? Does the new ISR wait to execute until the first one completes, or is the first one interrupted and put on the stack until the new one completes?
    We appreciate any help/insight TI can provide. Here's the updated while{} loop code to toggle the LED and GPIO pin:

    // for a UDP connection connect is not required
    // sending 1000 packets to the UDP server
    while (lLoopCount < g_ulPacketCount)
    {

     // toggle LED and pin

        g_ucLEDStatus ^=  (1 << (GPIO_LED3 % 8));

        g_ucGPIOValue ^=  (1 << (22 % 8));

        GPIOPinWrite(g_uiLED3Port,g_ucLED3Pin,g_ucLEDStatus);

        GPIOPinWrite(g_uiGP22Port,g_ucGP22Pin,g_ucGPIOValue);


    // sending packet
    iStatus = sl_SendTo(iSockID, g_cBsdBuf, sTestBufLen, 0,
    (SlSockAddr_t *)&sAddr, iAddrSize);
    if( iStatus <= 0 )
    {
    // error
    sl_Close(iSockID);
    ASSERT_ON_ERROR(SEND_ERROR);
    }
    lLoopCount++;
    }

    Here's the UDP scope capture for 1,000 80bit data packets:

  • Hi Nicholas,

    You will not be able to reach the optimum performance just using the Launchpad.

    I'm confused as to how the timer is being used with the current loop. Does the timer trigger the while loop which runs to completion and then starts over after another timer interrupt or have you removed that functionality from the test? Are you using a blocking or non-blocking socket?

    Note that the sl_Send() function does not indicate when the data has actually been sent by the device, but rather when the data transfer to the networking subsystem finishes.

    Try checking the actual data throughput using a utility like iperf. I recommend also capturing network logs to understand what is happening and see all traffic.

    Regarding (3), the second ISR should wait to be handled until the first routine completes.

    Best Regards,
    Ben