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;
	}
	portBASE_TYPE xNetworkInterfaceOutput( xNetworkBufferDescriptor_t * const pxNetworkBuffer )
	{
		xSemaphoreTake( xPCAPMutex, portMAX_DELAY );
		{
			iptraceNETWORK_INTERFACE_TRANSMIT();
			pcap_sendpacket( pxOpenedInterfaceHandle, pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength );
		}
		xSemaphoreGive( xPCAPMutex );

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

		return pdPASS;
	}
Ejemplo n.º 3
0
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t bReleaseAfterSend )
{
/* Do not wait too long for a free TX DMA buffer. */
const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u );

	do {
		if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) == 0 )
		{
			/* Do not attempt to send packets as long as the Link Status is low. */
			break;
		}
		if( xTXDescriptorSemaphore == NULL )
		{
			/* Semaphore has not been created yet? */
			break;
		}
		if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )
		{
			/* Time-out waiting for a free TX descriptor. */
			tx_release_count[ 3 ]++;
			break;
		}
		#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
		{
			/* Confirm that the pxDescriptor may be kept by the driver. */
			configASSERT( bReleaseAfterSend != pdFALSE );
		}
		#endif /* ipconfigZERO_COPY_TX_DRIVER */

		gmac_dev_write( &gs_gmac_dev, (void *)pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength, prvTxCallback );

		#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
		{
			/* Confirm that the pxDescriptor may be kept by the driver. */
			bReleaseAfterSend = pdFALSE;
		}
		#endif /* ipconfigZERO_COPY_TX_DRIVER */
		/* Not interested in a call-back after TX. */
		iptraceNETWORK_INTERFACE_TRANSMIT();
	} while( 0 );

	if( bReleaseAfterSend != pdFALSE )
	{
		vReleaseNetworkBufferAndDescriptor( pxDescriptor );
	}
	return pdTRUE;
}
portBASE_TYPE xNetworkInterfaceOutput( xNetworkBufferDescriptor_t * const pxNetworkBuffer )
{
portBASE_TYPE xReturn = pdFAIL;
int32_t x;
extern void EMAC_StartTransmitNextBuffer( uint32_t ulLength );
extern void EMAC_SetNextPacketToSend( uint8_t * pucBuffer );


	/* Attempt to obtain access to a Tx buffer. */
	for( x = 0; x < niMAX_TX_ATTEMPTS; x++ )
	{
		if( EMAC_CheckTransmitIndex() == TRUE )
		{
			/* Will the data fit in the Tx buffer? */
			if( pxNetworkBuffer->xDataLength < EMAC_ETH_MAX_FLEN ) /*_RB_ The size needs to come from FreeRTOSIPConfig.h. */
			{
				/* Assign the buffer to the Tx descriptor that is now known to
				be free. */
				EMAC_SetNextPacketToSend( pxNetworkBuffer->pucEthernetBuffer );

				/* The EMAC now owns the buffer. */
				pxNetworkBuffer->pucEthernetBuffer = NULL;

				/* Initiate the Tx. */
				EMAC_StartTransmitNextBuffer( pxNetworkBuffer->xDataLength );
				iptraceNETWORK_INTERFACE_TRANSMIT();

				/* The Tx has been initiated. */
				xReturn = pdPASS;
			}
			break;
		}
		else
		{
			vTaskDelay( niTX_BUFFER_FREE_WAIT );
		}
	}

	/* Finished with the network buffer. */
	vNetworkBufferRelease( pxNetworkBuffer );

	return xReturn;
}
Ejemplo n.º 5
0
BaseType_t xNetworkInterfaceOutput( xNetworkBufferDescriptor_t * const pxNetworkBuffer )
{
BaseType_t xReturn = pdFAIL;
int32_t x;

	/* Attempt to obtain access to a Tx descriptor. */
	for( x = 0; x < niMAX_TX_ATTEMPTS; x++ )
	{
		if( EMAC_CheckTransmitIndex() == TRUE )
		{
			/* Assign the buffer being transmitted to the Tx descriptor. */
			EMAC_SetNextPacketToSend( pxNetworkBuffer->pucEthernetBuffer );

			/* The EMAC now owns the buffer and will free it when it has been
			transmitted.  Set pucBuffer to NULL to ensure the buffer is not
			freed when the network buffer structure is returned to the pool
			of network buffers. */
			pxNetworkBuffer->pucEthernetBuffer = NULL;

			/* Initiate the Tx. */
			EMAC_StartTransmitNextBuffer( pxNetworkBuffer->xDataLength );
			iptraceNETWORK_INTERFACE_TRANSMIT();

			/* The Tx has been initiated. */
			xReturn = pdPASS;

			break;
		}
		else
		{
			iptraceWAITING_FOR_TX_DMA_DESCRIPTOR();
			vTaskDelay( niTX_BUFFER_FREE_WAIT );
		}
	}

	/* Finished with the network buffer. */
	vNetworkBufferRelease( pxNetworkBuffer );

	return xReturn;
}
Ejemplo n.º 6
0
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t bReleaseAfterSend )
{
size_t xSpace;

	iptraceNETWORK_INTERFACE_TRANSMIT();
	configASSERT( xIsCallingFromIPTask() == pdTRUE );

	/* Both the length of the data being sent and the actual data being sent
	are placed in the thread safe buffer used to pass data between the FreeRTOS
	tasks and the Win32 thread that sends data via the WinPCAP library.  Drop
	the packet if there is insufficient space in the buffer to hold both. */
	xSpace = uxStreamBufferGetSpace( xSendBuffer );

	if( ( pxNetworkBuffer->xDataLength <= ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) &&
		( xSpace >= ( pxNetworkBuffer->xDataLength + sizeof( pxNetworkBuffer->xDataLength ) ) ) )
	{
		/* First write in the length of the data, then write in the data
		itself. */
		uxStreamBufferAdd( xSendBuffer, 0, ( const uint8_t * ) &( pxNetworkBuffer->xDataLength ), sizeof( pxNetworkBuffer->xDataLength ) );
		uxStreamBufferAdd( xSendBuffer, 0, ( const uint8_t * ) pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength );
	}
	else
	{
		FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: send buffers full to store %lu\n", pxNetworkBuffer->xDataLength ) );
	}

	/* Kick the Tx task in either case in case it doesn't know the buffer is
	full. */
	SetEvent( pvSendEvent );

	/* The buffer has been sent so can be released. */
	if( bReleaseAfterSend != pdFALSE )
	{
		vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
	}

	return pdPASS;
}
BaseType_t xNetworkInterfaceOutput(
xNetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend) {

	uint8_t *buffer = (uint8_t *) (heth_global.TxDesc->Buffer1Addr);
	__IO ETH_DMADescTypeDef *DmaTxDesc;
	uint32_t framelength = 0;
	uint32_t byteslefttocopy = 0;
	uint32_t payloadoffset = 0;
	DmaTxDesc = heth_global.TxDesc;

	uint8_t errval;

	/* copy frame from pbufs to driver buffers */

	/* Is this buffer available? If not, goto error */
	if ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t) RESET) {
		errval = pdFAIL;
		goto error;
	}

