Exemple #1
0
static void prvCreateDHCPSocket( void )
{
struct freertos_sockaddr xAddress;
portBASE_TYPE xReturn;
portTickType xTimeoutTime = 0;

	/* Create the socket, if it has not already been created. */
	if( xDHCPSocket == NULL )
	{
		xDHCPSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
		configASSERT( ( xDHCPSocket != FREERTOS_INVALID_SOCKET ) );

		/* Ensure the Rx and Tx timeouts are zero as the DHCP executes in the
		context of the IP task. */
		FreeRTOS_setsockopt( xDHCPSocket, 0, FREERTOS_SO_RCVTIMEO, ( void * ) &xTimeoutTime, sizeof( portTickType ) );
		FreeRTOS_setsockopt( xDHCPSocket, 0, FREERTOS_SO_SNDTIMEO, ( void * ) &xTimeoutTime, sizeof( portTickType ) );

		/* Bind to the standard DHCP client port. */
		xAddress.sin_port = dhcpCLIENT_PORT;
		xReturn = FreeRTOS_bind( xDHCPSocket, &xAddress, sizeof( xAddress ) );
		configASSERT( xReturn == 0 );

		/* Remove compiler warnings if configASSERT() is not defined. */
		( void ) xReturn;
	}
}
Exemple #2
0
static Socket_t prvCreateDNSSocket( void )
{
static Socket_t xSocket = NULL;
struct freertos_sockaddr xAddress;
BaseType_t xReturn;
TickType_t xTimeoutTime = pdMS_TO_TICKS( 200 );

	/* This must be the first time this function has been called.  Create
	the socket. */
	xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );

	/* Auto bind the port. */
	xAddress.sin_port = 0u;
	xReturn = FreeRTOS_bind( xSocket, &xAddress, sizeof( xAddress ) );

	/* Check the bind was successful, and clean up if not. */
	if( xReturn != 0 )
	{
		FreeRTOS_closesocket( xSocket );
		xSocket = NULL;
	}
	else
	{
		/* Set the send and receive timeouts. */
		FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, ( void * ) &xTimeoutTime, sizeof( TickType_t ) );
		FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDTIMEO, ( void * ) &xTimeoutTime, sizeof( TickType_t ) );
	}

	return xSocket;
}
Exemple #3
0
static Socket_t prvOpenTCPServerSocket( uint16_t usPort )
{
struct freertos_sockaddr xBindAddress;
Socket_t xSocket;
static const TickType_t xReceiveTimeOut = portMAX_DELAY;
const BaseType_t xBacklog = 20;
BaseType_t xReuseSocket = pdTRUE;

	/* Attempt to open the socket. */
	xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );
	configASSERT( xSocket != FREERTOS_INVALID_SOCKET );

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

	/* Only one connection will be used at a time, so re-use the listening
	socket as the connected socket.  See SimpleTCPEchoServer.c for an example
	that accepts multiple connections. */
	FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_REUSE_LISTEN_SOCKET, &xReuseSocket, sizeof( xReuseSocket ) );

	/* NOTE:  The CLI is a low bandwidth interface (typing characters is slow),
	so the TCP window properties are left at their default.  See
	SimpleTCPEchoServer.c for an example of a higher throughput TCP server that
	uses are larger RX and TX buffer. */

	/* Bind the socket to the port that the client task will send to, then
	listen for incoming connections. */
	xBindAddress.sin_port = usPort;
	xBindAddress.sin_port = FreeRTOS_htons( xBindAddress.sin_port );
	FreeRTOS_bind( xSocket, &xBindAddress, sizeof( xBindAddress ) );
	FreeRTOS_listen( xSocket, xBacklog );

	return xSocket;
}
Exemple #4
0
void vStartNTPTask( uint16_t usTaskStackSize, UBaseType_t uxTaskPriority )
{
	/* The only public function in this module: start a task to contact
	some NTP server. */

	if( xNTPTaskhandle != NULL )
	{
		switch( xStatus )
		{
		case EStatusPause:
			xStatus = EStatusAsking;
			vSignalTask();
			break;
		case EStatusLookup:
			FreeRTOS_printf( ( "NTP looking up server\n" ) );
			break;
		case EStatusAsking:
			FreeRTOS_printf( ( "NTP still asking\n" ) );
			break;
		case EStatusFailed:
			FreeRTOS_printf( ( "NTP failed somehow\n" ) );
			ulIPAddressFound = 0ul;
			xStatus = EStatusLookup;
			vSignalTask();
			break;
		}
	}
	else
	{
		xUDPSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
		if( xUDPSocket != NULL )
		{
		struct freertos_sockaddr xAddress;
		#if( ipconfigUSE_CALLBACKS != 0 )
			BaseType_t xReceiveTimeOut = pdMS_TO_TICKS( 0 );
		#else
			BaseType_t xReceiveTimeOut = pdMS_TO_TICKS( 5000 );
		#endif

			xAddress.sin_addr = 0ul;
			xAddress.sin_port = FreeRTOS_htons( NTP_PORT );

			FreeRTOS_bind( xUDPSocket, &xAddress, sizeof( xAddress ) );
			FreeRTOS_setsockopt( xUDPSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) );
			xTaskCreate( 	prvNTPTask,						/* The function that implements the task. */
							( const char * ) "NTP client",	/* Just a text name for the task to aid debugging. */
							usTaskStackSize,				/* The stack size is defined in FreeRTOSIPConfig.h. */
							NULL,							/* The task parameter, not used in this case. */
							uxTaskPriority,					/* The priority assigned to the task is defined in FreeRTOSConfig.h. */
							&xNTPTaskhandle );				/* The task handle. */
		}
		else
		{
			FreeRTOS_printf( ( "Creating socket failed\n" ) );
		}
	}
}
Exemple #5
0
static void prvMultipleSocketTxTask( void *pvParameters )
{
uint32_t ulTxValue = 0;
struct freertos_sockaddr xDestinationAddress;
uint32_t ulIPAddress, ulFirstDestinationPortNumber, xPortNumber;
xSocket_t xTxSocket;
const TickType_t xShortDelay = 100 / portTICK_RATE_MS, xSendBlockTime = 500 / portTICK_RATE_MS;

	srand( ( unsigned int ) &xPortNumber );

	/* The first destination port number is passed in as the task parameter.
	Other destination port numbers used are consecutive from this. */
	ulFirstDestinationPortNumber = ( uint32_t ) pvParameters;

	/* Create the socket used to send to the sockets created by the Rx task.
	Let the IP stack select a port to bind to. */
	xTxSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
	FreeRTOS_bind( xTxSocket, NULL, sizeof( struct freertos_sockaddr ) );

	/* The Rx and Tx tasks execute at the same priority so it is possible that
	the Tx task will fill up the send queue - set a Tx block time to ensure
	flow control is managed if this happens. */
	FreeRTOS_setsockopt( xTxSocket, 0, FREERTOS_SO_SNDTIMEO, &xSendBlockTime, sizeof( xSendBlockTime ) );

	/* It is assumed that this task is not created until the network is up,
	so the IP address can be obtained immediately.  Store the IP address being
	used in ulIPAddress.  This is done so the socket can send to a different
	port on the same IP address. */
	FreeRTOS_GetAddressConfiguration( &ulIPAddress, NULL, NULL, NULL );

	/* This test sends to itself, so data sent from here is received by a server
	socket on the same IP address.  Setup the freertos_sockaddr structure with
	this nodes IP address. */
	xDestinationAddress.sin_addr = ulIPAddress;

	/* Block for a short time to ensure the task implemented by the
	prvMultipleSocketRxTask() function has finished creating the Rx sockets. */
	vTaskDelay( xShortDelay );

	for( ;; )
	{
		/* Pseudo randomly select the destination port number from the range of
		valid destination port numbers. */
		xPortNumber = rand() % selNUMBER_OF_SOCKETS;
		xDestinationAddress.sin_port = ( uint16_t ) ( ulFirstDestinationPortNumber + xPortNumber );
		xDestinationAddress.sin_port = FreeRTOS_htons( xDestinationAddress.sin_port );

		/* Send an incrementing value. */
		FreeRTOS_sendto( xTxSocket, &ulTxValue, sizeof( ulTxValue ), 0, &xDestinationAddress, sizeof( xDestinationAddress ) );
		ulTxValue++;

		/* Delay here because in the Windows simulator the MAC interrupt
		simulator delays, so network trafic cannot be received any faster
		than this. */
		vTaskDelay( configWINDOWS_MAC_INTERRUPT_SIMULATOR_DELAY );
	}
}
static void prvSimpleZeroCopyServerTask( void *pvParameters )
{
int32_t lBytes;
uint8_t *pucUDPPayloadBuffer;
struct freertos_sockaddr xClient, xBindAddress;
uint32_t xClientLength = sizeof( xClient ), ulIPAddress;
xSocket_t xListeningSocket;

	/* Just to prevent compiler warnings. */
	( void ) pvParameters;

	/* Attempt to open the socket. */
	xListeningSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
	configASSERT( xListeningSocket != FREERTOS_INVALID_SOCKET );

	/* This test receives data sent from a different port on the same IP address.
	Obtain the nodes IP address.  Configure the freertos_sockaddr structure with
	the address being bound to.  The strange casting is to try and remove
	compiler warnings on 32 bit machines.  Note that this task is only created
	after the network is up, so the IP address is valid here. */
	FreeRTOS_GetAddressConfiguration( &ulIPAddress, NULL, NULL, NULL );
	xBindAddress.sin_addr = ulIPAddress;
	xBindAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL;
	xBindAddress.sin_port = FreeRTOS_htons( xBindAddress.sin_port );

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

	for( ;; )
	{
		/* Receive data on 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. */
		lBytes = FreeRTOS_recvfrom( xListeningSocket, ( void * ) &pucUDPPayloadBuffer, 0, FREERTOS_ZERO_COPY, &xClient, &xClientLength );

		/* It is expected to receive one more byte than the string length as
		the NULL terminator is also transmitted. */
		configASSERT( lBytes == ( ( portBASE_TYPE ) strlen( ( const char * ) pucUDPPayloadBuffer ) + 1 ) );

		/* Print the received characters. */
		if( lBytes > 0 )
		{
			vOutputString( ( char * ) pucUDPPayloadBuffer );
		}

		if( lBytes >= 0 )
		{
			/* The buffer *must* be freed once it is no longer needed. */
			FreeRTOS_ReleaseUDPPayloadBuffer( pucUDPPayloadBuffer );
		}
	}
}
static void prvSimpleServerTask( void *pvParameters )
{
long lBytes;
uint8_t cReceivedString[ 60 ];
struct freertos_sockaddr xClient, xBindAddress;
uint32_t xClientLength = sizeof( xClient );
xSocket_t xListeningSocket;

	/* Just to prevent compiler warnings. */
	( void ) pvParameters;

	/* Attempt to open the socket. */
	xListeningSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
	configASSERT( xListeningSocket != FREERTOS_INVALID_SOCKET );

	/* This test receives data sent from a different port on the same IP
	address.  Configure the freertos_sockaddr structure with the address being
	bound to.  The strange casting is to try and remove	compiler warnings on 32
	bit machines.  Note that this task is only created after the network is up,
	so the IP address is valid here. */
	xBindAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL;
	xBindAddress.sin_port = FreeRTOS_htons( xBindAddress.sin_port );

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

	for( ;; )
	{
		/* Zero out the receive array so there is NULL at the end of the string
		when it is printed out. */
		memset( cReceivedString, 0x00, sizeof( cReceivedString ) );

		/* Receive data on the socket.  ulFlags is zero, so the zero copy option
		is not set and the received data is copied into the buffer pointed to by
		cReceivedString.  By default the block time is portMAX_DELAY.
		xClientLength is not actually used by FreeRTOS_recvfrom(), but is set
		appropriately in case future versions do use it. */
		lBytes = FreeRTOS_recvfrom( xListeningSocket, cReceivedString, sizeof( cReceivedString ), 0, &xClient, &xClientLength );

		/* Print the received characters. */
		if( lBytes > 0 )
		{
			vOutputString( ( char * ) cReceivedString );
		}

		/* Error check. */
		configASSERT( lBytes == ( portBASE_TYPE ) strlen( ( const char * ) cReceivedString ) );
	}
}
Exemple #8
0
static void prvConnectionListeningTask( void *pvParameters )
{
struct freertos_sockaddr xClient, xBindAddress;
xSocket_t xListeningSocket, xConnectedSocket;
socklen_t xSize = sizeof( xClient );
static const TickType_t xReceiveTimeOut = portMAX_DELAY;
const BaseType_t xBacklog = 20;
xWinProperties_t xWinProps;

	/* Just to prevent compiler warnings. */
	( void ) pvParameters;

	/* Attempt to open the socket. */
	xListeningSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );
	configASSERT( xListeningSocket != FREERTOS_INVALID_SOCKET );

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

	/* Fill in the buffer and window sizes that will be used by the socket. */
	xWinProps.lTxBufSize = 6 * ipconfigTCP_MSS;
	xWinProps.lTxWinSize = 3;
	xWinProps.lRxBufSize = 6 * ipconfigTCP_MSS;
	xWinProps.lRxWinSize = 3;

	/* Set the window and buffer sizes. */
	FreeRTOS_setsockopt( xListeningSocket, 0, FREERTOS_SO_WIN_PROPERTIES, ( void * ) &xWinProps, sizeof( xWinProps ) );

	/* Bind the socket to the port that the client task will send to, then
	listen for incoming connections. */
	xBindAddress.sin_port = tcpechoPORT_NUMBER;
	xBindAddress.sin_port = FreeRTOS_htons( xBindAddress.sin_port );
	FreeRTOS_bind( xListeningSocket, &xBindAddress, sizeof( xBindAddress ) );
	FreeRTOS_listen( xListeningSocket, xBacklog );

	/* Create the clients that will connect to the listening socket. */
	prvCreateWindowsThreadClients();

	for( ;; )
	{
		/* Wait for a client to connect. */
		xConnectedSocket = FreeRTOS_accept( xListeningSocket, &xClient, &xSize );
		configASSERT( xConnectedSocket != FREERTOS_INVALID_SOCKET );

		/* Spawn a task to handle the connection. */
		xTaskCreate( prvServerConnectionInstance, "EchoServer", usUsedStackSize, ( void * ) xConnectedSocket, tskIDLE_PRIORITY, NULL );
	}
}
bool nabto_init_socket( uint32_t localAddr, uint16_t* localPort, nabto_socket_t* socketDescriptor )
{
int to = 0;
struct freertos_sockaddr xAddress, *pxAddressToUse;
bool bReturn = true;

    if (MAX_SOCKETS <= nSockets)
    {
        bReturn = false;
    }
    else
    {
        *socketDescriptor = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );

        if( NULL == *socketDescriptor )
        {
            bReturn = false;
        }
        else
        {
            memset( &xAddress, 0, sizeof( xAddress ) );
            xAddress.sin_addr = FreeRTOS_htonl( localAddr );
            xAddress.sin_port = FreeRTOS_htons( *localPort );


            pxAddressToUse = &xAddress;


            if( 0 > FreeRTOS_bind(*socketDescriptor, pxAddressToUse, sizeof( xAddress ) ) )
            {
                FreeRTOS_closesocket( *socketDescriptor );
                bReturn = false;
            }
            else
            {
                /* Set receive time out to 0.  Timeouts are performed using a
                select() call. */
                FreeRTOS_setsockopt( *socketDescriptor, 0, FREERTOS_SO_RCVTIMEO, &to, sizeof( to ) );
                activeSockets[nSockets++] = *socketDescriptor;
            }

            *localPort = FreeRTOS_htons( xAddress.sin_port );
        }
    }
    return bReturn;
}
Exemple #10
0
static xSocket_t prvOpenUDPServerSocket( uint16_t usPort )
{
    struct freertos_sockaddr xServer;
    xSocket_t xSocket = FREERTOS_INVALID_SOCKET;

    xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
    if( xSocket != FREERTOS_INVALID_SOCKET) {
        /* Zero out the server structure. */
        memset( ( void * ) &xServer, 0x00, sizeof( xServer ) );

        /* Set family and port. */
        xServer.sin_port = FreeRTOS_htons( usPort );

        /* Bind the address to the socket. */
        if( FreeRTOS_bind( xSocket, &xServer, sizeof( xServer ) ) == -1 ) {
            FreeRTOS_closesocket( xSocket );
            xSocket = FREERTOS_INVALID_SOCKET;
        }
    }

    return xSocket;
}
Exemple #11
0
static void prvConnectionListeningTask( void *pvParameters )
{
struct freertos_sockaddr xClient, xBindAddress;
xSocket_t xListeningSocket;

socklen_t xSize = sizeof( xClient );
static const TickType_t xReceiveTimeOut = 0; //portMAX_DELAY;
const BaseType_t xBacklog = 10;
xSocketSet_t xSocketSet;
struct xTCP_SERVER *pxServerList = NULL;
struct xTCP_SERVER *pxIterator;

xWinProperties_t winProps;

	/* Just to prevent compiler warnings. */
	( void ) pvParameters;

	/* Attempt to open the socket. */
	xListeningSocket = FreeRTOS_socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
	configASSERT( xListeningSocket != FREERTOS_INVALID_SOCKET );

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

	memset(&winProps, '\0', sizeof( winProps ) );
	// Size in units of MSS
	winProps.lTxBufSize   = 1 * 1460;//1000;
	winProps.lTxWinSize   = 2;

	winProps.lRxBufSize   = 2 * 1460;
	winProps.lRxWinSize   =  2;

	FreeRTOS_setsockopt( xListeningSocket, 0, FREERTOS_SO_WIN_PROPERTIES, ( void * ) &winProps, sizeof( winProps ) );

	/* The strange casting is to remove compiler errors. */
	xBindAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL;
	xBindAddress.sin_port = FreeRTOS_htons( xBindAddress.sin_port );

	/* Bind the socket to the port that the client task will send to, then
	listen for incoming connections. */
	while( FreeRTOS_bind( xListeningSocket, &xBindAddress, sizeof( xBindAddress ) ) != 0 );
	FreeRTOS_listen( xListeningSocket, xBacklog );
	lastTickTime = xTaskGetTickCount ();

	pxServerList = NULL;

	xSocketSet = FreeRTOS_createsocketset( );
	configASSERT( xSocketSet != NULL );
	FreeRTOS_FD_SET( xListeningSocket, xSocketSet, eSELECT_READ );

	for( ;; )
	{
		TickType_t xMask = FreeRTOS_select( xSocketSet, 3000 );

		if( FreeRTOS_FD_ISSET( xListeningSocket, xSocketSet ) )
		{
			xSocket_t xNewSocket;

			xNewSocket = FreeRTOS_accept( xListeningSocket, &xClient, &xSize );
			if ( xNewSocket && xNewSocket != FREERTOS_INVALID_SOCKET )
			{
				xTcpServer_t *pxServer;

				FreeRTOS_debug_printf( ( "prvConnectionListeningTask: new connection %xip:%u\n",
					FreeRTOS_ntohl( xClient.sin_addr ), FreeRTOS_ntohs( xClient.sin_port ) ) );

				pxServer = (xTcpServer_t *)pvPortMalloc( sizeof( *pxServer ) );
				memset( pxServer, '\0', sizeof( *pxServer ));

				pxServer->xSocket = xNewSocket;
				FreeRTOS_FD_SET( xNewSocket, xSocketSet, eSELECT_READ | eSELECT_EXCEPT );
				if( pxServerList == NULL )
				{
					/* This is the first server */
					pxServerList = pxServer;
				}
				else
				{
					/* Attach it to the end of the list */
					for( pxIterator = pxServerList; pxIterator->pxNext != NULL; pxIterator = pxIterator->pxNext )
					{
					}
					pxIterator->pxNext = pxServer;
				}
				prvTcpInit( pxServer );
			}
		}
		{
			xTcpServer_t *pxThisServer = NULL;

			for( pxIterator = pxServerList; pxIterator != NULL;  )
			{
				BaseType_t rc;
				pxThisServer = pxIterator;
				/* Move to the next one before the current gets deleted */
				pxIterator = pxIterator->pxNext;

				if( FreeRTOS_FD_ISSET( pxThisServer->xSocket, xSocketSet )  == 0 )
				{
					continue;
				}

				rc = prvTcpWork( pxThisServer );

				if( rc < 0)
				{
					FreeRTOS_FD_CLR( pxThisServer->xSocket, xSocketSet, eSELECT_ALL );

					if( pxServerList = pxThisServer )
					{
						pxServerList = pxThisServer->pxNext;
					}
					else
					{
						struct xTCP_SERVER *pxOther;
						for( pxOther = pxServerList; pxOther->pxNext != NULL; pxOther = pxOther->pxNext )
						{
							if( pxOther->pxNext == pxThisServer )
							{
								pxOther->pxNext == pxThisServer->pxNext;
								break;
							}
						}
					}
					/* Close the socket and free the space */
					prvTcpClose( pxThisServer );
				} else
				{
					pxThisServer->bHasSendRequest = prvTcpHasSendData( pxThisServer );
					if( pxThisServer->bHasSendRequest )
						FreeRTOS_FD_SET( pxThisServer->xSocket, xSocketSet, eSELECT_WRITE );
					else
						FreeRTOS_FD_CLR( pxThisServer->xSocket, xSocketSet, eSELECT_WRITE );
					//FreeRTOS_debug_printf( ( "SET_FD WRITE %d\n", pxServerFound->bHasSendRequest != 0 ) );
				}
			}
		}
		if( ( xTaskGetTickCount () - lastTickTime ) > 30000 )
		{
			lastTickTime = xTaskGetTickCount ();
			//plusPrintf( "ListeningTask %ld,%ld tasks\n", xTaskCount, xConfirmedCount );
		}
	}
}
Exemple #12
0
static void prvMultipleSocketRxTask( void *pvParameters )
{
xSocketSet_t xFD_Set;
xSocket_t xSocket;
struct freertos_sockaddr xAddress;
uint32_t xClientLength = sizeof( struct freertos_sockaddr ), ulFirstRxPortNumber, x;
uint32_t ulReceivedValue = 0, ulExpectedValue = 0UL, ulReceivedCount[ selNUMBER_OF_SOCKETS ] = { 0 };
int32_t lBytes;
const TickType_t xRxBlockTime = 0;

	/* The number of the port the first Rx socket will be bound to is passed in
	as the task parameter.  Other port numbers used are consecutive from this. */
	ulFirstRxPortNumber = ( uint32_t ) pvParameters;

	/* Create the set of sockets that will be passed into FreeRTOS_select(). */
	xFD_Set = FreeRTOS_CreateSocketSet( selSELECT_QUEUE_SIZE );

	for( x = 0; x < selNUMBER_OF_SOCKETS; x++ )
	{
		/* Create the next Rx socket. */
		xRxSockets[ x ] = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
		configASSERT( xRxSockets[ x ] );

		/* Bind to the next port number. */
		xAddress.sin_port = FreeRTOS_htons( ( uint16_t ) ( ulFirstRxPortNumber + x ) );
		FreeRTOS_bind( xRxSockets[ x ], &xAddress, sizeof( struct freertos_sockaddr ) );

		/* There should always be data available on the socket returned from
		FreeRTOS_select() so blocking on a read should not be necessary. */
		FreeRTOS_setsockopt( xRxSockets[ x ], 0, FREERTOS_SO_RCVTIMEO, &xRxBlockTime, sizeof( xRxBlockTime ) );

		/* Add the created socket to the set. */
		FreeRTOS_FD_SET( xRxSockets[ x ], xFD_Set );
	}

	for( ;; )
	{
		/* Wait for a socket from the set to become available for reading. */
		xSocket = FreeRTOS_select( xFD_Set, portMAX_DELAY );

		/* xSocket should never be NULL because FreeRTOS_select() was called
		with an indefinite delay (assuming INCLUDE_vTaskSuspend is set to 1). */
		configASSERT( xSocket );

		lBytes = FreeRTOS_recvfrom( xSocket, &( ulReceivedValue ), sizeof( uint32_t ), 0, &xAddress, &xClientLength );

		/* It is possible that the first value received will not be zero
		because the first few transmitted packets may have been dropped to
		send an ARP and then wait the ARP reply. */
		if( ulExpectedValue == 0 )
		{
			if( ulExpectedValue != ulReceivedValue )
			{
				/* Correct for packets lost to ARP traffic. */
				ulExpectedValue = ulReceivedValue;
			}
		}

		/* Data should always be available even though the block time was set
		to zero because the socket was returned from FreeRTOS_select(). */
		configASSERT( lBytes == 4 );
		configASSERT( ulReceivedValue == ulExpectedValue );

		ulExpectedValue++;

		/* Keep a record of the number of times each socket has been used so it
		can be verified (using the debugger) that they all get used. */
		for( x= 0; x < selNUMBER_OF_SOCKETS; x++ )
		{
			if( xSocket == xRxSockets[ x ] )
			{
				( ulReceivedCount[ x ] )++;
				break;
			}
		}
	}
}
	int32_t FreeRTOS_sendto( xSocket_t xSocket, const void *pvBuffer, size_t xTotalDataLength, uint32_t ulFlags, const struct freertos_sockaddr *pxDestinationAddress, socklen_t xDestinationAddressLength )
	{
	xNetworkBufferDescriptor_t *pxNetworkBuffer;
	xIPStackEvent_t xStackTxEvent = { eStackTxEvent, NULL };
	extern xQueueHandle xNetworkEventQueue;
	xTimeOutType xTimeOut;
	TickType_t xTicksToWait;
	int32_t lReturn = 0;
	xFreeRTOS_Socket_t *pxSocket;
	uint8_t *pucBuffer;

		pxSocket = ( xFreeRTOS_Socket_t * ) xSocket;

		/* The function prototype is designed to maintain the expected Berkeley
		sockets standard, but this implementation does not use all the
		parameters. */
		( void ) xDestinationAddressLength;
		configASSERT( xNetworkEventQueue );
		configASSERT( pvBuffer );

		if( xTotalDataLength <= ipMAX_UDP_PAYLOAD_LENGTH )
		{
			if( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE )
			{
				/* If the socket is not already bound to an address, bind it now.
				Passing NULL as the address parameter tells FreeRTOS_bind() to
				select the address to bind to. */
				FreeRTOS_bind( pxSocket, NULL, 0 );
			}

			if( socketSOCKET_IS_BOUND( pxSocket ) != pdFALSE )
			{
				xTicksToWait = pxSocket->xSendBlockTime;

				if( ( ulFlags & FREERTOS_ZERO_COPY ) == 0 )
				{
					/* Zero copy is not set, so obtain a network buffer into
					which the payload will be copied. */
					vTaskSetTimeOutState( &xTimeOut );
					pxNetworkBuffer = pxNetworkBufferGet( xTotalDataLength + sizeof( xUDPPacket_t ), xTicksToWait );

					if( pxNetworkBuffer != NULL )
					{
						memcpy( ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET ] ), ( void * ) pvBuffer, xTotalDataLength );

						if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdTRUE )
						{
							/* The entire block time has been used up. */
							xTicksToWait = 0;
						}
					}
				}
				else
				{
					/* When zero copy is used, pvBuffer is a pointer to the
					payload of a buffer that has already been obtained from the
					stack.  Obtain the network buffer pointer from the buffer. */
					pucBuffer = ( uint8_t * ) pvBuffer;
					pucBuffer -= ( ipBUFFER_PADDING + sizeof( xUDPPacket_t ) );
					pxNetworkBuffer = * ( ( xNetworkBufferDescriptor_t ** ) pucBuffer );
				}

				if( pxNetworkBuffer != NULL )
				{
					pxNetworkBuffer->xDataLength = xTotalDataLength;
					pxNetworkBuffer->usPort = pxDestinationAddress->sin_port;
					pxNetworkBuffer->usBoundPort = ( uint16_t ) socketGET_SOCKET_ADDRESS( pxSocket );
					pxNetworkBuffer->ulIPAddress = pxDestinationAddress->sin_addr;

					/* The socket options are passed to the IP layer in the
					space that will eventually get used by the Ethernet header. */
					pxNetworkBuffer->pucEthernetBuffer[ ipSOCKET_OPTIONS_OFFSET ] = pxSocket->ucSocketOptions;

					/* Tell the networking task that the packet needs sending. */
					xStackTxEvent.pvData = pxNetworkBuffer;

					if( xQueueSendToBack( xNetworkEventQueue, &xStackTxEvent, xTicksToWait ) != pdPASS )
					{
						/* If the buffer was allocated in this function, release it. */
						if( ( ulFlags & FREERTOS_ZERO_COPY ) == 0 )
						{
							vNetworkBufferRelease( pxNetworkBuffer );
						}
						iptraceSTACK_TX_EVENT_LOST( ipSTACK_TX_EVENT );
					}
					else
					{
						lReturn = ( int32_t ) xTotalDataLength;
					}
				}
				else
				{
					/* If errno was available, errno would be set to
					FREERTOS_ENOPKTS.  As it is, the function must return the
					number of transmitted bytes, so the calling function knows how
					much data was actually sent. */
					iptraceNO_BUFFER_FOR_SENDTO();
				}
			}
			else
			{
				iptraceSENDTO_SOCKET_NOT_BOUND();
			}
		}
		else
		{
			/* The data is longer than the available buffer space.  Setting
			ipconfigCAN_FRAGMENT_OUTGOING_PACKETS to 1 may allow this packet
			to be sent. */
			iptraceSENDTO_DATA_TOO_LONG();
		}

		return lReturn;
	} /* Tested */
	int32_t FreeRTOS_sendto( xSocket_t xSocket, const void *pvBuffer, size_t xTotalDataLength, uint32_t ulFlags, const struct freertos_sockaddr *pxDestinationAddress, socklen_t xDestinationAddressLength )
	{
	xNetworkBufferDescriptor_t *pxNetworkBuffer;
	xIPFragmentParameters_t *pxFragmentParameters;
	size_t xBytesToSend, xBytesRemaining;
	xIPStackEvent_t xStackTxEvent = { eStackTxEvent, NULL };
	extern xQueueHandle xNetworkEventQueue;
	uint8_t *pucBuffer;
	xTimeOutType xTimeOut;
	TickType_t xTicksToWait;
	uint16_t usFragmentOffset;
	xFreeRTOS_Socket_t *pxSocket;

		pxSocket = ( xFreeRTOS_Socket_t * ) xSocket;

		/* The function prototype is designed to maintain the expected Berkeley
		sockets standard, but this implementation does not use all the
		parameters. */
		( void ) xDestinationAddressLength;
		configASSERT( xNetworkEventQueue );
		configASSERT( pvBuffer );

		xBytesRemaining = xTotalDataLength;

		if( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE )
		{
			/* If the socket is not already bound to an address, bind it now.
			Passing NULL as the address parameter tells FreeRTOS_bind() to select
			the address to bind to. */
			FreeRTOS_bind( xSocket, NULL, 0 );
		}

		if( socketSOCKET_IS_BOUND( pxSocket ) != pdFALSE )
		{
			/* pucBuffer will be reset if this send turns out to be a zero copy
			send because in that case pvBuffer is actually a pointer to an
			xUserData_t structure, not the UDP payload. */
			pucBuffer = ( uint8_t * ) pvBuffer;
			vTaskSetTimeOutState( &xTimeOut );
			xTicksToWait = pxSocket->xSendBlockTime;

			/* The data being transmitted will be sent in
			ipMAX_UDP_PAYLOAD_LENGTH chunks if xDataLength is greater than the
			network buffer payload size.  Loop until all the data is sent. */
			while( xBytesRemaining > 0 )
			{
				if( xBytesRemaining > ipMAX_UDP_PAYLOAD_LENGTH )
				{
					/* Cap the amount being sent in this packet to the maximum
					UDP payload size.  This will be a multiple of 8 already,
					removing the need to check in the code. */
					xBytesToSend = ipMAX_UDP_PAYLOAD_LENGTH;
				}
				else
				{
					/* Send all remaining bytes - which may well be the total
					number of bytes if the packet was not chopped up. */
					xBytesToSend = xBytesRemaining;
				}

				/* If the zero copy flag is set, then the data is already in a
				network buffer.  Otherwise, get a new network buffer. */
				if( ( ulFlags & FREERTOS_ZERO_COPY ) == 0 )
				{
					if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdTRUE )
					{
						xTicksToWait = 0;
					}

					pxNetworkBuffer = pxNetworkBufferGet( xBytesToSend + sizeof( xUDPPacket_t ), xTicksToWait );
				}
				else
				{
					if( xTotalDataLength > ipMAX_UDP_PAYLOAD_LENGTH )
					{
						/* The packet needs fragmenting, but zero copy buffers
						cannot be fragmented. */
						pxNetworkBuffer = NULL;
					}
					else
					{
						/* When zero copy is used, pvBuffer is a pointer to the
						payload of a buffer that has already been obtained from the
						stack.  Obtain the network buffer pointer from the buffer. */
						pucBuffer = ( uint8_t * ) pvBuffer;
						pucBuffer -= ( ipBUFFER_PADDING + sizeof( xUDPPacket_t ) );
						pxNetworkBuffer = * ( ( xNetworkBufferDescriptor_t ** ) pucBuffer );
					}
				}

				if( pxNetworkBuffer != NULL )
				{
					/* Use the part of the network buffer that will be completed
					by the IP layer as temporary storage to pass extra
					information required by the IP layer. */
					pxFragmentParameters = ( xIPFragmentParameters_t * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipFRAGMENTATION_PARAMETERS_OFFSET ] );
					pxFragmentParameters->ucSocketOptions = pxSocket->ucSocketOptions;

					if( xBytesRemaining > ipMAX_UDP_PAYLOAD_LENGTH )
					{
						/* The packet is being chopped up, and more data will
						follow. */
						pxFragmentParameters->ucSocketOptions = ( pxSocket->ucSocketOptions | FREERTOS_NOT_LAST_IN_FRAGMENTED_PACKET );
					}

					if( xTotalDataLength > ipMAX_UDP_PAYLOAD_LENGTH )
					{
						/* Let the IP layer know this packet has been chopped up,
						and supply the IP layer with any addition information it
						needs to make sense of it. */
						pxFragmentParameters->ucSocketOptions |= FREERTOS_FRAGMENTED_PACKET;
						usFragmentOffset = ( uint16_t ) ( xTotalDataLength - xBytesRemaining );
						pxFragmentParameters->usFragmentedPacketOffset = usFragmentOffset;
						pxFragmentParameters->usFragmentLength = ( uint16_t ) xBytesToSend;
					}
					else
					{
						usFragmentOffset = 0;
					}

					/* Write the payload into the packet.  The IP layer is
					queried to find where in the IP payload the data should be
					written.  This is because the necessary offset is different
					for the first packet, because the first packet leaves space
					for a UDP header.  Note that this changes usFragmentOffset
					from the offset in the entire UDP packet, to the offset
					in the IP packet. */
					if( ( ulFlags & FREERTOS_ZERO_COPY ) == 0 )
					{
						/* Only copy the data if it is not already in the
						expected location. */
						usFragmentOffset = ipGET_UDP_PAYLOAD_OFFSET_FOR_FRAGMENT( usFragmentOffset );
						memcpy( ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ usFragmentOffset ] ), ( void * ) pucBuffer, xBytesToSend );
					}
					pxNetworkBuffer->xDataLength = xTotalDataLength;
					pxNetworkBuffer->usPort = pxDestinationAddress->sin_port;
					pxNetworkBuffer->usBoundPort = ( uint16_t ) socketGET_SOCKET_ADDRESS( pxSocket );
					pxNetworkBuffer->ulIPAddress = pxDestinationAddress->sin_addr;

					/* Tell the networking task that the packet needs sending. */
					xStackTxEvent.pvData = pxNetworkBuffer;

					if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdTRUE )
					{
						xTicksToWait = 0;
					}

					if( xQueueSendToBack( xNetworkEventQueue, &xStackTxEvent, xTicksToWait ) != pdPASS )
					{
						/* If the buffer was allocated in this function, release it. */
						if( ( ulFlags & FREERTOS_ZERO_COPY ) == 0 )
						{
							vNetworkBufferRelease( pxNetworkBuffer );
						}
						iptraceSTACK_TX_EVENT_LOST( ipSTACK_TX_EVENT );
						break;
					}

					/* Adjust counters ready to either exit the loop, or send
					another chunk of data. */
					xBytesRemaining -= xBytesToSend;
					pucBuffer += xBytesToSend;
				}
				else
				{
					/* If errno was available, errno would be set to
					FREERTOS_ENOPKTS.  As it is, the function must return the
					number of transmitted bytes, so the calling function knows how
					much data was actually sent. */
					break;
				}
			}
		}

		return ( xTotalDataLength - xBytesRemaining );
	} /* Tested */
