]> git.sur5r.net Git - freertos/commitdiff
Update the A2F uIP_Task definition for use with the updated (zero copy) A2F Ethernet...
authorRichardBarry <RichardBarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Sun, 24 Apr 2011 19:09:12 +0000 (19:09 +0000)
committerRichardBarry <RichardBarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Sun, 24 Apr 2011 19:09:12 +0000 (19:09 +0000)
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@1385 1d2547de-c912-0410-9cb9-b8ca96c0e9e2

Demo/CORTEX_A2F200_IAR_and_Keil/uIP_Task.c

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