/*\r
- FreeRTOS V6.1.0 - Copyright (C) 2010 Real Time Engineers Ltd.\r
+ FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+ \r
\r
***************************************************************************\r
- * *\r
- * If you are: *\r
- * *\r
- * + New to FreeRTOS, *\r
- * + Wanting to learn FreeRTOS or multitasking in general quickly *\r
- * + Looking for basic training, *\r
- * + Wanting to improve your FreeRTOS skills and productivity *\r
- * *\r
- * then take a look at the FreeRTOS books - available as PDF or paperback *\r
- * *\r
- * "Using the FreeRTOS Real Time Kernel - a Practical Guide" *\r
- * http://www.FreeRTOS.org/Documentation *\r
- * *\r
- * A pdf reference manual is also available. Both are usually delivered *\r
- * to your inbox within 20 minutes to two hours when purchased between 8am *\r
- * and 8pm GMT (although please allow up to 24 hours in case of *\r
- * exceptional circumstances). Thank you for your support! *\r
- * *\r
+ * *\r
+ * FreeRTOS tutorial books are available in pdf and paperback. *\r
+ * Complete, revised, and edited pdf reference manuals are also *\r
+ * available. *\r
+ * *\r
+ * Purchasing FreeRTOS documentation will not only help you, by *\r
+ * ensuring you get running as quickly as possible and with an *\r
+ * in-depth knowledge of how to use FreeRTOS, it will also help *\r
+ * the FreeRTOS project to continue with its mission of providing *\r
+ * professional grade, cross platform, de facto standard solutions *\r
+ * for microcontrollers - completely free of charge! *\r
+ * *\r
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *\r
+ * *\r
+ * Thank you for using FreeRTOS, and thank you for your support! *\r
+ * *\r
***************************************************************************\r
\r
+\r
This file is part of the FreeRTOS distribution.\r
\r
FreeRTOS is free software; you can redistribute it and/or modify it under\r
the terms of the GNU General Public License (version 2) as published by the\r
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
- ***NOTE*** The exception to the GPL is included to allow you to distribute\r
- a combined work that includes FreeRTOS without being obliged to provide the\r
- source code for proprietary components outside of the FreeRTOS kernel.\r
- FreeRTOS is distributed in the hope that it will be useful, but WITHOUT\r
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\r
+ >>>NOTE<<< The modification to the GPL is included to allow you to\r
+ distribute a combined work that includes FreeRTOS without being obliged to\r
+ provide the source code for proprietary components outside of the FreeRTOS\r
+ kernel. FreeRTOS is distributed in the hope that it will be useful, but\r
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\r
more details. You should have received a copy of the GNU General Public\r
License and the FreeRTOS license exception along with FreeRTOS; if not it\r
can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
/* 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
- /* 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
+ ulUIP_Events &= ~uipARP_TIMER_EVENT;\r
+ uip_arp_timer();\r
}\r
+ \r
+ if( ulUIP_Events == pdFALSE )\r
+ {\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
+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( "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( "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
char *c;\r
\r
- /* Process the form input sent by the IO page of the served HTML. */\r
-\r
- c = strstr( pcInputString, "?" );\r
- if( c )\r
- {\r
- /* Turn the LED's on or off in accordance with the check box status. */\r
- if( strstr( c, "LED0=1" ) != NULL )\r
- {\r
- /* Turn LEDs on. */\r
- vParTestSetLED( 7, 1 );\r
- vParTestSetLED( 8, 1 );\r
- vParTestSetLED( 9, 1 );\r
- vParTestSetLED( 10, 1 );\r
- }\r
+ /* Only interested in processing form input if this is the IO page. */\r
+ c = strstr( pcInputString, "io.shtml" );\r
+ \r
+ if( c )\r
+ {\r
+ /* Is there a command in the string? */\r
+ c = strstr( pcInputString, "?" );\r
+ if( c )\r
+ {\r
+ /* Turn the LED's on or off in accordance with the check box status. */\r
+ if( strstr( c, "LED0=1" ) != NULL )\r
+ {\r
+ /* Turn the LEDs on. */\r
+ vParTestSetLED( 7, 1 );\r
+ vParTestSetLED( 8, 1 );\r
+ vParTestSetLED( 9, 1 );\r
+ vParTestSetLED( 10, 1 );\r
+ }\r
+ else\r
+ {\r
+ /* Turn the LEDs off. */\r
+ vParTestSetLED( 7, 0 );\r
+ vParTestSetLED( 8, 0 );\r
+ vParTestSetLED( 9, 0 );\r
+ vParTestSetLED( 10, 0 );\r
+ }\r
+ }\r
else\r
{\r
- /* Turn LED 4 off. */\r
+ /* Commands to turn LEDs off are not always explicit. */\r
vParTestSetLED( 7, 0 );\r
vParTestSetLED( 8, 0 );\r
vParTestSetLED( 9, 0 );\r
vParTestSetLED( 10, 0 );\r
}\r
- }\r
+ }\r
}\r
\r