From: richardbarry Date: Sun, 17 Apr 2011 14:38:50 +0000 (+0000) Subject: Continue work on the SmartFusion demo web interface. The uIP task has been updated... X-Git-Tag: V7.0.1~61 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=333d16606ce631af1006c64e6ab5f6fc25fa75c7;p=freertos Continue work on the SmartFusion demo web interface. The uIP task has been updated to use software timers, and the mac interface updated to use vTaskDelay() in place of busy waits. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@1363 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- diff --git a/Demo/CORTEX_A2F200_SoftConsole/MicroSemi_Code/drivers/mss_ethernet_mac/mss_ethernet_mac.c b/Demo/CORTEX_A2F200_SoftConsole/MicroSemi_Code/drivers/mss_ethernet_mac/mss_ethernet_mac.c index 42214d835..014ce512c 100644 --- a/Demo/CORTEX_A2F200_SoftConsole/MicroSemi_Code/drivers/mss_ethernet_mac/mss_ethernet_mac.c +++ b/Demo/CORTEX_A2F200_SoftConsole/MicroSemi_Code/drivers/mss_ethernet_mac/mss_ethernet_mac.c @@ -14,6 +14,7 @@ extern "C" { #endif #include "FreeRTOS.h" +#include "task.h" #include "crc32.h" @@ -111,16 +112,15 @@ MSS_MAC_init ) { const uint8_t mac_address[6] = { DEFAULT_MAC_ADDRESS }; - int32_t a; /* Try to reset chip */ MAC_BITBAND->CSR0_SWR = 1u; - - while ( 1u == MAC_BITBAND->CSR0_SWR ) + + do { - ; - } + vTaskDelay( 10 ); + } while ( 1u == MAC_BITBAND->CSR0_SWR ); /* Check reset values of some registers to constrol * base address validity */ @@ -145,7 +145,7 @@ MSS_MAC_init for( a = 0; a < TX_RING_SIZE; a++ ) { - g_mss_mac.tx_descriptors[a].buffer_1 = (uint32_t)g_mss_mac.tx_buffers[a]; + g_mss_mac.tx_descriptors[a].buffer_1 = ( unsigned long ) NULL; /* _RB_ used to be "(uint32_t)g_mss_mac.tx_buffers[a];" but set to NULL now to implement a zero copy scheme. */ } g_mss_mac.tx_descriptors[TX_RING_SIZE - 1].descriptor_1 |= TDES1_TER; @@ -197,11 +197,7 @@ MSS_MAC_init /* Set default MAC address and reset mac filters */ MAC_memcpy( g_mss_mac.mac_address, mac_address, 6u ); MSS_MAC_set_mac_filters( 0u, NULL_buffer ); - - - /* Start receiving and transmission */ - MAC_start_receiving(); - MAC_start_transmission(); + MAC_BITBAND->CSR6_RA = 1; /* Receive all. */ } @@ -266,9 +262,6 @@ MSS_MAC_configure ((((configuration & MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE) != 0u) ? MSS_MAC_LINK_STATUS_100MB : 0u ) | (((configuration & MSS_MAC_CFG_FULL_DUPLEX_MODE) != 0u) ? MSS_MAC_LINK_STATUS_FDX : 0u )) ); - MAC_start_transmission(); - MAC_start_receiving(); - MSS_MAC_auto_setup_link(); } @@ -460,10 +453,8 @@ MSS_MAC_tx_packet { pacLen = (uint16_t)MSS_TX_BUFF_SIZE; } - MAC_memcpy( - (uint8_t*) - g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].buffer_1, - pacData, (uint32_t)pacLen ); + + g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].buffer_1 = ( unsigned long ) pacData; /* update counters */ desc = g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0; diff --git a/Demo/CORTEX_A2F200_SoftConsole/MicroSemi_Code/drivers/mss_ethernet_mac/phy.c b/Demo/CORTEX_A2F200_SoftConsole/MicroSemi_Code/drivers/mss_ethernet_mac/phy.c index dd1ca43b5..9fb08984a 100644 --- a/Demo/CORTEX_A2F200_SoftConsole/MicroSemi_Code/drivers/mss_ethernet_mac/phy.c +++ b/Demo/CORTEX_A2F200_SoftConsole/MicroSemi_Code/drivers/mss_ethernet_mac/phy.c @@ -20,6 +20,9 @@ extern "C" { #include "phy.h" +#include "FreeRTOS.h" +#include "task.h" + extern MAC_instance_t g_mss_mac; /***************************** MDIO FUNCTIONS *********************************/ @@ -267,7 +270,6 @@ void PHY_auto_negotiate( void ) { int32_t a; uint16_t reg; - int32_t exit = 1; reg = MDIO_read( PHYREG_MIIMCR ); MDIO_write( PHYREG_MIIMCR, @@ -275,10 +277,12 @@ void PHY_auto_negotiate( void ) MIIMCR_RESTART_AUTONEGOTIATION | reg) ); - for(a=0; (a<1000) && (exit); a++) { + for( ;; ) { reg = MDIO_read( PHYREG_MIIMSR ); if( (reg & MIIMSR_ANC) != 0 ) { - exit = 0; + break; + } else { + vTaskDelay( 200 ); } } } diff --git a/Demo/CORTEX_A2F200_SoftConsole/main-full.c b/Demo/CORTEX_A2F200_SoftConsole/main-full.c index 06e48c471..0fcf07046 100644 --- a/Demo/CORTEX_A2F200_SoftConsole/main-full.c +++ b/Demo/CORTEX_A2F200_SoftConsole/main-full.c @@ -445,10 +445,6 @@ static void prvSetupHardware( void ) NVIC_EnableIRQ( GPIO8_IRQn ); MSS_GPIO_config( MSS_GPIO_8, MSS_GPIO_INPUT_MODE | MSS_GPIO_IRQ_EDGE_NEGATIVE ); MSS_GPIO_enable_irq( MSS_GPIO_8 ); - - /* Setup the EMAC and the NVIC for MAC interrupts. */ - NVIC_SetPriority( EthernetMAC_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); - NVIC_EnableIRQ( EthernetMAC_IRQn ); } /*-----------------------------------------------------------*/ diff --git a/Demo/CORTEX_A2F200_SoftConsole/uIP_Task.c b/Demo/CORTEX_A2F200_SoftConsole/uIP_Task.c index 73ed4eefe..41c4b02a7 100644 --- a/Demo/CORTEX_A2F200_SoftConsole/uIP_Task.c +++ b/Demo/CORTEX_A2F200_SoftConsole/uIP_Task.c @@ -57,7 +57,8 @@ /* Scheduler includes. */ #include "FreeRTOS.h" #include "task.h" -#include "semphr.h" +#include "queue.h" +#include "timers.h" /* uip includes. */ #include "net/uip.h" @@ -69,7 +70,28 @@ /* Demo includes. */ #include "ParTest.h" -#include "EMAC.h" +/* Hardware driver includes. */ +#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. */ +unsigned char *uip_buf = NULL; + +static const unsigned char ucMACAddress[] = { configMAC_ADDR0, configMAC_ADDR1, configMAC_ADDR2, configMAC_ADDR3, configMAC_ADDR4, configMAC_ADDR5 }; + +#define uipARP_TIMER 0 +#define uipPERIODIC_TIMER 1 + +#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 + +#define uipDONT_BLOCK 0UL /*-----------------------------------------------------------*/ @@ -89,6 +111,29 @@ */ static void prvSetMACAddress( void ); +/* + * Perform any uIP initialisation required to ready the stack for http + * processing. + */ +static void prvInitialise_uIP( void ); + +/* + * Handles Ethernet interrupt events. + */ +static void prvEMACEventListener( unsigned long ulISREvents ); + +static void prvUIPTimerCallback( xTimerHandle xTimer ); + +/* + * Initialise the MAC hardware. + */ +static void prvInitEmac( void ); + +void vEMACWrite( void ); + +unsigned long ulEMACRead( void ); +long lEMACWaitForLink( void ); + /* * Port functions required by the uIP stack. */ @@ -97,8 +142,10 @@ clock_time_t clock_time( void ); /*-----------------------------------------------------------*/ -/* The semaphore used by the ISR to wake the uIP task. */ -xSemaphoreHandle xEMACSemaphore = NULL; +/* The queue used to send TCP/IP events to the uIP stack. */ +xQueueHandle xEMACEventQueue = NULL; + +static unsigned long ulUIP_Events = 0UL; /*-----------------------------------------------------------*/ @@ -117,32 +164,15 @@ clock_time_t clock_time( void ) void vuIP_Task( void *pvParameters ) { portBASE_TYPE i, xDoneSomething; -uip_ipaddr_t xIPAddr; -struct timer periodic_timer, arp_timer; +unsigned long ulNewEvent; ( void ) pvParameters; - /* Initialise the uIP stack. */ - timer_set( &periodic_timer, configTICK_RATE_HZ / 2 ); - timer_set( &arp_timer, configTICK_RATE_HZ * 10 ); - uip_init(); - uip_ipaddr( &xIPAddr, configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3 ); - uip_sethostaddr( &xIPAddr ); - uip_ipaddr( &xIPAddr, configNET_MASK0, configNET_MASK1, configNET_MASK2, configNET_MASK3 ); - uip_setnetmask( &xIPAddr ); - prvSetMACAddress(); - httpd_init(); - - /* Create the semaphore used to wake the uIP task. */ - vSemaphoreCreateBinary( xEMACSemaphore ); + /* Initialise the uIP stack, configuring for web server usage. */ + prvInitialise_uIP(); /* Initialise the MAC. */ - vInitEmac(); - - while( lEMACWaitForLink() != pdPASS ) - { - vTaskDelay( uipINIT_WAIT ); - } + prvInitEmac(); for( ;; ) { @@ -186,9 +216,10 @@ struct timer periodic_timer, arp_timer; } } - if( timer_expired( &periodic_timer ) && ( uip_buf != NULL ) ) + if( ( ( ulUIP_Events & uipPERIODIC_TIMER_EVENT ) != 0UL ) && ( uip_buf != NULL ) ) { - timer_reset( &periodic_timer ); + ulUIP_Events &= ~uipPERIODIC_TIMER_EVENT; + for( i = 0; i < UIP_CONNS; i++ ) { uip_periodic( i ); @@ -204,9 +235,9 @@ struct timer periodic_timer, arp_timer; } /* Call the ARP timer function every 10 seconds. */ - if( timer_expired( &arp_timer ) ) + if( ( ulUIP_Events & uipARP_TIMER_EVENT ) != 0 ) { - timer_reset( &arp_timer ); + ulUIP_Events &= ~uipARP_TIMER_EVENT; uip_arp_timer(); } @@ -215,11 +246,8 @@ struct timer periodic_timer, arp_timer; if( xDoneSomething == pdFALSE ) { - /* We did not receive a packet, and there was no periodic - processing to perform. Block for a fixed period. If a packet - is received during this period we will be woken by the ISR - giving us the Semaphore. */ - xSemaphoreTake( xEMACSemaphore, configTICK_RATE_HZ / 20 ); + xQueueReceive( xEMACEventQueue, &ulNewEvent, portMAX_DELAY ); + ulUIP_Events |= ulNewEvent; } } } @@ -281,4 +309,130 @@ char *c; } } } +/*-----------------------------------------------------------*/ + +static void prvInitialise_uIP( void ) +{ +uip_ipaddr_t xIPAddr; +xTimerHandle xARPTimer, xPeriodicTimer; + + uip_init(); + uip_ipaddr( &xIPAddr, configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3 ); + uip_sethostaddr( &xIPAddr ); + uip_ipaddr( &xIPAddr, configNET_MASK0, configNET_MASK1, configNET_MASK2, configNET_MASK3 ); + uip_setnetmask( &xIPAddr ); + prvSetMACAddress(); + httpd_init(); + + /* Create the queue used to sent TCP/IP events to the uIP stack. */ + xEMACEventQueue = xQueueCreate( uipEVENT_QUEUE_LENGTH, sizeof( unsigned long ) ); + + /* 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. */ + pdTRUE, /* Autor-reload. */ + ( void * ) uipARP_TIMER, + prvUIPTimerCallback + ); + + xPeriodicTimer = xTimerCreate( ( const signed char * const ) "PeriodicTimer", + ( 5000 / portTICK_RATE_MS ), + pdTRUE, /* Autor-reload. */ + ( void * ) uipPERIODIC_TIMER, + prvUIPTimerCallback + ); + + configASSERT( xARPTimer ); + configASSERT( xPeriodicTimer ); + + xTimerStart( xARPTimer, portMAX_DELAY ); + xTimerStart( xPeriodicTimer, portMAX_DELAY ); +} +/*-----------------------------------------------------------*/ + +static void prvEMACEventListener( unsigned long ulISREvents ) +{ +long lHigherPriorityTaskWoken = pdFALSE; +unsigned long ulUIPEvents = 0UL; + + configASSERT( xEMACEventQueue ); + + if( ( ulISREvents & MSS_MAC_EVENT_PACKET_SEND ) != 0UL ) + { + /* Handle send event. */ + ulUIPEvents |= uipETHERNET_TX_EVENT; + } + + if( ( ulISREvents & MSS_MAC_EVENT_PACKET_RECEIVED ) != 0UL ) + { + /* Wake the uIP task as new data has arrived. */ + ulUIPEvents |= uipETHERNET_RX_EVENT; + xQueueSendFromISR( xEMACEventQueue, &ulUIPEvents, &lHigherPriorityTaskWoken ); + } + + portEND_SWITCHING_ISR( lHigherPriorityTaskWoken ); +} +/*-----------------------------------------------------------*/ + +static void prvInitEmac( void ) +{ +unsigned long ulMACCfg; +const unsigned char ucPHYAddress = 1; + + MSS_MAC_init( ucPHYAddress ); + + MSS_MAC_set_callback( prvEMACEventListener ); + + /* Setup the EMAC and the NVIC for MAC interrupts. */ + NVIC_SetPriority( EthernetMAC_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); + NVIC_EnableIRQ( EthernetMAC_IRQn ); +} +/*-----------------------------------------------------------*/ + +void vEMACWrite( void ) +{ + MSS_MAC_tx_packet( uip_buf, uip_len, 0 ); +} +/*-----------------------------------------------------------*/ + +unsigned long ulEMACRead( void ) +{ + return MSS_MAC_rx_packet( &uip_buf, ( MSS_RX_BUFF_SIZE + 4 ), 0UL ); +} +/*-----------------------------------------------------------*/ + +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. */ + switch( ( int ) pvTimerGetTimerID( xTimer ) ) + { + case uipARP_TIMER : xQueueSend( xEMACEventQueue, &ulARPTimerExpired, uipDONT_BLOCK ); + break; + + case uipPERIODIC_TIMER : xQueueSend( xEMACEventQueue, &ulPeriodicTimerExpired, uipDONT_BLOCK ); + break; + + default : /* Should not get here. */ + break; + } +} +/*-----------------------------------------------------------*/