]> git.sur5r.net Git - freertos/blob - Demo/CORTEX_Kinetis_K60_Tower_IAR/webserver/EMAC.c
Ethernet working in the Kinetis K60 demo.
[freertos] / Demo / CORTEX_Kinetis_K60_Tower_IAR / webserver / EMAC.c
1 /*\r
2     FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
3         \r
4 \r
5     ***************************************************************************\r
6      *                                                                       *\r
7      *    FreeRTOS tutorial books are available in pdf and paperback.        *\r
8      *    Complete, revised, and edited pdf reference manuals are also       *\r
9      *    available.                                                         *\r
10      *                                                                       *\r
11      *    Purchasing FreeRTOS documentation will not only help you, by       *\r
12      *    ensuring you get running as quickly as possible and with an        *\r
13      *    in-depth knowledge of how to use FreeRTOS, it will also help       *\r
14      *    the FreeRTOS project to continue with its mission of providing     *\r
15      *    professional grade, cross platform, de facto standard solutions    *\r
16      *    for microcontrollers - completely free of charge!                  *\r
17      *                                                                       *\r
18      *    >>> See http://www.FreeRTOS.org/Documentation for details. <<<     *\r
19      *                                                                       *\r
20      *    Thank you for using FreeRTOS, and thank you for your support!      *\r
21      *                                                                       *\r
22     ***************************************************************************\r
23 \r
24 \r
25     This file is part of the FreeRTOS distribution.\r
26 \r
27     FreeRTOS is free software; you can redistribute it and/or modify it under\r
28     the terms of the GNU General Public License (version 2) as published by the\r
29     Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
30     >>>NOTE<<< The modification to the GPL is included to allow you to\r
31     distribute a combined work that includes FreeRTOS without being obliged to\r
32     provide the source code for proprietary components outside of the FreeRTOS\r
33     kernel.  FreeRTOS is distributed in the hope that it will be useful, but\r
34     WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
35     or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
36     more details. You should have received a copy of the GNU General Public\r
37     License and the FreeRTOS license exception along with FreeRTOS; if not it\r
38     can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
39     by writing to Richard Barry, contact details for whom are available on the\r
40     FreeRTOS WEB site.\r
41 \r
42     1 tab == 4 spaces!\r
43 \r
44     http://www.FreeRTOS.org - Documentation, latest information, license and\r
45     contact details.\r
46 \r
47     http://www.SafeRTOS.com - A version that is certified for use in safety\r
48     critical systems.\r
49 \r
50     http://www.OpenRTOS.com - Commercial support, development, porting,\r
51     licensing and training services.\r
52 */\r
53 \r
54 /* Freescale includes. */\r
55 #include "common.h"\r
56 #include "eth_phy.h"\r
57 #include "enet.h"\r
58 #include "mii.h"\r
59 \r
60 /* FreeRTOS includes. */\r
61 #include "FreeRTOS.h"\r
62 #include "task.h"\r
63 #include "semphr.h"\r
64 \r
65 /* uIP includes. */\r
66 #include "net/uip.h"\r
67 \r
68 /* The time to wait between attempts to obtain a free buffer. */\r
69 #define emacBUFFER_WAIT_DELAY_ms                ( 3 / portTICK_RATE_MS )\r
70 \r
71 /* The number of times emacBUFFER_WAIT_DELAY_ms should be waited before giving\r
72 up on attempting to obtain a free buffer all together. */\r
73 #define emacBUFFER_WAIT_ATTEMPTS        ( 30 )\r
74 \r
75 /* The number of Rx descriptors. */\r
76 #define emacNUM_RX_DESCRIPTORS  8\r
77 \r
78 /* The number of Tx descriptors.  When using uIP there is not point in having\r
79 more than two. */\r
80 #define emacNUM_TX_BUFFERS      2\r
81 \r
82 /* The total number of EMAC buffers to allocate. */\r
83 #define emacNUM_BUFFERS         ( emacNUM_RX_DESCRIPTORS + emacNUM_TX_BUFFERS )\r
84 \r
85 /* The time to wait for the Tx descriptor to become free. */\r
86 #define emacTX_WAIT_DELAY_ms ( 10 / portTICK_RATE_MS )\r
87 \r
88 /* The total number of times to wait emacTX_WAIT_DELAY_ms for the Tx descriptor to\r
89 become free. */\r
90 #define emacTX_WAIT_ATTEMPTS ( 50 )\r
91 \r
92 #define emacTX_INTERRUPT_NO                     ( 76 )\r
93 #define emacRX_INTERRUPT_NO                     ( 77 )\r
94 #define emacERROR_INTERRUPT_NO          ( 78 )\r
95 #define emacLINK_DELAY                          ( 500 / portTICK_RATE_MS )\r
96 #define emacPHY_STATUS                          ( 0x1F )\r
97 #define emacPHY_DUPLEX_STATUS           ( 4 << 2 )\r
98 #define emacPHY_SPEED_STATUS            ( 1 << 2 )\r
99 \r
100 /*-----------------------------------------------------------*/\r
101 \r
102 /*\r
103  * Initialise both the Rx and Tx descriptors.\r
104  */\r
105 static void prvInitialiseDescriptors( void );\r
106 \r
107 /*\r
108  * Return a pointer to a free buffer within xEthernetBuffers.\r
109  */\r
110 static unsigned char *prvGetNextBuffer( void );\r
111 \r
112 /*\r
113  * Return a buffer to the list of free buffers.\r
114  */\r
115 static void prvReturnBuffer( unsigned char *pucBuffer );\r
116 \r
117 /*\r
118  * Examine the status of the next Rx descriptor to see if it contains new data.\r
119  */\r
120 static unsigned short prvCheckRxStatus( void );\r
121 \r
122 /*\r
123  * Something has gone wrong with the descriptor usage.  Reset all the buffers\r
124  * and descriptors.\r
125  */\r
126 static void prvResetEverything( void );\r
127 \r
128 /*-----------------------------------------------------------*/\r
129 \r
130 /* The buffers and descriptors themselves.  */\r
131 #pragma data_alignment=16\r
132 volatile NBUF xRxDescriptors[ emacNUM_RX_DESCRIPTORS ];\r
133 \r
134 #pragma data_alignment=16\r
135 volatile NBUF xTxDescriptors[ emacNUM_TX_BUFFERS ];\r
136 \r
137 #pragma data_alignment=16\r
138 char xEthernetBuffers[ emacNUM_BUFFERS ][ UIP_BUFSIZE ];\r
139 \r
140 /* Used to indicate which buffers are free and which are in use.  If an index\r
141 contains 0 then the corresponding buffer in xEthernetBuffers is free, otherwise\r
142 the buffer is in use or about to be used. */\r
143 static unsigned char ucBufferInUse[ emacNUM_BUFFERS ];\r
144 \r
145 /* Points to the Rx descriptor currently in use. */\r
146 static volatile NBUF *pxCurrentRxDesc = NULL;\r
147 \r
148 /* pxCurrentRxDesc points to descriptor within the xRxDescriptors array that\r
149 has an index defined by ulRxDescriptorIndex. */\r
150 static unsigned long ulRxDescriptorIndex = 0UL;\r
151 \r
152 /* The buffer used by the uIP stack to both receive and send.  This points to\r
153 one of the Ethernet buffers when its actually in use. */\r
154 unsigned char *uip_buf = NULL;\r
155 \r
156 /*-----------------------------------------------------------*/\r
157 #define ENET_HARDWARE_CHECKSUM 0        //_RB_ for test only\r
158 void vEMACInit( void )\r
159 {\r
160 int iData;\r
161 extern int periph_clk_khz;\r
162 const unsigned portCHAR ucMACAddress[] =\r
163 {\r
164         configMAC_ADDR0, configMAC_ADDR1, configMAC_ADDR2, configMAC_ADDR3, configMAC_ADDR4, configMAC_ADDR5\r
165 };\r
166 \r
167         /* Enable the ENET clock. */\r
168         SIM_SCGC2 |= SIM_SCGC2_ENET_MASK;\r
169 \r
170         /* Allow concurrent access to MPU controller to avoid bus errors. */\r
171         MPU_CESR = 0;\r
172 \r
173         prvInitialiseDescriptors();\r
174 \r
175         /* Reset and enable. */\r
176         ENET_ECR = ENET_ECR_RESET_MASK;\r
177         \r
178         /* Wait at least 8 clock cycles */\r
179         vTaskDelay( 2 );\r
180         \r
181         /* Start the MII interface*/\r
182         mii_init( 0, periph_clk_khz / 1000L );\r
183 \r
184         /* Configure the transmit interrupt. */\r
185         set_irq_priority( emacTX_INTERRUPT_NO, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY );\r
186         enable_irq( emacTX_INTERRUPT_NO );\r
187 \r
188         /* Configure the receive interrupt. */\r
189         set_irq_priority( emacRX_INTERRUPT_NO, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY );\r
190         enable_irq( emacRX_INTERRUPT_NO );\r
191 \r
192         /* Configure the error interrupt. */\r
193         set_irq_priority( emacERROR_INTERRUPT_NO, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY );\r
194         enable_irq( emacERROR_INTERRUPT_NO );\r
195 \r
196         /* Configure the pins to the PHY - RMII mode used. */\r
197         PORTB_PCR0  = PORT_PCR_MUX( 4 ); /* RMII0_MDIO / MII0_MDIO. */\r
198         PORTB_PCR1  = PORT_PCR_MUX( 4 ); /* RMII0_MDC / MII0_MDC */\r
199         PORTA_PCR14 = PORT_PCR_MUX( 4 ); /* RMII0_CRS_DV / MII0_RXDV */\r
200         PORTA_PCR12 = PORT_PCR_MUX( 4 ); /* RMII0_RXD1 / MII0_RXD1 */\r
201         PORTA_PCR13 = PORT_PCR_MUX( 4 ); /* RMII0_RXD0/MII0_RXD0 */\r
202         PORTA_PCR15 = PORT_PCR_MUX( 4 ); /* RMII0_TXEN/MII0_TXEN */\r
203         PORTA_PCR16 = PORT_PCR_MUX( 4 ); /* RMII0_TXD0/MII0_TXD0 */\r
204         PORTA_PCR17 = PORT_PCR_MUX( 4 ); /* RMII0_TXD1/MII0_TXD1 */\r
205 \r
206         /* Is there communication with the PHY? */\r
207         do\r
208         {\r
209                 vTaskDelay( emacLINK_DELAY );\r
210                 iData = 0xFFFF;\r
211                 mii_read( 0, configPHY_ADDRESS, PHY_PHYIDR1, &iData );\r
212         \r
213         } while( iData == 0xFFFF );\r
214 \r
215         /* Start to auto negotiate. */\r
216         mii_write( 0, configPHY_ADDRESS, PHY_BMCR, ( PHY_BMCR_AN_RESTART | PHY_BMCR_AN_ENABLE ) );\r
217         \r
218         /* Wait for auto negotiate to complete. */\r
219         do\r
220         {\r
221                 vTaskDelay( emacLINK_DELAY );\r
222                 mii_read( 0, configPHY_ADDRESS, PHY_BMSR, &iData );\r
223         \r
224         } while( !( iData & PHY_BMSR_AN_COMPLETE ) );\r
225 \r
226         /* A link has been established.  What was negotiated? */\r
227         iData = 0;\r
228         mii_read( 0, configPHY_ADDRESS, emacPHY_STATUS, &iData );\r
229 \r
230         /* Clear the Individual and Group Address Hash registers */\r
231         ENET_IALR = 0;\r
232         ENET_IAUR = 0;\r
233         ENET_GALR = 0;\r
234         ENET_GAUR = 0;\r
235 \r
236         /* Set the Physical Address for the selected ENET */\r
237         enet_set_address( 0, ucMACAddress );\r
238 \r
239         ENET_RCR = ENET_RCR_MAX_FL( UIP_BUFSIZE ) | ENET_RCR_MII_MODE_MASK | ENET_RCR_CRCFWD_MASK | ENET_RCR_RMII_MODE_MASK;\r
240 \r
241         /* Clear the control registers. */\r
242         ENET_TCR = 0;\r
243 \r
244         if( iData & emacPHY_DUPLEX_STATUS )\r
245         {\r
246                 /* Full duplex */\r
247                 ENET_RCR &= ( unsigned long )~ENET_RCR_DRT_MASK;\r
248                 ENET_TCR |= ENET_TCR_FDEN_MASK;\r
249         }\r
250         else\r
251         {\r
252                 /* Half duplex */\r
253                 ENET_RCR |= ENET_RCR_DRT_MASK;\r
254                 ENET_TCR &= (unsigned portLONG)~ENET_TCR_FDEN_MASK;\r
255         }\r
256 \r
257         if( iData & emacPHY_SPEED_STATUS )\r
258         {\r
259                 /* 10Mbps */\r
260                 ENET_RCR |= ENET_RCR_RMII_10T_MASK;\r
261         }\r
262 \r
263     ENET_ECR = ENET_ECR_EN1588_MASK;\r
264 \r
265 #if 0\r
266 //_RB_  \r
267 // Enable Ethernet header alignment for rx\r
268 ENET_RACC |= 0\r
269                                          | ENET_RACC_SHIFT16_MASK\r
270                                          ;\r
271 \r
272 // Enable Ethernet header alignment for tx\r
273 ENET_TACC |= 0\r
274                                          | ENET_TACC_SHIFT16_MASK\r
275                                          ;\r
276 #endif\r
277         \r
278         /* Store and forward checksum. */\r
279         ENET_TFWR = ENET_TFWR_STRFWD_MASK;\r
280 \r
281         /* Set Rx Buffer Size */\r
282         ENET_MRBR = ( unsigned short ) UIP_BUFSIZE;\r
283         \r
284         /* Point to the start of the circular Rx buffer descriptor queue */\r
285         ENET_RDSR = ( unsigned long ) &( xRxDescriptors[ 0 ] );\r
286         \r
287         /* Point to the start of the circular Tx buffer descriptor queue */\r
288         ENET_TDSR = ( unsigned long ) &( xTxDescriptors[ 0 ] );\r
289         \r
290         /* Clear all ENET interrupt events */\r
291         ENET_EIR = ( unsigned long ) -1;\r
292         \r
293         /* Enable interrupts. */\r
294         ENET_EIMR = 0\r
295                         /*rx irqs*/\r
296                         | ENET_EIMR_RXF_MASK/*FSL: only for complete frame, not partial buffer descriptor | ENET_EIMR_RXB_MASK*/\r
297                         /*xmit irqs*/\r
298                         | ENET_EIMR_TXF_MASK/*FSL: only for complete frame, not partial buffer descriptor | ENET_EIMR_TXB_MASK*/\r
299                         /*enet irqs*/\r
300                         | ENET_EIMR_UN_MASK | ENET_EIMR_RL_MASK | ENET_EIMR_LC_MASK | ENET_EIMR_BABT_MASK | ENET_EIMR_BABR_MASK | ENET_EIMR_EBERR_MASK\r
301                         ;\r
302         \r
303         /* Enable the MAC itself. */\r
304         ENET_ECR |= ENET_ECR_ETHEREN_MASK;\r
305         \r
306         /* Indicate that there have been empty receive buffers produced */\r
307         ENET_RDAR = ENET_RDAR_RDAR_MASK;\r
308 }\r
309 /*-----------------------------------------------------------*/\r
310 \r
311 static void prvInitialiseDescriptors( void )\r
312 {\r
313 volatile NBUF *pxDescriptor;\r
314 long x;\r
315 \r
316         for( x = 0; x < emacNUM_BUFFERS; x++ )\r
317         {\r
318                 /* Ensure none of the buffers are shown as in use at the start. */\r
319                 ucBufferInUse[ x ] = pdFALSE;\r
320         }\r
321 \r
322         /* Initialise the Rx descriptors. */\r
323         for( x = 0; x < emacNUM_RX_DESCRIPTORS; x++ )\r
324         {\r
325                 pxDescriptor = &( xRxDescriptors[ x ] );\r
326                 pxDescriptor->data = ( uint8_t* ) &( xEthernetBuffers[ x ][ 0 ] );\r
327                 pxDescriptor->data = ( uint8_t* ) __REV( ( unsigned long ) pxDescriptor->data );\r
328                 pxDescriptor->length = 0;\r
329                 pxDescriptor->status = RX_BD_E;\r
330                 pxDescriptor->bdu = 0;\r
331                 pxDescriptor->ebd_status = RX_BD_INT;\r
332                 \r
333                 /* Mark this buffer as in use. */\r
334                 ucBufferInUse[ x ] = pdTRUE;\r
335         }\r
336 \r
337         /* The last descriptor points back to the start. */\r
338         pxDescriptor->status |= RX_BD_W;\r
339         \r
340         /* Initialise the Tx descriptors. */\r
341         for( x = 0; x < emacNUM_TX_BUFFERS; x++ )\r
342         {\r
343                 pxDescriptor = &( xTxDescriptors[ x ] );\r
344                 \r
345                 /* A buffer is not allocated to the Tx descriptor until a send is\r
346                 actually required. */\r
347                 pxDescriptor->data = NULL;\r
348                 pxDescriptor->length = 0;\r
349                 pxDescriptor->status = TX_BD_TC;\r
350                 pxDescriptor->ebd_status = TX_BD_INT;\r
351         }\r
352 \r
353         /* The last descriptor points back to the start. */\r
354         pxDescriptor->status |= TX_BD_W;\r
355         \r
356         /* Use the first Rx descriptor to start with. */\r
357         ulRxDescriptorIndex = 0UL;\r
358         pxCurrentRxDesc = &( xRxDescriptors[ 0 ] );\r
359 }\r
360 /*-----------------------------------------------------------*/\r
361 \r
362 void vEMACWrite( void )\r
363 {\r
364 long x;\r
365 \r
366         /* Wait until the second transmission of the last packet has completed. */\r
367         for( x = 0; x < emacTX_WAIT_ATTEMPTS; x++ )\r
368         {\r
369                 if( ( xTxDescriptors[ 1 ].status & TX_BD_R ) != 0 )\r
370                 {\r
371                         /* Descriptor is still active. */\r
372                         vTaskDelay( emacTX_WAIT_DELAY_ms );\r
373                 }\r
374                 else\r
375                 {\r
376                         break;\r
377                 }\r
378         }\r
379         \r
380         /* Is the descriptor free after waiting for it? */\r
381         if( ( xTxDescriptors[ 1 ].status & TX_BD_R ) != 0 )\r
382         {\r
383                 /* Something has gone wrong. */\r
384                 prvResetEverything();\r
385         }\r
386         \r
387         /* Setup both descriptors to transmit the frame. */\r
388         xTxDescriptors[ 0 ].data = ( uint8_t * ) __REV( ( unsigned long ) uip_buf );\r
389         xTxDescriptors[ 0 ].length = __REVSH( uip_len );\r
390         xTxDescriptors[ 1 ].data = ( uint8_t * ) __REV( ( unsigned long ) uip_buf );\r
391         xTxDescriptors[ 1 ].length = __REVSH( uip_len );\r
392 \r
393         /* uip_buf is being sent by the Tx descriptor.  Allocate a new buffer\r
394         for use by the stack. */\r
395         uip_buf = prvGetNextBuffer();\r
396 \r
397         /* Clear previous settings and go. */\r
398         xTxDescriptors[ 0 ].status |= ( TX_BD_R | TX_BD_L );\r
399         xTxDescriptors[ 1 ].status |= ( TX_BD_R | TX_BD_L );\r
400 \r
401         /* Start the Tx. */\r
402         ENET_TDAR = ENET_TDAR_TDAR_MASK;\r
403 }\r
404 /*-----------------------------------------------------------*/\r
405 \r
406 static unsigned char *prvGetNextBuffer( void )\r
407 {\r
408 long x;\r
409 unsigned char *pucReturn = NULL;\r
410 unsigned long ulAttempts = 0;\r
411 \r
412         while( pucReturn == NULL )\r
413         {\r
414                 /* Look through the buffers to find one that is not in use by\r
415                 anything else. */\r
416                 for( x = 0; x < emacNUM_BUFFERS; x++ )\r
417                 {\r
418                         if( ucBufferInUse[ x ] == pdFALSE )\r
419                         {\r
420                                 ucBufferInUse[ x ] = pdTRUE;\r
421                                 pucReturn = ( unsigned char * ) &( xEthernetBuffers[ x ][ 0 ] );\r
422                                 break;\r
423                         }\r
424                 }\r
425 \r
426                 /* Was a buffer found? */\r
427                 if( pucReturn == NULL )\r
428                 {\r
429                         ulAttempts++;\r
430 \r
431                         if( ulAttempts >= emacBUFFER_WAIT_ATTEMPTS )\r
432                         {\r
433                                 break;\r
434                         }\r
435 \r
436                         /* Wait then look again. */\r
437                         vTaskDelay( emacBUFFER_WAIT_DELAY_ms );\r
438                 }\r
439         }\r
440 \r
441         return pucReturn;\r
442 }\r
443 /*-----------------------------------------------------------*/\r
444 \r
445 static void prvResetEverything( void )\r
446 {\r
447         /* Temporary code just to see if this gets called.  This function has not\r
448         been implemented. */\r
449         portDISABLE_INTERRUPTS();\r
450         for( ;; );\r
451 }\r
452 /*-----------------------------------------------------------*/\r
453 \r
454 unsigned short usEMACRead( void )\r
455 {\r
456 unsigned short usBytesReceived;\r
457 \r
458         usBytesReceived = prvCheckRxStatus();\r
459         usBytesReceived = __REVSH( usBytesReceived );\r
460 \r
461         if( usBytesReceived > 0 )\r
462         {\r
463                 /* Mark the pxDescriptor buffer as free as uip_buf is going to be set to\r
464                 the buffer that contains the received data. */\r
465                 prvReturnBuffer( uip_buf );\r
466 \r
467                 /* Point uip_buf to the data about to be processed. */\r
468                 uip_buf = ( void * ) pxCurrentRxDesc->data;\r
469                 uip_buf = ( void * ) __REV( ( unsigned long ) uip_buf );\r
470                 \r
471                 /* Allocate a new buffer to the descriptor, as uip_buf is now using it's\r
472                 old descriptor. */\r
473                 pxCurrentRxDesc->data = ( uint8_t * ) prvGetNextBuffer();\r
474                 pxCurrentRxDesc->data = ( uint8_t* ) __REV( ( unsigned long ) pxCurrentRxDesc->data );\r
475 \r
476                 /* Prepare the descriptor to go again. */\r
477                 pxCurrentRxDesc->status |= RX_BD_E;\r
478 \r
479                 /* Move onto the next buffer in the ring. */\r
480                 ulRxDescriptorIndex++;\r
481                 if( ulRxDescriptorIndex >= emacNUM_RX_DESCRIPTORS )\r
482                 {\r
483                         ulRxDescriptorIndex = 0UL;\r
484                 }\r
485                 pxCurrentRxDesc = &( xRxDescriptors[ ulRxDescriptorIndex ] );\r
486                 \r
487                 /* Restart Ethernet if it has stopped */\r
488                 ENET_RDAR = ENET_RDAR_RDAR_MASK;\r
489         }\r
490 \r
491         return usBytesReceived;\r
492 }\r
493 /*-----------------------------------------------------------*/\r
494 \r
495 static void prvReturnBuffer( unsigned char *pucBuffer )\r
496 {\r
497 unsigned long ul;\r
498 \r
499         /* Return a buffer to the pool of free buffers. */\r
500         for( ul = 0; ul < emacNUM_BUFFERS; ul++ )\r
501         {\r
502                 if( &( xEthernetBuffers[ ul ][ 0 ] ) == ( void * ) pucBuffer )\r
503                 {\r
504                         ucBufferInUse[ ul ] = pdFALSE;\r
505                         break;\r
506                 }\r
507         }\r
508 }\r
509 /*-----------------------------------------------------------*/\r
510 \r
511 static unsigned short prvCheckRxStatus( void )\r
512 {\r
513 unsigned long usReturn = 0;\r
514 \r
515         if( ( pxCurrentRxDesc->status & RX_BD_E ) != 0 )\r
516         {\r
517                 /* Current descriptor is still active. */\r
518         }\r
519         else\r
520         {\r
521                 /* The descriptor contains a frame.  Because of the size of the buffers\r
522                 the frame should always be complete. */\r
523                 usReturn = pxCurrentRxDesc->length;\r
524         }\r
525         \r
526         return usReturn;\r
527 }\r
528 /*-----------------------------------------------------------*/\r
529 \r
530 void vEMAC_TxISRHandler( void )\r
531 {\r
532         /* Check the buffers have not already been freed in the first of the\r
533         two Tx interrupts - which could potentially happen if the second Tx completed\r
534         during the interrupt for the first Tx. */\r
535         if( xTxDescriptors[ 0 ].data != NULL )\r
536         {\r
537                 if( ( ( xTxDescriptors[ 0 ].status & TX_BD_R ) == 0 ) && ( ( xTxDescriptors[ 0 ].status & TX_BD_R ) == 0 ) )\r
538                 {\r
539                         configASSERT( xTxDescriptors[ 0 ].data == xTxDescriptors[ 1 ].data );\r
540                         \r
541                         xTxDescriptors[ 0 ].data = ( uint8_t* ) __REV( ( unsigned long ) xTxDescriptors[ 0 ].data );\r
542                         prvReturnBuffer( xTxDescriptors[ 0 ].data );\r
543                         \r
544                         /* Just to mark the fact that the buffer has already been released. */\r
545                         xTxDescriptors[ 0 ].data = NULL;\r
546                 }\r
547         }\r
548 }\r
549 /*-----------------------------------------------------------*/\r
550 \r
551 void vEMAC_RxISRHandler( void )\r
552 {\r
553 const unsigned long ulRxEvent = uipETHERNET_RX_EVENT;\r
554 long lHigherPriorityTaskWoken = pdFALSE;\r
555 extern xQueueHandle xEMACEventQueue;\r
556 \r
557         /* An Ethernet Rx event has occurred. */\r
558         xQueueSendFromISR( xEMACEventQueue, &ulRxEvent, &lHigherPriorityTaskWoken );\r
559         portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );\r
560 }\r
561 /*-----------------------------------------------------------*/\r
562 \r
563 void vEMAC_ErrorISRHandler( void )\r
564 {\r
565         portDISABLE_INTERRUPTS();\r
566         for( ;; );\r
567 }\r
568 /*-----------------------------------------------------------*/\r
569 \r
570 volatile unsigned long ulEvent, ulMask;\r
571 void vEMAC_ISRHandler( void )\r
572 {\r
573 //unsigned long ulEvent;\r
574 long lHigherPriorityTaskWoken = pdFALSE;\r
575 const unsigned long ulRxEvent = uipETHERNET_RX_EVENT;\r
576 extern xQueueHandle xEMACEventQueue;\r
577 \r
578         /* What caused the interrupt? */\r
579         ulMask = ENET_EIMR;\r
580         ulEvent = ENET_EIR;\r
581         ulEvent &= ulMask;\r
582         \r
583         ENET_EIR = ulEvent;\r
584 \r
585         if( ( ulEvent & ENET_EIR_TXF_MASK ) != 0UL )\r
586         {\r
587                 /* Transmit complete.\r
588                 Check the buffers have not already been freed in the first of the\r
589                 two Tx interrupts - which could potentially happen if the second Tx completed\r
590                 during the interrupt for the first Tx. */\r
591                 if( xTxDescriptors[ 0 ].data != NULL )\r
592                 {\r
593                         if( ( ( xTxDescriptors[ 0 ].status & TX_BD_R ) == 0 ) && ( ( xTxDescriptors[ 0 ].status & TX_BD_R ) == 0 ) )\r
594                         {\r
595                                 configASSERT( xTxDescriptors[ 0 ].data == xTxDescriptors[ 1 ].data );\r
596                                 \r
597                                 xTxDescriptors[ 0 ].data = ( uint8_t* ) __REV( ( unsigned long ) xTxDescriptors[ 0 ].data );\r
598                                 prvReturnBuffer( xTxDescriptors[ 0 ].data );\r
599                                 \r
600                                 /* Just to mark the fact that the buffer has already been released. */\r
601                                 xTxDescriptors[ 0 ].data = NULL;\r
602                         }\r
603                 }\r
604         }\r
605 \r
606         if( ( ulEvent & ENET_EIR_RXF_MASK ) != 0UL )\r
607         {\r
608                 /* Packet Rxed. */\r
609                 xQueueSendFromISR( xEMACEventQueue, &ulRxEvent, &lHigherPriorityTaskWoken );\r
610                 portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );\r
611         }\r
612 \r
613         if( ulEvent & ( ENET_EIR_UN_MASK | ENET_EIR_RL_MASK | ENET_EIR_LC_MASK | ENET_EIR_EBERR_MASK | ENET_EIR_BABT_MASK | ENET_EIR_BABR_MASK | ENET_EIR_EBERR_MASK ) )\r
614         {\r
615                 /* Error. */\r
616                 prvInitialiseDescriptors();\r
617                 ENET_RDAR = ENET_RDAR_RDAR_MASK;\r
618         }\r
619 }\r
620 \r