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; + } +} +/*-----------------------------------------------------------*/