2 FreeRTOS.org V5.1.0 - Copyright (C) 2003-2008 Richard Barry.
\r
4 This file is part of the FreeRTOS.org distribution.
\r
6 FreeRTOS.org is free software; you can redistribute it and/or modify
\r
7 it under the terms of the GNU General Public License as published by
\r
8 the Free Software Foundation; either version 2 of the License, or
\r
9 (at your option) any later version.
\r
11 FreeRTOS.org is distributed in the hope that it will be useful,
\r
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
14 GNU General Public License for more details.
\r
16 You should have received a copy of the GNU General Public License
\r
17 along with FreeRTOS.org; if not, write to the Free Software
\r
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\r
20 A special exception to the GPL can be applied should you wish to distribute
\r
21 a combined work that includes FreeRTOS.org, without being obliged to provide
\r
22 the source code for any proprietary components. See the licensing section
\r
23 of http://www.FreeRTOS.org for full details of how and when the exception
\r
26 ***************************************************************************
\r
27 See http://www.FreeRTOS.org for documentation, latest information, license
\r
28 and contact details. Please ensure to read the configuration and relevant
\r
29 port sections of the online documentation.
\r
30 ***************************************************************************
\r
33 /* Kernel includes. */
\r
34 #include "FreeRTOS.h"
\r
38 /* Demo includes. */
\r
41 #include "eth_phy.h"
\r
46 #include "uip_arp.h"
\r
48 #define MCF_FEC_MSCR_MII_SPEED(x) (((x)&0x3F)<<0x1)
\r
49 #define MCF_FEC_RCR_MAX_FL(x) (((x)&0x7FF)<<0x10)
\r
51 /* Delay between polling the PHY to see if a link has been established. */
\r
52 #define fecLINK_DELAY ( 500 / portTICK_RATE_MS )
\r
54 /* Delay to wait for an MII access. */
\r
55 #define fecMII_DELAY ( 10 / portTICK_RATE_MS )
\r
56 #define fecMAX_POLLS ( 20 )
\r
58 /* Delay between looking for incoming packets. In ideal world this would be
\r
60 #define netifBLOCK_TIME_WAITING_FOR_INPUT fecLINK_DELAY
\r
62 /* Constants used to delay while waiting for a tx descriptor to be free. */
\r
63 #define fecTX_BUFFER_WAIT ( 200 / portTICK_RATE_MS )
\r
65 /* We only use a single Tx descriptor - the duplicate send silicon errata
\r
66 actually assists in this case. */
\r
67 #define fecNUM_FEC_TX_BUFFERS ( 1 )
\r
68 #define fecTX_BUFFER_TO_USE ( 0 )
\r
69 /*-----------------------------------------------------------*/
\r
71 /* The semaphore used to wake the uIP task when data arrives. */
\r
72 xSemaphoreHandle xFECSemaphore = NULL, xTxSemaphore = NULL;
\r
74 /* The buffer used by the uIP stack. In this case the pointer is used to
\r
75 point to one of the Rx buffers. */
\r
76 unsigned portCHAR *uip_buf;
\r
78 /* The DMA descriptors. This is a char array to allow us to align it correctly. */
\r
79 static unsigned portCHAR xFECTxDescriptors_unaligned[ ( fecNUM_FEC_TX_BUFFERS * sizeof( FECBD ) ) + 16 ];
\r
80 static unsigned portCHAR xFECRxDescriptors_unaligned[ ( configNUM_FEC_RX_BUFFERS * sizeof( FECBD ) ) + 16 ];
\r
81 static FECBD *xFECTxDescriptors;
\r
82 static FECBD *xFECRxDescriptors;
\r
84 /* The DMA buffers. These are char arrays to allow them to be alligned correctly. */
\r
85 static unsigned portCHAR ucFECRxBuffers[ ( configNUM_FEC_RX_BUFFERS * configFEC_BUFFER_SIZE ) + 16 ];
\r
86 static unsigned portBASE_TYPE uxNextRxBuffer = 0, uxIndexToBufferOwner = 0;
\r
88 /*-----------------------------------------------------------*/
\r
90 static void prvEnableFECInterrupts( void );
\r
91 static void prvResetFEC( portBASE_TYPE xCalledFromISR );
\r
93 /********************************************************************/
\r
95 * Write a value to a PHY's MII register.
\r
99 * phy_addr Address of the PHY.
\r
100 * reg_addr Address of the register in the PHY.
\r
101 * data Data to be written to the PHY register.
\r
107 * Please refer to your PHY manual for registers and their meanings.
\r
108 * mii_write() polls for the FEC's MII interrupt event and clears it.
\r
109 * If after a suitable amount of time the event isn't triggered, a
\r
110 * value of 0 is returned.
\r
112 static int fec_mii_write( int phy_addr, int reg_addr, int data )
\r
114 int timeout, iReturn;
\r
117 /* Clear the MII interrupt bit */
\r
118 MCF_FEC_EIR = MCF_FEC_EIR_MII;
\r
120 /* Mask the MII interrupt */
\r
121 eimr = MCF_FEC_EIMR;
\r
122 MCF_FEC_EIMR &= ~MCF_FEC_EIMR_MII;
\r
124 /* Write to the MII Management Frame Register to kick-off the MII write */
\r
125 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 );
\r
127 /* Poll for the MII interrupt (interrupt should be masked) */
\r
128 for( timeout = 0; timeout < fecMAX_POLLS; timeout++ )
\r
130 if( MCF_FEC_EIR & MCF_FEC_EIR_MII )
\r
136 vTaskDelay( fecMII_DELAY );
\r
140 if( timeout == fecMAX_POLLS )
\r
149 /* Clear the MII interrupt bit */
\r
150 MCF_FEC_EIR = MCF_FEC_EIR_MII;
\r
152 /* Restore the EIMR */
\r
153 MCF_FEC_EIMR = eimr;
\r
158 /********************************************************************/
\r
160 * Read a value from a PHY's MII register.
\r
164 * phy_addr Address of the PHY.
\r
165 * reg_addr Address of the register in the PHY.
\r
166 * data Pointer to storage for the Data to be read
\r
167 * from the PHY register (passed by reference)
\r
173 * Please refer to your PHY manual for registers and their meanings.
\r
174 * mii_read() polls for the FEC's MII interrupt event and clears it.
\r
175 * If after a suitable amount of time the event isn't triggered, a
\r
176 * value of 0 is returned.
\r
178 static int fec_mii_read( int phy_addr, int reg_addr, unsigned portSHORT* data )
\r
180 int timeout, iReturn;
\r
183 /* Clear the MII interrupt bit */
\r
184 MCF_FEC_EIR = MCF_FEC_EIR_MII;
\r
186 /* Mask the MII interrupt */
\r
187 eimr = MCF_FEC_EIMR;
\r
188 MCF_FEC_EIMR &= ~MCF_FEC_EIMR_MII;
\r
190 /* Write to the MII Management Frame Register to kick-off the MII read */
\r
191 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;
\r
193 /* Poll for the MII interrupt (interrupt should be masked) */
\r
194 for( timeout = 0; timeout < fecMAX_POLLS; timeout++ )
\r
196 if (MCF_FEC_EIR & MCF_FEC_EIR_MII)
\r
202 vTaskDelay( fecMII_DELAY );
\r
206 if( timeout == fecMAX_POLLS )
\r
212 *data = (uint16)(MCF_FEC_MMFR & 0x0000FFFF);
\r
216 /* Clear the MII interrupt bit */
\r
217 MCF_FEC_EIR = MCF_FEC_EIR_MII;
\r
219 /* Restore the EIMR */
\r
220 MCF_FEC_EIMR = eimr;
\r
226 /********************************************************************/
\r
228 * Generate the hash table settings for the given address
\r
231 * addr 48-bit (6 byte) Address to generate the hash for
\r
234 * The 6 most significant bits of the 32-bit CRC result
\r
236 static unsigned portCHAR fec_hash_address( const unsigned portCHAR* addr )
\r
238 unsigned portLONG crc;
\r
239 unsigned portCHAR byte;
\r
248 if((byte & 0x01)^(crc & 0x01))
\r
251 crc = crc ^ 0xEDB88320;
\r
262 return (unsigned portCHAR)(crc >> 26);
\r
265 /********************************************************************/
\r
267 * Set the Physical (Hardware) Address and the Individual Address
\r
268 * Hash in the selected FEC
\r
272 * pa Physical (Hardware) Address for the selected FEC
\r
274 static void fec_set_address( const unsigned portCHAR *pa )
\r
276 unsigned portCHAR crc;
\r
279 * Set the Physical Address
\r
281 /* Set the source address for the controller */
\r
282 MCF_FEC_PALR = ( pa[ 0 ] << 24 ) | ( pa[ 1 ] << 16 ) | ( pa[ 2 ] << 8 ) | ( pa[ 3 ] << 0 );
\r
283 MCF_FEC_PAUR = ( pa[ 4 ] << 24 ) | ( pa[ 5 ] << 16 );
\r
286 * Calculate and set the hash for given Physical Address
\r
287 * in the Individual Address Hash registers
\r
289 crc = fec_hash_address( pa );
\r
292 MCF_FEC_IAUR |= (unsigned portLONG)(1 << (crc - 32));
\r
296 MCF_FEC_IALR |= (unsigned portLONG)(1 << crc);
\r
299 /*-----------------------------------------------------------*/
\r
301 static void prvInitialiseFECBuffers( void )
\r
303 unsigned portBASE_TYPE ux;
\r
304 unsigned portCHAR *pcBufPointer;
\r
306 pcBufPointer = &( xFECTxDescriptors_unaligned[ 0 ] );
\r
307 while( ( ( unsigned portLONG ) pcBufPointer & 0x0fUL ) != 0 )
\r
312 xFECTxDescriptors = ( FECBD * ) pcBufPointer;
\r
314 pcBufPointer = &( xFECRxDescriptors_unaligned[ 0 ] );
\r
315 while( ( ( unsigned portLONG ) pcBufPointer & 0x0fUL ) != 0 )
\r
320 xFECRxDescriptors = ( FECBD * ) pcBufPointer;
\r
323 /* Setup the buffers and descriptors. The data member does not point
\r
324 anywhere yet as there is not yet anything to send and a zero copy policy
\r
326 for( ux = 0; ux < fecNUM_FEC_TX_BUFFERS; ux++ )
\r
328 xFECTxDescriptors[ ux ].status = TX_BD_TC;
\r
329 xFECTxDescriptors[ ux ].data = NULL;
\r
330 xFECTxDescriptors[ ux ].length = 0;
\r
333 pcBufPointer = &( ucFECRxBuffers[ 0 ] );
\r
334 while( ( ( unsigned portLONG ) pcBufPointer & 0x0fUL ) != 0 )
\r
339 for( ux = 0; ux < configNUM_FEC_RX_BUFFERS; ux++ )
\r
341 xFECRxDescriptors[ ux ].status = RX_BD_E;
\r
342 xFECRxDescriptors[ ux ].length = configFEC_BUFFER_SIZE;
\r
343 xFECRxDescriptors[ ux ].data = pcBufPointer;
\r
344 pcBufPointer += configFEC_BUFFER_SIZE;
\r
347 /* Set the wrap bit in the last descriptors to form a ring. */
\r
348 xFECTxDescriptors[ fecNUM_FEC_TX_BUFFERS - 1 ].status |= TX_BD_W;
\r
349 xFECRxDescriptors[ configNUM_FEC_RX_BUFFERS - 1 ].status |= RX_BD_W;
\r
351 uxNextRxBuffer = 0;
\r
353 /*-----------------------------------------------------------*/
\r
355 void vInitFEC( void )
\r
357 unsigned portSHORT usData;
\r
358 struct uip_eth_addr xAddr;
\r
359 const unsigned portCHAR ucMACAddress[6] =
\r
361 configMAC_0, configMAC_1,configMAC_2, configMAC_3, configMAC_4, configMAC_5
\r
364 /* Create the semaphore used by the ISR to wake the uIP task. */
\r
365 vSemaphoreCreateBinary( xFECSemaphore );
\r
366 vSemaphoreCreateBinary( xTxSemaphore );
\r
368 prvInitialiseFECBuffers();
\r
370 for( usData = 0; usData < 6; usData++ )
\r
372 xAddr.addr[ usData ] = ucMACAddress[ usData ];
\r
374 uip_setethaddr( xAddr );
\r
376 /* Set the Reset bit and clear the Enable bit */
\r
377 MCF_FEC_ECR = MCF_FEC_ECR_RESET;
\r
379 /* Wait at least 8 clock cycles */
\r
380 for( usData = 0; usData < 10; usData++ )
\r
385 /* Set MII speed to 2.5MHz. */
\r
386 MCF_FEC_MSCR = MCF_FEC_MSCR_MII_SPEED( ( ( ( configCPU_CLOCK_HZ / 1000000 ) / 5 ) + 1 ) );
\r
388 /* Initialize PLDPAR to enable Ethernet LEDs. */
\r
389 MCF_GPIO_PLDPAR = MCF_GPIO_PLDPAR_ACTLED_ACTLED | MCF_GPIO_PLDPAR_LINKLED_LINKLED | MCF_GPIO_PLDPAR_SPDLED_SPDLED
\r
390 | MCF_GPIO_PLDPAR_DUPLED_DUPLED | MCF_GPIO_PLDPAR_COLLED_COLLED | MCF_GPIO_PLDPAR_RXLED_RXLED
\r
391 | MCF_GPIO_PLDPAR_TXLED_TXLED;
\r
393 /* Initialize Port TA to enable Axcel control. */
\r
394 MCF_GPIO_PTAPAR = 0x00;
\r
395 MCF_GPIO_DDRTA = 0x0F;
\r
396 MCF_GPIO_PORTTA = 0x04;
\r
398 /* Set phy address to zero. */
\r
399 MCF_EPHY_EPHYCTL1 = MCF_EPHY_EPHYCTL1_PHYADD( 0 );
\r
401 /* Enable EPHY module with PHY clocks disabled. Do not turn on PHY clocks
\r
402 until both FEC and EPHY are completely setup (see Below). */
\r
403 MCF_EPHY_EPHYCTL0 = (uint8)(MCF_EPHY_EPHYCTL0_DIS100 | MCF_EPHY_EPHYCTL0_DIS10);
\r
405 /* Enable auto_neg at start-up */
\r
406 MCF_EPHY_EPHYCTL0 = (uint8)(MCF_EPHY_EPHYCTL0 & (MCF_EPHY_EPHYCTL0_ANDIS));
\r
408 /* Enable EPHY module. */
\r
409 MCF_EPHY_EPHYCTL0 = (uint8)(MCF_EPHY_EPHYCTL0_EPHYEN | MCF_EPHY_EPHYCTL0);
\r
411 /* Let PHY PLLs be determined by PHY. */
\r
412 MCF_EPHY_EPHYCTL0 = (uint8)(MCF_EPHY_EPHYCTL0 & ~(MCF_EPHY_EPHYCTL0_DIS100 | MCF_EPHY_EPHYCTL0_DIS10));
\r
415 vTaskDelay( fecLINK_DELAY );
\r
417 /* Can we talk to the PHY? */
\r
420 vTaskDelay( fecLINK_DELAY );
\r
422 fec_mii_read( configPHY_ADDRESS, PHY_PHYIDR1, &usData );
\r
424 } while( usData == 0xffff );
\r
428 /* Start auto negotiate. */
\r
429 fec_mii_write( configPHY_ADDRESS, PHY_BMCR, ( PHY_BMCR_AN_RESTART | PHY_BMCR_AN_ENABLE ) );
\r
431 /* Wait for auto negotiate to complete. */
\r
434 vTaskDelay( fecLINK_DELAY );
\r
435 fec_mii_read( configPHY_ADDRESS, PHY_BMSR, &usData );
\r
437 } while( !( usData & PHY_BMSR_AN_COMPLETE ) );
\r
439 } while( 0 ); //while( !( usData & PHY_BMSR_LINK ) );
\r
441 /* When we get here we have a link - find out what has been negotiated. */
\r
442 fec_mii_read( configPHY_ADDRESS, PHY_ANLPAR, &usData );
\r
444 if( ( usData & PHY_ANLPAR_100BTX_FDX ) || ( usData & PHY_ANLPAR_100BTX ) )
\r
446 /* Speed is 100. */
\r
453 if( ( usData & PHY_ANLPAR_100BTX_FDX ) || ( usData & PHY_ANLPAR_10BTX_FDX ) )
\r
455 MCF_FEC_RCR &= (unsigned portLONG)~MCF_FEC_RCR_DRT;
\r
456 MCF_FEC_TCR |= MCF_FEC_TCR_FDEN;
\r
460 MCF_FEC_RCR |= MCF_FEC_RCR_DRT;
\r
461 MCF_FEC_TCR &= (unsigned portLONG)~MCF_FEC_TCR_FDEN;
\r
464 /* Clear the Individual and Group Address Hash registers */
\r
470 /* Set the Physical Address for the selected FEC */
\r
471 fec_set_address( ucMACAddress );
\r
473 /* Set Rx Buffer Size */
\r
474 MCF_FEC_EMRBR = (unsigned portSHORT)configFEC_BUFFER_SIZE;
\r
476 /* Point to the start of the circular Rx buffer descriptor queue */
\r
477 MCF_FEC_ERDSR = ( volatile unsigned portLONG ) &( xFECRxDescriptors[ 0 ] );
\r
479 /* Point to the start of the circular Tx buffer descriptor queue */
\r
480 MCF_FEC_ETSDR = ( volatile unsigned portLONG ) &( xFECTxDescriptors[ 0 ] );
\r
482 /* Mask all FEC interrupts */
\r
483 MCF_FEC_EIMR = ( unsigned portLONG ) -1;
\r
485 /* Clear all FEC interrupt events */
\r
486 MCF_FEC_EIR = ( unsigned portLONG ) -1;
\r
488 /* Initialize the Receive Control Register */
\r
489 MCF_FEC_RCR = MCF_FEC_RCR_MAX_FL(ETH_MAX_FRM) | MCF_FEC_RCR_FCE;
\r
491 MCF_FEC_RCR |= MCF_FEC_RCR_MII_MODE;
\r
493 #if( configUSE_PROMISCUOUS_MODE == 1 )
\r
495 MCF_FEC_RCR |= MCF_FEC_RCR_PROM;
\r
499 prvEnableFECInterrupts();
\r
501 MCF_FEC_ECR = MCF_FEC_ECR_ETHER_EN;
\r
502 MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;
\r
504 /*-----------------------------------------------------------*/
\r
506 static void prvEnableFECInterrupts( void )
\r
508 const unsigned portBASE_TYPE uxFirstFECVector = 23, uxLastFECVector = 35;
\r
509 unsigned portBASE_TYPE ux;
\r
511 #if configFEC_INTERRUPT_PRIORITY > configMAX_SYSCALL_INTERRUPT_PRIORITY
\r
512 #error configFEC_INTERRUPT_PRIORITY must be less than or equal to configMAX_SYSCALL_INTERRUPT_PRIORITY
\r
515 for( ux = uxFirstFECVector; ux <= uxLastFECVector; ux++ )
\r
517 MCF_INTC0_ICR( ux ) = MCF_INTC_ICR_IL( configFEC_INTERRUPT_PRIORITY );
\r
520 /* Enable the FEC interrupts in the mask register */
\r
521 MCF_INTC0_IMRH &= ~( MCF_INTC_IMRH_INT_MASK33 | MCF_INTC_IMRH_INT_MASK34 | MCF_INTC_IMRH_INT_MASK35 );
\r
522 MCF_INTC0_IMRL &= ~( MCF_INTC_IMRL_INT_MASK25 | MCF_INTC_IMRL_INT_MASK26 | MCF_INTC_IMRL_INT_MASK27
\r
523 | MCF_INTC_IMRL_INT_MASK28 | MCF_INTC_IMRL_INT_MASK29 | MCF_INTC_IMRL_INT_MASK30
\r
524 | MCF_INTC_IMRL_INT_MASK31 | MCF_INTC_IMRL_INT_MASK23 | MCF_INTC_IMRL_INT_MASK24
\r
525 | MCF_INTC_IMRL_MASKALL );
\r
527 /* Clear any pending FEC interrupt events */
\r
528 MCF_FEC_EIR = MCF_FEC_EIR_CLEAR_ALL;
\r
530 /* Unmask all FEC interrupts */
\r
531 MCF_FEC_EIMR = MCF_FEC_EIMR_UNMASK_ALL;
\r
533 /*-----------------------------------------------------------*/
\r
535 static void prvResetFEC( portBASE_TYPE xCalledFromISR )
\r
539 if( xCalledFromISR == pdFALSE )
\r
541 taskENTER_CRITICAL();
\r
545 prvInitialiseFECBuffers();
\r
547 /* Set the Reset bit and clear the Enable bit */
\r
548 MCF_FEC_ECR = MCF_FEC_ECR_RESET;
\r
550 /* Wait at least 8 clock cycles */
\r
551 for( x = 0; x < 10; x++ )
\r
556 MCF_FEC_ECR = MCF_FEC_ECR_ETHER_EN;
\r
557 MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;
\r
560 if( xCalledFromISR == pdFALSE )
\r
562 taskEXIT_CRITICAL();
\r
565 /*-----------------------------------------------------------*/
\r
567 unsigned short usGetFECRxData( void )
\r
569 unsigned portSHORT usLen;
\r
571 /* Obtain the size of the packet and put it into the "len" variable. */
\r
572 usLen = xFECRxDescriptors[ uxNextRxBuffer ].length;
\r
574 if( ( usLen != 0 ) && ( ( xFECRxDescriptors[ uxNextRxBuffer ].status & RX_BD_E ) == 0 ) )
\r
576 uip_buf = xFECRxDescriptors[ uxNextRxBuffer ].data;
\r
585 /*-----------------------------------------------------------*/
\r
587 void vDiscardRxData( void )
\r
589 /* Free the descriptor as the buffer it points to is no longer in use. */
\r
590 xFECRxDescriptors[ uxNextRxBuffer ].status |= RX_BD_E;
\r
591 MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;
\r
593 if( uxNextRxBuffer >= configNUM_FEC_RX_BUFFERS )
\r
595 uxNextRxBuffer = 0;
\r
598 /*-----------------------------------------------------------*/
\r
600 void vSendBufferToFEC( void )
\r
602 /* Ensure no Tx frames are outstanding. */
\r
603 if( xSemaphoreTake( xTxSemaphore, fecTX_BUFFER_WAIT ) == pdPASS )
\r
605 /* Get a DMA buffer into which we can write the data to send. */
\r
606 if( xFECTxDescriptors[ fecTX_BUFFER_TO_USE ].status & TX_BD_R )
\r
608 /*** ERROR didn't expect this. Sledge hammer error handling. ***/
\r
609 prvResetFEC( pdFALSE );
\r
611 /* Make sure we leave the semaphore in the expected state as nothing
\r
612 is being transmitted this will not happen in the Tx ISR. */
\r
613 xSemaphoreGive( xTxSemaphore );
\r
617 /* Setup the buffer descriptor for transmission. The data being
\r
618 sent is actually stored in one of the Rx descripter buffers,
\r
619 pointed to by uip_buf. */
\r
620 xFECTxDescriptors[ fecTX_BUFFER_TO_USE ].length = uip_len;
\r
621 xFECTxDescriptors[ fecTX_BUFFER_TO_USE ].status |= ( TX_BD_R | TX_BD_L );
\r
622 xFECTxDescriptors[ fecTX_BUFFER_TO_USE ].data = uip_buf;
\r
624 /* Remember which Rx descriptor owns the buffer we are sending. */
\r
625 uxIndexToBufferOwner = uxNextRxBuffer;
\r
627 /* We have finished with this Rx descriptor now. */
\r
629 if( uxNextRxBuffer >= configNUM_FEC_RX_BUFFERS )
\r
631 uxNextRxBuffer = 0;
\r
634 /* Continue the Tx DMA (in case it was waiting for a new TxBD) */
\r
635 MCF_FEC_TDAR = MCF_FEC_TDAR_X_DES_ACTIVE;
\r
643 /*-----------------------------------------------------------*/
\r
645 void vFEC_ISR( void )
\r
647 unsigned portLONG ulEvent;
\r
648 portBASE_TYPE xHighPriorityTaskWoken = pdFALSE;
\r
650 ulEvent = MCF_FEC_EIR & MCF_FEC_EIMR;
\r
651 MCF_FEC_EIR = ulEvent;
\r
653 if( ( ulEvent & MCF_FEC_EIR_RXB ) || ( ulEvent & MCF_FEC_EIR_RXF ) )
\r
655 /* A packet has been received. Wake the handler task. */
\r
656 xSemaphoreGiveFromISR( xFECSemaphore, &xHighPriorityTaskWoken );
\r
659 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 ) )
\r
661 /* Sledge hammer error handling. */
\r
662 prvResetFEC( pdTRUE );
\r
665 if( ( ulEvent & MCF_FEC_EIR_TXF ) || ( ulEvent & MCF_FEC_EIR_TXB ) )
\r
667 /* The buffer being sent is pointed to by an Rx descriptor, now the
\r
668 buffer has been sent we can mark the Rx descriptor as free again. */
\r
669 xFECRxDescriptors[ uxIndexToBufferOwner ].status |= RX_BD_E;
\r
670 MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;
\r
671 xSemaphoreGiveFromISR( xTxSemaphore, &xHighPriorityTaskWoken );
\r
674 portEND_SWITCHING_ISR( xHighPriorityTaskWoken );
\r
676 /*-----------------------------------------------------------*/
\r
678 void __attribute__ ((interrupt)) __cs3_isr_interrupt_87( void ) { vFEC_ISR(); }
\r
679 void __attribute__ ((interrupt)) __cs3_isr_interrupt_88( void ) { vFEC_ISR(); }
\r
680 void __attribute__ ((interrupt)) __cs3_isr_interrupt_89( void ) { vFEC_ISR(); }
\r
681 void __attribute__ ((interrupt)) __cs3_isr_interrupt_90( void ) { vFEC_ISR(); }
\r
682 void __attribute__ ((interrupt)) __cs3_isr_interrupt_91( void ) { vFEC_ISR(); }
\r
683 void __attribute__ ((interrupt)) __cs3_isr_interrupt_92( void ) { vFEC_ISR(); }
\r
684 void __attribute__ ((interrupt)) __cs3_isr_interrupt_93( void ) { vFEC_ISR(); }
\r
685 void __attribute__ ((interrupt)) __cs3_isr_interrupt_94( void ) { vFEC_ISR(); }
\r
686 void __attribute__ ((interrupt)) __cs3_isr_interrupt_95( void ) { vFEC_ISR(); }
\r
687 void __attribute__ ((interrupt)) __cs3_isr_interrupt_96( void ) { vFEC_ISR(); }
\r
688 void __attribute__ ((interrupt)) __cs3_isr_interrupt_97( void ) { vFEC_ISR(); }
\r
689 void __attribute__ ((interrupt)) __cs3_isr_interrupt_98( void ) { vFEC_ISR(); }
\r
690 void __attribute__ ((interrupt)) __cs3_isr_interrupt_99( void ) { vFEC_ISR(); }
\r