TMS570LS3137 + FreeRTOS TCP IP

Hello. I have a problem with the stack of FreeRTOS TCP IP. I have do a TCP client in my board, que saque del ejemplo de FreeRTOS, and I verified with the Wirersharck on the PC.

When I used the TCP client example from the page:

The task that call this function vCreateTCPClientSocket( void ) stopt. I debug the program, and the problem is when it enters in FreeRTOS_Socket.c, in the line: ( void ) xEventGroupWaitBits( pxSocket->xEventGroup, ( EventBits_t ) eSOCKET_BOUND, pdTRUE /xClearOnExit/, pdFALSE /xWaitAllBits/, portMAX_DELAY );

I don´t understand how this could be solved.

I left my code:

uint8	emacAddress[6U] = 	{0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU};
uint32 	emacPhyAddress	=	0U;

uint8   ucMACAddress[6U] =   {0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU};


/* Include Files */
#include "sys_common.h"
#include "stdio.h"
/* FreeRTOS headers */
#include "FreeRTOS.h"
//#include "FreeRTOS_IO.h"
#include "os_task.h"
#include "os_queue.h"
#include "os_semphr.h"
#include "het.h"
#include "gio.h"
#include "sci.h"


#include "FreeRTOS_IP.h"
#include "FreeRTOS_sockets.h"

/* Define the network addressing.  These parameters will be used if either
ipconfigUDE_DHCP is 0 or if ipconfigUSE_DHCP is 1 but DHCP auto configuration
failed. */
static const uint8_t ucIPAddress[ 4 ] = { 192, 168, 0, 100 };
static const uint8_t ucNetMask[ 4 ] = { 255, 255, 255, 0 };
static const uint8_t ucGatewayAddress[ 4 ] = { 192, 168, 0, 1 };

/* The following is the address of an OpenDNS server. */
static const uint8_t ucDNSServerAddress[ 4 ] = { 208, 67, 222, 222 };


/* Define Task Handles */
xTaskHandle xTask1Handle;
xTaskHandle xTask2Handle;

char *pcBufferToTransmit = {'h','o','l','a'};

size_t xTotalLengthToSend = 4;


/* Use by the pseudo random number generator. */
static UBaseType_t ulNextRand;


UBaseType_t uxRand( void )
{
const uint32_t ulMultiplier = 0x015a4e35UL, ulIncrement = 1UL;

    /* Utility function to generate a pseudo random number. */

    ulNextRand = ( ulMultiplier * ulNextRand ) + ulIncrement;
    return( ( int ) ( ulNextRand >> 16UL ) & 0x7fffUL );
}


uint32_t ulApplicationGetNextSequenceNumber( uint32_t
ulSourceAddress,
     uint16_t usSourcePort,
     uint32_t ulDestinationAddress,
     uint16_t usDestinationPort )
{
     ( void ) ulSourceAddress;
     ( void ) usSourcePort;
     ( void ) ulDestinationAddress;
     ( void ) usDestinationPort;

     return uxRand();
}
/*-----------------------------------------------------------*/


