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.

RTOS/CC3220SF-LAUNCHXL: sl_Select - Fatal Error - Driver aborted

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

Tool/software: TI-RTOS

Hi,

i have a problem with receiving and sending tcp data. I use network_terminal example, sdk version 2.3.

my cc3220sf is used in ap mode and starts a tcp server. after starting the connection socket, clients can open connection sockets to communicate.

after a varying period of time, sl_select returns -2005L driver aborted. why? Please see my socket_cmd.c below

int32_t         conn_socket      = -1;
int32_t         comm_socket      = -1;
SlSockAddr_t    *sa;             /* Contains the local ip address and port */
SlSockAddr_t    *csa;            /* Contains the ip address and port of the connected peer. */
sockAddr_t      sAddr;
int32_t         addrSize;
SlFdSet_t       masterFds;

int32_t openConnectionSocket(uint16_t portNumber)
{
    int32_t         nonBlocking = TRUE;
    int32_t         status;
    uint32_t        i = 0;

    /* clear the global data buffer */
    memset(&app_CB.gDataBuffer.nwData, 0x0 , sizeof(app_CB.gDataBuffer));

    /* clear the global data buffer */
    for (i = 0 ; i < MAX_BUF_SIZE ; i++)
    {
        app_CB.gDataBuffer.nwData[i] = (char)(i % 10);
    }
    /* filling the TCP server socket address */
    sAddr.in4.sin_family = SL_AF_INET;
    sAddr.in4.sin_port = sl_Htons((unsigned short)portNumber);
    sAddr.in4.sin_addr.s_addr = SL_INADDR_ANY;
    sa = (SlSockAddr_t*)&sAddr.in4;
    csa = (SlSockAddr_t*)&sAddr.in4;
    addrSize = sizeof(SlSockAddrIn_t);

    /*
     * Open a TCP socket:
     * Since TCP is a connection oriented channel,
     * the opened socket would serve as 'welcome' socket,
     * on which we'll receive connection requests from clients.
     */
    conn_socket = sl_Socket(SL_AF_INET, SL_SOCK_STREAM, TCP_PROTOCOL_FLAGS);
    if (conn_socket < 0)
    {
        ASSERT_ON_ERROR(conn_socket, SL_SOCKET_ERROR);
    }
    /* Bind socket to server's port */
    status = sl_Bind(conn_socket, sa, addrSize);
    if(status < 0)
    {
        UART_PRINT("[line:%d, error:%d] %s\r\n", __LINE__, status, SL_SOCKET_ERROR);
        sl_Close(conn_socket);
        return -1;
    }
    /* 'Listen' signify that wer'e ready to receive connection's from clients */
    status = sl_Listen(conn_socket, 0);
    if(status < 0)
    {
        UART_PRINT("[line:%d, error:%d] %s\r\n", __LINE__, status, SL_SOCKET_ERROR);
        sl_Close(conn_socket);
        return -1;
    }
    status = sl_SetSockOpt(conn_socket, SL_SOL_SOCKET, SL_SO_NONBLOCKING, &nonBlocking, sizeof(nonBlocking));
    if(status < 0)
    {
        UART_PRINT("[line:%d, error:%d] %s\r\n", __LINE__, status, SL_SOCKET_ERROR);
        return -1;
    }
    comm_socket = SL_ERROR_BSD_EAGAIN;
    SL_SOCKET_FD_SET(conn_socket, &masterFds);
}

// Nonblocking, no-IPV6 Server
int32_t StartTCPServer(uint16_t portNumber)
{
    SlFdSet_t       readFds;
    int32_t         status;
    status = openConnectionSocket(portNumber);
    while(1)
    {
        readFds = masterFds;
        status = sl_Select(conn_socket, &readFds, 0, 0, 0);
        if (status <= 0)
        {
            UART_PRINT("select: Socket closed because of %d",status);
            UART_PRINT(lineBreak);

        }
        else if (SL_SOCKET_FD_ISSET(conn_socket,&readFds))
        {
            if (comm_socket > 1) sl_Close(comm_socket);
            comm_socket = sl_Accept(conn_socket, (SlSockAddr_t*)&csa, (SlSocklen_t*)&addrSize);
            if (comm_socket < 0)
            {
                UART_PRINT("[line:%d, error:%d] %s comm_socket not accepted \r\n", __LINE__, comm_socket, SL_SOCKET_ERROR);
                continue;
            }
            else
            {
                SL_SOCKET_FD_SET(comm_socket, &masterFds);
                UART_PRINT(lineBreak);
                UART_PRINT("client connected");
                UART_PRINT(lineBreak);
            }
        }
    }

}

