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.

TM4C129ENCPDT: NDK_Send blocking - using a mailbox within the tcpEcho example

Part Number: TM4C129ENCPDT

Tool/software:

Hello,

I am modifying the TI-RTOS tcpEcho function. In short, I have two tasks: a tcp task, and a UART task. This is the same tcp task that is originally with the tcpEcho example.

In summary, I want to echo whatever the tcp socket receives out of both the tcp socket, and the UART. Please note that these are separate tasks, and UART is at a lower priority.

The problem I have encountering is that the "send" function, which calls NDK_send, does not appear to be blocking. Because of this, the tcp task is put to sleep before the send function has finished. This is creating timing issues, or appears to be.

Questions: 1) can I make the send function blocking? 2) Is there a status or callback that indicates when the send function is done? 

Below is my current code. I've commented out the mailbox related items.

Thank you!

//=============================================================================
/**
@return
- Void

 Task to handle TCP connection. Can be multiple Tasks running
 this function.
*/
Void tcpWorker
(
UArg arg0,    ///< task argument 0
UArg arg1    ///< task argument 1
)
{
    int32_t  clientfd = (int32_t)arg0;
    int32_t  bytesRcvd;
    int32_t  bytesSent;

    bool loopError = false;

    volatile bool mailboxPostSuccess = false;

    System_printf("tcpWorker: start clientfd = 0x%x\n", clientfd);
    /* SysMin will only print to the console when you call flush or exit */
    System_flush();

    while ((!loopError) && ((bytesRcvd = recv(clientfd, tcpTaskSys.buffer.x, TCPPACKETSIZE, 0))) > 0)
    {
        /* TCP Echo Functionality */
        bytesSent = send(clientfd, tcpTaskSys.buffer.x, bytesRcvd, 0);

        if ((bytesSent < 0) || (bytesSent != bytesRcvd))
        {
            System_printf("Error: send failed.\n");
            /* SysMin will only print to the console when you call flush or exit */
            System_flush();
            break;
            //loopError = true;
        }
        //else
        //{
        
            /* EGSE Code */
        
            //mailboxPostSuccess = Mailbox_post(*(tcpTaskSys.rs422Handle), tcpTaskSys.buffer.x, BIOS_NO_WAIT);//sizeof(buffer)); //TODO double check the sizeof(buffer) statement.
        
            //if (true == mailboxPostSuccess)
            //{
                //System_printf("Mailbox post to RS422 successful.\n");
                /* SysMin will only print to the console when you call flush or exit */
                //System_flush();
        
                //Task_sleep(GetSleepTickCount());
            //}
            //else
            //{
                //TODO if the mailbox is full, add push to FIFO here
                //System_printf("Mailbox error!\n");
                /* SysMin will only print to the console when you call flush or exit */
                //System_flush();
            //}
       // }





    }

    System_printf("tcpWorker stop clientfd = 0x%x\n", clientfd);

    close(clientfd);
}

  • The problem I have encountering is that the "send" function, which calls NDK_send, does not appear to be blocking. Because of this, the tcp task is put to sleep before the send function has finished. This is creating timing issues, or appears to be.
    Questions: 1) can I make the send function blocking? 2) Is there a status or callback that indicates when the send function is done? 

    Hi Noah,

      My understanding is that send() is implemented with the same behavior like a BSD socket send() function. Therefore, by default it should block until it finishes the transmit. Can you check the return value in bytesSent. Was the send() successful? Maybe there was an error. What does bytesSent indicate? Note that if there is an error, it it going to break out and close the socket. If there is no error, tcpWorker task remains active as it is in a while loop waiting for incoming data. If your UART task is of lower priority, I don't think it will be served. 

      When you run the tchpecho example as-is, does it work?

  • Charles,

    I have not yet observed an error coming back from send(), so I assume it's functioning. And, yes, the tcpecho example is working as-is.

    You're right that because of the while loop, the UART task does not get serviced. This is why I am putting the tcpWorker task to sleep. Now, I'm probably doing this incorrectly, but my process is: 1) receive tcp, 2) echo back tcp 3) post to the mailbox, 4) put the tcpWorker task to sleep for 500 uSec, 5) send the same message out of the UART.

    Perhaps, I'm putting the task to sleep at the wrong location. I want it to be "real time" enough where it appears that both the tcp echo and the UART write are occurring around the same time.

  • Hi Noah,

      Does the processor reach the Task_sleep(GetSleepTickCount())? The RTOS ticks is 1ms by default.  Did you somehow change the tick rate? If you use the default 1ms, you cannot do 500uSec sleep. Why don't you try a longer delay with several mS to see if it makes a difference.  

  • Good suggestion. I'll give this a try.

    FYI - I am using this function to change the tick

    //=============================================================================
    /**
    @return
    - int32_t: positive values means pass; negative values means error

    Calculates and assigns the sleep tick value, and it is set to 10 mSec (currently).
    */
    static int32_t CalculateSleepTick
    (
    uint32_t* val   ///< value of sleep ticks by reference
    )
    {

        int32_t returnVal = -1;

        if (val)
        {
            returnVal = 1;

            /* We want to sleep for macro-defined microseconds */
            *(val) = TASK_SLEEP_TIME_MICROSECS / Clock_tickPeriod;
        }

        return returnVal;
    }

    #define TASK_SLEEP_TIME_MICROSECS    10000u

  • I changed the sleep time to 1 mSec. Additionally, the debug Console was bogging down the real-time performance. Now, I'm able to use the mail box to send the transfer, and I'm printing the first byte of this transfer out of UART 4!