/* Scheduler includes. */\r
#include "FreeRTOS.h"\r
#include "task.h"\r
-#include "semphr.h"\r
+#include "queue.h"\r
+#include "timers.h"\r
\r
/* uip includes. */\r
#include "net/uip.h"\r
/* Demo includes. */\r
#include "ParTest.h"\r
\r
-#include "EMAC.h"\r
+/* Hardware driver includes. */\r
+#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
+unsigned char *uip_buf = NULL;\r
+\r
+static const unsigned char ucMACAddress[] = { configMAC_ADDR0, configMAC_ADDR1, configMAC_ADDR2, configMAC_ADDR3, configMAC_ADDR4, configMAC_ADDR5 };\r
+\r
+#define uipARP_TIMER 0\r
+#define uipPERIODIC_TIMER 1\r
+\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
+#define uipDONT_BLOCK 0UL\r
\r
/*-----------------------------------------------------------*/\r
\r
*/\r
static void prvSetMACAddress( void );\r
\r
+/*\r
+ * Perform any uIP initialisation required to ready the stack for http\r
+ * processing.
+ */\r
+static void prvInitialise_uIP( void );\r
+\r
+/*\r
+ * Handles Ethernet interrupt events.
+ */\r
+static void prvEMACEventListener( unsigned long ulISREvents );\r
+\r
+static void prvUIPTimerCallback( xTimerHandle xTimer );\r
+\r
+/*\r
+ * Initialise the MAC hardware.
+ */\r
+static void prvInitEmac( void );\r
+\r
+void vEMACWrite( void );\r
+\r
+unsigned long ulEMACRead( void );\r
+long lEMACWaitForLink( void );\r
+\r
/*\r
* Port functions required by the uIP stack.\r
*/\r
\r
/*-----------------------------------------------------------*/\r
\r
-/* The semaphore used by the ISR to wake the uIP task. */\r
-xSemaphoreHandle xEMACSemaphore = NULL;\r
+/* 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 vuIP_Task( void *pvParameters )\r
{\r
portBASE_TYPE i, xDoneSomething;\r
-uip_ipaddr_t xIPAddr;\r
-struct timer periodic_timer, arp_timer;\r
+unsigned long ulNewEvent;\r
\r
( void ) pvParameters;\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
+ /* Initialise the uIP stack, configuring for web server usage. */\r
+ prvInitialise_uIP();\r
\r
/* Initialise the MAC. */\r
- vInitEmac();\r
-\r
- while( lEMACWaitForLink() != pdPASS )\r
- {\r
- vTaskDelay( uipINIT_WAIT );\r
- }\r
+ prvInitEmac();\r
\r
for( ;; )\r
{\r
}\r
}\r
\r
- if( timer_expired( &periodic_timer ) && ( uip_buf != NULL ) )\r
+ if( ( ( ulUIP_Events & uipPERIODIC_TIMER_EVENT ) != 0UL ) && ( uip_buf != NULL ) )\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
}\r
\r
/* Call the ARP timer function every 10 seconds. */\r
- if( timer_expired( &arp_timer ) )\r
+ if( ( ulUIP_Events & uipARP_TIMER_EVENT ) != 0 )\r
{\r
- timer_reset( &arp_timer );\r
+ ulUIP_Events &= ~uipARP_TIMER_EVENT;\r
uip_arp_timer();\r
}\r
\r
\r
if( xDoneSomething == 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
}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvInitialise_uIP( void )\r
+{\r
+uip_ipaddr_t xIPAddr;\r
+xTimerHandle xARPTimer, xPeriodicTimer;\r
+\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( uipEVENT_QUEUE_LENGTH, 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
+ ( 500 / 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
+ 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 prvEMACEventListener( unsigned long ulISREvents )\r
+{\r
+long lHigherPriorityTaskWoken = pdFALSE;\r
+unsigned long ulUIPEvents = 0UL;\r
+\r
+ configASSERT( xEMACEventQueue );\r
+\r
+ if( ( ulISREvents & MSS_MAC_EVENT_PACKET_SEND ) != 0UL )\r
+ {\r
+ /* Handle send event. */\r
+ ulUIPEvents |= uipETHERNET_TX_EVENT;\r
+ }\r
+\r
+ if( ( ulISREvents & MSS_MAC_EVENT_PACKET_RECEIVED ) != 0UL )\r
+ {\r
+ /* Wake the uIP task as new data has arrived. */\r
+ ulUIPEvents |= uipETHERNET_RX_EVENT;\r
+ xQueueSendFromISR( xEMACEventQueue, &ulUIPEvents, &lHigherPriorityTaskWoken );\r
+ }\r
+\r
+ portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvInitEmac( void )\r
+{\r
+unsigned long ulMACCfg;\r
+const unsigned char ucPHYAddress = 1;\r
+\r
+ MSS_MAC_init( ucPHYAddress );\r
+\r
+ MSS_MAC_set_callback( prvEMACEventListener );\r
+\r
+ /* Setup the EMAC and the NVIC for MAC interrupts. */\r
+ NVIC_SetPriority( EthernetMAC_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY );\r
+ NVIC_EnableIRQ( EthernetMAC_IRQn );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vEMACWrite( void )\r
+{\r
+ MSS_MAC_tx_packet( uip_buf, uip_len, 0 );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+unsigned long ulEMACRead( void )\r
+{\r
+ return MSS_MAC_rx_packet( &uip_buf, ( MSS_RX_BUFF_SIZE + 4 ), 0UL );\r
+}\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
+ 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