in FreeRTOS_IP.c [375:628]
static void prvIPTask( void * pvParameters )
{
IPStackEvent_t xReceivedEvent;
TickType_t xNextIPSleep;
FreeRTOS_Socket_t * pxSocket;
struct freertos_sockaddr xAddress;
/* Just to prevent compiler warnings about unused parameters. */
( void ) pvParameters;
/* A possibility to set some additional task properties. */
iptraceIP_TASK_STARTING();
/* Generate a dummy message to say that the network connection has gone
* down. This will cause this task to initialise the network interface. After
* this it is the responsibility of the network interface hardware driver to
* send this message if a previously connected network is disconnected. */
FreeRTOS_NetworkDown();
#if ( ipconfigUSE_TCP == 1 )
{
/* Initialise the TCP timer. */
prvIPTimerReload( &xTCPTimer, pdMS_TO_TICKS( ipTCP_TIMER_PERIOD_MS ) );
}
#endif
/* Mark the timer as inactive since we are not waiting on any ARP resolution as of now. */
vIPSetARPResolutionTimerEnableState( pdFALSE );
/* Initialisation is complete and events can now be processed. */
xIPTaskInitialised = pdTRUE;
FreeRTOS_debug_printf( ( "prvIPTask started\n" ) );
/* Loop, processing IP events. */
for( ; ; )
{
ipconfigWATCHDOG_TIMER();
/* Check the ARP, DHCP and TCP timers to see if there is any periodic
* or timeout processing to perform. */
prvCheckNetworkTimers();
/* Calculate the acceptable maximum sleep time. */
xNextIPSleep = prvCalculateSleepTime();
/* Wait until there is something to do. If the following call exits
* due to a time out rather than a message being received, set a
* 'NoEvent' value. */
if( xQueueReceive( xNetworkEventQueue, ( void * ) &xReceivedEvent, xNextIPSleep ) == pdFALSE )
{
xReceivedEvent.eEventType = eNoEvent;
}
#if ( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
{
if( xReceivedEvent.eEventType != eNoEvent )
{
UBaseType_t uxCount;
uxCount = uxQueueSpacesAvailable( xNetworkEventQueue );
if( uxQueueMinimumSpace > uxCount )
{
uxQueueMinimumSpace = uxCount;
}
}
}
#endif /* ipconfigCHECK_IP_QUEUE_SPACE */
iptraceNETWORK_EVENT_RECEIVED( xReceivedEvent.eEventType );
switch( xReceivedEvent.eEventType )
{
case eNetworkDownEvent:
/* Attempt to establish a connection. */
xNetworkUp = pdFALSE;
prvProcessNetworkDownEvent();
break;
case eNetworkRxEvent:
/* The network hardware driver has received a new packet. A
* pointer to the received buffer is located in the pvData member
* of the received event structure. */
prvHandleEthernetPacket( ipCAST_PTR_TO_TYPE_PTR( NetworkBufferDescriptor_t, xReceivedEvent.pvData ) );
break;
case eNetworkTxEvent:
{
NetworkBufferDescriptor_t * pxDescriptor = ipCAST_PTR_TO_TYPE_PTR( NetworkBufferDescriptor_t, xReceivedEvent.pvData );
/* Send a network packet. The ownership will be transferred to
* the driver, which will release it after delivery. */
iptraceNETWORK_INTERFACE_OUTPUT( pxDescriptor->xDataLength, pxDescriptor->pucEthernetBuffer );
( void ) xNetworkInterfaceOutput( pxDescriptor, pdTRUE );
}
break;
case eARPTimerEvent:
/* The ARP timer has expired, process the ARP cache. */
vARPAgeCache();
break;
case eSocketBindEvent:
/* FreeRTOS_bind (a user API) wants the IP-task to bind a socket
* to a port. The port number is communicated in the socket field
* usLocalPort. vSocketBind() will actually bind the socket and the
* API will unblock as soon as the eSOCKET_BOUND event is
* triggered. */
pxSocket = ipCAST_PTR_TO_TYPE_PTR( FreeRTOS_Socket_t, xReceivedEvent.pvData );
xAddress.sin_addr = 0U; /* For the moment. */
xAddress.sin_port = FreeRTOS_ntohs( pxSocket->usLocalPort );
pxSocket->usLocalPort = 0U;
( void ) vSocketBind( pxSocket, &xAddress, sizeof( xAddress ), pdFALSE );
/* Before 'eSocketBindEvent' was sent it was tested that
* ( xEventGroup != NULL ) so it can be used now to wake up the
* user. */
pxSocket->xEventBits |= ( EventBits_t ) eSOCKET_BOUND;
vSocketWakeUpUser( pxSocket );
break;
case eSocketCloseEvent:
/* The user API FreeRTOS_closesocket() has sent a message to the
* IP-task to actually close a socket. This is handled in
* vSocketClose(). As the socket gets closed, there is no way to
* report back to the API, so the API won't wait for the result */
( void ) vSocketClose( ipCAST_PTR_TO_TYPE_PTR( FreeRTOS_Socket_t, xReceivedEvent.pvData ) );
break;
case eStackTxEvent:
/* The network stack has generated a packet to send. A
* pointer to the generated buffer is located in the pvData
* member of the received event structure. */
vProcessGeneratedUDPPacket( ipCAST_PTR_TO_TYPE_PTR( NetworkBufferDescriptor_t, xReceivedEvent.pvData ) );
break;
case eDHCPEvent:
/* The DHCP state machine needs processing. */
#if ( ipconfigUSE_DHCP == 1 )
{
uintptr_t uxState;
eDHCPState_t eState;
/* Cast in two steps to please MISRA. */
uxState = ( uintptr_t ) xReceivedEvent.pvData;
eState = ( eDHCPState_t ) uxState;
/* Process DHCP messages for a given end-point. */
vDHCPProcess( pdFALSE, eState );
}
#endif /* ipconfigUSE_DHCP */
break;
case eSocketSelectEvent:
/* FreeRTOS_select() has got unblocked by a socket event,
* vSocketSelect() will check which sockets actually have an event
* and update the socket field xSocketBits. */
#if ( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
#if ( ipconfigSELECT_USES_NOTIFY != 0 )
{
SocketSelectMessage_t * pxMessage = ipCAST_PTR_TO_TYPE_PTR( SocketSelectMessage_t, xReceivedEvent.pvData );
vSocketSelect( pxMessage->pxSocketSet );
( void ) xTaskNotifyGive( pxMessage->xTaskhandle );
}
#else
{
vSocketSelect( ipCAST_PTR_TO_TYPE_PTR( SocketSelect_t, xReceivedEvent.pvData ) );
}
#endif /* ( ipconfigSELECT_USES_NOTIFY != 0 ) */
#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
break;
case eSocketSignalEvent:
#if ( ipconfigSUPPORT_SIGNALS != 0 )
/* Some task wants to signal the user of this socket in
* order to interrupt a call to recv() or a call to select(). */
( void ) FreeRTOS_SignalSocket( ipPOINTER_CAST( Socket_t, xReceivedEvent.pvData ) );
#endif /* ipconfigSUPPORT_SIGNALS */
break;
case eTCPTimerEvent:
#if ( ipconfigUSE_TCP == 1 )
/* Simply mark the TCP timer as expired so it gets processed
* the next time prvCheckNetworkTimers() is called. */
xTCPTimer.bExpired = pdTRUE_UNSIGNED;
#endif /* ipconfigUSE_TCP */
break;
case eTCPAcceptEvent:
/* The API FreeRTOS_accept() was called, the IP-task will now
* check if the listening socket (communicated in pvData) actually
* received a new connection. */
#if ( ipconfigUSE_TCP == 1 )
pxSocket = ipCAST_PTR_TO_TYPE_PTR( FreeRTOS_Socket_t, xReceivedEvent.pvData );
if( xTCPCheckNewClient( pxSocket ) != pdFALSE )
{
pxSocket->xEventBits |= ( EventBits_t ) eSOCKET_ACCEPT;
vSocketWakeUpUser( pxSocket );
}
#endif /* ipconfigUSE_TCP */
break;
case eTCPNetStat:
/* FreeRTOS_netstat() was called to have the IP-task print an
* overview of all sockets and their connections */
#if ( ( ipconfigUSE_TCP == 1 ) && ( ipconfigHAS_PRINTF == 1 ) )
vTCPNetStat();
#endif /* ipconfigUSE_TCP */
break;
case eSocketSetDeleteEvent:
#if ( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
{
SocketSelect_t * pxSocketSet = ( SocketSelect_t * ) ( xReceivedEvent.pvData );
iptraceMEM_STATS_DELETE( pxSocketSet );
vEventGroupDelete( pxSocketSet->xSelectGroup );
vPortFree( ( void * ) pxSocketSet );
}
#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
break;
case eNoEvent:
/* xQueueReceive() returned because of a normal time-out. */
break;
default:
/* Should not get here. */
break;
}
if( xNetworkDownEventPending != pdFALSE )
{
/* A network down event could not be posted to the network event
* queue because the queue was full.
* As this code runs in the IP-task, it can be done directly by
* calling prvProcessNetworkDownEvent(). */
prvProcessNetworkDownEvent();
}
}
}