portBASE_TYPE xNetworkInterfaceOutput( xNetworkBufferDescriptor_t * const pxNetworkBuffer )
	{
	xEthernetHeader_t *pxEthernetHeader;
	xIPStackEvent_t xRxEvent = { eEthernetRxEvent, NULL };
	extern uint8_t xDefaultPartUDPPacketHeader[];
	static const xMACAddress_t xBroadcastMACAddress = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
	portBASE_TYPE xCanLoopback;

		pxEthernetHeader = ( xEthernetHeader_t * ) pxNetworkBuffer->pucEthernetBuffer;

		if( memcmp( ( void * ) &( pxEthernetHeader->xDestinationAddress ), ( void * ) &xBroadcastMACAddress, sizeof( xMACAddress_t ) ) == 0 )
		{
			/* This is a broadcast. */
			xCanLoopback = pdTRUE;
		}
		else if( memcmp( ( void * ) &( pxEthernetHeader->xDestinationAddress ), ( void * ) xDefaultPartUDPPacketHeader, sizeof( xMACAddress_t ) ) == 0 )
		{
			/* This is being sent to itself. */
			xCanLoopback = pdTRUE;
		}
		else
		{
			/* This is being sent externally. */
			xCanLoopback = pdFALSE;
		}

		iptraceNETWORK_INTERFACE_TRANSMIT();

		if( xCanLoopback == pdTRUE )
		{
			/* Just loop the frame back to the input queue.  Here the loopback
			is sending a message to itself, so a block time cannot be used for
			fear of deadlocking. */
			xRxEvent.pvData = ( void * ) pxNetworkBuffer;
			if( xQueueSendToBack( xNetworkEventQueue, &xRxEvent, ( portTickType ) 0 ) == pdFALSE )
			{
				vNetworkBufferRelease( pxNetworkBuffer );
				iptraceETHERNET_RX_EVENT_LOST();
			}
			else
			{
				iptraceNETWORK_INTERFACE_RECEIVE();
			}
		}
		else
		{
			/* Send the packet. */
			xSemaphoreTake( xPCAPMutex, portMAX_DELAY );
			{
				pcap_sendpacket( pxOpenedInterfaceHandle, pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength );
			}
			xSemaphoreGive( xPCAPMutex );

			/* The buffer has been transmitted so can be released. */
			vNetworkBufferRelease( pxNetworkBuffer );
		}

		return pdPASS;
	}
