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/TM4C1294NCPDT: fdOpenSession / fdCloseSession

Part Number: TM4C1294NCPDT

Tool/software: TI-RTOS

I have a project that is going to have several tasks, all working on a single set of Ethernet handles.

It seems to me that so far, each task has to open/close the file system with fdOpenSession/fdCloseSession separately.

My question is this:

I have one task that creates the file handles for the Ethernet communications, and if that is successfully completed, it will then start tasks to 'receive / send/ control / monitor' these processes.

As the tasks progress, a number of additional handles may be opened for additional communications.

Does each of these tasks have a unique file handle system, or do they all point to some kind of 'global' system?  Reason I ask is that once the main task opens the handles, none of the sibling tasks seem to be able to receive / transmit items using the same handles.

Documentation on these things seems to be sorely lacking.

Later-

David

  • Hi David,

    Each task has to do a fdOpenSession.

    Todd
  • Does each task get a unique set of HANDLEs, or are the HANDLEs global between all tasks? If I open a HANDLE in task A, can than handle be processed by HANDLE B?
  • Correction:

    Does each task get a unique set of HANDLEs, or are the HANDLEs global between all tasks? If I open a HANDLE in task A, can that HANDLE be processed by Task B?
  • Each task has to do a fdOpenSession. This allocates a little memory and assigns it to the task's env. It cannot be shared between tasks.
  • Maybe my question isn't clear, but I'm probably just dense...

    I have 2 tasks I'm trying to startup right now (just an initial subset, there are 6 in the whole thing). 'Supervisor', and 'Receive'. All the tasks do the fdOpenSession/fdCloseSession in them (they will never get to the fdCloseSession call, as they never end).

    'Supervisor' opens the master sockets that are going to be used. If it creates them successfully (and it does as far as I can tell), it starts the 'Receive' task, and goes into it's system monitoring function (successfully).
    'Receive' is supposed to get commands from the master socket set, and then operate on them.
    I open a TCP socket from my PC and transmit the initial command, however fdSelect never seems to recognize that something has been received.
    I traced through my setup code to make sure things were opened correctly (seems to be to me), upon completion I have the 3 HANDLES I'm supposed to have opened with no errors.

    I look down the code and from my point of view, it's pretty apparent that the fdSelect is not indicating that something has been received.
    What I'm wondering is this: Are the HANDLEs that appear to the 'Supervisor' task the same as the HANDLEs that the 'Receive' task has access to?
  • Hi David,

    To my knowledge, the file descriptors are shared across different Tasks. In fact, that is exactly what is shown in the tcpEcho example in TIRTOS - it has one 'master' Task that creates the sockets, and then passes the file descriptor for the accepted socket connection to a tcpWorker Task that calls recv() and send(). If you haven't yet seen this example, you may wish to take a look. It can be found in CCS under TI Network Examples for the TM4C1294NCPDT in the TI Resource Explorer.

    I did a quick test with TIRTOS 2.16.1.14 and modified the tcpEcho example as in the attached file by adding an fdSelect() call in the tcpWorker() function. The program came out of fdSelect() with a return code of 1 and was able to get to while loop. You can try to compare this with what you are doing and see if it helps you spot the difference.

    Best regards,

    Vincent

    /*
     * Copyright (c) 2014-2015, 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.
     */
    
    /*
     *    ======== tcpEcho.c ========
     *    Contains BSD sockets code.
     */
    
    #include <string.h>
    
    #include <xdc/std.h>
    #include <xdc/runtime/Error.h>
    #include <xdc/runtime/System.h>
    
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>
    #include <ti/drivers/GPIO.h>
    
    /* NDK BSD support */
    #include <sys/socket.h>
    
    /* Example/Board Header file */
    #include "Board.h"
    
    #define TCPPACKETSIZE 256
    #define NUMTCPWORKERS 3
    
    /*
     *  ======== tcpWorker ========
     *  Task to handle TCP connection. Can be multiple Tasks running
     *  this function.
     */
    Void tcpWorker(UArg arg0, UArg arg1)
    {
        int  clientfd = (int)arg0;
        int  bytesRcvd;
        int  bytesSent;
        char buffer[TCPPACKETSIZE];
        int ret;
        fd_set readset;
        fd_set writeset;
        struct timeval tv = {5, 0};
    
        FD_ZERO(&readset);
        FD_ZERO(&writeset);
    
        FD_SET(clientfd, &readset);
    
        System_printf("tcpWorker: start clientfd = 0x%x\n", clientfd);
    
        ret = fdSelect(1, &readset, &writeset, NULL, &tv);
    
        while ((bytesRcvd = recv(clientfd, buffer, TCPPACKETSIZE, 0)) > 0) {
            bytesSent = send(clientfd, buffer, bytesRcvd, 0);
            if (bytesSent < 0 || bytesSent != bytesRcvd) {
                System_printf("Error: send failed.\n");
                break;
            }
        }
        System_printf("tcpWorker stop clientfd = 0x%x\n", clientfd);
    
        close(clientfd);
    }
    
    /*
     *  ======== tcpHandler ========
     *  Creates new Task to handle new TCP connections.
     */
    Void tcpHandler(UArg arg0, UArg arg1)
    {
        int                status;
        int                clientfd;
        int                server;
        struct sockaddr_in localAddr;
        struct sockaddr_in clientAddr;
        int                optval;
        int                optlen = sizeof(optval);
        socklen_t          addrlen = sizeof(clientAddr);
        Task_Handle        taskHandle;
        Task_Params        taskParams;
        Error_Block        eb;
    
        server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (server == -1) {
            System_printf("Error: socket not created.\n");
            goto shutdown;
        }
    
    
        memset(&localAddr, 0, sizeof(localAddr));
        localAddr.sin_family = AF_INET;
        localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
        localAddr.sin_port = htons(arg0);
    
        status = bind(server, (struct sockaddr *)&localAddr, sizeof(localAddr));
        if (status == -1) {
            System_printf("Error: bind failed.\n");
            goto shutdown;
        }
    
        status = listen(server, NUMTCPWORKERS);
        if (status == -1) {
            System_printf("Error: listen failed.\n");
            goto shutdown;
        }
    
        optval = 1;
        if (setsockopt(server, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0) {
            System_printf("Error: setsockopt failed\n");
            goto shutdown;
        }
    
        while ((clientfd =
                accept(server, (struct sockaddr *)&clientAddr, &addrlen)) != -1) {
    
            System_printf("tcpHandler: Creating thread clientfd = %d\n", clientfd);
    
            /* Init the Error_Block */
            Error_init(&eb);
    
            /* Initialize the defaults and set the parameters. */
            Task_Params_init(&taskParams);
            taskParams.arg0 = (UArg)clientfd;
            taskParams.stackSize = 1280;
            taskHandle = Task_create((Task_FuncPtr)tcpWorker, &taskParams, &eb);
            if (taskHandle == NULL) {
                System_printf("Error: Failed to create new Task\n");
                close(clientfd);
            }
    
            /* addrlen is a value-result param, must reset for next accept call */
            addrlen = sizeof(clientAddr);
        }
    
        System_printf("Error: accept failed.\n");
    
    shutdown:
        if (server > 0) {
            close(server);
        }
    }
    
    /*
     *  ======== main ========
     */
    int main(void)
    {
        /* Call board init functions */
        Board_initGeneral();
        Board_initGPIO();
        Board_initEMAC();
    
        System_printf("Starting the TCP Echo example\nSystem provider is set to "
                      "SysMin. Halt the target to view any SysMin contents in"
                      " ROV.\n");
        /* SysMin will only print to the console when you call flush or exit */
        System_flush();
    
        /* Start BIOS */
        BIOS_start();
    
        return (0);
    }