On this page:
FreeRTOS-Plus-UDP [Contains the source files that implement the IP stack] | +-include [Contains the header files for the IP stack] | +-portable | +-BufferManagement [Source files that implement optional buffer allocation schemes] | +-Compiler [Contains sub directories that port the stack to different compilers] | +-Compiler_x [Contains structure packing header files for Compiler_x] | +-Compiler_y [Contains structure packing header files for Compiler_y] | +-Compiler_z [Contains structure packing header files for Compiler_z] | +-NetworkInterface [Contains sub directories that port the stack to different hardware] +-MCU_x [Contains a network interface for the MCU_x family of microcontrollers] +-MCU_y [Contains a network interface for the MCU_y family of microcontrollers] +-MCU_z [Contains a network interface for the MCU_z family of microcontrollers] The FreeRTOS+UDP Directory Structure
FreeRTOSIPConfig.h tailors the core UDP/IP stack for your application. It is application specific, not IP stack specific, and should therefore be located in an application directory rather than a FreeRTOS+UDP directory. Existing FreeRTOSIPConfig.h header files are found in the reference projects available on this website.
/* 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, 200 }; static const uint8_t ucNetMask[ 4 ] = { 255, 255, 255, 255 }; 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 }; /* The MAC address array is not declared const as the MAC address will normally be read from an EEPROM and not hard coded (in real deployed applications).*/ static uint8_t ucMACAddress[ 6 ] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }; int main( void ) { /* Initialise the embedded Ethernet interface. 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 ); /* * Other RTOS tasks can be created here. */ /* 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( ;; ); } Example use of the FreeRTOS_IPInit() API function
FreeRTOS_IPInit() creates the FreeRTOS+UDP RTOS task. The FreeRTOS+UDP task
configures and initialises the network interface. If ipconfigUSE_NETWORK_EVENT_HOOK is
set to 1 in FreeRTOSIPConfig.h
then the IP stack will execute the
vIPNetworkEventHook()
callback function when the network is ready for use.
void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent )
{
static BaseType_t xTasksAlreadyCreated = pdFALSE;
/* Check this was a network up event, as opposed to a network down event. */
if( eNetworkEvent == eNetworkUp )
{
/* Create the tasks that use the IP stack if they have not already been
created. */
if( xTasksAlreadyCreated == pdFALSE )
{
/*
* For convenience, tasks that use FreeRTOS+UDP can be created here
* to ensure they are not created before the network is usable.
*/
xTasksAlreadyCreated = pdTRUE;
}
}
}
Example vApplicationIPNetworkEventHook() definition
static void prvSimpleServerTask( void *pvParameters ) { long lBytes; struct freertos_sockaddr xBindAddress; xSocket_t xListeningSocket; const TickType_t xSendTimeOut = 200 / portTICK_PERIOD_MS; /* Attempt to open the socket. */ xListeningSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP ); /* Check for errors. */ configASSERT( xListeningSocket != FREERTOS_INVALID_SOCKET ); /* Ensure calls to FreeRTOS_sendto() timeout if a network buffer cannot be obtained within 200ms. */ FreeRTOS_setsockopt( xListeningSocket, 0, FREERTOS_SO_SNDTIMEO, &xSendTimeOut, sizeof( xSendTimeOut ) ); /* Bind the socket to port 0x1234. */ xBindAddress.sin_port = FreeRTOS_htons( 0x1234 ); FreeRTOS_bind( xListeningSocket, &xBindAddress, sizeof( xBindAddress ) ); for( ;; ) { /* * The socket can now receive data here. */ } } Creating, configuring and binding a socket
As detailed on the FreeRTOS_sendto() API reference page, FreeRTOS_sendto() can be used with standard calling semantics, or zero copy calling semantics. This subsection demonstrates the standard calling semantics.
The source code below shows a task that creates a socket before entering a loop that sends a string to the socket (using the standard calling semantics) every 1 second (1000ms).
static void vSendUsingStandardInterface( void *pvParameters ) { xSocket_t xSocket; struct freertos_sockaddr xDestinationAddress; uint8_t cString[ 50 ]; uint32_t ulCount = 0UL; const TickType_t x1000ms = 1000UL / portTICK_PERIOD_MS; /* Send strings to port 10000 on IP address 192.168.0.200. */ xDestinationAddress.sin_addr = FreeRTOS_inet_addr( "192.168.0.200" ); xDestinationAddress.sin_port = FreeRTOS_htons( 10000 ); /* Create the socket. */ xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP ); /* Check the socket was created. */ configASSERT( xSocket != FREERTOS_INVALID_SOCKET ); /* NOTE: FreeRTOS_bind() is not called. This will only work if ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is set to 1 in FreeRTOSIPConfig.h. */ for( ;; ) { /* Create the string that is sent. */ sprintf( cString, "Standard send message number %lu\r\n", ulCount ); /* Send the string to the socket. ulFlags is set to 0, so the standard semantics are used. That means the data from cString[] is copied into a network buffer inside FreeRTOS_sendto(), and cString[] can be reused as soon as FreeRTOS_sendto() has returned. */ FreeRTOS_sendto( xSocket, cString, strlen( cString ), 0, &xDestinationAddress, sizeof( xDestinationAddress ) ); ulCount++; /* Wait until it is time to send again. */ vTaskDelay( x1000ms ); } } Example using FreeRTOS_sendto() with the standard (as opposed to zero copy) calling semantics
As detailed on the FreeRTOS_sendto() API reference page, FreeRTOS_sendto() can be used with standard calling semantics, or zero copy calling semantics. This subsection demonstrates the zero copy calling semantics.
The source code below shows a task that creates a socket before entering a loop that sends a string to the socket (using the zero copy calling semantics) every 1 second (1000ms).
static void vSendingUsingZeroCopyInterface( void *pvParameters ) { xSocket_t xSocket; uint8_t *pucBuffer; struct freertos_sockaddr xDestinationAddress; BaseType_t lReturned; uint32_t ulCount = 0UL; const uint8_t *pucStringToSend = "Zero copy send message number "; const TickType_t x1000ms = 1000UL / portTICK_PERIOD_MS; /* 15 is added to ensure the number, \r\n and terminating zero fit. */ const size_t xStringLength = strlen( ( char * ) pucStringToSend ) + 15; /* Send strings to port 10000 on IP address 192.168.0.200. */ xDestinationAddress.sin_addr = FreeRTOS_inet_addr( "192.168.0.200" ); xDestinationAddress.sin_port = FreeRTOS_htons( 10000 ); /* Create the socket. */ xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP ); /* Check the socket was created. */ configASSERT( xSocket != FREERTOS_INVALID_SOCKET ); /* NOTE: FreeRTOS_bind() is not called. This will only work if ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is set to 1 in FreeRTOSIPConfig.h. */ for( ;; ) { /* This task is going to send using the zero copy interface. The data being sent is therefore written directly into a buffer that is passed into, rather than copied into, the FreeRTOS_sendto() function. First obtain a buffer of adequate length from the IP stack into which the string will be written. */ pucBuffer = FreeRTOS_GetUDPPayloadBuffer( xStringLength, portMAX_DELAY ); /* Check a buffer was obtained. */ configASSERT( pucBuffer ); /* Create the string that is sent. */ memset( pucBuffer, 0x00, xStringLength ); sprintf( pucBuffer, "%s%lu\r\n", ucStringToSend, ulCount ); /* Pass the buffer into the send function. ulFlags has the FREERTOS_ZERO_COPY bit set so the IP stack will take control of the buffer rather than copy data out of the buffer. */ lReturned = FreeRTOS_sendto( xSocket, ( void * ) pucBuffer, strlen( ( const char * ) pucBuffer ) + 1, FREERTOS_ZERO_COPY, &xDestinationAddress, sizeof( xDestinationAddress ) ); if( lReturned == 0 ) { /* The send operation failed, so this task is still responsible for the buffer obtained from the IP stack. To ensure the buffer is not lost it must either be used again, or, as in this case, returned to the IP stack using FreeRTOS_ReleaseUDPPayloadBuffer(). pucBuffer can be safely re-used after this call. */ FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucBuffer ); } else { /* The send was successful so the IP stack is now managing the buffer pointed to by pucBuffer, and the IP stack will return the buffer once it has been sent. pucBuffer can be safely re-used. */ } ulCount++; /* Wait until it is time to send again. */ vTaskDelay( x1000ms ); } } Example using FreeRTOS_sendto() with the zero copy calling semantics
As detailed on the FreeRTOS_recvfrom() API reference page, FreeRTOS_recvfrom() can be used with standard calling semantics, or zero copy calling semantics. This subsection demonstrates the standard calling semantics.
The source code below shows a task that creates a socket before entering a loop that receives data using the standard calling semantics.
static void vReceivingUsingStandardInterface( void *pvParameters ) { long lBytes; uint8_t cReceivedString[ 60 ]; struct freertos_sockaddr xClient, xBindAddress; uint32_t xClientLength = sizeof( xClient ); xSocket_t xListeningSocket; /* Attempt to open the socket. */ xListeningSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP ); /* Check the socket was created. */ configASSERT( xListeningSocket != FREERTOS_INVALID_SOCKET ); /* Bind to port 10000. */ xBindAddress.sin_port = FreeRTOS_htons( 10000 ); FreeRTOS_bind( xListeningSocket, &xBindAddress, sizeof( xBindAddress ) ); for( ;; ) { /* Receive data from the socket. ulFlags is zero, so the standard interface is used. By default the block time is portMAX_DELAY, but it can be changed using FreeRTOS_setsockopt(). */ lBytes = FreeRTOS_recvfrom( xListeningSocket, cReceivedString, sizeof( cReceivedString ), 0, &xClient, &xClientLength ); if( lBytes > 0 ) { /* Data was received and can be process here. */ } } } Example using FreeRTOS_recvfrom() with the standard (as opposed to zero copy) calling semantics
As detailed on the FreeRTOS_recvfrom() API reference page, FreeRTOS_recvfrom() can be used with standard calling semantics, or zero copy calling semantics. This subsection demonstrates the zero copy calling semantics.
The source code below shows a task that creates a socket before entering a loop that receives data using the zero copy calling semantics.
static void vReceivingUsingZeroCopyInterface( void *pvParameters ) { int32_t lBytes; uint8_t *pucUDPPayloadBuffer; struct freertos_sockaddr xClient, xBindAddress; uint32_t xClientLength = sizeof( xClient ), ulIPAddress; xSocket_t xListeningSocket; /* Attempt to open the socket. */ xListeningSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP ); /* Check the socket was created. */ configASSERT( xListeningSocket != FREERTOS_INVALID_SOCKET ); /* Bind to port 10000. */ xBindAddress.sin_port = FreeRTOS_htons( 10000 ); FreeRTOS_bind( xListeningSocket, &xBindAddress, sizeof( xBindAddress ) ); for( ;; ) { /* Receive data from the socket. ulFlags has the zero copy bit set (FREERTOS_ZERO_COPY) indicating to the stack that a reference to the received data should be passed out to this task using the second parameter to the FreeRTOS_recvfrom() call. When this is done the IP stack is no longer responsible for releasing the buffer, and the task must return the buffer to the stack when it is no longer needed. By default the block time is portMAX_DELAY but it can be changed using FreeRTOS_setsockopt(). */ lBytes = FreeRTOS_recvfrom( xListeningSocket, &pucUDPPayloadBuffer, 0, FREERTOS_ZERO_COPY, &xClient, &xClientLength ); if( lBytes > 0 ) { /* Data was received and can be processed here. */ } if( lBytes >= 0 ) { /* The receive was successful so this task is now responsible for the buffer. The buffer must be freed once it is no longer needed. */ /* * The data can be processed here. */ /* Return the buffer to the IP stack. */ FreeRTOS_ReleaseUDPPayloadBuffer( pucUDPPayloadBuffer ); } } } Example using FreeRTOS_recvfrom() with the zero copy (as opposed to standard) calling semantics