void vTCPSend( char *pcBufferToTransmit, const size_t xTotalLengthToSend )
{

    sciSend(scilinREG, 10, " TCP FUNC");

Socket_t xSocket;
struct freertos_sockaddr xRemoteAddress;
BaseType_t xAlreadyTransmitted = 0, xBytesSent = 0;
TaskHandle_t xRxTask = NULL;
size_t xLenToSend;

    /* Set the IP address (192.168.0.200) and port (1500) of the remote socket
    to which this client socket will transmit. */
   // xRemoteAddress.sin_port = FreeRTOS_htons( 15000 );
    xRemoteAddress.sin_port = FreeRTOS_htons( 7070 );
    xRemoteAddress.sin_addr = FreeRTOS_inet_addr_quick( 192, 168, 0, 200 );
    sciSend(scilinREG, 10, " SOCKET 1 ");

    /* Create a socket. */
    xSocket = FreeRTOS_socket( FREERTOS_AF_INET,
                               FREERTOS_SOCK_STREAM,/* FREERTOS_SOCK_STREAM for TCP. */
                               FREERTOS_IPPROTO_TCP );
    sciSend(scilinREG, 10, " SOCKET 2");

    configASSERT( xSocket != FREERTOS_INVALID_SOCKET );

    sciSend(scilinREG, 10, " SOCKET 3");

    /* Connect to the remote socket.  The socket has not previously been bound to
    a local port number so will get automatically bound to a local port inside
    the FreeRTOS_connect() function. */
    if( FreeRTOS_connect( xSocket, &xRemoteAddress, sizeof( xRemoteAddress ) ) == 0 )
    {
        sciSend(scilinREG, 10, " SOCKET 4");
        /* Keep sending until the entire buffer has been sent. */
        while( xAlreadyTransmitted < xTotalLengthToSend )
        {
            sciSend(scilinREG, 10, " SOCKET 5");
            /* How many bytes are left to send? */
            xLenToSend = xTotalLengthToSend - xAlreadyTransmitted;
            xBytesSent = FreeRTOS_send( /* The socket being sent to. */
                                        xSocket,
                                        /* The data being sent. */
                                        &( pcBufferToTransmit[ xAlreadyTransmitted ] ),
                                        /* The remaining length of data to send. */
                                        xLenToSend,
                                        /* ulFlags. */
                                        0 );
            sciSend(scilinREG, 10, " SOCKET 6");
            if( xBytesSent >= 0 )
            {
                sciSend(scilinREG, 10, " SOCKET 7");
                /* Data was sent successfully. */
                xAlreadyTransmitted += xBytesSent;
            }
            else
            {
                sciSend(scilinREG, 10, " SOCKET 8");
                /* Error - break out of the loop for graceful socket close. */
                break;
            }
        }
    }
    sciSend(scilinREG, 10, " SOCKET 9");
    /* Initiate graceful shutdown. */
    FreeRTOS_shutdown( xSocket, FREERTOS_SHUT_RDWR );

    /* Wait for the socket to disconnect gracefully (indicated by FreeRTOS_recv()
    returning a FREERTOS_EINVAL error) before closing the socket. */
    while( FreeRTOS_recv( xSocket, pcBufferToTransmit, xTotalLengthToSend, 0 ) >= 0 )
    {
        sciSend(scilinREG, 12, " SOCKET 10");
        /* Wait for shutdown to complete.  If a receive block time is used then
        this delay will not be necessary as FreeRTOS_recv() will place the RTOS task
        into the Blocked state anyway. */
      //  vTaskDelay( pdTICKS_TO_MS( 250 ) );
        vTaskDelay(300);

        /* Note - real applications should implement a timeout here, not just
        loop forever. */
    }

    /* The socket has shut down and is safe to close. */
    FreeRTOS_closesocket( xSocket );
}



/*----------------------------------------------------------------------------------------------------------------------*/

/* USER CODE BEGIN (4) */
/* Task1 */
void vTask1(void *pvParameters)
{
    gioSetBit(hetPORT1, 05, gioGetBit(hetPORT1, 05) ^ 1);

    for(;;)
    {
        gioSetBit(hetPORT1, 0, gioGetBit(hetPORT1, 0) ^ 1);
        vTaskDelay(1000);
        vTCPSend(pcBufferToTransmit, xTotalLengthToSend);
    }
}


/* Task2 */
void vTask2(void *pvParameters)
{
    char hola = {'H','O','L','A'};
    char *string = " HOLA OTB ";

    for(;;)
    {
        /* Taggle HET[1] with timer tick */
        gioSetBit(hetPORT1, 17, gioGetBit(hetPORT1, 17) ^ 1);
        vTaskDelay(500);

    }
}




void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent )
{
    sciSend(scilinREG, 10, " HOOK ");
uint32_t ulIPAddress, ulNetMask, ulGatewayAddress, ulDNSServerAddress;
static BaseType_t xTasksAlreadyCreated = pdFALSE;
int8_t cBuffer[ 16 ];

    /* Check this was a network up event, as opposed to a network down event. */
    if( eNetworkEvent == eNetworkUp )
    {
        /* Create the tasks that use the TCP/IP stack if they have not already been
        created. */
        if( xTasksAlreadyCreated == pdFALSE )
        {


            /*
             * Create the tasks here.
             */

            xTasksAlreadyCreated = pdTRUE;
        }

        /* The network is up and configured.  Print out the configuration,
        which may have been obtained from a DHCP server. */
        FreeRTOS_GetAddressConfiguration( &ulIPAddress,
                                          &ulNetMask,
                                          &ulGatewayAddress,
                                          &ulDNSServerAddress );
    }
}


