/* Scheduler includes. */\r
#include "FreeRTOS.h"\r
#include "task.h"\r
-#include "semphr.h"\r
+#include "timers.h"\r
+#include "queue.h"\r
\r
/* uip includes. */\r
#include "net/uip.h"\r
/* Standard constant. */\r
#define uipTOTAL_FRAME_HEADER_SIZE 54\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
+/* A block time of zero ticks simply means, "don't block". */\r
+#define uipDONT_BLOCK 0UL\r
+\r
/*-----------------------------------------------------------*/\r
\r
/*\r
*/\r
static void prvSetMACAddress( void );\r
\r
+/*\r
+ * Perform any uIP initialisation necessary. \r
+ */\r
+static void prvInitialise_uIP( void );\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
* Port functions required by the uIP stack.\r
*/\r
-void clock_init( void );\r
clock_time_t clock_time( void );\r
\r
/*-----------------------------------------------------------*/\r
\r
-/* The semaphore used by the ISR to wake the uIP task. */\r
-xSemaphoreHandle xEMACSemaphore = NULL;\r
-\r
-/*-----------------------------------------------------------*/\r
+/* The queue used to send TCP/IP events to the uIP stack. */\r
+xQueueHandle xEMACEventQueue = NULL;\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
\r
void vuIP_Task( void *pvParameters )\r
{\r
-portBASE_TYPE i, xDoneSomething;\r
-uip_ipaddr_t xIPAddr;\r
-struct timer periodic_timer, arp_timer;\r
+portBASE_TYPE i;\r
+unsigned long ulNewEvent = 0UL;\r
+unsigned long ulUIP_Events = 0UL;\r
\r
( void ) pvParameters;\r
-\r
+ \r
/* Initialise the uIP stack. */\r
- timer_set( &periodic_timer, configTICK_RATE_HZ / 2 );\r
- timer_set( &arp_timer, configTICK_RATE_HZ * 10 );\r
- uip_init();\r
- uip_ipaddr( &xIPAddr, configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3 );\r
- uip_sethostaddr( &xIPAddr );\r
- uip_ipaddr( &xIPAddr, configNET_MASK0, configNET_MASK1, configNET_MASK2, configNET_MASK3 );\r
- uip_setnetmask( &xIPAddr );\r
- prvSetMACAddress();\r
- httpd_init();\r
-\r
- /* Create the semaphore used to wake the uIP task. */\r
- vSemaphoreCreateBinary( xEMACSemaphore );\r
+ prvInitialise_uIP();\r
\r
/* Initialise the MAC. */\r
vInitEmac();\r
\r
for( ;; )\r
{\r
- xDoneSomething = pdFALSE;\r
- \r
- /* Is there received data ready to be processed? */\r
- uip_len = ( unsigned short ) ulEMACRead();\r
- \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
+ if( ( ulUIP_Events & uipETHERNET_RX_EVENT ) != 0UL )\r
+ { \r
+ /* Is there received data ready to be processed? */\r
+ uip_len = ( unsigned short ) ulEMACRead();\r
+ \r
+ if( ( uip_len > 0 ) && ( uip_buf != NULL ) )\r
{\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
+ /* Standard uIP loop taken from the uIP manual. */\r
+ if( xHeader->type == htons( UIP_ETHTYPE_IP ) )\r
{\r
- uip_arp_out();\r
- vEMACWrite();\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
- \r
- xDoneSomething = pdTRUE;\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
+ else if( xHeader->type == htons( UIP_ETHTYPE_ARP ) )\r
{\r
- vEMACWrite();\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
}\r
- \r
- xDoneSomething = pdTRUE;\r
+ }\r
+ else\r
+ {\r
+ ulUIP_Events &= ~uipETHERNET_RX_EVENT;\r
}\r
}\r
-\r
- if( timer_expired( &periodic_timer ) && ( uip_buf != NULL ) )\r
+ \r
+ if( ( ulUIP_Events & uipPERIODIC_TIMER_EVENT ) != 0UL )\r
{\r
- timer_reset( &periodic_timer );\r
+ ulUIP_Events &= ~uipPERIODIC_TIMER_EVENT;\r
+ \r
for( i = 0; i < UIP_CONNS; i++ )\r
{\r
uip_periodic( i );\r
vEMACWrite();\r
}\r
}\r
-\r
- /* Call the ARP timer function every 10 seconds. */\r
- if( timer_expired( &arp_timer ) )\r
- {\r
- timer_reset( &arp_timer );\r
- uip_arp_timer();\r
- }\r
- \r
- xDoneSomething = pdTRUE;\r
}\r
\r
- if( xDoneSomething == pdFALSE )\r
+ /* Call the ARP timer function every 10 seconds. */\r
+ if( ( ulUIP_Events & uipARP_TIMER_EVENT ) != 0 )\r
+ {\r
+ ulUIP_Events &= ~uipARP_TIMER_EVENT;\r
+ uip_arp_timer();\r
+ }\r
+ \r
+ if( ulUIP_Events == pdFALSE )\r
{\r
- /* We did not receive a packet, and there was no periodic\r
- processing to perform. Block for a fixed period. If a packet\r
- is received during this period we will be woken by the ISR\r
- giving us the Semaphore. */\r
- xSemaphoreTake( xEMACSemaphore, configTICK_RATE_HZ / 20 );\r
+ xQueueReceive( xEMACEventQueue, &ulNewEvent, portMAX_DELAY );\r
+ ulUIP_Events |= ulNewEvent;\r
}\r
}\r
}\r
/*-----------------------------------------------------------*/\r
\r
+static void prvInitialise_uIP( void )\r
+{\r
+xTimerHandle xARPTimer, xPeriodicTimer;\r
+uip_ipaddr_t xIPAddr;\r
+struct timer periodic_timer, arp_timer;\r
+const unsigned long ul_uIPEventQueueLength = 10UL;\r
+\r
+ /* Initialise the uIP stack. */\r
+ uip_init();\r
+ uip_ipaddr( &xIPAddr, configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3 );\r
+ uip_sethostaddr( &xIPAddr );\r
+ uip_ipaddr( &xIPAddr, configNET_MASK0, configNET_MASK1, configNET_MASK2, configNET_MASK3 );\r
+ uip_setnetmask( &xIPAddr );\r
+ prvSetMACAddress();\r
+ httpd_init();\r
+\r
+ /* Create the queue used to sent TCP/IP events to the uIP stack. */\r
+ xEMACEventQueue = xQueueCreate( ul_uIPEventQueueLength, sizeof( unsigned long ) );\r
+\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
+ ( 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
+ ( 500 / portTICK_RATE_MS ),\r
+ pdTRUE, /* Autor-reload. */\r
+ ( void * ) uipPERIODIC_TIMER,\r
+ prvUIPTimerCallback\r
+ );\r
+\r
+ configASSERT( xARPTimer );\r
+ configASSERT( xPeriodicTimer );\r
+\r
+ xTimerStart( xARPTimer, portMAX_DELAY );\r
+ xTimerStart( xPeriodicTimer, portMAX_DELAY );\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
+ switch( ( int ) pvTimerGetTimerID( xTimer ) )\r
+ {\r
+ case uipARP_TIMER : xQueueSend( xEMACEventQueue, &ulARPTimerExpired, uipDONT_BLOCK );\r
+ break;\r
+\r
+ case uipPERIODIC_TIMER : xQueueSend( xEMACEventQueue, &ulPeriodicTimerExpired, uipDONT_BLOCK );\r
+ break;\r
+\r
+ default : /* Should not get here. */\r
+ break;\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
static void prvSetMACAddress( void )\r
{\r
struct uip_eth_addr xAddr;\r