/* * Copyright (c) 2010-2013 Xilinx, Inc. All rights reserved. * * Xilinx, Inc. * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. * */ /* Standard includes. */ #include #include #include #include "x_emacpsif.h" /* FreeRTOS includes. */ #include "FreeRTOS.h" #include "task.h" #include "queue.h" ///* FreeRTOS+TCP includes. */ /* FreeRTOS+TCP includes. */ #include "include/FreeRTOS_IP.h" #include "include/FreeRTOS_Sockets.h" #include "include/FreeRTOS_IP_Private.h" #include "include/NetworkBufferManagement.h" extern TaskHandle_t xEMACTaskHandle; /*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c *** to run it on a PEEP board ***/ unsigned int link_speed = 100; extern const uint8_t ucMACAddress[ 6 ]; void setup_isr( xemacpsif_s *xemacpsif ) { /* * Setup callbacks */ XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMASEND, (void *) emacps_send_handler, (void *) xemacpsif); XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMARECV, (void *) emacps_recv_handler, (void *) xemacpsif); XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_ERROR, (void *) emacps_error_handler, (void *) xemacpsif); } void start_emacps (xemacpsif_s *xemacps) { /* start the temac */ XEmacPs_Start(&xemacps->emacps); } extern struct xtopology_t xXTopology; volatile int error_msg_count = 0; volatile const char *last_err_msg = ""; struct xERROR_MSG { void *arg; u8 Direction; u32 ErrorWord; }; static struct xERROR_MSG xErrorList[ 8 ]; static BaseType_t xErrorHead, xErrorTail; void emacps_error_handler(void *arg, u8 Direction, u32 ErrorWord) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; xemacpsif_s *xemacpsif; BaseType_t xNextHead = xErrorHead; xemacpsif = (xemacpsif_s *)(arg); if( ( Direction != XEMACPS_SEND ) || (ErrorWord != XEMACPS_TXSR_USEDREAD_MASK ) ) { if( ++xNextHead == ( sizeof( xErrorList ) / sizeof( xErrorList[ 0 ] ) ) ) xNextHead = 0; if( xNextHead != xErrorTail ) { xErrorList[ xErrorHead ].arg = arg; xErrorList[ xErrorHead ].Direction = Direction; xErrorList[ xErrorHead ].ErrorWord = ErrorWord; xErrorHead = xNextHead; xemacpsif = (xemacpsif_s *)(arg); xemacpsif->isr_events |= EMAC_IF_ERR_EVENT; } if( xEMACTaskHandle != NULL ) { vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken ); } } portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); } static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord); int emacps_check_errors( xemacpsif_s *xemacps ) { int xResult; ( void ) xemacps; if( xErrorHead == xErrorTail ) { xResult = 0; } else { xResult = 1; emacps_handle_error( xErrorList[ xErrorTail ].arg, xErrorList[ xErrorTail ].Direction, xErrorList[ xErrorTail ].ErrorWord ); } return xResult; } BaseType_t xNetworkInterfaceInitialise( void ); static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord) { xemacpsif_s *xemacpsif; struct xtopology_t *xtopologyp; XEmacPs *xemacps; xemacpsif = (xemacpsif_s *)(arg); xtopologyp = &xXTopology; xemacps = &xemacpsif->emacps; /* Do not appear to be used. */ ( void ) xemacps; ( void ) xtopologyp; last_err_msg = NULL; if( ErrorWord != 0 ) { switch (Direction) { case XEMACPS_RECV: if( ( ErrorWord & XEMACPS_RXSR_HRESPNOK_MASK ) != 0 ) { last_err_msg = "Receive DMA error"; xNetworkInterfaceInitialise( ); } if( ( ErrorWord & XEMACPS_RXSR_RXOVR_MASK ) != 0 ) { last_err_msg = "Receive over run"; emacps_recv_handler(arg); } if( ( ErrorWord & XEMACPS_RXSR_BUFFNA_MASK ) != 0 ) { last_err_msg = "Receive buffer not available"; emacps_recv_handler(arg); } break; case XEMACPS_SEND: if( ( ErrorWord & XEMACPS_TXSR_HRESPNOK_MASK ) != 0 ) { last_err_msg = "Transmit DMA error"; xNetworkInterfaceInitialise( ); } if( ( ErrorWord & XEMACPS_TXSR_URUN_MASK ) != 0 ) { last_err_msg = "Transmit under run"; HandleTxErrors( xemacpsif ); } if( ( ErrorWord & XEMACPS_TXSR_BUFEXH_MASK ) != 0 ) { last_err_msg = "Transmit buffer exhausted"; HandleTxErrors( xemacpsif ); } if( ( ErrorWord & XEMACPS_TXSR_RXOVR_MASK ) != 0 ) { last_err_msg = "Transmit retry excessed limits"; HandleTxErrors( xemacpsif ); } if( ( ErrorWord & XEMACPS_TXSR_FRAMERX_MASK ) != 0 ) { last_err_msg = "Transmit collision"; emacps_check_tx( xemacpsif ); } break; } } // Break on this statement and inspect error_msg if you like if( last_err_msg != NULL ) { error_msg_count++; FreeRTOS_printf( ( "emacps_handle_error: %s\n", last_err_msg ) ); } } extern XEmacPs_Config mac_config; void HandleTxErrors(xemacpsif_s *xemacpsif) { u32 netctrlreg; //taskENTER_CRITICAL() { netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET); netctrlreg = netctrlreg & (~XEMACPS_NWCTRL_TXEN_MASK); XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, netctrlreg); clean_dma_txdescs( xemacpsif ); netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET); netctrlreg = netctrlreg | (XEMACPS_NWCTRL_TXEN_MASK); XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, netctrlreg); } //taskEXIT_CRITICAL( ); }