FreeRTOS_bind call causes a reset

Hi

My application has developped a bug!..
I’m using FreeRTOS 10 on a STM32F767ZI, developping with IAR 8.30.1

I call FreeRTOS_bind()

which then calls

        ( void ) xEventGroupWaitBits( pxSocket->xEventGroup, ( EventBits_t ) eSOCKET_BOUND, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, portMAX_DELAY );

It causes a reset on portYIELD_WITHIN_API call.

if( xTicksToWait != ( TickType_t ) 0 )
{
    if( xAlreadyYielded == pdFALSE )
    {
        portYIELD_WITHIN_API();		<<----
    }

Could someone give some ideas about could be wrong? interrupts ? priorities?

thanks

I would be curious to see from which context FreeRTOS_bind() is being called.

It should be called from a normal task, other than the IP-task.

So if it is called from within an application hook, it is actually the IP-task calling it. The IP-task would hang forever.

Almost all functions in the FreeRTOS+TCP library work in a normal ( non-ISR ) context.

thanks for the answer.

The FreeRTOSbind() is being called from a task (look for -->):

void Downloader_task_code ( void * pvParameters )
{
    struct freertos_sockaddr xClient, xBindAddress;
    Socket_t xListeningSocket, xConnectedSocket;
    socklen_t xSize = sizeof( xClient );
    static const TickType_t xReceiveTimeOut = portMAX_DELAY;

    for (;;)
    {
        /* Attempt to open the socket. */
        xListeningSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );

        /* Check the socket was created. */
        if( xListeningSocket == FREERTOS_INVALID_SOCKET )
            FATAL_ERROR;

        /* If FREERTOS_SO_RCVBUF or FREERTOS_SO_SNDBUF are to be used with
        FreeRTOS_setsockopt() to change the buffer sizes from their default then do
        it here!.  (see the FreeRTOS_setsockopt() documentation. */

        /* If ipconfigUSE_TCP_WIN is set to 1 and FREERTOS_SO_WIN_PROPERTIES is to
        be used with FreeRTOS_setsockopt() to change the sliding window size from
        its default then do it here! (see the FreeRTOS_setsockopt()
        documentation. */

        /* Set a time out so accept() will just wait for a connection. */
        FreeRTOS_setsockopt( xListeningSocket,
                             0,
                             FREERTOS_SO_RCVTIMEO,
                             &xReceiveTimeOut,
                             sizeof( xReceiveTimeOut ) );

        /* Set the listening port to 88. */
        xBindAddress.sin_port = ( uint16_t ) IP_PORT_NUMBER;
        xBindAddress.sin_port = FreeRTOS_htons( xBindAddress.sin_port );

        /* Bind the socket to the port that the client RTOS task will send to. */
-->        FreeRTOS_bind( xListeningSocket, &xBindAddress, sizeof( xBindAddress ) );

        /* Set the socket into a listening state so it can accept connections.
        The maximum number of simultaneous connections is limited to 1. */
        FreeRTOS_listen( xListeningSocket, 1/*xBacklog*/ );

        for( ;; )
        {
            /* Wait for incoming connections. */
            xConnectedSocket = FreeRTOS_accept( xListeningSocket, &xClient, &xSize );
            if ( xConnectedSocket == FREERTOS_INVALID_SOCKET )
                  continue;

            for( ;; )
            {
                BaseType_t lBytesReceived;
                
                /* Receive another block of data into the cRxedData buffer. */
                lBytesReceived = FreeRTOS_recv( xConnectedSocket, &cRxedData, BUFFER_SIZE, 0 );

                if( lBytesReceived > 0 )                      /* Data was received, process it here. */
                {
                    bool Download_finished;
                    uint8_t Error;

                    extern bool Bootloader_Process ( uint16_t Data_NChars, char *Data, bool *p_Download_finished, uint8_t *p_Error );

                    if ( Bootloader_Process ( lBytesReceived, cRxedData, &Download_finished, &Error ) )
                    {
                        static char Frame_Tx [30];      // ACK,<CRC32>\n  ERROR,1A,<CRC32>\n

                        if ( Error == ERROR_NO_ERROR )
                            Frame_Build_ACK ( Frame_Tx );
                        else
                            Frame_Build_ERROR ( Frame_Tx, Error );

                        {
                            BaseType_t xBytesSent;
                            /* How many bytes are left to send? */
                            xBytesSent = FreeRTOS_send( xConnectedSocket,   /* The socket being sent to. */
                                                        Frame_Tx,           /* The data being sent. */
                                                        strlen(Frame_Tx),   /* The remaining length of data to send. */                                                        
                                                        0                   /* ulFlags. */
                                                      );

                            if( xBytesSent < 0 )
                            {
                                /* Error - break out of the loop for graceful socket close. */
                                FreeRTOS_shutdown( xConnectedSocket, FREERTOS_SHUT_RDWR );
                                break;
                            }
                        }
                        
                        if ( Download_finished )
                        {
                            vTaskDelay ( 1000 / portTICK_PERIOD_MS );       // Let the last ACK to get there before reset...

                            Bootloader_Mailbox_Reset();
                        }

                    }
                }
                else if( lBytesReceived == 0 )
                {
                    /* No data was received, but FreeRTOS_recv() did not return an error.
                    Timeout? */
                }
                else
                {
                    /* Error (maybe the connected socket already shut down the socket?).
                    Attempt graceful shutdown. */
                    FreeRTOS_shutdown( xConnectedSocket, FREERTOS_SHUT_RDWR );
                    break;
                }
            }

            /* The RTOS task will get here if an error is received on a read or write.
               Ensure the socket has shut down (indicated by FreeRTOS_recv() returning a FREERTOS_EINVAL
               error before closing the socket). */

            {
                uint8_t timeout_counter = 0;
                while( FreeRTOS_recv( xConnectedSocket, cRxedData, BUFFER_SIZE, 0 ) >= 0 )
                {
                    /* 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( 100 ) );

                    /* Note - real applications should implement a timeout here, not just loop forever. */
                    timeout_counter++;
                    if ( timeout_counter == 5 )
                      break;
                }
            }

            /* Shutdown is complete and the socket can be safely closed. */
            FreeRTOS_closesocket( xConnectedSocket );
        }
    }
}


