From: RichardBarry Date: Sun, 24 Apr 2011 19:09:12 +0000 (+0000) Subject: Update the A2F uIP_Task definition for use with the updated (zero copy) A2F Ethernet... X-Git-Tag: V7.0.1~39 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=92612c9c8f735417bae15022240622e148112191;p=freertos Update the A2F uIP_Task definition for use with the updated (zero copy) A2F Ethernet driver. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@1385 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- diff --git a/Demo/CORTEX_A2F200_IAR_and_Keil/uIP_Task.c b/Demo/CORTEX_A2F200_IAR_and_Keil/uIP_Task.c index 914e570a5..5f35cf532 100644 --- a/Demo/CORTEX_A2F200_IAR_and_Keil/uIP_Task.c +++ b/Demo/CORTEX_A2F200_IAR_and_Keil/uIP_Task.c @@ -1,4 +1,3 @@ -unsigned long ulRxed = 0, ulRxISR = 0, ulTxed = 0, ulTxISR = 0; /* FreeRTOS V7.0.0 - Copyright (C) 2011 Real Time Engineers Ltd. @@ -75,27 +74,25 @@ unsigned long ulRxed = 0, ulRxISR = 0, ulTxed = 0, ulTxISR = 0; #include "mss_ethernet_mac_regs.h" #include "mss_ethernet_mac.h" -/* The buffer used by the uIP stack to both receive and send. This points to -one of the Ethernet buffers when its actually in use. */ +/* The buffer used by the uIP stack to both receive and send. In this case, +because the Ethernet driver has been modified to be zero copy - the uip_buf +variable is just a pointer to an Ethernet buffer, and not a buffer in its own +right. */ extern unsigned char *uip_buf; -static const unsigned char ucMACAddress[] = { configMAC_ADDR0, configMAC_ADDR1, configMAC_ADDR2, configMAC_ADDR3, configMAC_ADDR4, configMAC_ADDR5 }; - +/* The ARP timer and the periodic timer share a callback function, so the +respective timer IDs are used to determine which timer actually expired. These +constants are assigned to the timer IDs. */ #define uipARP_TIMER 0 #define uipPERIODIC_TIMER 1 +/* The length of the queue used to send events from timers or the Ethernet +driver to the uIP stack. */ #define uipEVENT_QUEUE_LENGTH 10 -#define uipETHERNET_RX_EVENT 0x01UL -#define uipETHERNET_TX_EVENT 0x02UL -#define uipARP_TIMER_EVENT 0x04UL -#define uipPERIODIC_TIMER_EVENT 0x08UL -#define uipAPPLICATION_SEND_EVENT 0x10UL - +/* A block time of zero simply means "don't block". */ #define uipDONT_BLOCK 0UL -/*-----------------------------------------------------------*/ - /* How long to wait before attempting to connect the MAC again. */ #define uipINIT_WAIT ( 100 / portTICK_RATE_MS ) @@ -123,6 +120,10 @@ static void prvInitialise_uIP( void ); */ static void prvEMACEventListener( unsigned long ulISREvents ); +/* + * The callback function that is assigned to both the periodic timer and the + * ARP timer. + */ static void prvUIPTimerCallback( xTimerHandle xTimer ); /* @@ -130,14 +131,16 @@ static void prvUIPTimerCallback( xTimerHandle xTimer ); */ static void prvInitEmac( void ); +/* + * Write data to the Ethener. Note that this actually writes data twice for the + * to get around delayed ack issues when communicating with a non real-time + * peer (for example, a Windows machine). + */ void vEMACWrite( void ); -long lEMACWaitForLink( void ); - /* * Port functions required by the uIP stack. */ -void clock_init( void ); clock_time_t clock_time( void ); /*-----------------------------------------------------------*/ @@ -145,14 +148,6 @@ clock_time_t clock_time( void ); /* The queue used to send TCP/IP events to the uIP stack. */ xQueueHandle xEMACEventQueue = NULL; -static unsigned long ulUIP_Events = 0UL; - -/*-----------------------------------------------------------*/ - -void clock_init(void) -{ - /* This is done when the scheduler starts. */ -} /*-----------------------------------------------------------*/ clock_time_t clock_time( void ) @@ -164,84 +159,92 @@ clock_time_t clock_time( void ) void vuIP_Task( void *pvParameters ) { portBASE_TYPE i; -unsigned long ulNewEvent; +unsigned long ulNewEvent = 0UL; +unsigned long ulUIP_Events = 0UL; + /* Just to prevent compiler warnings about the unused parameter. */ ( void ) pvParameters; /* Initialise the uIP stack, configuring for web server usage. */ prvInitialise_uIP(); - /* Initialise the MAC. */ + /* Initialise the MAC and PHY. */ prvInitEmac(); for( ;; ) { - if( ( ulUIP_Events & uipETHERNET_RX_EVENT ) != 0UL ) - { - ulUIP_Events &= ~uipETHERNET_RX_EVENT; - - /* Is there received data ready to be processed? */ - uip_len = MSS_MAC_rx_packet(); + /* Is there received data ready to be processed? */ + uip_len = MSS_MAC_rx_packet(); - if( ( uip_len > 0 ) && ( uip_buf != NULL ) ) + /* Statements to be executed if data has been received on the Ethernet. */ + if( ( uip_len > 0 ) && ( uip_buf != NULL ) ) + { + /* Standard uIP loop taken from the uIP manual. */ + if( xHeader->type == htons( UIP_ETHTYPE_IP ) ) { - ulRxed++; - /* Standard uIP loop taken from the uIP manual. */ - if( xHeader->type == htons( UIP_ETHTYPE_IP ) ) - { - uip_arp_ipin(); - uip_input(); + uip_arp_ipin(); + uip_input(); - /* If the above function invocation resulted in data that - should be sent out on the network, the global variable - uip_len is set to a value > 0. */ - if( uip_len > 0 ) - { - uip_arp_out(); - vEMACWrite(); - } - } - else if( xHeader->type == htons( UIP_ETHTYPE_ARP ) ) + /* If the above function invocation resulted in data that + should be sent out on the network, the global variable + uip_len is set to a value > 0. */ + if( uip_len > 0 ) { - uip_arp_arpin(); + uip_arp_out(); + vEMACWrite(); + } + } + else if( xHeader->type == htons( UIP_ETHTYPE_ARP ) ) + { + uip_arp_arpin(); - /* If the above function invocation resulted in data that - should be sent out on the network, the global variable - uip_len is set to a value > 0. */ - if( uip_len > 0 ) - { - vEMACWrite(); - } + /* If the above function invocation resulted in data that + should be sent out on the network, the global variable + uip_len is set to a value > 0. */ + if( uip_len > 0 ) + { + vEMACWrite(); } } } + else + { + /* Clear the RX event latched in ulUIP_Events - if one was latched. */ + ulUIP_Events &= ~uipETHERNET_RX_EVENT; + } + /* Statements to be executed if the TCP/IP period timer has expired. */ if( ( ulUIP_Events & uipPERIODIC_TIMER_EVENT ) != 0UL ) { ulUIP_Events &= ~uipPERIODIC_TIMER_EVENT; - for( i = 0; i < UIP_CONNS; i++ ) + if( uip_buf != NULL ) { - uip_periodic( i ); - - /* If the above function invocation resulted in data that - should be sent out on the network, the global variable - uip_len is set to a value > 0. */ - if( uip_len > 0 ) + for( i = 0; i < UIP_CONNS; i++ ) { - uip_arp_out(); - vEMACWrite(); + uip_periodic( i ); + + /* If the above function invocation resulted in data that + should be sent out on the network, the global variable + uip_len is set to a value > 0. */ + if( uip_len > 0 ) + { + uip_arp_out(); + vEMACWrite(); + } } } } - /* Call the ARP timer function every 10 seconds. */ + /* Statements to be executed if the ARP timer has expired. */ if( ( ulUIP_Events & uipARP_TIMER_EVENT ) != 0 ) { ulUIP_Events &= ~uipARP_TIMER_EVENT; uip_arp_timer(); } + /* If all latched events have been cleared - block until another event + occurs. */ if( ulUIP_Events == pdFALSE ) { xQueueReceive( xEMACEventQueue, &ulNewEvent, portMAX_DELAY ); @@ -327,22 +330,25 @@ xTimerHandle xARPTimer, xPeriodicTimer; /* Create and start the uIP timers. */ xARPTimer = xTimerCreate( ( const signed char * const ) "ARPTimer", /* Just a name that is helpful for debugging, not used by the kernel. */ - ( 500 / portTICK_RATE_MS ), /* Timer period. */ + ( 10000UL / portTICK_RATE_MS ), /* Timer period. */ pdTRUE, /* Autor-reload. */ ( void * ) uipARP_TIMER, prvUIPTimerCallback ); xPeriodicTimer = xTimerCreate( ( const signed char * const ) "PeriodicTimer", - ( 5000 / portTICK_RATE_MS ), + ( 500UL / portTICK_RATE_MS ), pdTRUE, /* Autor-reload. */ ( void * ) uipPERIODIC_TIMER, prvUIPTimerCallback ); + /* Sanity check that the timers were indeed created. */ configASSERT( xARPTimer ); configASSERT( xPeriodicTimer ); + /* These commands will block indefinitely until they succeed, so there is + no point in checking their return values. */ xTimerStart( xARPTimer, portMAX_DELAY ); xTimerStart( xPeriodicTimer, portMAX_DELAY ); } @@ -353,23 +359,25 @@ static void prvEMACEventListener( unsigned long ulISREvents ) long lHigherPriorityTaskWoken = pdFALSE; unsigned long ulUIPEvents = 0UL; + /* Sanity check that the event queue was indeed created. */ configASSERT( xEMACEventQueue ); if( ( ulISREvents & MSS_MAC_EVENT_PACKET_SEND ) != 0UL ) { - ulTxISR++; - MSS_MAC_TxBufferCompleted(); + /* An Ethernet Tx event has occurred. */ + MSS_MAC_CheckTxBufferStatus(); } if( ( ulISREvents & MSS_MAC_EVENT_PACKET_RECEIVED ) != 0UL ) { - ulRxISR++; - /* Wake the uIP task as new data has arrived. */ + /* An Ethernet Rx event has occurred. */ ulUIPEvents |= uipETHERNET_RX_EVENT; } if( ulUIPEvents != 0UL ) { + /* Send any events that have occurred to the uIP stack (the uIP task in + this case). */ xQueueSendFromISR( xEMACEventQueue, &ulUIPEvents, &lHigherPriorityTaskWoken ); } @@ -381,8 +389,11 @@ static void prvInitEmac( void ) { const unsigned char ucPHYAddress = 1; + /* Initialise the MAC and PHY hardware. */ MSS_MAC_init( ucPHYAddress ); + /* Register the event listener. The Ethernet interrupt handler will call + this listener whenever an Rx or a Tx interrupt occurs. */ MSS_MAC_set_callback( ( MSS_MAC_callback_t ) prvEMACEventListener ); /* Setup the EMAC and the NVIC for MAC interrupts. */ @@ -397,11 +408,14 @@ const long lMaxAttempts = 10; long lAttempt; const portTickType xShortDelay = ( 10 / portTICK_RATE_MS ); + /* Try to send data to the Ethernet. Keep trying for a while if data cannot + be sent immediately. Note that this will actually cause the data to be sent + twice to get around delayed ACK problems when communicating with non real- + time TCP/IP stacks (such as a Windows machine). */ for( lAttempt = 0; lAttempt < lMaxAttempts; lAttempt++ ) { if( MSS_MAC_tx_packet( uip_len ) != 0 ) { - ulTxed++; break; } else @@ -412,28 +426,14 @@ const portTickType xShortDelay = ( 10 / portTICK_RATE_MS ); } /*-----------------------------------------------------------*/ -long lEMACWaitForLink( void ) -{ -long lReturn = pdFAIL; -unsigned long ulStatus; - - ulStatus = MSS_MAC_link_status(); - if( ( ulStatus & ( unsigned long ) MSS_MAC_LINK_STATUS_LINK ) != 0UL ) - { - lReturn = pdPASS; - } - - return lReturn; -} -/*-----------------------------------------------------------*/ - static void prvUIPTimerCallback( xTimerHandle xTimer ) { static const unsigned long ulARPTimerExpired = uipARP_TIMER_EVENT; static const unsigned long ulPeriodicTimerExpired = uipPERIODIC_TIMER_EVENT; /* This is a time callback, so calls to xQueueSend() must not attempt to - block. */ + block. As this callback is assigned to both the ARP and Periodic timers, the + first thing to do is ascertain which timer it was that actually expired. */ switch( ( int ) pvTimerGetTimerID( xTimer ) ) { case uipARP_TIMER : xQueueSend( xEMACEventQueue, &ulARPTimerExpired, uipDONT_BLOCK );