static void prvInterruptSimulatorTask( void *pvParameters )
{
static struct pcap_pkthdr *pxHeader;
const uint8_t *pucPacketData;
long lResult;
xNetworkBufferDescriptor_t *pxNetworkBuffer;
xIPStackEvent_t xRxEvent = { eEthernetRxEvent, NULL };
eFrameProcessingResult_t eResult;

	/* Just to kill the compiler warning. */
	( void ) pvParameters;

	for( ;; )
	{
		/* Get the next packet. */
		xSemaphoreTake( xPCAPMutex, portMAX_DELAY );
		{
			lResult = pcap_next_ex( pxOpenedInterfaceHandle, &pxHeader, &pucPacketData );
		}
		xSemaphoreGive( xPCAPMutex );

		if( lResult == 1 )
		{
			eResult = ipCONSIDER_FRAME_FOR_PROCESSING( pucPacketData );
			if( eResult == eProcessBuffer )
			{
				/* Will the data fit into the frame buffer? */
				if( pxHeader->len <= ipTOTAL_ETHERNET_FRAME_SIZE )
				{
					/* Obtain a buffer into which the data can be placed.  This
					is only	an interrupt simulator, not a real interrupt, so it
					is ok to call the task level function here.  */
					xSemaphoreTake( xPCAPMutex, portMAX_DELAY );
					{
						pxNetworkBuffer = pxNetworkBufferGet( pxHeader->len, 0 );
					}
					xSemaphoreGive( xPCAPMutex );

					if( pxNetworkBuffer != NULL )
					{
						memcpy( pxNetworkBuffer->pucEthernetBuffer, pucPacketData, pxHeader->len );
						pxNetworkBuffer->xDataLength = ( size_t ) pxHeader->len;
						xRxEvent.pvData = ( void * ) pxNetworkBuffer;

						/* Data was received and stored.  Send a message to the IP
						task to let it know. */
						if( xQueueSendToBack( xNetworkEventQueue, &xRxEvent, ( portTickType ) 0 ) == pdFALSE )
						{
							/* The buffer could not be sent to the stack so
							must be released again.  This is only an interrupt
							simulator, not a real interrupt, so it is ok to use
							the task level function here. */
							vNetworkBufferRelease( pxNetworkBuffer );
							iptraceETHERNET_RX_EVENT_LOST();
						}
						else
						{
							iptraceNETWORK_INTERFACE_RECEIVE();
						}
					}
					else
					{
						iptraceETHERNET_RX_EVENT_LOST();
					}
				}
				else
				{
					/* Log that a packet was dropped because it would have
					overflowed the buffer. */
				}
			}
		}
		else
		{
			/* There is no real way of simulating an interrupt.  Make sure
			other tasks can run. */
			vTaskDelay( configWINDOWS_MAC_INTERRUPT_SIMULATOR_DELAY );
		}
	}
}
Example #3
0
static void prvGMACDeferredInterruptHandlerTask( void *pvParameters )
{
    xNetworkBufferDescriptor_t *pxNetworkBuffer = NULL;
    xIPStackEvent_t xRxEvent = { eEthernetRxEvent, NULL };
    static const TickType_t xBufferWaitDelay = 1500UL / portTICK_RATE_MS;
    uint32_t ulReturned;

    /* This is a very simply but also inefficient implementation. */

    ( void ) pvParameters;

    for( ;; )
    {
        /* Wait for the GMAC interrupt to indicate that another packet has been
        received.  A while loop is used to process all received frames each time
        this task is notified, so it is ok to clear the notification count on the
        take (hence the first parameter is pdTRUE ). */
        ulTaskNotifyTake( pdTRUE, xBufferWaitDelay );

        ulReturned = GMAC_OK;
        while( ulReturned == GMAC_OK )
        {
            /* Allocate a buffer to hold the data if one is not already held. */
            if( pxNetworkBuffer == NULL )
            {
                pxNetworkBuffer = pxNetworkBufferGet( ipTOTAL_ETHERNET_FRAME_SIZE, xBufferWaitDelay );
            }

            if( pxNetworkBuffer != NULL )
            {
                /* Attempt to read data. */
                ulReturned = gmac_dev_read( &xGMACStruct, pxNetworkBuffer->pucEthernetBuffer, ipTOTAL_ETHERNET_FRAME_SIZE, ( uint32_t * ) &( pxNetworkBuffer->xDataLength ) );

                if( ulReturned == GMAC_OK )
                {
#if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 1
                    {
                        if( pxNetworkBuffer->xDataLength > 0 )
                        {
                            /* If the frame would not be processed by the IP
                            stack then don't even bother sending it to the IP
                            stack. */
                            if( eConsiderFrameForProcessing( pxNetworkBuffer->pucEthernetBuffer ) != eProcessBuffer )
                            {
                                pxNetworkBuffer->xDataLength = 0;
                            }
                        }
                    }
#endif

                    if( pxNetworkBuffer->xDataLength > 0 )
                    {
                        /* Store a pointer to the network buffer structure in
                        the	padding	space that was left in front of the Ethernet
                        frame.  The pointer is needed to ensure the network
                        buffer structure can be located when it is time for it
                        to be freed if the Ethernet frame gets used as a zero
                        copy buffer. */
                        *( ( xNetworkBufferDescriptor_t ** ) ( ( pxNetworkBuffer->pucEthernetBuffer - ipBUFFER_PADDING ) ) ) = pxNetworkBuffer;

                        /* Data was received and stored.  Send it to the IP task
                        for processing. */
                        xRxEvent.pvData = ( void * ) pxNetworkBuffer;
                        if( xQueueSendToBack( xNetworkEventQueue, &xRxEvent, ( TickType_t ) 0 ) == pdFALSE )
                        {
                            /* The buffer could not be sent to the IP task. The
                            frame will be dropped and the buffer reused. */
                            iptraceETHERNET_RX_EVENT_LOST();
                        }
                        else
                        {
                            iptraceNETWORK_INTERFACE_RECEIVE();

                            /* The buffer is not owned by the IP task - a new
                            buffer is needed the next time around. */
                            pxNetworkBuffer = NULL;
                        }
                    }
                    else
                    {
                        /* The buffer does not contain any data so there is no
                        point sending it to the IP task.  Re-use the buffer on
                        the next loop. */
                        iptraceETHERNET_RX_EVENT_LOST();
                    }
                }
                else
                {
                    /* No data was received, keep the buffer for re-use.  The
                    loop will exit as ulReturn is not GMAC_OK. */
                }
            }
            else
            {
                /* Left a frame in the driver as a buffer was not available.
                Break out of loop. */
                ulReturned = GMAC_INVALID;
            }
        }
    }
}
static void prvGMACDeferredInterruptHandlerTask( void *pvParameters )
{
xNetworkBufferDescriptor_t *pxNetworkBuffer;
xIPStackEvent_t xRxEvent = { eEthernetRxEvent, NULL };
static const TickType_t xBufferWaitDelay = 1500UL / portTICK_RATE_MS;
uint32_t ulReturned;

	( void ) pvParameters;
	configASSERT( xGMACRxEventSemaphore );

	for( ;; )
	{
		/* Wait for the GMAC interrupt to indicate that another packet has been
		received.  The while() loop is only needed if INCLUDE_vTaskSuspend is
		set to 0 in FreeRTOSConfig.h.  If INCLUDE_vTaskSuspend is set to 1
		then portMAX_DELAY would be an indefinite block time and
		xSemaphoreTake() would only return when the semaphore was actually
		obtained. */
		while( xSemaphoreTake( xGMACRxEventSemaphore, portMAX_DELAY ) == pdFALSE );

		/* Allocate a buffer to hold the data. */
		pxNetworkBuffer = pxNetworkBufferGet( ipTOTAL_ETHERNET_FRAME_SIZE, xBufferWaitDelay );

		if( pxNetworkBuffer != NULL )
		{
			/* At least one packet has been received. */
			ulReturned = gmac_dev_read( &xGMACStruct, pxNetworkBuffer->pucEthernetBuffer, ipTOTAL_ETHERNET_FRAME_SIZE, ( uint32_t * ) &( pxNetworkBuffer->xDataLength ) );
			if( ulReturned == GMAC_OK )
			{
				#if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 1
				{
					if( pxNetworkBuffer->xDataLength > 0 )
					{
						/* If the frame would not be processed by the IP stack then
						don't even bother sending it to the IP stack. */
						if( eConsiderFrameForProcessing( pxNetworkBuffer->pucEthernetBuffer ) != eProcessBuffer )
						{
							pxNetworkBuffer->xDataLength = 0;
						}
					}
				}
				#endif

				if( pxNetworkBuffer->xDataLength > 0 )
				{
					/* Store a pointer to the network buffer structure in the
					padding	space that was left in front of the Ethernet frame.
					The pointer	is needed to ensure the network buffer structure
					can be located when it is time for it to be freed if the
					Ethernet frame gets	used as a zero copy buffer. */
					*( ( xNetworkBufferDescriptor_t ** ) ( ( pxNetworkBuffer->pucEthernetBuffer - ipBUFFER_PADDING ) ) ) = pxNetworkBuffer;

					/* Data was received and stored.  Send it to the IP task
					for processing. */
					xRxEvent.pvData = ( void * ) pxNetworkBuffer;
					if( xQueueSendToBack( xNetworkEventQueue, &xRxEvent, ( TickType_t ) 0 ) == pdFALSE )
					{
						/* The buffer could not be sent to the IP task so the
						buffer must be released. */
						vNetworkBufferRelease( pxNetworkBuffer );
						iptraceETHERNET_RX_EVENT_LOST();
					}
					else
					{
						iptraceNETWORK_INTERFACE_RECEIVE();
					}
				}
				else
				{
					/* The buffer does not contain any data so there is no
					point sending it to the IP task.  Just release it. */
					vNetworkBufferRelease( pxNetworkBuffer );
					iptraceETHERNET_RX_EVENT_LOST();
				}
			}
			else
			{
				vNetworkBufferRelease( pxNetworkBuffer );
				iptraceETHERNET_RX_EVENT_LOST();
			}
		}
		else
		{
			/* Left a frame in the driver as a buffer was not available. */
			gmac_dev_reset( &xGMACStruct );
		}
	}
}
static void prvEMACHandlerTask( void *pvParameters )
{
size_t xDataLength;
const uint16_t usCRCLength = 4;
xNetworkBufferDescriptor_t *pxNetworkBuffer;
xIPStackEvent_t xRxEvent = { eEthernetRxEvent, NULL };

/* This is not included in the header file for some reason. */
extern uint8_t *EMAC_NextPacketToRead( void );

	( void ) pvParameters;
	configASSERT( xEMACRxEventSemaphore );

	for( ;; )
	{
		/* Wait for the EMAC interrupt to indicate that another packet has been
		received.  The while() loop is only needed if INCLUDE_vTaskSuspend is
		set to 0 in FreeRTOSConfig.h. */
		while( xSemaphoreTake( xEMACRxEventSemaphore, portMAX_DELAY ) == pdFALSE );

		/* At least one packet has been received. */
		while( EMAC_CheckReceiveIndex() != FALSE )
		{
			/* Obtain the length, minus the CRC.  The CRC is four bytes
			but the length is already minus 1. */
			xDataLength = ( size_t ) EMAC_GetReceiveDataSize() - ( usCRCLength - 1U );

			if( xDataLength > 0U )
			{
				/* Obtain a network buffer to pass this data into the
				stack.  No storage is required as the network buffer
				will point directly to the buffer that already holds
				the	received data. */
				pxNetworkBuffer = pxNetworkBufferGet( 0, ( portTickType ) 0 );

				if( pxNetworkBuffer != NULL )
				{
					pxNetworkBuffer->pucEthernetBuffer = EMAC_NextPacketToRead();
					pxNetworkBuffer->xDataLength = xDataLength;
					xRxEvent.pvData = ( void * ) pxNetworkBuffer;

					/* Data was received and stored.  Send a message to the IP
					task to let it know. */
					if( xQueueSendToBack( xNetworkEventQueue, &xRxEvent, ( portTickType ) 0 ) == pdFALSE )
					{
						vNetworkBufferRelease( pxNetworkBuffer );
						iptraceETHERNET_RX_EVENT_LOST();
					}
				}
				else
				{
					iptraceETHERNET_RX_EVENT_LOST();
				}

				iptraceNETWORK_INTERFACE_RECEIVE();
			}

			/* Release the frame. */
			EMAC_UpdateRxConsumeIndex();
		}
	}
}
Example #6
0
static void prvEMACDeferredInterruptHandlerTask( void *pvParameters )
{
xNetworkBufferDescriptor_t *pxNetworkBuffer;
xIPStackEvent_t xRxEvent = { eEthernetRxEvent, NULL };

	( void ) pvParameters;
	configASSERT( xEMACRxEventSemaphore );

	for( ;; )
	{
		/* Wait for the EMAC interrupt to indicate that another packet has been
		received.  The while() loop is only needed if INCLUDE_vTaskSuspend is
		set to 0 in FreeRTOSConfig.h.  If INCLUDE_vTaskSuspend is set to 1
		then portMAX_DELAY would be an indefinite block time and
		xSemaphoreTake() would only return when the semaphore was actually
		obtained. */
		while( xSemaphoreTake( xEMACRxEventSemaphore, portMAX_DELAY ) == pdFALSE );

		/* At least one packet has been received. */
		while( EMAC_CheckReceiveIndex() != FALSE )
		{
			/* The buffer filled by the DMA is going to be passed into the IP
			stack.  Allocate another buffer for the DMA descriptor. */
			pxNetworkBuffer = pxNetworkBufferGet( ipTOTAL_ETHERNET_FRAME_SIZE, ( TickType_t ) 0 );

			if( pxNetworkBuffer != NULL )
			{
				/* Swap the buffer just allocated and referenced from the
				pxNetworkBuffer with the buffer that has already been filled by
				the DMA.  pxNetworkBuffer will then hold a reference to the
				buffer that already contains the data without any data having
				been copied between buffers. */
				EMAC_NextPacketToRead( pxNetworkBuffer );

				#if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 1
				{
					if( pxNetworkBuffer->xDataLength > 0 )
					{
						/* If the frame would not be processed by the IP stack then
						don't even bother sending it to the IP stack. */
						if( eConsiderFrameForProcessing( pxNetworkBuffer->pucEthernetBuffer ) != eProcessBuffer )
						{
							pxNetworkBuffer->xDataLength = 0;
						}
					}
				}
				#endif

				if( pxNetworkBuffer->xDataLength > 0 )
				{
					/* Store a pointer to the network buffer structure in the
					padding	space that was left in front of the Ethernet frame.
					The pointer	is needed to ensure the network buffer structure
					can be located when it is time for it to be freed if the
					Ethernet frame gets	used as a zero copy buffer. */
					*( ( xNetworkBufferDescriptor_t ** ) ( ( pxNetworkBuffer->pucEthernetBuffer - ipBUFFER_PADDING ) ) ) = pxNetworkBuffer;

					/* Data was received and stored.  Send it to the IP task
					for processing. */
					xRxEvent.pvData = ( void * ) pxNetworkBuffer;
					if( xQueueSendToBack( xNetworkEventQueue, &xRxEvent, ( TickType_t ) 0 ) == pdFALSE )
					{
						/* The buffer could not be sent to the IP task so the
						buffer must be released. */
						vNetworkBufferRelease( pxNetworkBuffer );
						iptraceETHERNET_RX_EVENT_LOST();
					}
					else
					{
						iptraceNETWORK_INTERFACE_RECEIVE();
					}
				}
				else
				{
					/* The buffer does not contain any data so there is no
					point sending it to the IP task.  Just release it. */
					vNetworkBufferRelease( pxNetworkBuffer );
					iptraceETHERNET_RX_EVENT_LOST();
				}
			}
			else
			{
				iptraceETHERNET_RX_EVENT_LOST();
			}

			/* Release the descriptor. */
			EMAC_UpdateRxConsumeIndex();
		}
	}
}
/* The deferred interrupt handler is a standard RTOS task.  FreeRTOS's centralised
 deferred interrupt handling capabilities can also be used. */