void sendTCP(const char *pcBuffer, size_t uiBufLen)
{
    _i16    status;
    _u16    bytesSent   = 0;

    if (pcBuffer != NULL && uiBufLen > 0 && comm_socket != -1)
    {
        while(TRUE)
        {
            /* Send packet to client */
            status = sl_Send(comm_socket, pcBuffer, (_i16) uiBufLen, 0);
            if(status == SL_ERROR_BSD_EAGAIN)
            {
                sleep(1);
                continue;
            }
            else if(status < 0)
            {
                UART_PRINT("no client connected [line:%d, error:%d] %s\r\n", __LINE__, status, SL_SOCKET_ERROR);
                break;
            }
            else if (status > 0 && (size_t) status == uiBufLen)
            {
                bytesSent   = (_u16)uiBufLen;
                UART_PRINT("Sent 1 packet (%u bytes) successfully\r\n", bytesSent);
                break;
            }
        }
    }
}

size_t receiveTCP(char *pcBuffer, size_t uiBufLen)
{
    _i16    status;
    _u16    bytesRcvd   = 0;

    if (pcBuffer != NULL && uiBufLen > 0 && comm_socket > 0)
    {
        /* Receive packet from client */
        status = sl_Recv(comm_socket, pcBuffer, uiBufLen, 0);
        if(status == SL_ERROR_BSD_EAGAIN || status == SL_ERROR_BSD_EBADF || status == 0)
        {
            /* No data received: Ignore and tell so */
            bytesRcvd = 0;
        }
        else if(status < 0)
        {
            UART_PRINT("[line:%d, error:%d] %s\r\n", __LINE__, status, SL_SOCKET_ERROR);
        }
        else
        {
            bytesRcvd = status;
            UART_PRINT("Received 1 packet (%u bytes) successfully\r\n", bytesRcvd);
            if (bytesRcvd >= uiBufLen)
            {
                bytesRcvd = uiBufLen - 1;
                UART_PRINT("Warning: Data limited to %u bytes\r\n", bytesRcvd);
            }
            pcBuffer[bytesRcvd] = '\0';
        }
    }
    return bytesRcvd;
}


  • /*
     * Copyright (c) 2016, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /* Standard includes */
    #include <stdlib.h>
    
    /* Example Header files */
    #include "socket_cmd.h"
    #include "network_terminal.h"
    
    //#define SECURE_SOCKET
    //#define CLIENT_AUTHENTICATION
    
    #ifdef SECURE_SOCKET
    #define TCP_PROTOCOL_FLAGS    SL_SEC_SOCKET
    #define ROOT_CA_CERT_FILE     "dummy-root-ca-cert"
    #define PRIVATE_KEY_FILE      "dummy-trusted-cert-key"
    #define TRUSTED_CERT_FILE     "dummy-trusted-cert"
    #define TRUSTED_CERT_CHAIN    "trusted-chain.pem"
    
    #define DEVICE_YEAR                 (2017)
    #define DEVICE_MONTH                (4)
    #define DEVICE_DATE                 (5)
    
    #define BUF_LEN                (MAX_BUF_SIZE - 20)
    #else
    #define TCP_PROTOCOL_FLAGS      0
    #define BUF_LEN                (MAX_BUF_SIZE)
    #endif
    
    typedef union
    {
        SlSockAddrIn6_t in6;       /* Socket info for Ipv6 */
        SlSockAddrIn_t in4;        /* Socket info for Ipv4 */
    }sockAddr_t;
    
    /****************************************************************************
                          LOCAL FUNCTION PROTOTYPES
    ****************************************************************************/
    int32_t TCPServer(uint8_t nb,
                      uint16_t portNumber,
                      uint8_t ipv6,
                      uint32_t numberOfPackets,
                      uint8_t tx);
    
    /*****************************************************************************
                      Callback Functions
    *****************************************************************************/
    
    
    
    
    /*!
        \brief          Plot RX histogram.
    
        This routine prints the rate and RSSI histogram,
        which were sampled by 'sl_WlanRxStatStart'.
            For each received packet over the sampling period.
    
        \param          rxStatResp       -   Points to the RX statistics structure,
                                             returned by sl_WlanRxStatGet().
    
        \sa             sl_WlanRxStatGet, sl_WlanRxStatStart
    
     */
    void drawRxHist(SlWlanGetRxStatResponse_t *rxStatResp)
    {
        float percent;
        int32_t i,j;
    
        UART_PRINT(
            "\r\n*********************************Rx Statistics"
    		"**********************************\r\n");
        UART_PRINT("Received Packets: %d \r\n",
                   rxStatResp->ReceivedValidPacketsNumber);
        UART_PRINT(
            "Average RSSI for management: %d Average"
    		" RSSI for other packets: %d\r\n\r\n",
            rxStatResp->AvarageMgMntRssi,rxStatResp->AvarageDataCtrlRssi);
    
        if(rxStatResp->ReceivedValidPacketsNumber == 0)
        {
            UART_PRINT(
                "    -----------------------   no data collected"
    			"   -----------------------\r\n");
        }
        else
        {
            UART_PRINT(
                "    -----------------------   RSSI Histogram"
    			"   -----------------------\r\n\r\n");
            UART_PRINT(
                "-40dBm to -87dBm (below and above RSSI will"
    			" appear in the first and last cells]\r\n\r\n");
    
            UART_PRINT(
                "           10   20   30   40   50   60   70   80   90   100\r\n");
            UART_PRINT(
                "         |----+----+----+----+----+----+----+----+----+----|\r\n");
    
            //RSSI histogram from -40 until -87 
    		//(all below and above RSSI will appear in the first and last cells
            for(i = 0; i < SL_WLAN_SIZE_OF_RSSI_HISTOGRAM; i++)
            {
                percent =
                    ((float)rxStatResp->RssiHistogram[i] /
                     (float)rxStatResp->ReceivedValidPacketsNumber * (float)100);
                if(0 == i)
                {
                    UART_PRINT(">-40dBm  ");
                }
                else
                {
                    if((SL_WLAN_SIZE_OF_RSSI_HISTOGRAM - 1) == i)
                    {
                        UART_PRINT("<-87dBm");
                    }
                    else
                    {
                        UART_PRINT("  -%-2ddBm",40 +
                                   (i * 47 / (SL_WLAN_SIZE_OF_RSSI_HISTOGRAM - 1)));
                    }
                }
                for(j = 0; j < (int)percent / 2; j++)
                {
                    UART_PRINT("*");
                }
                for(j = 0; j < 50 - (int)percent / 2; j++)
                {
                    UART_PRINT(" ");
                }
                UART_PRINT("(%.2f%%)\r\n",percent);
                UART_PRINT(
                    "         |----+----+----+----+----+----+----+----+----+----|"
    				"\r\n");
            }
    
            UART_PRINT(
                "              10   20   30   40   50 "
    			"  60   70   80   90   100\r\n\r\n");
    
            /* Print Rate Histogram */
    
            UART_PRINT(
                "    -----------------------   Rate Histogram"
    			"   -----------------------\r\n\r\n");
            UART_PRINT(
                "           10   20   30   40   50   60   70   80   90   100\r\n");
            UART_PRINT(
                "         |----+----+----+----+----+----+----+----+----+----|\r\n");
    
            for(i = 0; i < SL_WLAN_NUM_OF_RATE_INDEXES; i++)
            {
                percent =
                    ((float)rxStatResp->RateHistogram[i] /
                     (float)rxStatResp->ReceivedValidPacketsNumber * (float)100);
                UART_PRINT("%-2d         ",i);
                for(j = 0; j < (int)percent / 2; j++)
                {
                    UART_PRINT("*");
                }
                for(j = 0; j < 50 - (int)percent / 2; j++)
                {
                    UART_PRINT(" ");
                }
                UART_PRINT("(%.2f%%)\r\n",percent);
                UART_PRINT(
                    "         |----+----+----+----+----+----+----+----+----+----|"
    				"\r\n");
            }
    
            UART_PRINT(
                "              10   20   30   40   50   60   70   80   90   100\r\n");
        }
    
        UART_PRINT(
            "\r\n                     The data was sampled during %umSec\r\n",
            (((unsigned int)rxStatResp->GetTimeStamp -
              rxStatResp->StartTimeStamp)) / 1000);
    
        UART_PRINT(
            "*******************************End Rx Statistics"
    		"********************************");
    }
    
    /*****************************************************************************
                      Local Functions
    *****************************************************************************/
    
    /*!
        \brief          TCP Server.
    
        This routine shows how to set up a simple TCP server.
        It shows sending and receiving packets as well.
    
        \param          nb              -   Sets the socket type:
    										blocking or non-blocking.
    
        \param          portNumber      -   Decides which port is
    										affiliated with the server's socket.
    
        \param          ipv6            -   Sets the version of the
    										L3 IP protocol, IPv4 or IPv6.
    
        \param          numberOfPackets -   Sets the Number of 
    										packets to send \ receive.
    
        \param          tx              -   Decides if the function would 
    										transmit data. If this flag
                                            is set to false, 
    										this function would receive.
    
        \return         Upon successful completion,
    					the function shall return 0.
                        In case of failure, 
    					this function would return -1;
    
        \sa             cmdSendCallback, cmdRecvCallback
    
     */
    
    int32_t TCPServer(uint8_t nb,
                      uint16_t portNumber,
                      uint8_t ipv6,
                      uint32_t numberOfPackets,
                      uint8_t tx)
    {
        int32_t sock;
        int32_t status;
        int32_t newsock = -1;
        uint32_t i = 0;
        int32_t nonBlocking = FALSE;
    	/* Contains the local ip address and port */
        SlSockAddr_t    *sa;    
    	/* Contains the ip address and port of the connected peer. */	
        SlSockAddr_t    *csa;           
        sockAddr_t sAddr;
        int32_t addrSize;
    
        /* clear the global data buffer */
        memset(&app_CB.gDataBuffer.nwData, 0x0, sizeof(app_CB.gDataBuffer));
    
        /* clear the global data buffer */
        for(i = 0; i < MAX_BUF_SIZE; i++)
        {
            app_CB.gDataBuffer.nwData[i] = (char)(i % 10);
        }
    
        if(ipv6)
        {
            sAddr.in6.sin6_family = SL_AF_INET6;
            sAddr.in6.sin6_port = sl_Htons(portNumber);
            memset(sAddr.in6.sin6_addr._S6_un._S6_u32, SL_INADDR_ANY,
                   sizeof(sAddr.in6.sin6_addr._S6_un._S6_u32));
    
            sa = (SlSockAddr_t*)&sAddr.in6;
            csa = (SlSockAddr_t*)&sAddr.in6;
            addrSize = sizeof(SlSockAddrIn6_t);
        }
        else
        {
            /* filling the TCP server socket address */
            sAddr.in4.sin_family = SL_AF_INET;
    
            /* Set the server's port: 
    		   We'll receive connection requests on this port */
            sAddr.in4.sin_port = sl_Htons((unsigned short)portNumber);
            sAddr.in4.sin_addr.s_addr = SL_INADDR_ANY;
    
            sa = (SlSockAddr_t*)&sAddr.in4;
            csa = (SlSockAddr_t*)&sAddr.in4;
            addrSize = sizeof(SlSockAddrIn_t);
        }
    
        /*
         *  Open a TCP socket:
         *  Since TCP is a connection oriented channel,
         *  the opened socket would serve as 'welcome' socket,
         *  on which we'll receive connection requests from clients.
         */
        sock = sl_Socket(sa->sa_family, SL_SOCK_STREAM, TCP_PROTOCOL_FLAGS);
        ASSERT_ON_ERROR(sock, SL_SOCKET_ERROR);
    
    #ifdef SECURE_SOCKET
    
    #ifdef CLIENT_AUTHENTICATION
        SlDateTime_t dateTime;
        dateTime.tm_day = DEVICE_DATE;
        dateTime.tm_mon = DEVICE_MONTH;
        dateTime.tm_year = DEVICE_YEAR;
    
        sl_DeviceSet(SL_DEVICE_GENERAL, SL_DEVICE_GENERAL_DATE_TIME,
                     sizeof(SlDateTime_t), (uint8_t *)(&dateTime));
    
        /* Set the following to enable Client Authentication */
        sl_SetSockOpt(sock,SL_SOL_SOCKET,SL_SO_SECURE_FILES_CA_FILE_NAME,
                      ROOT_CA_CERT_FILE, strlen(
                          ROOT_CA_CERT_FILE));
    #endif
        /* Set the following to pass Server Authentication */
        sl_SetSockOpt(sock,SL_SOL_SOCKET,SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME,
                      PRIVATE_KEY_FILE, strlen(
                          PRIVATE_KEY_FILE));
        sl_SetSockOpt(sock,SL_SOL_SOCKET,SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME,
                      TRUSTED_CERT_CHAIN, strlen(
                          TRUSTED_CERT_CHAIN));
    #endif
    
        /* Bind socket to server's port */
        status = sl_Bind(sock, sa, addrSize);
        if(status < 0)
        {
            UART_PRINT("[line:%d, error:%d] %s\n\r", __LINE__, status,
                       SL_SOCKET_ERROR);
            sl_Close(sock);
            return(-1);
        }
    
       /* 'Listen' signify that wer'e ready to receive connection's from clients */
        status = sl_Listen(sock, 0);
        if(status < 0)
        {
            UART_PRINT("[line:%d, error:%d] %s\n\r", __LINE__, status,
                       SL_SOCKET_ERROR);
            sl_Close(sock);
            return(-1);
        }
    
        /* Set socket as non-blocking socket (if needed):
         * Non-blocking sockets allows user to handle other tasks rather than block
         * on socket API calls. 
    	 * If an API call using the Non-blocking socket descriptor
         * returns 'SL_ERROR_BSD_EAGAIN' - 
    	 * this indicate that the user should try the API again later.
         */
        if(TRUE == nb)
        {
            nonBlocking = TRUE;
            status =
                sl_SetSockOpt(sock, SL_SOL_SOCKET, SL_SO_NONBLOCKING, &nonBlocking,
                              sizeof(nonBlocking));
            if(status < 0)
            {
                UART_PRINT("[line:%d, error:%d] %s\n\r", __LINE__, status,
                           SL_SOCKET_ERROR);
                return(-1);
            }
            newsock = SL_ERROR_BSD_EAGAIN;
        }
    
        while(newsock < 0)
        {
            /* This call accepts incoming client's connection requests.
             * Accept returns a new socket descriptor, which is dedicated for
             * the accepted client's session. Accept takes the 'welcome' socket
             * descriptor as socket descriptor.
             */
            newsock = sl_Accept(sock, csa, (SlSocklen_t*)&addrSize);
    
            if((newsock == SL_ERROR_BSD_EAGAIN) && (TRUE == nb))
            {
                sleep(1);
            }
            else if(newsock < 0)
            {
                UART_PRINT("[line:%d, error:%d] %s\n\r", __LINE__, status,
                           SL_SOCKET_ERROR);
                sl_Close(newsock);
                sl_Close(sock);
                return(-1);
            }
        }
    
        UART_PRINT("Connected to client: ");
    
        if(ipv6)
        {
            PrintIPAddress(ipv6,(void*)&sAddr.in6.sin6_addr);
        }
        else
        {
            sAddr.in4.sin_addr.s_addr = sl_Htonl(sAddr.in4.sin_addr.s_addr);
            PrintIPAddress(ipv6,(void*)&sAddr.in4.sin_addr);
        }
    
        UART_PRINT(lineBreak);
    
        i = 0;
    
        if(tx)
        {
            int32_t buflen;
            uint32_t sent_bytes = 0;
            uint32_t bytes_to_send = (numberOfPackets * BUF_LEN);
    
            while(sent_bytes < bytes_to_send)
            {
                if(bytes_to_send - sent_bytes >= BUF_LEN)
                {
                    buflen = BUF_LEN;
                }
                else
                {
                    buflen = bytes_to_send - sent_bytes;
                }
    
                /* Send packets to server */
                status = sl_Send(newsock, &app_CB.gDataBuffer.nwData, buflen, 0);
                if((status == SL_ERROR_BSD_EAGAIN) && (TRUE == nb))
                {
                    sleep(1);
                    continue;
                }
                else if(status < 0)
                {
                    UART_PRINT("[line:%d, error:%d] %s\n\r", __LINE__, status,
                               SL_SOCKET_ERROR);
                    sl_Close(newsock);
                    sl_Close(sock);
                    return(-1);
                }
                i++;
                sent_bytes += status;
            }
    
            UART_PRINT("Sent %u packets (%u bytes) successfully\n\r",
                       i,
                       sent_bytes);
        }
        else
        {
            uint32_t rcvd_bytes = 0;
    
            while(rcvd_bytes < (numberOfPackets * BUF_LEN))
            {
                status = sl_Recv(newsock, &app_CB.gDataBuffer.nwData, MAX_BUF_SIZE,
                                 0);
                if((status == SL_ERROR_BSD_EAGAIN) && (TRUE == nb))
                {
                    sleep(1);
                    continue;
                }
                else if(status < 0)
                {
                    UART_PRINT("[line:%d, error:%d] %s\n\r", __LINE__, status,
                               BSD_SOCKET_ERROR);
                    sl_Close(sock);
                    return(-1);
                }
                else if(status == 0)
                {
                    UART_PRINT("TCP Client closed the connection \n\r");
                    break;
                }
                rcvd_bytes += status;
            }
    
            UART_PRINT("Received %u packets (%u bytes) successfully\n\r",
                       (rcvd_bytes / BUF_LEN), rcvd_bytes);
        }
    
        /* Calling 'close' with the both socket descriptors,
         * once operation is finished.
         */
        status = sl_Close(newsock);
        ASSERT_ON_ERROR(status, SL_SOCKET_ERROR);
    
        status = sl_Close(sock);
        ASSERT_ON_ERROR(status, SL_SOCKET_ERROR);
    
        return(0);
    }
    
    
    
    int32_t         conn_socket      = -1;
    int32_t         comm_socket      = -1;
    SlSockAddr_t    *sa;             /* Contains the local ip address and port */
    SlSockAddr_t    *csa;            /* Contains the ip address and port of the connected peer. */
    sockAddr_t      sAddr;
    int32_t         addrSize;
    SlFdSet_t       masterFds;
    
    int32_t openConnectionSocket(uint16_t portNumber)
    {
        int32_t         nonBlocking = TRUE;
        int32_t         status;
        uint32_t        i = 0;
    
        /* clear the global data buffer */
        memset(&app_CB.gDataBuffer.nwData, 0x0 , sizeof(app_CB.gDataBuffer));
    
        /* clear the global data buffer */
        for (i = 0 ; i < MAX_BUF_SIZE ; i++)
        {
            app_CB.gDataBuffer.nwData[i] = (char)(i % 10);
        }
        /* filling the TCP server socket address */
        sAddr.in4.sin_family = SL_AF_INET;
        sAddr.in4.sin_port = sl_Htons((unsigned short)portNumber);
        sAddr.in4.sin_addr.s_addr = SL_INADDR_ANY;
        sa = (SlSockAddr_t*)&sAddr.in4;
        csa = (SlSockAddr_t*)&sAddr.in4;
        addrSize = sizeof(SlSockAddrIn_t);
    
        /*
         * Open a TCP socket:
         * Since TCP is a connection oriented channel,
         * the opened socket would serve as 'welcome' socket,
         * on which we'll receive connection requests from clients.
         */
        conn_socket = sl_Socket(SL_AF_INET, SL_SOCK_STREAM, TCP_PROTOCOL_FLAGS);
        if (conn_socket < 0)
        {
            ASSERT_ON_ERROR(conn_socket, SL_SOCKET_ERROR);
        }
        /* Bind socket to server's port */
        status = sl_Bind(conn_socket, sa, addrSize);
        if(status < 0)
        {
            UART_PRINT("[line:%d, error:%d] %s\r\n", __LINE__, status, SL_SOCKET_ERROR);
            sl_Close(conn_socket);
            return -1;
        }
        /* 'Listen' signify that wer'e ready to receive connection's from clients */
        status = sl_Listen(conn_socket, 0);
        if(status < 0)
        {
            UART_PRINT("[line:%d, error:%d] %s\r\n", __LINE__, status, SL_SOCKET_ERROR);
            sl_Close(conn_socket);
            return -1;
        }
        status = sl_SetSockOpt(conn_socket, SL_SOL_SOCKET, SL_SO_NONBLOCKING, &nonBlocking, sizeof(nonBlocking));
        if(status < 0)
        {
            UART_PRINT("[line:%d, error:%d] %s\r\n", __LINE__, status, SL_SOCKET_ERROR);
            return -1;
        }
        comm_socket = SL_ERROR_BSD_EAGAIN;
        SL_SOCKET_FD_SET(conn_socket, &masterFds);
    }
    
    // Nonblocking, no-IPV6 Server
    int32_t StartTCPServer(uint16_t portNumber)
    {
        SlFdSet_t       readFds;
        int32_t         status;
        status = openConnectionSocket(portNumber);
        while(1)
        {
            readFds = masterFds;
            status = sl_Select(conn_socket, &readFds, 0, 0, 0);
            if (status <= 0)
            {
                UART_PRINT("select: Socket closed because of %d",status);
                UART_PRINT(lineBreak);
    
            }
            else if (SL_SOCKET_FD_ISSET(conn_socket,&readFds))
            {
                if (comm_socket > 1) sl_Close(comm_socket);
                comm_socket = sl_Accept(conn_socket, (SlSockAddr_t*)&csa, (SlSocklen_t*)&addrSize);
                if (comm_socket < 0)
                {
                    UART_PRINT("[line:%d, error:%d] %s comm_socket not accepted \r\n", __LINE__, comm_socket, SL_SOCKET_ERROR);
                    continue;
                }
                else
                {
                    SL_SOCKET_FD_SET(comm_socket, &masterFds);
                    UART_PRINT(lineBreak);
                    UART_PRINT("client connected");
                    UART_PRINT(lineBreak);
                }
            }
        }
    
    }
    
    void sendTCP(const char *pcBuffer, size_t uiBufLen)
    {
        _i16    status;
        _u16    bytesSent   = 0;
    
        if (pcBuffer != NULL && uiBufLen > 0 && comm_socket != -1)
        {
            while(TRUE)
            {
                /* Send packet to client */
                status = sl_Send(comm_socket, pcBuffer, (_i16) uiBufLen, 0);
                if(status == SL_ERROR_BSD_EAGAIN)
                {
                    sleep(1);
                    continue;
                }
                else if(status < 0)
                {
                    UART_PRINT("no client connected [line:%d, error:%d] %s\r\n", __LINE__, status, SL_SOCKET_ERROR);
                    break;
                }
                else if (status > 0 && (size_t) status == uiBufLen)
                {
                    bytesSent   = (_u16)uiBufLen;
                    UART_PRINT("Sent 1 packet (%u bytes) successfully\r\n", bytesSent);
                    break;
                }
            }
        }
    }
    
    size_t receiveTCP(char *pcBuffer, size_t uiBufLen)
    {
        _i16    status;
        _u16    bytesRcvd   = 0;
    
        if (pcBuffer != NULL && uiBufLen > 0 && comm_socket > 0)
        {
            /* Receive packet from client */
            status = sl_Recv(comm_socket, pcBuffer, uiBufLen, 0);
            if(status == SL_ERROR_BSD_EAGAIN || status == SL_ERROR_BSD_EBADF || status == 0)
            {
                /* No data received: Ignore and tell so */
                bytesRcvd = 0;
            }
            else if(status < 0)
            {
                UART_PRINT("[line:%d, error:%d] %s\r\n", __LINE__, status, SL_SOCKET_ERROR);
            }
            else
            {
                bytesRcvd = status;
                UART_PRINT("Received 1 packet (%u bytes) successfully\r\n", bytesRcvd);
                if (bytesRcvd >= uiBufLen)
                {
                    bytesRcvd = uiBufLen - 1;
                    UART_PRINT("Warning: Data limited to %u bytes\r\n", bytesRcvd);
                }
                pcBuffer[bytesRcvd] = '\0';
            }
        }
        return bytesRcvd;
    }
    

  • Hello,

    There is a very good explanation and a code example for the select in the NWP UG, http://www.ti.com/lit/ug/swru455e/swru455e.pdf. Look at section 5.7.2.1.

    From the code you attached, you are missing SL_SOCKET_FD_ZERO before SL_SOCKET_FD_SET.

    Also, nfds should be larger by 1 from the SD. In your case, you use the conn_socket without the +1.

    Please align to the example and let me know how it goes.

    Shlomi 

  • Hi,

    thank you for your quick response.

    I added the SL_SOCKET_FD_ZERO command before every SL_SOCKET_FD_SET and it works fine.

    But with the increment of +1 i get a bad file number error (-9L). Without the increment i have no error so far.

    I will test the server and let you know if I have any other problems.

    Thank you very much!

    Jonas

  • Hi Shlomi,

    is it necassary that the nfds is larger by 1 from SD? Why do I need to increment the sd?

    Furthermore, we are not sure, what SOCKET_FD_ZERO and SOCKET_FD_SET are supposed to. We assume that SOCKET_FD_ZERO is to initialize an array of file descriptors to zero and SOCKET_FD_SET activates the bit corresponding to the current file descriptor . Why do the file descriptors have to be cleared before a new one is set? what is the purpose of setting just a bit with FD_SET?

    we want to use the code in an industrial application.
    Is this way of starting tcp communication and handling an unstable connection feasible and robust?
  • Hello,

    This is the common practice regardless of simplelink solution (BSD compliance).

    nfds should be one greater than value of the largest valued socket by-definition.

    Using the macros for zeroing and masking the sockets you want is also a common practice.

    Additional comment is that you use conn_socket for sl_select() which is OK as conn_socket is your main socket and any signal you get on it means that a client is trying to connect (and then you call sl_accept() in return. However, you also set comm_socket (after client is connected) as part of the readFds which means you would get signalled also on the client socket (means you received data) but I do not see you are referring to it and tries to read data on this socket in return.

    Shlomi

  • Hello,

    thanks for your reply and sorry for my english. Its been a long time, since i had to write in english.

    Although its common practice, I try to understand those things. You mentioned that the macros are zeroing and masking the sockets. So i have to call these macros always when i get a new client connection (before sl_select) and after accepting (sl_accept)?

    Receiving data is handled in a task, that continuosly calls sl_Recv using the global comm_socket handle. The application gets tcp data from client, sends it via uart to a device, waits for uart response and sends the response via tcp to the client. UART-Communication is done in a seperate task with UART_read() and UART_write().
    Sometimes (after varying time) my TCP-Task is "blocked by Unknown" (Seen in ROV). Do you have an idea why this can happen and how I can get it back to ready state?

    Jonas

  • Hello,

    Yes, you need to use the macros before calling sl_select().

    Regarding the blocking task, it can be many reasons but I cannot speculate the reason.

    Can you provide more information? what API gets blocked? is it sl_recv()? try to run in debug mode and see where you are stuck.

    Shlomi

  • Hello,

    i have separated tasks for incoming tcp and incoming UART. Both are constructed at start.

    TCP task waits for input via sl_Recv and UART task waits via UART_read().

    Everything works fine but after a varying time the tcp task stops and i am not langer able to receive tcp.

    ROV callstacks of task tells me for my tcp-task:

    0x20008824, Fxn: inTask_TCP, Task Mode: Blocked
    0 ti_sysbios_knl_Task_schedule__I at Task.c:90 :	PC=0x0100E659
    1 ti_sysbios_knl_Task_restore__E at Task.c:380 :	PC=0x0100FBCC
    2 ti_sysbios_knl_Semaphore_pend__E at Semaphore.c:276 :	PC=0x010081AA
    3 sem_wait at semaphore.c:170 :	                        PC=0x01010D02
    4 Semaphore_pend_handle at cc_pal.c:404 :	        PC=0x0100BA74
    5 _SlDrvSyncObjWaitForever at driver.c:2852 :	        PC=0x0100FDBA
    6 _SlDrvWaitForPoolObj at driver.c:2439 :	        PC=0x01003DD4
    7 _SlDrvDataReadOp at driver.c:924 :	                PC=0x01004CEC
    8 sl_Recv at sl_socket.c:897 :	                        PC=0x0100BF5C
    9 receiveTCP at socket_cmd.c:237 :	                PC=0x0100710A
    10 inTask_TCP at uart_term.c:382 :	                PC=0x0100D5DC
    11 ti_sysbios_knl_Task_exit__E at Task.c:489 :	        PC=0x0100BB88

    The task never reaches ready state again.

    Here is my task: receiveTCP just calls sl_receive, writes received bytes in buffer and returns number of received bytes

    Void inTask_TCP(UArg arg0, UArg arg1)
    {
        char    cChar[64];
        size_t  len;
    
        while(!app_CB.Exit)
        {
            len = receiveTCP(cChar, sizeof(cChar));
            if (len > 0)
            {
                if (len < sizeof(cChar) - 2)
                {
                    cChar[len++] = '\r';
                    cChar[len++] = '\n';
                }
                UART_write(uartHandle_com, cChar, len);
            }
            Task_sleep(sleepTickCount);
        }
    }

    Regards,

    Jonas

  • Hello Jonas,

    In your case it seems that you are stuck at _SlDrvWaitForPoolObj().

    This is related to a pool of objects which are relevant in cases of actions which has async events as return (e.g. accept, select, recv, etc).

    When the event arrives, the blocked operation should be released.

    So in your case it seems that the async event is not fired so it makes you get stuck.

    Hard to tell what went wrong.

    Can you just make sure it is not the size of the list that causes it? the size is defined in user.h under MAX_CONCURRENT_ACTIONS.

    What is defined in your case?

    Shlomi

  • Hi Shlomi,

    MAX_CONCURRENT_ACTIONS is set to 18.

    The problem occurs when sl_select is called while sl_recv is running. I used Semaphore to separate these two api calls and it seems that it fixed my problem.

    I have a infinite test with: connect WLAN, open tcp communication, send datagram, kill wlan connection, reconnect wlan, open tcp .... and the tcp communication is more stable than before. But now, i sometimes (every 2 - 3 hours) get a FATAL ERROR (No Cmd Ack detected - cmd opcode = 0x9407).

    is there any other chance to separate those two api calls from different tasks? or is there any possibility to avoid the fatal error while selecting a new socket?

    Thanks!

    Jonas

  • Hello,

    I wouldn't go to the semaphore implementation yet as tis should work as-is.

    When it gets stuck, can you please show the values on the global related sync object?

    To be more specific, I would like to see:

    • g_pCB->ActiveActionsBitmap
    • g_pCB->ObjPool[0..MAX_CONCURRENT_ACTIONS-1] with
      • ActionID
      • AdditionalData

    Shlomi