Example #1
0
/**
 * \brief Test GMAC read/write interfaces.
 *
 * \param test Current test case.
 */
static void run_gmac_read_write_test(const struct test_case *test)
{
	uint32_t ul_frm_size;
	uint8_t uc_rc = 0;
	uint32_t ul_retry_time = 0;

	/* Write the arp frame first */
	gmac_dev_write(&gs_gmac_dev, gs_arp_frame, sizeof(gs_arp_frame), NULL);

	while ( ul_retry_time < GMAC_UINT_TEST_MAX_RETRY_TIME ) {
		/* Read the frame in the gmac buffer */
		if (GMAC_OK != gmac_dev_read(&gs_gmac_dev, (uint8_t *) gs_uc_eth_buffer,
						sizeof(gs_uc_eth_buffer), &ul_frm_size)) {
			continue;
		}

		/* Is arp frame sent? */
		if (strncmp((const char *)gs_uc_eth_buffer, (const char *)gs_uc_mac_address, sizeof(gs_uc_mac_address))) {
			uc_rc = 1;
			break;
		}

		ul_retry_time++;
	}

	test_assert_true(test, uc_rc == 1, "Test GMAC: gmac write error!");
}
Example #2
0
/**
 * \brief Should allocate a pbuf and transfer the bytes of the incoming
 * packet from the interface into the pbuf.
 *
 * \param netif the lwip network interface structure for this ethernetif.
 *
 * \return a pbuf filled with the received packet (including MAC header)
 *         NULL on memory error.
 */
static struct pbuf *low_level_input(struct netif *netif)
{
    struct pbuf *p = NULL, *q = NULL;
    u16_t s_len;
    uint8_t pc_buf[NET_RW_BUFF_SIZE];
    int8_t *bufptr = (int8_t *)&pc_buf[0];

    uint32_t ul_frmlen;
    uint8_t uc_rc;

    /* Obtain the size of the packet and put it into the "len"
     * variable. */
    uc_rc = gmac_dev_read(&gs_gmac_dev, pc_buf, sizeof(pc_buf), &ul_frmlen);
    if (uc_rc != GMAC_OK) {
        return NULL;
    }

    s_len = ul_frmlen;

#if ETH_PAD_SIZE
    s_len += ETH_PAD_SIZE;    /* allow room for Ethernet padding */
#endif

    /* We allocate a pbuf chain of pbufs from the pool. */
    p = pbuf_alloc(PBUF_RAW, s_len, PBUF_POOL);

    if (p != NULL) {
#if ETH_PAD_SIZE
        pbuf_header(p, -ETH_PAD_SIZE);  /* drop the padding word */
#endif

        /* Iterate over the pbuf chain until we have read the entire
         * packet into the pbuf. */
        for (q = p; q != NULL; q = q->next) {
            /* Read enough bytes to fill this pbuf in the chain. The
             * available data in the pbuf is given by the q->len
             * variable. */
            /* read data into(q->payload, q->len); */
            memcpy(q->payload, bufptr, q->len);
            bufptr += q->len;
        }
        /* Acknowledge that packet has been read(); */

#if ETH_PAD_SIZE
        pbuf_header(p, ETH_PAD_SIZE);    /* Reclaim the padding word */
#endif

        LINK_STATS_INC(link.recv);
    } else {
        /* Drop packet(); */
        LINK_STATS_INC(link.memerr);
        LINK_STATS_INC(link.drop);
    }

    return p;
}
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 );
		}
	}
}
Example #5
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;
}