static void prvEMACDeferredInterruptHandlerTask(void *pvParameters) {
	xNetworkBufferDescriptor_t *pxBufferDescriptor;
	size_t xBytesReceived;
	/* Used to indicate that xSendEventStructToIPTask() is being called because
	 of an Ethernet receive event. */
	xIPStackEvent_t xRxEvent;

	uint8_t *buffer;
	__IO ETH_DMADescTypeDef *dmarxdesc;
	uint32_t payloadoffset = 0;
	uint32_t byteslefttocopy = 0;
	uint32_t i = 0;

	xEMACRxEventSemaphore = xSemaphoreCreateCounting(10, 0);

	for (;;) {
		/* Wait for the Ethernet MAC interrupt to indicate that another packet
		 has been received.  It is assumed xEMACRxEventSemaphore is a counting
		 semaphore (to count the Rx events) and that the semaphore has already
		 been created (remember this is an example of a simple rather than
		 optimised port layer). */
		if (xSemaphoreTake( xEMACRxEventSemaphore, portMAX_DELAY ) == pdTRUE) {

			/* get received frame */
			if (HAL_ETH_GetReceivedFrame_IT(&heth_global) != HAL_OK)
				return;

			/* Obtain the size of the packet */
			xBytesReceived = (uint16_t) heth_global.RxFrameInfos.length;
			buffer = (uint8_t *) heth_global.RxFrameInfos.buffer;

			if (xBytesReceived > 0) {
				/* Allocate a network buffer descriptor that points to a buffer
				 large enough to hold the received frame.  As this is the simple
				 rather than efficient example the received data will just be copied
				 into this buffer. */
				pxBufferDescriptor = pxGetNetworkBufferWithDescriptor(xBytesReceived, 0);

				if (pxBufferDescriptor != NULL) {
					/* pxBufferDescriptor->pucEthernetBuffer now points to an Ethernet
					 buffer large enough to hold the received data.  Copy the
					 received data into pcNetworkBuffer->pucEthernetBuffer.  Here it
					 is assumed ReceiveData() is a peripheral driver function that
					 copies the received data into a buffer passed in as the function's
					 parameter.  Remember! While is is a simple robust technique -
					 it is not efficient.  An example that uses a zero copy technique
					 is provided further down this page. */

					dmarxdesc = heth_global.RxFrameInfos.FSRxDesc;

					pxBufferDescriptor->xDataLength = xBytesReceived;

					byteslefttocopy = xBytesReceived;
					payloadoffset = 0;

					/* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size*/
					while (byteslefttocopy > ETH_RX_BUF_SIZE) {
						/* Copy data to pbuf */
						memcpy(
								(uint8_t*) ((uint8_t*) pxBufferDescriptor->pucEthernetBuffer
										+ payloadoffset), (uint8_t*) ((uint8_t*) buffer),
								ETH_RX_BUF_SIZE);

						/* Point to next descriptor */
						dmarxdesc = (ETH_DMADescTypeDef *) (dmarxdesc->Buffer2NextDescAddr);
						buffer = (uint8_t *) (dmarxdesc->Buffer1Addr);

						byteslefttocopy -= ETH_RX_BUF_SIZE;
						payloadoffset += ETH_RX_BUF_SIZE;
					}
					/* Copy remaining data in pbuf */
					memcpy(
							(uint8_t*) ((uint8_t*) pxBufferDescriptor->pucEthernetBuffer
									+ payloadoffset), (uint8_t*) ((uint8_t*) buffer),
							byteslefttocopy);
				}

				/* See if the data contained in the received Ethernet frame needs
				 to be processed.  NOTE! It is preferable to do this in
				 the interrupt service routine itself, which would remove the need
				 to unblock this task for packets that don't need processing. */
				if (eConsiderFrameForProcessing(pxBufferDescriptor->pucEthernetBuffer)
						== eProcessBuffer) {
					/* The event about to be sent to the TCP/IP is an Rx event. */
					xRxEvent.eEventType = eNetworkRxEvent;

					/* pvData is used to point to the network buffer descriptor that
					 now references the received data. */
					xRxEvent.pvData = (void *) pxBufferDescriptor;

					/* Send the data to the TCP/IP stack. */
					if (xSendEventStructToIPTask(&xRxEvent, 0) == pdFALSE) {
						/* The buffer could not be sent to the IP task so the buffer
						 must be released. */
						vReleaseNetworkBufferAndDescriptor(pxBufferDescriptor);

						/* Make a call to the standard trace macro to log the
						 occurrence. */
						iptraceETHERNET_RX_EVENT_LOST();
					}
					else {
						/* The message was successfully sent to the TCP/IP stack.
						 Call the standard trace macro to log the occurrence. */
						iptraceNETWORK_INTERFACE_RECEIVE();
						gdb.monit.rx_eth_frames++;
					}
				}
				else {
					/* The Ethernet frame can be dropped, but the Ethernet buffer
					 must be released. */
					vReleaseNetworkBufferAndDescriptor(pxBufferDescriptor);
				}

				/* Release descriptors to DMA */
				/* Point to first descriptor */
				dmarxdesc = heth_global.RxFrameInfos.FSRxDesc;
				/* Set Own bit in Rx descriptors: gives the buffers back to DMA */
				for (i = 0; i < heth_global.RxFrameInfos.SegCount; i++) {
					dmarxdesc->Status |= ETH_DMARXDESC_OWN;
					dmarxdesc = (ETH_DMADescTypeDef *) (dmarxdesc->Buffer2NextDescAddr);
				}

				/* Clear Segment_Count */
				heth_global.RxFrameInfos.SegCount = 0;

			}
			else {
				/* The event was lost because a network buffer was not available.
				 Call the standard trace macro to log the occurrence. */
				iptraceETHERNET_RX_EVENT_LOST();
			}
		}

		/* When Rx Buffer unavailable flag is set: clear it and resume reception */
		if ((heth_global.Instance->DMASR & ETH_DMASR_RBUS) != (uint32_t) RESET) {
			/* Clear RBUS ETHERNET DMA flag */
			heth_global.Instance->DMASR = ETH_DMASR_RBUS;
			/* Resume DMA reception */
			heth_global.Instance->DMARPDR = 0;
		}
	}

}
Example #8
0
static uint32_t prvEMACRxPoll( void )
{
unsigned char *pucUseBuffer;
uint32_t ulReceiveCount, ulResult, ulReturnValue = 0;
static NetworkBufferDescriptor_t *pxNextNetworkBufferDescriptor = NULL;
const UBaseType_t xMinDescriptorsToLeave = 2UL;
const TickType_t xBlockTime = pdMS_TO_TICKS( 100UL );
static IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };

	for( ;; )
	{
		/* If pxNextNetworkBufferDescriptor was not left pointing at a valid
		descriptor then allocate one now. */
		if( ( pxNextNetworkBufferDescriptor == NULL ) && ( uxGetNumberOfFreeNetworkBuffers() > xMinDescriptorsToLeave ) )
		{
			pxNextNetworkBufferDescriptor = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, xBlockTime );
		}

		if( pxNextNetworkBufferDescriptor != NULL )
		{
			/* Point pucUseBuffer to the buffer pointed to by the descriptor. */
			pucUseBuffer = ( unsigned char* ) ( pxNextNetworkBufferDescriptor->pucEthernetBuffer - ipconfigPACKET_FILLER_SIZE );
		}
		else
		{
			/* As long as pxNextNetworkBufferDescriptor is NULL, the incoming
			messages will be flushed and ignored. */
			pucUseBuffer = NULL;
		}

		/* Read the next packet from the hardware into pucUseBuffer. */
		ulResult = gmac_dev_read( &gs_gmac_dev, pucUseBuffer, ipTOTAL_ETHERNET_FRAME_SIZE, &ulReceiveCount );

		if( ( ulResult != GMAC_OK ) || ( ulReceiveCount == 0 ) )
		{
			/* No data from the hardware. */
			break;
		}

		if( pxNextNetworkBufferDescriptor == NULL )
		{
			/* Data was read from the hardware, but no descriptor was available
			for it, so it will be dropped. */
			iptraceETHERNET_RX_EVENT_LOST();
			continue;
		}

		iptraceNETWORK_INTERFACE_RECEIVE();
		pxNextNetworkBufferDescriptor->xDataLength = ( size_t ) ulReceiveCount;
		xRxEvent.pvData = ( void * ) pxNextNetworkBufferDescriptor;

		/* Send the descriptor to the IP task for processing. */
		if( xSendEventStructToIPTask( &xRxEvent, xBlockTime ) != pdTRUE )
		{
			/* The buffer could not be sent to the stack so must be released
			again. */
			vReleaseNetworkBufferAndDescriptor( pxNextNetworkBufferDescriptor );
			iptraceETHERNET_RX_EVENT_LOST();
			FreeRTOS_printf( ( "prvEMACRxPoll: Can not queue return packet!\n" ) );
		}

		/* Now the buffer has either been passed to the IP-task,
		or it has been released in the code above. */
		pxNextNetworkBufferDescriptor = NULL;
		ulReturnValue++;
	}

	return ulReturnValue;
}
Example #9
0
static void prvInterruptSimulatorTask( void *pvParameters )
{
struct pcap_pkthdr xHeader;
static struct pcap_pkthdr *pxHeader;
const uint8_t *pucPacketData;
uint8_t ucRecvBuffer[ ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ];
NetworkBufferDescriptor_t *pxNetworkBuffer;
IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
eFrameProcessingResult_t eResult;

	/* Remove compiler warnings about unused parameters. */
	( void ) pvParameters;

	for( ;; )
	{
		/* Does the circular buffer used to pass data from the Win32 thread that
		handles WinPCAP Rx into the FreeRTOS simulator contain another packet? */
		if( uxStreamBufferGetSize( xRecvBuffer ) > sizeof( xHeader ) )
		{
			/* Get the next packet. */
			uxStreamBufferGet( xRecvBuffer, 0, (uint8_t*)&xHeader, sizeof( xHeader ), pdFALSE );
			uxStreamBufferGet( xRecvBuffer, 0, (uint8_t*)ucRecvBuffer, ( size_t ) xHeader.len, pdFALSE );
			pucPacketData = ucRecvBuffer;
			pxHeader = &xHeader;

			iptraceNETWORK_INTERFACE_RECEIVE();

			eResult = ipCONSIDER_FRAME_FOR_PROCESSING( pucPacketData );
			if( eResult == eProcessBuffer )
			{
				/* Will the data fit into the frame buffer? */
				if( pxHeader->len <= ipTOTAL_ETHERNET_FRAME_SIZE )
				{
					/* Obtain a buffer into which the data can be placed.  This
					is only	an interrupt simulator, not a real interrupt, so it
					is ok to call the task level function here, but note that
					some buffer implementations cannot be called from a real
					interrupt. */
					pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( pxHeader->len, 0 );

					if( pxNetworkBuffer != NULL )
					{
						memcpy( pxNetworkBuffer->pucEthernetBuffer, pucPacketData, pxHeader->len );
						pxNetworkBuffer->xDataLength = ( size_t ) pxHeader->len;

						#if( niDISRUPT_PACKETS == 1 )
						{
							pxNetworkBuffer = vRxFaultInjection( pxNetworkBuffer, pucPacketData );
						}
						#endif /* niDISRUPT_PACKETS */

						if( pxNetworkBuffer != NULL )
						{
							xRxEvent.pvData = ( void * ) pxNetworkBuffer;

							/* Data was received and stored.  Send a message to
							the IP task to let it know. */
							if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )
							{
								/* The buffer could not be sent to the stack so
								must be released again.  This is only an
								interrupt simulator, not a real interrupt, so it
								is ok to use the task level function here, but
								note no all buffer implementations will allow
								this function to be executed from a real
								interrupt. */
								vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
								iptraceETHERNET_RX_EVENT_LOST();
							}
						}
						else
						{
							/* The packet was already released or stored inside
							vRxFaultInjection().  Don't release it here. */
						}
					}
					else
					{
						iptraceETHERNET_RX_EVENT_LOST();
					}
				}
				else
				{
					/* Log that a packet was dropped because it would have
					overflowed the buffer, but there may be more buffers to
					process. */
				}
			}
		}
		else
		{
			/* There is no real way of simulating an interrupt.  Make sure
			other tasks can run. */
			vTaskDelay( configWINDOWS_MAC_INTERRUPT_SIMULATOR_DELAY );
		}
	}
}
Example #10
0
int emacps_check_rx( xemacpsif_s *xemacpsif )
{
NetworkBufferDescriptor_t *pxBuffer;
int rx_bytes;
volatile int msgCount = 0;
int head = xemacpsif->rxHead;

	/* There seems to be an issue (SI# 692601), see comments below. */
	resetrx_on_no_rxdata(xemacpsif);

	/* This FreeRTOS+TCP driver shall be compiled with the option
	"ipconfigUSE_LINKED_RX_MESSAGES" enabled.  It allows the driver to send a
	chain of RX messages within one message to the IP-task.	*/
	for( ; ; )
	{
		if( ( ( xemacpsif->rxSegments[ head ].address & XEMACPS_RXBUF_NEW_MASK ) == 0 ) ||
			( pxDMA_rx_buffers[ head ] == NULL ) )
		{
			break;
		}

		pxBuffer = ( NetworkBufferDescriptor_t * )pxDMA_rx_buffers[ head ];

		/* Just avoiding to use or refer to the same buffer again */
		pxDMA_rx_buffers[ head ] = NULL;

		/*
		 * Adjust the buffer size to the actual number of bytes received.
		 */
		rx_bytes = xemacpsif->rxSegments[ head ].flags & XEMACPS_RXBUF_LEN_MASK;

		pxBuffer->xDataLength = rx_bytes;

		if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 )
		{
			Xil_DCacheInvalidateRange( ( ( uint32_t )pxBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE, (unsigned)rx_bytes );
		}

		/* store it in the receive queue, where it'll be processed by a
		different handler. */
		iptraceNETWORK_INTERFACE_RECEIVE();
		pxBuffer->pxNextBuffer = NULL;

		if( ethMsg == NULL )
		{
			// Becomes the first message
			ethMsg = pxBuffer;
		}
		else if( ethLast != NULL )
		{
			// Add to the tail
			ethLast->pxNextBuffer = pxBuffer;
		}

		ethLast = pxBuffer;
		msgCount++;

		if( ++head == ipconfigNIC_N_RX_DESC )
		{
			head = 0;
		}
	}
	xemacpsif->rxHead = head;

	if( ethMsg != NULL )
	{
		passEthMessages( );
	}

	if( msgCount != 0 )
	{
		/* Some packets (network buffer descriptors) have been passed to the
		IP-stack.  Now allocate new descriptors and put them in place. */
		emacps_set_rx_buffers( xemacpsif, msgCount );
	}

	return msgCount;
}