/* | |
* 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 <stdint.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include "Zynq/x_emacpsif.h" | |
/* FreeRTOS includes. */ | |
#include "FreeRTOS.h" | |
#include "task.h" | |
#include "queue.h" | |
///* FreeRTOS+TCP includes. */ | |
/* FreeRTOS+TCP includes. */ | |
#include "FreeRTOS_IP.h" | |
#include "FreeRTOS_Sockets.h" | |
#include "FreeRTOS_IP_Private.h" | |
#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; | |
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( ); | |
} |