void Downloader_task (void)
{
    /* 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 );
    {
        BaseType_t xReturned;
        TaskHandle_t xHandle = NULL;

        /* Create the task, storing the handle. */
        xReturned = xTaskCreate(
                        Heartbeat_task_code,    /* Function that implements the task. */
                        "HeartbeatTask",        /* Text name for the task. */
                        TASK_STACK_SIZE,        /* Stack size in words, not bytes. */
                        NULL,                   /* Parameter passed into the task. */
                        tskIDLE_PRIORITY,       /* Priority at which the task is created. */
                        &xHandle );             /* Used to pass out the created task's handle. */
        if( xReturned != pdPASS )
            FATAL_ERROR;

        /* Create the task, storing the handle. */
        xReturned = xTaskCreate(
                        Downloader_task_code,       /* Function that implements the task. */
                        "DownloaderTask",           /* Text name for the task. */
                        TASK_STACK_SIZE,            /* Stack size in words, not bytes. */
                        NULL,                       /* Parameter passed into the task. */
                        tskIDLE_PRIORITY,           /* Priority at which the task is created. */
                        &xHandle );                 /* Used to pass out the created task's handle. */
        if( xReturned != pdPASS )
            FATAL_ERROR;
    }

    /* Start the RTOS scheduler. */
    vTaskStartScheduler();

    /* If all is well, the scheduler will now be running, and the following
    line will never be reached.  If the following line does execute, then
    there was insufficient FreeRTOS heap memory available for the idle and/or
    timer tasks to be created. */
    for( ;; );
}

Hi Eduardo,

first of all, DO make it a habit to check ALL return values of ALL socket functions. Possibly the problem you see is a follow up on an earlier function call failure. This is REALLY essential.

Edit: Also, I believe you must initialize the address member of the xBindStructure, frequently to INADDR_ANY. If it is uninitialized, bind() may get confused. Also initialize the family member to AF_INET.

I’d like to add another hint. Better don’t wait a bit and pray for the last ACK being received by the host. That’s not reliable and shouldn’t be needed with a slightly improved download protocol/procedure.
If your downloader uses a dedicated service/port just send the last ACK and let the host e.g. just close the socket on receiption of it. Then you could simply re-arm the downloader for the next procedure.

Sorry - except the usual question if the stack size is large enough resp. stack overflow checking enabled along with configASSERT being defined I’ve no idea why portYIELD_WITHIN_API causes a RESET. There might be a HardFault which should be catched by the corresponding handler, but RESET :thinking:
Hmm … do you have a watchdog activated but don’t feed it in time ? This could cause a RESET…

Edit: Please enclose posted code blocks properly by 3 tildas ‘~” or 3 backticks ‘`’ at the beginning and at the end for better readability.