/*----------------------------------------------------------------------------------------------------------------------*/

int main(void)
{
/* USER CODE BEGIN (3) */
    /* Set high end timer GIO port hetPort pin direction to all output */
    gioSetDirection(hetPORT1, 0xFFFFFFFF);
    sciInit();

    /* Create Task 1 */
            xTaskCreate(vTask1, (const signed char *)"Task1", configMINIMAL_STACK_SIZE, NULL, 4, &xTask1Handle);

    /* Create Task 2 */
    xTaskCreate(vTask2, (const signed char *)"Task2", configMINIMAL_STACK_SIZE, NULL, 2, &xTask2Handle);

    /* Initialise the RTOS's TCP/IP stack.  The tasks that use the network
    are created in the vApplicationIPNetworkEventHook() hook function
    below.  The hook function is called when the network connects. */
    FreeRTOS_IPInit( ucIPAddress,
                     ucNetMask,
                     ucGatewayAddress,
                     ucDNSServerAddress,
                     ucMACAddress );

    /* Start Scheduler */
    vTaskStartScheduler();

    /* Run forever */
    while(1);
/* USER CODE END */

    return 0;
}

I think there are a couple of problems in your code.

  • your MAC address is a broadcast MAC address and can’t be used for an ethernet/MAC interface (why are there 2 of them emacAddres and ucMACAddress ? FreeRTOS_IPInit is called with ucMACAddress)
  • using configMINIMAL_STACK_SIZE might be far too small for a task doing some more work like Task1, you might have to increase it

Did you verify that the PHY link came up ?

Did you define configASSERT and also enable stack overflow checking for development/debugging. I’d strongly recommend to do so since it really helps a lot !
The FreeRTOS FAQ is also very helpful.

Hello Harmut, thaks for your reply. Yes, it is an error that I have from a previous code. The MAC I am using is the umMACAddress …
As for the stack size, I tested it by increasing it, getting the same result.

The link I verify with the Wireshark, but for now no package appeared.

Task 1 is stuck. Is it possible that I am missing some configuration so that it does not get stuck in xEventGroupWaitBits?

In the FreeRTOS-Plus-TCP NetworkInterface folder I only have one file: NetworkInterface.c. Is it possible that I am missing something there?

Thank you very much for your reply

So Task1 calls vTCPSend which tries to establish a temporary TCP connection to a host (server) to do some application protocol, right ?
You should check the call stack to determine which of the TCP stack API calls internally waits forever for some response from the IP stack (which runs as a task) to narrow down the issue.
Did you verify that the PHY was detected on the (R)MII and the link came up with the desired mode (e.g. 100 MBit-FD) ? The PHY usually signals successful link detection/auto-negotiation finally with eNetworkUp and can be checked (e.g. setting a breakpoint) in vApplicationIPNetworkEventHook.
The EMAC driver and it’s adoption to the TCP stack is another point. Did you get a ready-to-use package from TI ?

Unless you are using the latest version FreeRTOS (possibly around the HEAD). you will have to define the mac address using the macros in the config file in case you have not already done so.

#define configMAC_ADDR0    0x52
#define configMAC_ADDR1    0x54
#define configMAC_ADDR2    0x00
#define configMAC_ADDR3    0x12
#define configMAC_ADDR4    0x34
#define configMAC_ADDR5    0xAD 

Hi!. Thank you very much for your answers. you made me realize that in the HalCoGen I was missing the MII configuration part. Thanks a lot.

Now, rearranging my code, I realized that I have another problem.

The vApplicationIPNetworkEventHook function is called, and there I create task 1 (which will be the one who handles the TCP part).

After the scheduler enters, and starts running, task 1 never executes. This seems very strange to me. If I put other tasks, created in the main, they are executed. Do you know what it could become? Thanks a lot.

Hi, Sorry for the late reply, I did not get notified as you did not reply/tag me directly.
It should be ok to do xTaskCreate from a hook function… i am surprised you did not get it to run… is it something related to priorities and your task is getting starved or processor time ?

Yes, I would think so too.

The function vApplicationIPNetworkEventHook() poses one limitation: you should not use the +TCP API’s because the function hook is running within the IP-task.
If you create or bind a socket or read from a socket with blocking, you will get a dead-lock. That could be the reason that task 1 never starts.

All what you should do in the hook is set a variable to remember that the +TCP is up, and leave the rest to a application task.