From b93d1f6a67679e0074d09550447e9f13ba2c080f Mon Sep 17 00:00:00 2001 From: richardbarry Date: Wed, 27 Jul 2011 16:52:32 +0000 Subject: [PATCH] git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@1518 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- .../MicroBlaze-Ethernet-Lite/ethernetif.c | 242 +++++++++++++++--- .../ports/MicroBlaze-Ethernet-Lite/sys_arch.c | 53 +++- 2 files changed, 257 insertions(+), 38 deletions(-) diff --git a/Demo/Common/ethernet/lwip-1.4.0/ports/MicroBlaze-Ethernet-Lite/ethernetif.c b/Demo/Common/ethernet/lwip-1.4.0/ports/MicroBlaze-Ethernet-Lite/ethernetif.c index edcfa0de4..f7f6913ba 100644 --- a/Demo/Common/ethernet/lwip-1.4.0/ports/MicroBlaze-Ethernet-Lite/ethernetif.c +++ b/Demo/Common/ethernet/lwip-1.4.0/ports/MicroBlaze-Ethernet-Lite/ethernetif.c @@ -58,6 +58,7 @@ /* BSP includes. */ #include "xemaclite.h" +#include "xintc_l.h" /* lwIP includes. */ #include "lwip/opt.h" @@ -73,6 +74,14 @@ #define IFNAME0 'e' #define IFNAME1 'l' +/* When a packet is ready to be sent, if it cannot be sent immediately then + * the task performing the transmit will block for netifTX_BUFFER_FREE_WAIT + * milliseconds. It will do this a maximum of netifMAX_TX_ATTEMPTS before + * giving up. + */ +#define netifTX_BUFFER_FREE_WAIT ( ( portTickType ) 5UL / portTICK_RATE_MS ) +#define netifMAX_TX_ATTEMPTS ( 5 ) + #define netifMAX_MTU 1500 struct xEthernetIf @@ -90,7 +99,7 @@ static void prvEthernetInput( struct netif *pxNetIf, const unsigned char * const /* * Copy the received data into a pbuf. */ -static struct pbuf *prvLowLevelInput( const unsigned char * const pucInputData, long lDataLength ); +static struct pbuf *prvLowLevelInput( const unsigned char * const pucInputData, unsigned short usDataLength ); /* * Send data from a pbuf to the hardware. @@ -102,6 +111,19 @@ static err_t prvLowLevelOutput( struct netif *pxNetIf, struct pbuf *p ); */ static void prvLowLevelInit( struct netif *pxNetIf ); +/* + * Functions that get registered as the Rx and Tx interrupt handers + * respectively. + */ +static void prvRxHandler( void *pvNetIf ); +static void prvTxHandler( void *pvUnused ); + + +/*-----------------------------------------------------------*/ + +/* The instance of the xEmacLite IP being used in this driver. */ +static XEmacLite xEMACInstance; + /*-----------------------------------------------------------*/ /** @@ -113,6 +135,8 @@ static void prvLowLevelInit( struct netif *pxNetIf ); */ static void prvLowLevelInit( struct netif *pxNetIf ) { +portBASE_TYPE xStatus; + /* set MAC hardware address length */ pxNetIf->hwaddr_len = ETHARP_HWADDR_LEN; @@ -125,30 +149,44 @@ static void prvLowLevelInit( struct netif *pxNetIf ) pxNetIf->hwaddr[ 5 ] = configMAC_ADDR5; /* device capabilities */ - /* don't set pxNetIf_FLAG_ETHARP if this device is not an ethernet one */ pxNetIf->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; -#if 0 -_RB_ - - /* Query the computer the simulation is being executed on to find the - network interfaces it has installed. */ - pxAllNetworkInterfaces = prvPrintAvailableNetworkInterfaces(); - - /* Open the network interface. The number of the interface to be opened is - set by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h. - Calling this function will set the pxOpenedInterfaceHandle variable. If, - after calling this function, pxOpenedInterfaceHandle is equal to NULL, then - the interface could not be opened. */ - if( pxAllNetworkInterfaces != NULL ) + /* maximum transfer unit */ + pxNetIf->mtu = netifMAX_MTU; + + /* Broadcast capability */ + pxNetIf->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; + + /* Initialize the mac */ + xStatus = XEmacLite_Initialize( &xEMACInstance, XPAR_EMACLITE_0_DEVICE_ID ); + + if( xStatus == XST_SUCCESS ) { - prvOpenSelectedNetworkInterface( pxAllNetworkInterfaces ); + /* Set mac address */ + XEmacLite_SetMacAddress( &xEMACInstance, ( Xuint8* )( pxNetIf->hwaddr ) ); + + /* Flush any frames already received */ + XEmacLite_FlushReceive( &xEMACInstance ); + + /* Set Rx, Tx interrupt handlers */ + XEmacLite_SetRecvHandler( &xEMACInstance, ( void * ) pxNetIf, prvRxHandler ); + XEmacLite_SetSendHandler( &xEMACInstance, NULL, prvTxHandler ); + + /* Enable Rx, Tx interrupts */ + XEmacLite_EnableInterrupts( &xEMACInstance ); + + /* Install the standard Xilinx library interrupt handler itself. + *NOTE* The xPortInstallInterruptHandler() API function must be used + for this purpose. */ + xStatus = xPortInstallInterruptHandler( XPAR_INTC_0_EMACLITE_0_VEC_ID, ( XInterruptHandler ) XEmacLite_InterruptHandler, &xEMACInstance ); + + /* Enable the interrupt in the interrupt controller. + *NOTE* The vPortEnableInterrupt() API function must be used for this + purpose. */ + vPortEnableInterrupt( XPAR_INTC_0_EMACLITE_0_VEC_ID ); } - /* Remember which interface was opened as it is used in the interrupt - simulator task. */ - pxlwIPNetIf = pxNetIf; -#endif + configASSERT( xStatus == pdPASS ); } /** @@ -174,12 +212,13 @@ static err_t prvLowLevelOutput( struct netif *pxNetIf, struct pbuf *p ) to the FreeRTOS coding standard. */ struct pbuf *q; -static unsigned char ucBuffer[ 1520 ]; +static unsigned char ucBuffer[ 1520 ] __attribute__((aligned(32))); unsigned char *pucBuffer = ucBuffer; unsigned char *pucChar; struct eth_hdr *pxHeader; u16_t usTotalLength = p->tot_len - ETH_PAD_SIZE; err_t xReturn = ERR_OK; +long x; #if defined(LWIP_DEBUG) && LWIP_NETIF_TX_SINGLE_PBUF LWIP_ASSERT("p->next == NULL && p->len == p->tot_len", p->next == NULL && p->len == p->tot_len); @@ -211,7 +250,7 @@ err_t xReturn = ERR_OK; time. The size of the data in each pbuf is kept in the ->len variable. */ /* send data from(q->payload, q->len); */ - LWIP_DEBUGF( NETIF_DEBUG, ("NETIF: send pucChar %p q->payload %p q->len %i q->next %p\n", pucChar, q->payload, ( int ) q->len, ( void* ) q->next ) ); + LWIP_DEBUGF( NETIF_DEBUG, ( "NETIF: send pucChar %p q->payload %p q->len %i q->next %p\n", pucChar, q->payload, ( int ) q->len, ( void* ) q->next ) ); if( q == p ) { memcpy( pucChar, &( ( char * ) q->payload )[ ETH_PAD_SIZE ], q->len - ETH_PAD_SIZE ); @@ -228,10 +267,20 @@ err_t xReturn = ERR_OK; if( xReturn == ERR_OK ) { -#if 0 -_RB_ - /* signal that packet should be sent */ - if( pcap_sendpacket( pxOpenedInterfaceHandle, pucBuffer, usTotalLength ) < 0 ) + for( x = 0; x < netifMAX_TX_ATTEMPTS; x++ ) + { + xReturn = XEmacLite_Send( &xEMACInstance, pucBuffer, ( int ) usTotalLength ); + if( xReturn == XST_SUCCESS ) + { + break; + } + else + { + vTaskDelay( netifTX_BUFFER_FREE_WAIT ); + } + } + + if( xReturn != XST_SUCCESS ) { LINK_STATS_INC( link.memerr ); LINK_STATS_INC( link.drop ); @@ -255,7 +304,6 @@ _RB_ snmp_inc_ifoutucastpkts( pxNetIf ); } } -#endif } return xReturn; @@ -269,18 +317,18 @@ _RB_ * @return a pbuf filled with the received packet (including MAC header) * NULL on memory error */ -static struct pbuf *prvLowLevelInput( const unsigned char * const pucInputData, long lDataLength ) +static struct pbuf *prvLowLevelInput( const unsigned char * const pucInputData, unsigned short usDataLength ) { struct pbuf *p = NULL, *q; - if( lDataLength > 0 ) + if( usDataLength > 0U ) { #if ETH_PAD_SIZE len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ #endif /* We allocate a pbuf chain of pbufs from the pool. */ - p = pbuf_alloc( PBUF_RAW, lDataLength, PBUF_POOL ); + p = pbuf_alloc( PBUF_RAW, usDataLength, PBUF_POOL ); if( p != NULL ) { @@ -290,7 +338,7 @@ struct pbuf *p = NULL, *q; /* We iterate over the pbuf chain until we have read the entire * packet into the pbuf. */ - lDataLength = 0; + usDataLength = 0U; for( q = p; q != NULL; q = q->next ) { /* Read enough bytes to fill this pbuf in the chain. The @@ -301,8 +349,8 @@ struct pbuf *p = NULL, *q; * actually received size. In this case, ensure the usTotalLength member of the * pbuf is the sum of the chained pbuf len members. */ - memcpy( q->payload, &( pucInputData[ lDataLength ] ), q->len ); - lDataLength += q->len; + memcpy( q->payload, &( pucInputData[ usDataLength ] ), q->len ); + usDataLength += q->len; } #if ETH_PAD_SIZE @@ -425,3 +473,131 @@ struct xEthernetIf *pxEthernetIf; return xReturn; } /*-----------------------------------------------------------*/ + +static void prvRxHandler( void *pvNetIf ) +{ + /* This is taken from lwIP example code and therefore does not conform + to the FreeRTOS coding standard. */ + +struct eth_hdr *pxHeader; +struct pbuf *p; +unsigned short usInputLength; +static unsigned char ucBuffer[ 1520 ] __attribute__((aligned(32))); +extern portBASE_TYPE xInsideISR; +struct netif *pxNetIf = ( struct netif * ) pvNetIf; + + XIntc_AckIntr( XPAR_ETHERNET_LITE_BASEADDR, XPAR_ETHERNET_LITE_IP2INTC_IRPT_MASK ); + + /* Ensure the pbuf handling functions don't attempt to use critical + sections. */ + xInsideISR++; + + usInputLength = ( long ) XEmacLite_Recv( &xEMACInstance, ucBuffer ); + + /* move received packet into a new pbuf */ + p = prvLowLevelInput( ucBuffer, usInputLength ); + + /* no packet could be read, silently ignore this */ + if( p != NULL ) + { + /* points to packet payload, which starts with an Ethernet header */ + pxHeader = p->payload; + + switch( htons( pxHeader->type ) ) + { + /* IP or ARP packet? */ + case ETHTYPE_IP: + case ETHTYPE_ARP: + /* full packet send to tcpip_thread to process */ + if( pxNetIf->input( p, pxNetIf ) != ERR_OK ) + { + LWIP_DEBUGF(NETIF_DEBUG, ( "ethernetif_input: IP input error\n" ) ); + pbuf_free(p); + p = NULL; + } + break; + + default: + pbuf_free( p ); + p = NULL; + break; + } + } + + xInsideISR--; +} +/*-----------------------------------------------------------*/ + +static void prvTxHandler( void *pvUnused ) +{ + XIntc_AckIntr( XPAR_ETHERNET_LITE_BASEADDR, XPAR_ETHERNET_LITE_IP2INTC_IRPT_MASK ); +} + + +void vTemp( void ) +{ +char *pc; + + XEmacLite_Recv( &xEMACInstance, pc ); +} + + + + + + +#if 0 + +static void +xemacif_recv_handler(void *arg) { + struct xemac_s *xemac = (struct xemac_s *)(arg); + xemacliteif_s *xemacliteif = (xemacliteif_s *)(xemac->state); + XEmacLite *instance = xemacliteif->instance; + struct pbuf *p; + int len = 0; + struct xtopology_t *xtopologyp = &xtopology[xemac->topology_index]; + + XIntc_AckIntr(xtopologyp->intc_baseaddr, 1 << xtopologyp->intc_emac_intr); + p = pbuf_alloc(PBUF_RAW, XEL_MAX_FRAME_SIZE, PBUF_POOL); + if (!p) { +#if LINK_STATS + lwip_stats.link.memerr++; + lwip_stats.link.drop++; +#endif + /* receive and just ignore the frame. + * we need to receive the frame because otherwise emaclite will + * not generate any other interrupts since it cannot receive, + * and we do not actively poll the emaclite + */ + XEmacLite_Recv(instance, xemac_tx_frame); + return; + } + + /* receive the packet */ + len = XEmacLite_Recv(instance, p->payload); + + if (len == 0) { +#if LINK_STATS + lwip_stats.link.drop++; +#endif + return; + } + + /* store it in the receive queue, where it'll be processed by xemacif input thread */ + if (pq_enqueue(xemacliteif->recv_q, (void*)p) < 0) { +#if LINK_STATS + lwip_stats.link.memerr++; + lwip_stats.link.drop++; +#endif + return; + } + +#if !NO_SYS + sys_sem_signal(xemac->sem_rx_data_available); +#endif + +} + +#endif + + diff --git a/Demo/Common/ethernet/lwip-1.4.0/ports/MicroBlaze-Ethernet-Lite/sys_arch.c b/Demo/Common/ethernet/lwip-1.4.0/ports/MicroBlaze-Ethernet-Lite/sys_arch.c index 1859a3186..3c5bcba1b 100644 --- a/Demo/Common/ethernet/lwip-1.4.0/ports/MicroBlaze-Ethernet-Lite/sys_arch.c +++ b/Demo/Common/ethernet/lwip-1.4.0/ports/MicroBlaze-Ethernet-Lite/sys_arch.c @@ -48,6 +48,11 @@ #include "lwip/mem.h" #include "lwip/stats.h" +/* Very crude mechanism used to determine if the critical section handling +functions are being called from an interrupt context or not. This relies on +the interrupt handler setting this variable manually. */ +portBASE_TYPE xInsideISR = pdFALSE; + /*---------------------------------------------------------------------------* * Routine: sys_mbox_new *---------------------------------------------------------------------------* @@ -141,8 +146,18 @@ void sys_mbox_post( sys_mbox_t *pxMailBox, void *pxMessageToPost ) err_t sys_mbox_trypost( sys_mbox_t *pxMailBox, void *pxMessageToPost ) { err_t xReturn; +portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + + if( xInsideISR != pdFALSE ) + { + xReturn = xQueueSendFromISR( *pxMailBox, &pxMessageToPost, &xHigherPriorityTaskWoken ); + } + else + { + xReturn = xQueueSend( *pxMailBox, &pxMessageToPost, ( portTickType ) 0 ); + } - if( xQueueSend( *pxMailBox, &pxMessageToPost, 0UL ) == pdPASS ) + if( xReturn == pdPASS ) { xReturn = ERR_OK; } @@ -200,6 +215,8 @@ unsigned long ulReturn; if( ulTimeOut != 0UL ) { + configASSERT( xInsideISR == ( portBASE_TYPE ) 0 ); + if( pdTRUE == xQueueReceive( *pxMailBox, &( *ppvBuffer ), ulTimeOut/ portTICK_RATE_MS ) ) { xEndTime = xTaskGetTickCount(); @@ -249,13 +266,24 @@ u32_t sys_arch_mbox_tryfetch( sys_mbox_t *pxMailBox, void **ppvBuffer ) { void *pvDummy; unsigned long ulReturn; +long lResult; +portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; if( ppvBuffer== NULL ) { ppvBuffer = &pvDummy; } - if( pdTRUE == xQueueReceive( *pxMailBox, &( *ppvBuffer ), 0UL ) ) + if( xInsideISR != pdFALSE ) + { + lResult = xQueueReceiveFromISR( *pxMailBox, &( *ppvBuffer ), &xHigherPriorityTaskWoken ); + } + else + { + lResult = xQueueReceive( *pxMailBox, &( *ppvBuffer ), 0UL ); + } + + if( lResult == pdPASS ) { ulReturn = ERR_OK; } @@ -441,7 +469,16 @@ void sys_mutex_free( sys_mutex_t *pxMutex ) *---------------------------------------------------------------------------*/ void sys_sem_signal( sys_sem_t *pxSemaphore ) { - xSemaphoreGive( *pxSemaphore ); +portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + + if( xInsideISR != pdFALSE ) + { + xSemaphoreGiveFromISR( *pxSemaphore, &xHigherPriorityTaskWoken ); + } + else + { + xSemaphoreGive( *pxSemaphore ); + } } /*---------------------------------------------------------------------------* @@ -537,7 +574,10 @@ sys_thread_t xReturn; *---------------------------------------------------------------------------*/ sys_prot_t sys_arch_protect( void ) { - taskENTER_CRITICAL(); + if( xInsideISR == pdFALSE ) + { + taskENTER_CRITICAL(); + } return ( sys_prot_t ) 1; } @@ -555,7 +595,10 @@ sys_prot_t sys_arch_protect( void ) void sys_arch_unprotect( sys_prot_t xValue ) { (void) xValue; - taskEXIT_CRITICAL(); + if( xInsideISR == pdFALSE ) + { + taskEXIT_CRITICAL(); + } } /* -- 2.39.5