240 lines
6.0 KiB
C
240 lines
6.0 KiB
C
|
/*
|
||
|
* 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>
|
||
|
|
||
|
/* FreeRTOS includes. */
|
||
|
#include "FreeRTOS.h"
|
||
|
#include "task.h"
|
||
|
#include "queue.h"
|
||
|
|
||
|
/* FreeRTOS+TCP includes. */
|
||
|
#include "FreeRTOS_IP.h"
|
||
|
#include "FreeRTOS_Sockets.h"
|
||
|
#include "FreeRTOS_IP_Private.h"
|
||
|
#include "NetworkBufferManagement.h"
|
||
|
#include "NetworkInterface.h"
|
||
|
|
||
|
#include "Zynq/x_emacpsif.h"
|
||
|
|
||
|
extern TaskHandle_t xEMACTaskHandle;
|
||
|
|
||
|
/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c
|
||
|
*** to run it on a PEEP board
|
||
|
***/
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
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( );
|
||
|
}
|