#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )
	{
		ProtocolPacket_t *pxPacket;

		/* If the peripheral must calculate the checksum, it wants
		 the protocol checksum to have a value of zero. */
		pxPacket = (ProtocolPacket_t *) (pxDescriptor->pucEthernetBuffer);

		if (pxPacket->xICMPPacket.xIPHeader.ucProtocol == ipPROTOCOL_ICMP) {
			pxPacket->xICMPPacket.xICMPHeader.usChecksum = (uint16_t) 0u;
		}
	}
#endif

	/* Get bytes in current lwIP buffer */
	byteslefttocopy = pxDescriptor->xDataLength;
	framelength = byteslefttocopy; // copy of frame length
	payloadoffset = 0;

	/* Check if the length of data to copy is bigger than Tx buffer size*/
	while ((byteslefttocopy) > ETH_TX_BUF_SIZE) {
		/* Copy data to Tx buffer*/
		memcpy((uint8_t*) ((uint8_t*) buffer),
				(uint8_t*) ((uint8_t*) pxDescriptor->pucEthernetBuffer + payloadoffset),
				(ETH_TX_BUF_SIZE));

		/* Point to next descriptor */
		DmaTxDesc = (ETH_DMADescTypeDef *) (DmaTxDesc->Buffer2NextDescAddr);

		/* Check if the buffer is available */
		if ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t) RESET) {
			errval = pdFAIL;
			goto error;
		}

		// memcpy( (uint8_t*)((uint8_t*)buffer), (uint8_t*)((uint8_t*)pxDescriptor->pucEthernetBuffer + payloadoffset), byteslefttocopy );
		buffer = (uint8_t *) (DmaTxDesc->Buffer1Addr);

		byteslefttocopy -= (ETH_TX_BUF_SIZE);
		payloadoffset += (ETH_TX_BUF_SIZE);

	}

	/* Copy the remaining bytes */
	memcpy((uint8_t*) ((uint8_t*) buffer),
			(uint8_t*) ((uint8_t*) pxDescriptor->pucEthernetBuffer + payloadoffset),
			byteslefttocopy);

	/* Prepare transmit descriptors to give to DMA */
	HAL_ETH_TransmitFrame(&heth_global, framelength);

	gdb.monit.tx_eth_frames++;

	/* Call the standard trace macro to log the send event. */
	iptraceNETWORK_INTERFACE_TRANSMIT();

	errval = pdPASS;

	error:

	if (xReleaseAfterSend != pdFALSE) {
		/* It is assumed SendData() copies the data out of the FreeRTOS+TCP Ethernet
		 buffer.  The Ethernet buffer is therefore no longer needed, and must be
		 freed for re-use. */
		vReleaseNetworkBufferAndDescriptor(pxDescriptor);
	}

	/* When Transmit Underflow flag is set, clear it and issue a Transmit Poll Demand to resume transmission */
	if ((heth_global.Instance->DMASR & ETH_DMASR_TUS) != (uint32_t) RESET) {
		/* Clear TUS ETHERNET DMA flag */
		heth_global.Instance->DMASR = ETH_DMASR_TUS;

		/* Resume DMA transmission*/
		heth_global.Instance->DMATPDR = 0;
	}

	return errval;

}