]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/RX600_RX62N-RDK_Renesas/RTOSDemo/webserver/EMAC.c
Update version number to 9.0.0rc2.
[freertos] / FreeRTOS / Demo / RX600_RX62N-RDK_Renesas / RTOSDemo / webserver / EMAC.c
1 /*\r
2     FreeRTOS V9.0.0rc2 - Copyright (C) 2016 Real Time Engineers Ltd.\r
3     All rights reserved\r
4 \r
5     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
6 \r
7     This file is part of the FreeRTOS distribution.\r
8 \r
9     FreeRTOS is free software; you can redistribute it and/or modify it under\r
10     the terms of the GNU General Public License (version 2) as published by the\r
11     Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.\r
12 \r
13     ***************************************************************************\r
14     >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
15     >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
16     >>!   obliged to provide the source code for proprietary components     !<<\r
17     >>!   outside of the FreeRTOS kernel.                                   !<<\r
18     ***************************************************************************\r
19 \r
20     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
21     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
22     FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
23     link: http://www.freertos.org/a00114.html\r
24 \r
25     ***************************************************************************\r
26      *                                                                       *\r
27      *    FreeRTOS provides completely free yet professionally developed,    *\r
28      *    robust, strictly quality controlled, supported, and cross          *\r
29      *    platform software that is more than just the market leader, it     *\r
30      *    is the industry's de facto standard.                               *\r
31      *                                                                       *\r
32      *    Help yourself get started quickly while simultaneously helping     *\r
33      *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
34      *    tutorial book, reference manual, or both:                          *\r
35      *    http://www.FreeRTOS.org/Documentation                              *\r
36      *                                                                       *\r
37     ***************************************************************************\r
38 \r
39     http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
40     the FAQ page "My application does not run, what could be wrong?".  Have you\r
41     defined configASSERT()?\r
42 \r
43     http://www.FreeRTOS.org/support - In return for receiving this top quality\r
44     embedded software for free we request you assist our global community by\r
45     participating in the support forum.\r
46 \r
47     http://www.FreeRTOS.org/training - Investing in training allows your team to\r
48     be as productive as possible as early as possible.  Now you can receive\r
49     FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
50     Ltd, and the world's leading authority on the world's leading RTOS.\r
51 \r
52     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
53     including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
54     compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
55 \r
56     http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
57     Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
58 \r
59     http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
60     Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
61     licenses offer ticketed support, indemnification and commercial middleware.\r
62 \r
63     http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
64     engineered and independently SIL3 certified version for use in safety and\r
65     mission critical applications that require provable dependability.\r
66 \r
67     1 tab == 4 spaces!\r
68 */\r
69 \r
70 /* Hardware specific includes. */\r
71 #include "iodefine.h"\r
72 #include "typedefine.h"\r
73 #include "r_ether.h"\r
74 #include "phy.h"\r
75 \r
76 /* FreeRTOS includes. */\r
77 #include "FreeRTOS.h"\r
78 #include "task.h"\r
79 #include "semphr.h"\r
80 \r
81 /* uIP includes. */\r
82 #include "net/uip.h"\r
83 \r
84 /* The time to wait between attempts to obtain a free buffer. */\r
85 #define emacBUFFER_WAIT_DELAY_ms                ( 3 / portTICK_PERIOD_MS )\r
86 \r
87 /* The number of times emacBUFFER_WAIT_DELAY_ms should be waited before giving\r
88 up on attempting to obtain a free buffer all together. */\r
89 #define emacBUFFER_WAIT_ATTEMPTS        ( 30 )\r
90 \r
91 /* The number of Rx descriptors. */\r
92 #define emacNUM_RX_DESCRIPTORS  8\r
93 \r
94 /* The number of Tx descriptors.  When using uIP there is not point in having\r
95 more than two. */\r
96 #define emacNUM_TX_BUFFERS      2\r
97 \r
98 /* The total number of EMAC buffers to allocate. */\r
99 #define emacNUM_BUFFERS         ( emacNUM_RX_DESCRIPTORS + emacNUM_TX_BUFFERS )\r
100 \r
101 /* The time to wait for the Tx descriptor to become free. */\r
102 #define emacTX_WAIT_DELAY_ms ( 10 / portTICK_PERIOD_MS )\r
103 \r
104 /* The total number of times to wait emacTX_WAIT_DELAY_ms for the Tx descriptor to\r
105 become free. */\r
106 #define emacTX_WAIT_ATTEMPTS ( 50 )\r
107 \r
108 /* Only Rx end and Tx end interrupts are used by this driver. */\r
109 #define emacTX_END_INTERRUPT    ( 1UL << 21UL )\r
110 #define emacRX_END_INTERRUPT    ( 1UL << 18UL )\r
111 \r
112 /*-----------------------------------------------------------*/\r
113 \r
114 /* The buffers and descriptors themselves.  */\r
115 #pragma section _RX_DESC\r
116         volatile ethfifo xRxDescriptors[ emacNUM_RX_DESCRIPTORS ];\r
117 #pragma section _TX_DESC\r
118         volatile ethfifo xTxDescriptors[ emacNUM_TX_BUFFERS ];\r
119 #pragma section _ETHERNET_BUFFERS\r
120         struct\r
121         {\r
122                 unsigned long ulAlignmentVariable;\r
123                 char cBuffer[ emacNUM_BUFFERS ][ UIP_BUFSIZE ];\r
124         } xEthernetBuffers;\r
125 #pragma section\r
126 \r
127 \r
128 \r
129 \r
130 /* Used to indicate which buffers are free and which are in use.  If an index\r
131 contains 0 then the corresponding buffer in xEthernetBuffers is free, otherwise \r
132 the buffer is in use or about to be used. */\r
133 static unsigned char ucBufferInUse[ emacNUM_BUFFERS ];\r
134 \r
135 /*-----------------------------------------------------------*/\r
136 \r
137 /*\r
138  * Initialise both the Rx and Tx descriptors.\r
139  */\r
140 static void prvInitialiseDescriptors( void );\r
141 \r
142 /*\r
143  * Return a pointer to a free buffer within xEthernetBuffers.\r
144  */\r
145 static unsigned char *prvGetNextBuffer( void );\r
146 \r
147 /*\r
148  * Return a buffer to the list of free buffers.\r
149  */\r
150 static void prvReturnBuffer( unsigned char *pucBuffer );\r
151 \r
152 /*\r
153  * Examine the status of the next Rx FIFO to see if it contains new data.\r
154  */\r
155 static unsigned long prvCheckRxFifoStatus( void );\r
156 \r
157 /*\r
158  * Setup the microcontroller for communication with the PHY.\r
159  */\r
160 static void prvResetMAC( void );\r
161 \r
162 /*\r
163  * Configure the Ethernet interface peripherals.\r
164  */\r
165 static void prvConfigureEtherCAndEDMAC( void );\r
166 \r
167 /*\r
168  * Something has gone wrong with the descriptor usage.  Reset all the buffers\r
169  * and descriptors.\r
170  */\r
171 static void prvResetEverything( void );\r
172 \r
173 /*-----------------------------------------------------------*/\r
174 \r
175 /* Points to the Rx descriptor currently in use. */\r
176 static ethfifo *pxCurrentRxDesc = NULL;\r
177 \r
178 /* The buffer used by the uIP stack to both receive and send.  This points to\r
179 one of the Ethernet buffers when its actually in use. */\r
180 unsigned char *uip_buf = NULL;\r
181 \r
182 /*-----------------------------------------------------------*/\r
183 \r
184 void vInitEmac( void )\r
185 {\r
186         /* Software reset. */\r
187         prvResetMAC();\r
188         \r
189         /* Set the Rx and Tx descriptors into their initial state. */\r
190         prvInitialiseDescriptors();\r
191 \r
192         /* Set the MAC address into the ETHERC */\r
193         ETHERC.MAHR =   ( ( unsigned long ) configMAC_ADDR0 << 24UL ) | \r
194                                         ( ( unsigned long ) configMAC_ADDR1 << 16UL ) | \r
195                                         ( ( unsigned long ) configMAC_ADDR2 << 8UL ) | \r
196                                         ( unsigned long ) configMAC_ADDR3;\r
197                                         \r
198         ETHERC.MALR.BIT.MA = ( ( unsigned long ) configMAC_ADDR4 << 8UL ) |\r
199                                                  ( unsigned long ) configMAC_ADDR5;\r
200 \r
201         /* Perform rest of interface hardware configuration. */\r
202         prvConfigureEtherCAndEDMAC();\r
203         \r
204         /* Nothing received yet, so uip_buf points nowhere. */\r
205         uip_buf = NULL;\r
206 \r
207         /* Initialize the PHY */\r
208         phy_init();\r
209 }\r
210 /*-----------------------------------------------------------*/\r
211 \r
212 void vEMACWrite( void )\r
213 {\r
214 long x;\r
215 \r
216         /* Wait until the second transmission of the last packet has completed. */\r
217         for( x = 0; x < emacTX_WAIT_ATTEMPTS; x++ )\r
218         {\r
219                 if( ( xTxDescriptors[ 1 ].status & ACT ) != 0 )\r
220                 {\r
221                         /* Descriptor is still active. */\r
222                         vTaskDelay( emacTX_WAIT_DELAY_ms );\r
223                 }\r
224                 else\r
225                 {\r
226                         break;\r
227                 }\r
228         }\r
229         \r
230         /* Is the descriptor free after waiting for it? */\r
231         if( ( xTxDescriptors[ 1 ].status & ACT ) != 0 )\r
232         {\r
233                 /* Something has gone wrong. */\r
234                 prvResetEverything();\r
235         }\r
236         \r
237         /* Setup both descriptors to transmit the frame. */\r
238         xTxDescriptors[ 0 ].buf_p = ( char * ) uip_buf;\r
239         xTxDescriptors[ 0 ].bufsize = uip_len;  \r
240         xTxDescriptors[ 1 ].buf_p = ( char * ) uip_buf;\r
241         xTxDescriptors[ 1 ].bufsize = uip_len;\r
242 \r
243         /* uip_buf is being sent by the Tx descriptor.  Allocate a new buffer\r
244         for use by the stack. */\r
245         uip_buf = prvGetNextBuffer();\r
246 \r
247         /* Clear previous settings and go. */\r
248         xTxDescriptors[0].status &= ~( FP1 | FP0 );\r
249         xTxDescriptors[0].status |= ( FP1 | FP0 | ACT );\r
250         xTxDescriptors[1].status &= ~( FP1 | FP0 );\r
251         xTxDescriptors[1].status |= ( FP1 | FP0 | ACT );\r
252 \r
253         EDMAC.EDTRR.LONG = 0x00000001;\r
254 }\r
255 /*-----------------------------------------------------------*/\r
256 \r
257 unsigned long ulEMACRead( void )\r
258 {\r
259 unsigned long ulBytesReceived;\r
260 \r
261         ulBytesReceived = prvCheckRxFifoStatus();\r
262 \r
263         if( ulBytesReceived > 0 )\r
264         {\r
265                 /* Mark the pxDescriptor buffer as free as uip_buf is going to be set to\r
266                 the buffer that contains the received data. */\r
267                 prvReturnBuffer( uip_buf );\r
268 \r
269                 /* Point uip_buf to the data about ot be processed. */\r
270                 uip_buf = ( void * ) pxCurrentRxDesc->buf_p;\r
271                 \r
272                 /* Allocate a new buffer to the descriptor, as uip_buf is now using it's\r
273                 old descriptor. */\r
274                 pxCurrentRxDesc->buf_p = prvGetNextBuffer();\r
275 \r
276                 /* Prepare the descriptor to go again. */\r
277                 pxCurrentRxDesc->status &= ~( FP1 | FP0 );\r
278                 pxCurrentRxDesc->status |= ACT;\r
279 \r
280                 /* Move onto the next buffer in the ring. */\r
281                 pxCurrentRxDesc = pxCurrentRxDesc->next;\r
282                 \r
283                 if( EDMAC.EDRRR.LONG == 0x00000000L )\r
284                 {\r
285                         /* Restart Ethernet if it has stopped */\r
286                         EDMAC.EDRRR.LONG = 0x00000001L;\r
287                 }\r
288         }\r
289 \r
290         return ulBytesReceived;\r
291 }\r
292 /*-----------------------------------------------------------*/\r
293 \r
294 long lEMACWaitForLink( void )\r
295 {\r
296 long lReturn;\r
297 \r
298         /* Set the link status. */\r
299         switch( phy_set_autonegotiate() )\r
300         {\r
301                 /* Half duplex link */\r
302                 case PHY_LINK_100H:\r
303                                                                 ETHERC.ECMR.BIT.DM = 0;\r
304                                                                 ETHERC.ECMR.BIT.RTM = 1;\r
305                                                                 lReturn = pdPASS;\r
306                                                                 break;\r
307 \r
308                 case PHY_LINK_10H:\r
309                                                                 ETHERC.ECMR.BIT.DM = 0;\r
310                                                                 ETHERC.ECMR.BIT.RTM = 0;\r
311                                                                 lReturn = pdPASS;\r
312                                                                 break;\r
313 \r
314 \r
315                 /* Full duplex link */\r
316                 case PHY_LINK_100F:\r
317                                                                 ETHERC.ECMR.BIT.DM = 1;\r
318                                                                 ETHERC.ECMR.BIT.RTM = 1;\r
319                                                                 lReturn = pdPASS;\r
320                                                                 break;\r
321                 \r
322                 case PHY_LINK_10F:\r
323                                                                 ETHERC.ECMR.BIT.DM = 1;\r
324                                                                 ETHERC.ECMR.BIT.RTM = 0;\r
325                                                                 lReturn = pdPASS;\r
326                                                                 break;\r
327 \r
328                 default:\r
329                                                                 lReturn = pdFAIL;\r
330                                                                 break;\r
331         }\r
332 \r
333         if( lReturn == pdPASS )\r
334         {\r
335                 /* Enable receive and transmit. */\r
336                 ETHERC.ECMR.BIT.RE = 1;\r
337                 ETHERC.ECMR.BIT.TE = 1;\r
338 \r
339                 /* Enable EDMAC receive */\r
340                 EDMAC.EDRRR.LONG = 0x1;\r
341         }\r
342         \r
343         return lReturn;\r
344 }\r
345 /*-----------------------------------------------------------*/\r
346 \r
347 static void prvInitialiseDescriptors( void )\r
348 {\r
349 ethfifo *pxDescriptor;\r
350 long x;\r
351 \r
352         for( x = 0; x < emacNUM_BUFFERS; x++ )\r
353         {\r
354                 /* Ensure none of the buffers are shown as in use at the start. */\r
355                 ucBufferInUse[ x ] = pdFALSE;\r
356         }\r
357 \r
358         /* Initialise the Rx descriptors. */\r
359         for( x = 0; x < emacNUM_RX_DESCRIPTORS; x++ )\r
360         {\r
361                 pxDescriptor = &( xRxDescriptors[ x ] );\r
362                 pxDescriptor->buf_p = &( xEthernetBuffers.cBuffer[ x ][ 0 ] );\r
363 \r
364                 pxDescriptor->bufsize = UIP_BUFSIZE;\r
365                 pxDescriptor->size = 0;\r
366                 pxDescriptor->status = ACT;\r
367                 pxDescriptor->next = &xRxDescriptors[ x + 1 ];  \r
368                 \r
369                 /* Mark this buffer as in use. */\r
370                 ucBufferInUse[ x ] = pdTRUE;\r
371         }\r
372 \r
373         /* The last descriptor points back to the start. */\r
374         pxDescriptor->status |= DL;\r
375         pxDescriptor->next = &xRxDescriptors[ 0 ];\r
376         \r
377         /* Initialise the Tx descriptors. */\r
378         for( x = 0; x < emacNUM_TX_BUFFERS; x++ )\r
379         {\r
380                 pxDescriptor = &( xTxDescriptors[ x ] );\r
381                 \r
382                 /* A buffer is not allocated to the Tx descriptor until a send is\r
383                 actually required. */\r
384                 pxDescriptor->buf_p = NULL;\r
385 \r
386                 pxDescriptor->bufsize = UIP_BUFSIZE;\r
387                 pxDescriptor->size = 0;\r
388                 pxDescriptor->status = 0;\r
389                 pxDescriptor->next = &xTxDescriptors[ x + 1 ];  \r
390         }\r
391 \r
392         /* The last descriptor points back to the start. */\r
393         pxDescriptor->status |= DL;\r
394         pxDescriptor->next = &( xTxDescriptors[ 0 ] );\r
395         \r
396         /* Use the first Rx descriptor to start with. */\r
397         pxCurrentRxDesc = &( xRxDescriptors[ 0 ] );\r
398 }\r
399 /*-----------------------------------------------------------*/\r
400 \r
401 static unsigned char *prvGetNextBuffer( void )\r
402 {\r
403 long x;\r
404 unsigned char *pucReturn = NULL;\r
405 unsigned long ulAttempts = 0;\r
406 \r
407         while( pucReturn == NULL )\r
408         {\r
409                 /* Look through the buffers to find one that is not in use by\r
410                 anything else. */\r
411                 for( x = 0; x < emacNUM_BUFFERS; x++ )\r
412                 {\r
413                         if( ucBufferInUse[ x ] == pdFALSE )\r
414                         {\r
415                                 ucBufferInUse[ x ] = pdTRUE;\r
416                                 pucReturn = ( unsigned char * ) &( xEthernetBuffers.cBuffer[ x ][ 0 ] );\r
417                                 break;\r
418                         }\r
419                 }\r
420 \r
421                 /* Was a buffer found? */\r
422                 if( pucReturn == NULL )\r
423                 {\r
424                         ulAttempts++;\r
425 \r
426                         if( ulAttempts >= emacBUFFER_WAIT_ATTEMPTS )\r
427                         {\r
428                                 break;\r
429                         }\r
430 \r
431                         /* Wait then look again. */\r
432                         vTaskDelay( emacBUFFER_WAIT_DELAY_ms );\r
433                 }\r
434         }\r
435 \r
436         return pucReturn;\r
437 }\r
438 /*-----------------------------------------------------------*/\r
439 \r
440 static void prvReturnBuffer( unsigned char *pucBuffer )\r
441 {\r
442 unsigned long ul;\r
443 \r
444         /* Return a buffer to the pool of free buffers. */\r
445         for( ul = 0; ul < emacNUM_BUFFERS; ul++ )\r
446         {\r
447                 if( &( xEthernetBuffers.cBuffer[ ul ][ 0 ] ) == ( void * ) pucBuffer )\r
448                 {\r
449                         ucBufferInUse[ ul ] = pdFALSE;\r
450                         break;\r
451                 }\r
452         }\r
453 }\r
454 /*-----------------------------------------------------------*/\r
455 \r
456 static void prvResetEverything( void )\r
457 {\r
458         /* Temporary code just to see if this gets called.  This function has not\r
459         been implemented. */\r
460         portDISABLE_INTERRUPTS();\r
461         for( ;; );\r
462 }\r
463 /*-----------------------------------------------------------*/\r
464 \r
465 static unsigned long prvCheckRxFifoStatus( void )\r
466 {\r
467 unsigned long ulReturn = 0;\r
468 \r
469         if( ( pxCurrentRxDesc->status & ACT ) != 0 )\r
470         {\r
471                 /* Current descriptor is still active. */\r
472         }\r
473         else if( ( pxCurrentRxDesc->status & FE ) != 0 )\r
474         {\r
475                 /* Frame error.  Clear the error. */\r
476                 pxCurrentRxDesc->status &= ~( FP1 | FP0 | FE );\r
477                 pxCurrentRxDesc->status &= ~( RMAF | RRF | RTLF | RTSF | PRE | CERF );\r
478                 pxCurrentRxDesc->status |= ACT;\r
479                 pxCurrentRxDesc = pxCurrentRxDesc->next;\r
480 \r
481                 if( EDMAC.EDRRR.LONG == 0x00000000UL )\r
482                 {\r
483                         /* Restart Ethernet if it has stopped. */\r
484                         EDMAC.EDRRR.LONG = 0x00000001UL;\r
485                 }       \r
486         }\r
487         else\r
488         {\r
489                 /* The descriptor contains a frame.  Because of the size of the buffers\r
490                 the frame should always be complete. */\r
491                 if( ( pxCurrentRxDesc->status & FP0 ) == FP0 )\r
492                 {\r
493                         ulReturn = pxCurrentRxDesc->size;\r
494                 }\r
495                 else\r
496                 {\r
497                         /* Do not expect to get here. */\r
498                         prvResetEverything();\r
499                 }\r
500         }\r
501         \r
502         return ulReturn;\r
503 }\r
504 /*-----------------------------------------------------------*/\r
505 \r
506 static void prvResetMAC( void )\r
507 {\r
508         /* Ensure the EtherC and EDMAC are enabled. */\r
509         SYSTEM.MSTPCRB.BIT.MSTPB15 = 0;\r
510         vTaskDelay( 100 / portTICK_PERIOD_MS );\r
511         \r
512         EDMAC.EDMR.BIT.SWR = 1; \r
513         \r
514         /* Crude wait for reset to complete. */\r
515         vTaskDelay( 500 / portTICK_PERIOD_MS ); \r
516 }\r
517 /*-----------------------------------------------------------*/\r
518 \r
519 static void prvConfigureEtherCAndEDMAC( void )\r
520 {\r
521         /* Initialisation code taken from Renesas example project. */\r
522         \r
523         /* TODO:    Check   bit 5   */\r
524         ETHERC.ECSR.LONG = 0x00000037;                          /* Clear all ETHERC statuS BFR, PSRTO, LCHNG, MPD, ICD */\r
525 \r
526         /* Set the EDMAC interrupt priority. */\r
527         _IPR( _ETHER_EINT ) = configKERNEL_INTERRUPT_PRIORITY;\r
528 \r
529         /* Enable interrupts of interest only. */\r
530         EDMAC.EESIPR.LONG = emacTX_END_INTERRUPT | emacRX_END_INTERRUPT;\r
531         ETHERC.RFLR.LONG = 1518;                                        /* Ether payload is 1500+ CRC */\r
532         ETHERC.IPGR.LONG = 0x00000014;                          /* Intergap is 96-bit time */\r
533 \r
534         /* EDMAC */\r
535         EDMAC.EESR.LONG = 0x47FF0F9F;                           /* Clear all ETHERC and EDMAC status bits */\r
536         #ifdef __LIT\r
537                 EDMAC.EDMR.BIT.DE = 1;\r
538         #endif\r
539         EDMAC.RDLAR = ( void * ) pxCurrentRxDesc;       /* Initialaize Rx Descriptor List Address */\r
540         EDMAC.TDLAR = &( xTxDescriptors[ 0 ] );         /* Initialaize Tx Descriptor List Address */\r
541         EDMAC.TRSCER.LONG = 0x00000000;                         /* Copy-back status is RFE & TFE only   */\r
542         EDMAC.TFTR.LONG = 0x00000000;                           /* Threshold of Tx_FIFO */\r
543         EDMAC.FDR.LONG = 0x00000000;                            /* Transmit fifo & receive fifo is 256 bytes */\r
544         EDMAC.RMCR.LONG = 0x00000003;                           /* Receive function is normal mode(continued) */\r
545         ETHERC.ECMR.BIT.PRM = 0;                                        /* Ensure promiscuous mode is off. */\r
546                 \r
547         /* Enable the interrupt... */\r
548         _IEN( _ETHER_EINT ) = 1;        \r
549 }\r
550 /*-----------------------------------------------------------*/\r
551 \r
552 #pragma interrupt ( vEMAC_ISR_Handler( vect = VECT_ETHER_EINT, enable ) )\r
553 void vEMAC_ISR_Handler( void )\r
554 {\r
555 unsigned long ul = EDMAC.EESR.LONG;\r
556 long lHigherPriorityTaskWoken = pdFALSE;\r
557 extern QueueHandle_t xEMACEventQueue;\r
558 const unsigned long ulRxEvent = uipETHERNET_RX_EVENT;\r
559 \r
560         /* Has a Tx end occurred? */\r
561         if( ul & emacTX_END_INTERRUPT )\r
562         {\r
563                 /* Only return the buffer to the pool once both Txes have completed. */\r
564                 prvReturnBuffer( ( void * ) xTxDescriptors[ 0 ].buf_p );\r
565                 EDMAC.EESR.LONG = emacTX_END_INTERRUPT;\r
566         }\r
567 \r
568         /* Has an Rx end occurred? */\r
569         if( ul & emacRX_END_INTERRUPT )\r
570         {\r
571                 /* Make sure the Ethernet task is not blocked waiting for a packet. */\r
572                 xQueueSendFromISR( xEMACEventQueue, &ulRxEvent, &lHigherPriorityTaskWoken );\r
573                 portYIELD_FROM_ISR( lHigherPriorityTaskWoken );\r
574                 EDMAC.EESR.LONG = emacRX_END_INTERRUPT;\r
575         }\r
576 }\r
577 \r