Exemple #15
0
static void prvMultipleSocketTxTask( void *pvParameters )
{
uint32_t ulTxValue = 0;
struct freertos_sockaddr xDestinationAddress;
uint32_t ulIPAddress, ulFirstDestinationPortNumber, xPortNumber;
xSocket_t xTxSocket;
uint32_t ulSendCount[ selNUMBER_OF_SOCKETS ];

	memset( ulSendCount, '\0', sizeof( ulSendCount ) );

	/* The first destination port number is passed in as the task parameter.
	Other destination port numbers used are consecutive from this. */
	ulFirstDestinationPortNumber = ( uint32_t ) pvParameters;

	/* Create the socket used to send to the sockets created by the Rx task.
	Let the IP stack select a port to bind to. */
	xTxSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
	FreeRTOS_bind( xTxSocket, NULL, sizeof( struct freertos_sockaddr ) );

	/* The Rx and Tx tasks execute at the same priority so it is possible that
	the Tx task will fill up the send queue - set a Tx block time to ensure
	flow control is managed if this happens. */
	FreeRTOS_setsockopt( xTxSocket, 0, FREERTOS_SO_SNDTIMEO, &xSendBlockTime, sizeof( xSendBlockTime ) );

	/* It is assumed that this task is not created until the network is up,
	so the IP address can be obtained immediately.  Store the IP address being
	used in ulIPAddress.  This is done so the socket can send to a different
	port on the same IP address. */
	FreeRTOS_GetAddressConfiguration( &ulIPAddress, NULL, NULL, NULL );

	/* This test sends to itself, so data sent from here is received by a server
	socket on the same IP address.  Setup the freertos_sockaddr structure with
	this nodes IP address. */
	xDestinationAddress.sin_addr = ulIPAddress;

	/* Block for a short time to ensure the task implemented by the
	prvMultipleSocketRxTask() function has finished creating the Rx sockets. */
	while( eTaskGetState( xRxTaskHandle ) != eSuspended )
	{
		vTaskDelay( xSendBlockTime );
	}
	vTaskResume( xRxTaskHandle );

	for( ;; )
	{
		/* Pseudo randomly select the destination port number from the range of
		valid destination port numbers. */
		xPortNumber = ipconfigRAND32() % selNUMBER_OF_SOCKETS;
		ulSendCount[ xPortNumber ]++;
		xDestinationAddress.sin_port = ( uint16_t ) ( ulFirstDestinationPortNumber + xPortNumber );
		xDestinationAddress.sin_port = FreeRTOS_htons( xDestinationAddress.sin_port );

		/* Send an incrementing value to the pseudo randomly selected port. */
		FreeRTOS_sendto( xTxSocket, &ulTxValue, sizeof( ulTxValue ), 0, &xDestinationAddress, sizeof( xDestinationAddress ) );
		ulTxValue++;

		if( ulTxValue >= selMAX_TX_VALUE )
		{
			/* Start over. */
			ulTxValue = 0;

			/* As a sanity check that this demo is valid, ensure each socket has
			been used at least once. */
			for( xPortNumber = 0; xPortNumber < selNUMBER_OF_SOCKETS; xPortNumber++ )
			{
				if( ulSendCount[ xPortNumber ] == 0 )
				{
					ulErrorOccurred = pdTRUE;
				}

				ulSendCount[ xPortNumber ] = 0;
			}

			/* Allow the Rx task to check it has received all the values. */
			while( eTaskGetState( xRxTaskHandle ) != eSuspended )
			{
				vTaskDelay( xSendBlockTime );
			}
			vTaskResume( xRxTaskHandle );

			/* Increment to show this task is still executing. */
			ulTxCycles++;
		}

		/* Delay here because in the Windows simulator the MAC interrupt
		simulator delays, so network traffic cannot be received any faster than
		this. */
		vTaskDelay( configWINDOWS_MAC_INTERRUPT_SIMULATOR_DELAY << 2 );
	}
}
Exemple #16
0
static void prvMultipleSocketRxTask( void *pvParameters )
{
xSocketSet_t xFD_Set;
xSocket_t xSocket;
struct freertos_sockaddr xAddress;
uint32_t xClientLength = sizeof( struct freertos_sockaddr ), ulFirstRxPortNumber, x;
uint32_t ulReceivedValue = 0, ulCount;
uint8_t ucReceivedValues[ selMAX_TX_VALUE ]; /* If the array position is pdTRUE then the corresponding value has been received. */
int32_t lBytes;
const TickType_t xRxBlockTime = 0;
BaseType_t xResult;

	/* The number of the port the first Rx socket will be bound to is passed in
	as the task parameter.  Other port numbers used are consecutive from this. */
	ulFirstRxPortNumber = ( uint32_t ) pvParameters;

	/* Create the set for sockets that will be passed into FreeRTOS_select(). */
	xFD_Set = FreeRTOS_CreateSocketSet();

	/* Create the sockets and add them to the set. */
	for( x = 0; x < selNUMBER_OF_SOCKETS; x++ )
	{
		/* Create the next Rx socket. */
		xRxSockets[ x ] = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
		configASSERT( xRxSockets[ x ] != FREERTOS_INVALID_SOCKET );

		/* Bind to the next port number. */
		xAddress.sin_port = FreeRTOS_htons( ( uint16_t ) ( ulFirstRxPortNumber + x ) );
		FreeRTOS_bind( xRxSockets[ x ], &xAddress, sizeof( struct freertos_sockaddr ) );

		/* There should always be data available after FreeRTOS_select() so
		blocking on a read should not be necessary. */
		FreeRTOS_setsockopt( xRxSockets[ x ], 0, FREERTOS_SO_RCVTIMEO, &xRxBlockTime, sizeof( xRxBlockTime ) );

		/* Add the created socket to the set. */
		FreeRTOS_FD_SET( xRxSockets[ x ], xFD_Set, eSELECT_ALL );
	}

	for( ;; )
	{
		/* No values have yet been received so set each array position to
		pdFALSE.  Each expected Rx value has a corresponding array position. */
		memset( ( void * ) ucReceivedValues, pdFALSE, sizeof( ucReceivedValues ) );

		/* Wait for the other task to resume this task - indicating that it is
		about to start sending. */
		vTaskSuspend( NULL );

		/* Expect to receive selMAX_TX_VALUE values. */
		ulCount = 0;

		while( ulCount < selMAX_TX_VALUE )
		{
			/* Wait for a socket from the set to become available for
			reading. */
			xResult = FreeRTOS_select( xFD_Set, xReceiveBlockTime );

			if( xResult != 0 )
			{
				/* See which sockets have data waiting to be read. */
				for( x = 0; x < selNUMBER_OF_SOCKETS; x++ )
				{
					xSocket = xRxSockets[ x ];

					/* Find the expected value for this socket */
					if( FreeRTOS_FD_ISSET( xSocket, xFD_Set ) != 0 )
					{
						while( ( lBytes = FreeRTOS_recvfrom( xSocket, &( ulReceivedValue ), sizeof( uint32_t ), 0, &xAddress, &xClientLength ) ) > 0 )
						{
							/* Received another message. */
							ulCount++;

							/* It is always expected that the read will pass. */
							configASSERT( ( size_t ) lBytes == ( sizeof( uint32_t ) ) );

							/* Don't expect to receive anything greater than
							selMAX_TX_VALUE - 1. */
							configASSERT( ulReceivedValue < selMAX_TX_VALUE );

							/* Don't expect to receive any value twice. */
							configASSERT( ucReceivedValues[ ulReceivedValue ] != pdTRUE );
							if( ucReceivedValues[ ulReceivedValue ] != pdTRUE )
							{
								/* Mark the value as received by setting its
								index in the received array to pdTRUE. */
								ucReceivedValues[ ulReceivedValue ] = pdTRUE;
							}
							else
							{
								ulErrorOccurred = pdTRUE;
							}
						}
					}
				}
			}
			else
			{
				/* No value was received in time. */
				break;
			}
		}

		/* Were all values received? */
		if( ulCount == selMAX_TX_VALUE )
		{
			/* Check all selMAX_TX_VALUE values are present and correct
			before starting a new cycle.  It is valid for a few values at
			the beginning of the array to be missing as they may have been
			dropped for ARP messages, so start a few indexes in. */
			for( ulCount = 4; ulCount < selMAX_TX_VALUE; ulCount++ )
			{
				configASSERT( ucReceivedValues[ ulCount ] == pdTRUE );

				if( ucReceivedValues[ ulCount ] != pdTRUE )
				{
					/* The value corresponding to this array position was
					never received.  In a real application UDP is not
					reliable, but in this tightly controlled test it is
					unusual for a packet to be dropped. */
					ulErrorOccurred = pdTRUE;
				}
			}

			ulRxCycles++;
		}
		else
		{
			/* Just for viewing in the debugger. */
			ulFailedRxCycles++;
		}
	}
}