You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
FreeRTOS/Demo/ColdFire_MCF52233_Eclipse/RTOSDemo/webserver/FEC.c

656 lines
20 KiB
C

/*
FreeRTOS.org V5.1.0 - Copyright (C) 2003-2008 Richard Barry.
This file is part of the FreeRTOS.org distribution.
FreeRTOS.org is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
FreeRTOS.org is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FreeRTOS.org; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes FreeRTOS.org, without being obliged to provide
the source code for any proprietary components. See the licensing section
of http://www.FreeRTOS.org for full details of how and when the exception
can be applied.
***************************************************************************
See http://www.FreeRTOS.org for documentation, latest information, license
and contact details. Please ensure to read the configuration and relevant
port sections of the online documentation.
***************************************************************************
*/
/* Kernel includes. */
#include "FreeRTOS.h"
#include "semphr.h"
#include "task.h"
/* Demo includes. */
#include "fecbd.h"
#include "mii.h"
#include "eth_phy.h"
#include "eth.h"
/* uIP includes. */
#include "uip.h"
#include "uip_arp.h"
#define MCF_FEC_MSCR_MII_SPEED(x) (((x)&0x3F)<<0x1)
#define MCF_FEC_RCR_MAX_FL(x) (((x)&0x7FF)<<0x10)
/* Delay between polling the PHY to see if a link has been established. */
#define fecLINK_DELAY ( 500 / portTICK_RATE_MS )
/* Delay to wait for an MII access. */
#define fecMII_DELAY ( 10 / portTICK_RATE_MS )
#define fecMAX_POLLS ( 20 )
/* Delay between looking for incoming packets. In ideal world this would be
infinite. */
#define netifBLOCK_TIME_WAITING_FOR_INPUT fecLINK_DELAY
/* Constants used to delay while waiting for a tx descriptor to be free. */
#define fecMAX_TX_WAIT_ATTEMPTS 4
#define fecTX_BUFFER_WAIT ( 10 / portTICK_RATE_MS )
/*-----------------------------------------------------------*/
/* The semaphore used to wake the uIP task when data arrives. */
xSemaphoreHandle xFECSemaphore = NULL;
/* The buffer used by the uIP stack. In this case the pointer is used to
point to one of the Rx buffers. */
unsigned portCHAR *uip_buf;
/* The DMA descriptors. This is a char array to allow us to align it correctly. */
static unsigned portCHAR xFECTxDescriptors_unaligned[ ( configNUM_FEC_TX_BUFFERS * sizeof( FECBD ) ) + 16 ];
static unsigned portCHAR xFECRxDescriptors_unaligned[ ( configNUM_FEC_RX_BUFFERS * sizeof( FECBD ) ) + 16 ];
static FECBD *xFECTxDescriptors;
static FECBD *xFECRxDescriptors;
/* The DMA buffers. These are char arrays to allow them to be alligned correctly. */
static unsigned portCHAR ucFECRxBuffers[ ( configNUM_FEC_RX_BUFFERS * configFEC_BUFFER_SIZE ) + 16 ];
static unsigned portBASE_TYPE uxNextRxBuffer = 0, uxNextTxBuffer = 0, uxIndexToBufferOwner = 0;
/*-----------------------------------------------------------*/
static void prvEnableFECInterrupts( void );
/********************************************************************/
/*
* Write a value to a PHY's MII register.
*
* Parameters:
* ch FEC channel
* phy_addr Address of the PHY.
* reg_addr Address of the register in the PHY.
* data Data to be written to the PHY register.
*
* Return Values:
* 0 on failure
* 1 on success.
*
* Please refer to your PHY manual for registers and their meanings.
* mii_write() polls for the FEC's MII interrupt event and clears it.
* If after a suitable amount of time the event isn't triggered, a
* value of 0 is returned.
*/
static int fec_mii_write( int phy_addr, int reg_addr, int data )
{
int timeout, iReturn;
uint32 eimr;
/* Clear the MII interrupt bit */
MCF_FEC_EIR = MCF_FEC_EIR_MII;
/* Mask the MII interrupt */
eimr = MCF_FEC_EIMR;
MCF_FEC_EIMR &= ~MCF_FEC_EIMR_MII;
/* Write to the MII Management Frame Register to kick-off the MII write */
MCF_FEC_MMFR = MCF_FEC_MMFR_ST_01 | MCF_FEC_MMFR_OP_WRITE | MCF_FEC_MMFR_PA(phy_addr) | MCF_FEC_MMFR_RA(reg_addr) | MCF_FEC_MMFR_TA_10 | MCF_FEC_MMFR_DATA( data );
/* Poll for the MII interrupt (interrupt should be masked) */
for( timeout = 0; timeout < fecMAX_POLLS; timeout++ )
{
if( MCF_FEC_EIR & MCF_FEC_EIR_MII )
{
break;
}
else
{
vTaskDelay( fecMII_DELAY );
}
}
if( timeout == fecMAX_POLLS )
{
iReturn = 0;
}
else
{
iReturn = 1;
}
/* Clear the MII interrupt bit */
MCF_FEC_EIR = MCF_FEC_EIR_MII;
/* Restore the EIMR */
MCF_FEC_EIMR = eimr;
return iReturn;
}
/********************************************************************/
/*
* Read a value from a PHY's MII register.
*
* Parameters:
* ch FEC channel
* phy_addr Address of the PHY.
* reg_addr Address of the register in the PHY.
* data Pointer to storage for the Data to be read
* from the PHY register (passed by reference)
*
* Return Values:
* 0 on failure
* 1 on success.
*
* Please refer to your PHY manual for registers and their meanings.
* mii_read() polls for the FEC's MII interrupt event and clears it.
* If after a suitable amount of time the event isn't triggered, a
* value of 0 is returned.
*/
static int fec_mii_read( int phy_addr, int reg_addr, unsigned portSHORT* data )
{
int timeout, iReturn;
uint32 eimr;
/* Clear the MII interrupt bit */
MCF_FEC_EIR = MCF_FEC_EIR_MII;
/* Mask the MII interrupt */
eimr = MCF_FEC_EIMR;
MCF_FEC_EIMR &= ~MCF_FEC_EIMR_MII;
/* Write to the MII Management Frame Register to kick-off the MII read */
MCF_FEC_MMFR = MCF_FEC_MMFR_ST_01 | MCF_FEC_MMFR_OP_READ | MCF_FEC_MMFR_PA(phy_addr) | MCF_FEC_MMFR_RA(reg_addr) | MCF_FEC_MMFR_TA_10;
/* Poll for the MII interrupt (interrupt should be masked) */
for( timeout = 0; timeout < fecMAX_POLLS; timeout++ )
{
if (MCF_FEC_EIR & MCF_FEC_EIR_MII)
{
break;
}
else
{
vTaskDelay( fecMII_DELAY );
}
}
if( timeout == fecMAX_POLLS )
{
iReturn = 0;
}
else
{
*data = (uint16)(MCF_FEC_MMFR & 0x0000FFFF);
iReturn = 1;
}
/* Clear the MII interrupt bit */
MCF_FEC_EIR = MCF_FEC_EIR_MII;
/* Restore the EIMR */
MCF_FEC_EIMR = eimr;
return iReturn;
}
/********************************************************************/
/*
* Generate the hash table settings for the given address
*
* Parameters:
* addr 48-bit (6 byte) Address to generate the hash for
*
* Return Value:
* The 6 most significant bits of the 32-bit CRC result
*/
static unsigned portCHAR fec_hash_address( const unsigned portCHAR* addr )
{
unsigned portLONG crc;
unsigned portCHAR byte;
int i, j;
crc = 0xFFFFFFFF;
for(i=0; i<6; ++i)
{
byte = addr[i];
for(j=0; j<8; ++j)
{
if((byte & 0x01)^(crc & 0x01))
{
crc >>= 1;
crc = crc ^ 0xEDB88320;
}
else
{
crc >>= 1;
}
byte >>= 1;
}
}
return (unsigned portCHAR)(crc >> 26);
}
/********************************************************************/
/*
* Set the Physical (Hardware) Address and the Individual Address
* Hash in the selected FEC
*
* Parameters:
* ch FEC channel
* pa Physical (Hardware) Address for the selected FEC
*/
static void fec_set_address( const unsigned portCHAR *pa )
{
unsigned portCHAR crc;
/*
* Set the Physical Address
*/
/* Set the source address for the controller */
MCF_FEC_PALR = ( pa[ 0 ] << 24 ) | ( pa[ 1 ] << 16 ) | ( pa[ 2 ] << 8 ) | ( pa[ 3 ] << 0 );
MCF_FEC_PAUR = ( pa[ 4 ] << 24 ) | ( pa[ 5 ] << 16 );
/*
* Calculate and set the hash for given Physical Address
* in the Individual Address Hash registers
*/
crc = fec_hash_address( pa );
if( crc >= 32 )
{
MCF_FEC_IAUR |= (unsigned portLONG)(1 << (crc - 32));
}
else
{
MCF_FEC_IALR |= (unsigned portLONG)(1 << crc);
}
}
/*-----------------------------------------------------------*/
static void prvInitialiseFECBuffers( void )
{
unsigned portBASE_TYPE ux;
unsigned portCHAR *pcBufPointer;
pcBufPointer = &( xFECTxDescriptors_unaligned[ 0 ] );
while( ( ( unsigned portLONG ) pcBufPointer & 0x0fUL ) != 0 )
{
pcBufPointer++;
}
xFECTxDescriptors = ( FECBD * ) pcBufPointer;
pcBufPointer = &( xFECRxDescriptors_unaligned[ 0 ] );
while( ( ( unsigned portLONG ) pcBufPointer & 0x0fUL ) != 0 )
{
pcBufPointer++;
}
xFECRxDescriptors = ( FECBD * ) pcBufPointer;
/* Setup the buffers and descriptors. The data member does not point
anywhere yet as there is not yet anything to send and a zero copy policy
is used. */
for( ux = 0; ux < configNUM_FEC_TX_BUFFERS; ux++ )
{
xFECTxDescriptors[ ux ].status = TX_BD_TC;
xFECTxDescriptors[ ux ].data = NULL;
xFECTxDescriptors[ ux ].length = 0;
}
pcBufPointer = &( ucFECRxBuffers[ 0 ] );
while( ( ( unsigned portLONG ) pcBufPointer & 0x0fUL ) != 0 )
{
pcBufPointer++;
}
for( ux = 0; ux < configNUM_FEC_RX_BUFFERS; ux++ )
{
xFECRxDescriptors[ ux ].status = RX_BD_E;
xFECRxDescriptors[ ux ].length = configFEC_BUFFER_SIZE;
xFECRxDescriptors[ ux ].data = pcBufPointer;
pcBufPointer += configFEC_BUFFER_SIZE;
}
/* Set the wrap bit in the last descriptors to form a ring. */
xFECTxDescriptors[ configNUM_FEC_TX_BUFFERS - 1 ].status |= TX_BD_W;
xFECRxDescriptors[ configNUM_FEC_RX_BUFFERS - 1 ].status |= RX_BD_W;
uxNextRxBuffer = 0;
uxNextTxBuffer = 0;
}
/*-----------------------------------------------------------*/
void vInitFEC( void )
{
unsigned portSHORT usData;
struct uip_eth_addr xAddr;
const unsigned portCHAR ucMACAddress[6] =
{
configMAC_0, configMAC_1,configMAC_2, configMAC_3, configMAC_4, configMAC_5
};
/* Create the semaphore used by the ISR to wake the uIP task. */
vSemaphoreCreateBinary( xFECSemaphore );
prvInitialiseFECBuffers();
for( usData = 0; usData < 6; usData++ )
{
xAddr.addr[ usData ] = ucMACAddress[ usData ];
}
uip_setethaddr( xAddr );
/* Set the Reset bit and clear the Enable bit */
MCF_FEC_ECR = MCF_FEC_ECR_RESET;
/* Wait at least 8 clock cycles */
for( usData = 0; usData < 10; usData++ )
{
asm( "NOP" );
}
/* Set MII speed to 2.5MHz. */
MCF_FEC_MSCR = MCF_FEC_MSCR_MII_SPEED( ( ( ( configCPU_CLOCK_HZ / 1000000 ) / 5 ) + 1 ) );
/* Initialize PLDPAR to enable Ethernet LEDs. */
MCF_GPIO_PLDPAR = MCF_GPIO_PLDPAR_ACTLED_ACTLED | MCF_GPIO_PLDPAR_LINKLED_LINKLED | MCF_GPIO_PLDPAR_SPDLED_SPDLED
| MCF_GPIO_PLDPAR_DUPLED_DUPLED | MCF_GPIO_PLDPAR_COLLED_COLLED | MCF_GPIO_PLDPAR_RXLED_RXLED
| MCF_GPIO_PLDPAR_TXLED_TXLED;
/* Initialize Port TA to enable Axcel control. */
MCF_GPIO_PTAPAR = 0x00;
MCF_GPIO_DDRTA = 0x0F;
MCF_GPIO_PORTTA = 0x04;
/* Set phy address to zero. */
MCF_EPHY_EPHYCTL1 = MCF_EPHY_EPHYCTL1_PHYADD( 0 );
/* Enable EPHY module with PHY clocks disabled. Do not turn on PHY clocks
until both FEC and EPHY are completely setup (see Below). */
MCF_EPHY_EPHYCTL0 = (uint8)(MCF_EPHY_EPHYCTL0_DIS100 | MCF_EPHY_EPHYCTL0_DIS10);
/* Enable auto_neg at start-up */
MCF_EPHY_EPHYCTL0 = (uint8)(MCF_EPHY_EPHYCTL0 & (MCF_EPHY_EPHYCTL0_ANDIS));
/* Enable EPHY module. */
MCF_EPHY_EPHYCTL0 = (uint8)(MCF_EPHY_EPHYCTL0_EPHYEN | MCF_EPHY_EPHYCTL0);
/* Let PHY PLLs be determined by PHY. */
MCF_EPHY_EPHYCTL0 = (uint8)(MCF_EPHY_EPHYCTL0 & ~(MCF_EPHY_EPHYCTL0_DIS100 | MCF_EPHY_EPHYCTL0_DIS10));
/* Settle. */
vTaskDelay( fecLINK_DELAY );
/* Can we talk to the PHY? */
do
{
vTaskDelay( fecLINK_DELAY );
usData = 0;
fec_mii_read( configPHY_ADDRESS, PHY_PHYIDR1, &usData );
} while( usData == 0xffff );
do
{
/* Start auto negotiate. */
fec_mii_write( configPHY_ADDRESS, PHY_BMCR, ( PHY_BMCR_AN_RESTART | PHY_BMCR_AN_ENABLE ) );
/* Wait for auto negotiate to complete. */
do
{
vTaskDelay( fecLINK_DELAY );
fec_mii_read( configPHY_ADDRESS, PHY_BMSR, &usData );
} while( !( usData & PHY_BMSR_AN_COMPLETE ) );
} while( 0 ); //while( !( usData & PHY_BMSR_LINK ) );
/* When we get here we have a link - find out what has been negotiated. */
fec_mii_read( configPHY_ADDRESS, PHY_ANLPAR, &usData );
if( ( usData & PHY_ANLPAR_100BTX_FDX ) || ( usData & PHY_ANLPAR_100BTX ) )
{
/* Speed is 100. */
}
else
{
/* Speed is 10. */
}
if( ( usData & PHY_ANLPAR_100BTX_FDX ) || ( usData & PHY_ANLPAR_10BTX_FDX ) )
{
MCF_FEC_RCR &= (unsigned portLONG)~MCF_FEC_RCR_DRT;
MCF_FEC_TCR |= MCF_FEC_TCR_FDEN;
}
else
{
MCF_FEC_RCR |= MCF_FEC_RCR_DRT;
MCF_FEC_TCR &= (unsigned portLONG)~MCF_FEC_TCR_FDEN;
}
/* Clear the Individual and Group Address Hash registers */
MCF_FEC_IALR = 0;
MCF_FEC_IAUR = 0;
MCF_FEC_GALR = 0;
MCF_FEC_GAUR = 0;
/* Set the Physical Address for the selected FEC */
fec_set_address( ucMACAddress );
/* Set Rx Buffer Size */
MCF_FEC_EMRBR = (unsigned portSHORT)configFEC_BUFFER_SIZE;
/* Point to the start of the circular Rx buffer descriptor queue */
MCF_FEC_ERDSR = ( volatile unsigned portLONG ) &( xFECRxDescriptors[ 0 ] );
/* Point to the start of the circular Tx buffer descriptor queue */
MCF_FEC_ETSDR = ( volatile unsigned portLONG ) &( xFECTxDescriptors[ 0 ] );
/* Mask all FEC interrupts */
MCF_FEC_EIMR = ( unsigned portLONG ) -1;
/* Clear all FEC interrupt events */
MCF_FEC_EIR = ( unsigned portLONG ) -1;
/* Initialize the Receive Control Register */
MCF_FEC_RCR = MCF_FEC_RCR_MAX_FL(ETH_MAX_FRM) | MCF_FEC_RCR_FCE;
MCF_FEC_RCR |= MCF_FEC_RCR_MII_MODE;
#if( configUSE_PROMISCUOUS_MODE == 1 )
{
MCF_FEC_RCR |= MCF_FEC_RCR_PROM;
}
#endif
prvEnableFECInterrupts();
MCF_FEC_ECR = MCF_FEC_ECR_ETHER_EN;
MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;
}
/*-----------------------------------------------------------*/
static void prvEnableFECInterrupts( void )
{
const unsigned portBASE_TYPE uxFirstFECVector = 23, uxLastFECVector = 35;
unsigned portBASE_TYPE ux;
#if configFEC_INTERRUPT_PRIORITY > configMAX_SYSCALL_INTERRUPT_PRIORITY
#error configFEC_INTERRUPT_PRIORITY must be less than or equal to configMAX_SYSCALL_INTERRUPT_PRIORITY
#endif
for( ux = uxFirstFECVector; ux <= uxLastFECVector; ux++ )
{
MCF_INTC0_ICR( ux ) = MCF_INTC_ICR_IL( configFEC_INTERRUPT_PRIORITY );
}
/* Enable the FEC interrupts in the mask register */
MCF_INTC0_IMRH &= ~( MCF_INTC_IMRH_INT_MASK33 | MCF_INTC_IMRH_INT_MASK34 | MCF_INTC_IMRH_INT_MASK35 );
MCF_INTC0_IMRL &= ~( MCF_INTC_IMRL_INT_MASK25 | MCF_INTC_IMRL_INT_MASK26 | MCF_INTC_IMRL_INT_MASK27
| MCF_INTC_IMRL_INT_MASK28 | MCF_INTC_IMRL_INT_MASK29 | MCF_INTC_IMRL_INT_MASK30
| MCF_INTC_IMRL_INT_MASK31 | MCF_INTC_IMRL_MASKALL );
/* Clear any pending FEC interrupt events */
MCF_FEC_EIR = MCF_FEC_EIR_CLEAR_ALL;
/* Unmask all FEC interrupts */
MCF_FEC_EIMR = MCF_FEC_EIMR_UNMASK_ALL;
}
/*-----------------------------------------------------------*/
unsigned short usGetFECRxData( void )
{
unsigned portSHORT usLen;
/* Obtain the size of the packet and put it into the "len" variable. */
usLen = xFECRxDescriptors[ uxNextRxBuffer ].length;
if( ( usLen != 0 ) && ( ( xFECRxDescriptors[ uxNextRxBuffer ].status & RX_BD_E ) == 0 ) )
{
uip_buf = xFECRxDescriptors[ uxNextRxBuffer ].data;
}
else
{
usLen = 0;
}
return usLen;
}
/*-----------------------------------------------------------*/
void vDiscardRxData( void )
{
/* Free the descriptor as the buffer it points to is no longer in use. */
xFECRxDescriptors[ uxNextRxBuffer ].status |= RX_BD_E;
MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;
uxNextRxBuffer++;
if( uxNextRxBuffer >= configNUM_FEC_RX_BUFFERS )
{
uxNextRxBuffer = 0;
}
}
/*-----------------------------------------------------------*/
void vSendBufferToFEC( void )
{
portLONG l;
/* Get a DMA buffer into which we can write the data to send. */
for( l = 0; l < fecMAX_TX_WAIT_ATTEMPTS; l++ )
{
if( xFECTxDescriptors[ uxNextTxBuffer ].status & TX_BD_R )
{
/* Wait for the buffer to become available. */
vTaskDelay( fecTX_BUFFER_WAIT );
}
else
{
/* Setup the buffer descriptor for transmission. The data being
sent is actually stored in one of the Rx descripter buffers,
pointed to by uip_buf. */
xFECTxDescriptors[ uxNextTxBuffer ].length = uip_len;
xFECTxDescriptors[ uxNextTxBuffer ].status |= (TX_BD_R | TX_BD_L);
xFECTxDescriptors[ uxNextTxBuffer ].data = uip_buf;
/* Continue the Tx DMA (in case it was waiting for a new TxBD) */
MCF_FEC_TDAR = MCF_FEC_TDAR_X_DES_ACTIVE;
/* Remember which Rx descriptor owns the buffer we are sending. */
uxIndexToBufferOwner = uxNextRxBuffer;
uxNextTxBuffer++;
if( uxNextTxBuffer >= configNUM_FEC_TX_BUFFERS )
{
uxNextTxBuffer = 0;
}
/* We have finished with this Rx descriptor now. */
uxNextRxBuffer++;
if( uxNextRxBuffer >= configNUM_FEC_RX_BUFFERS )
{
uxNextRxBuffer = 0;
}
break;
}
}
}
/*-----------------------------------------------------------*/
void vFEC_ISR( void )
{
unsigned portLONG ulEvent;
portBASE_TYPE xHighPriorityTaskWoken = pdFALSE;
ulEvent = MCF_FEC_EIR & MCF_FEC_EIMR;
MCF_FEC_EIR = ulEvent;
if( ( ulEvent & MCF_FEC_EIR_RXB ) || ( ulEvent & MCF_FEC_EIR_RXF ) )
{
/* A packet has been received. Wake the handler task. */
xSemaphoreGiveFromISR( xFECSemaphore, &xHighPriorityTaskWoken );
}
if( ulEvent & ( MCF_FEC_EIR_UN | MCF_FEC_EIR_RL | MCF_FEC_EIR_LC | MCF_FEC_EIR_EBERR | MCF_FEC_EIR_BABT | MCF_FEC_EIR_BABR | MCF_FEC_EIR_HBERR ) )
{
/* Sledge hammer error handling. */
prvInitialiseFECBuffers();
MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;
}
if( ( ulEvent & MCF_FEC_EIR_TXF ) || ( ulEvent & MCF_FEC_EIR_TXB ) )
{
/* The buffer being sent is pointed to by an Rx descriptor, now the
buffer has been sent we can mark the Rx descriptor as free again. */
xFECRxDescriptors[ uxIndexToBufferOwner ].status |= RX_BD_E;
MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;
}
portEND_SWITCHING_ISR( xHighPriorityTaskWoken );
}
/*-----------------------------------------------------------*/
void __attribute__ ((interrupt)) __cs3_isr_interrupt_88( void ) { vFEC_ISR(); }
void __attribute__ ((interrupt)) __cs3_isr_interrupt_89( void ) { vFEC_ISR(); }
void __attribute__ ((interrupt)) __cs3_isr_interrupt_90( void ) { vFEC_ISR(); }
void __attribute__ ((interrupt)) __cs3_isr_interrupt_91( void ) { vFEC_ISR(); }
void __attribute__ ((interrupt)) __cs3_isr_interrupt_92( void ) { vFEC_ISR(); }
void __attribute__ ((interrupt)) __cs3_isr_interrupt_93( void ) { vFEC_ISR(); }
void __attribute__ ((interrupt)) __cs3_isr_interrupt_94( void ) { vFEC_ISR(); }
void __attribute__ ((interrupt)) __cs3_isr_interrupt_95( void ) { vFEC_ISR(); }
void __attribute__ ((interrupt)) __cs3_isr_interrupt_96( void ) { vFEC_ISR(); }
void __attribute__ ((interrupt)) __cs3_isr_interrupt_97( void ) { vFEC_ISR(); }
void __attribute__ ((interrupt)) __cs3_isr_interrupt_98( void ) { vFEC_ISR(); }
void __attribute__ ((interrupt)) __cs3_isr_interrupt_99( void ) { vFEC_ISR(); }
void __attribute__ ((interrupt)) __cs3_isr_interrupt_100( void ) { vFEC_ISR(); }