]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_Kinetis_K60_Tower_IAR/webserver/EMAC.c
bcbe08169bc36dcc6ee0b11942afab3a6707629f
[freertos] / FreeRTOS / Demo / CORTEX_Kinetis_K60_Tower_IAR / webserver / EMAC.c
1 /*\r
2  * FreeRTOS Kernel V10.3.0\r
3  * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software.\r
14  *\r
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
21  *\r
22  * http://www.FreeRTOS.org\r
23  * http://aws.amazon.com/freertos\r
24  *\r
25  * 1 tab == 4 spaces!\r
26  */\r
27 \r
28 /* Freescale includes. */\r
29 #include "common.h"\r
30 #include "eth_phy.h"\r
31 #include "enet.h"\r
32 #include "mii.h"\r
33 \r
34 /* FreeRTOS includes. */\r
35 #include "FreeRTOS.h"\r
36 #include "task.h"\r
37 #include "queue.h"\r
38 \r
39 /* uIP includes. */\r
40 #include "net/uip.h"\r
41 \r
42 /* The time to wait between attempts to obtain a free buffer. */\r
43 #define emacBUFFER_WAIT_DELAY_ms                ( 3 / portTICK_PERIOD_MS )\r
44 \r
45 /* The number of times emacBUFFER_WAIT_DELAY_ms should be waited before giving\r
46 up on attempting to obtain a free buffer all together. */\r
47 #define emacBUFFER_WAIT_ATTEMPTS                ( 30 )\r
48 \r
49 /* The number of Rx descriptors. */\r
50 #define emacNUM_RX_DESCRIPTORS                  8\r
51 \r
52 /* The number of Tx descriptors.  When using uIP there is not point in having\r
53 more than two. */\r
54 #define emacNUM_TX_BUFFERS                              2\r
55 \r
56 /* The total number of EMAC buffers to allocate. */\r
57 #define emacNUM_BUFFERS                                 ( emacNUM_RX_DESCRIPTORS + emacNUM_TX_BUFFERS )\r
58 \r
59 /* The time to wait for the Tx descriptor to become free. */\r
60 #define emacTX_WAIT_DELAY_ms                    ( 10 / portTICK_PERIOD_MS )\r
61 \r
62 /* The total number of times to wait emacTX_WAIT_DELAY_ms for the Tx descriptor to\r
63 become free. */\r
64 #define emacTX_WAIT_ATTEMPTS                    ( 50 )\r
65 \r
66 /* Constants used for set up and initialisation. */\r
67 #define emacTX_INTERRUPT_NO                     ( 76 )\r
68 #define emacRX_INTERRUPT_NO                     ( 77 )\r
69 #define emacERROR_INTERRUPT_NO          ( 78 )\r
70 #define emacLINK_DELAY                          ( 500 / portTICK_PERIOD_MS )\r
71 #define emacPHY_STATUS                          ( 0x1F )\r
72 #define emacPHY_DUPLEX_STATUS           ( 4 << 2 )\r
73 #define emacPHY_SPEED_STATUS            ( 1 << 2 )\r
74 \r
75 /*-----------------------------------------------------------*/\r
76 \r
77 /*\r
78  * Initialise both the Rx and Tx descriptors.\r
79  */\r
80 static void prvInitialiseDescriptors( void );\r
81 \r
82 /*\r
83  * Return a pointer to a free buffer within xEthernetBuffers.\r
84  */\r
85 static unsigned char *prvGetNextBuffer( void );\r
86 \r
87 /*\r
88  * Return a buffer to the list of free buffers.\r
89  */\r
90 static void prvReturnBuffer( unsigned char *pucBuffer );\r
91 \r
92 /*\r
93  * Examine the status of the next Rx descriptor to see if it contains new data.\r
94  */\r
95 static unsigned short prvCheckRxStatus( void );\r
96 \r
97 /*\r
98  * Something has gone wrong with the descriptor usage.  Reset all the buffers\r
99  * and descriptors.\r
100  */\r
101 static void prvResetEverything( void );\r
102 \r
103 /*-----------------------------------------------------------*/\r
104 \r
105 /* The buffers and descriptors themselves.  */\r
106 #pragma data_alignment=16\r
107 volatile NBUF xRxDescriptors[ emacNUM_RX_DESCRIPTORS ];\r
108 \r
109 #pragma data_alignment=16\r
110 volatile NBUF xTxDescriptors[ emacNUM_TX_BUFFERS ];\r
111 \r
112 #pragma data_alignment=16\r
113 char xEthernetBuffers[ emacNUM_BUFFERS ][ UIP_BUFSIZE ];\r
114 \r
115 /* Used to indicate which buffers are free and which are in use.  If an index\r
116 contains 0 then the corresponding buffer in xEthernetBuffers is free, otherwise\r
117 the buffer is in use or about to be used. */\r
118 static unsigned char ucBufferInUse[ emacNUM_BUFFERS ];\r
119 \r
120 /* Points to the Rx descriptor currently in use. */\r
121 static volatile NBUF *pxCurrentRxDesc = NULL;\r
122 \r
123 /* pxCurrentRxDesc points to descriptor within the xRxDescriptors array that\r
124 has an index defined by ulRxDescriptorIndex. */\r
125 static unsigned long ulRxDescriptorIndex = 0UL;\r
126 \r
127 /* The buffer used by the uIP stack to both receive and send.  This points to\r
128 one of the Ethernet buffers when its actually in use. */\r
129 unsigned char *uip_buf = NULL;\r
130 \r
131 /*-----------------------------------------------------------*/\r
132 \r
133 void vEMACInit( void )\r
134 {\r
135 int iData;\r
136 extern int periph_clk_khz;\r
137 const unsigned char ucMACAddress[] =\r
138 {\r
139         configMAC_ADDR0, configMAC_ADDR1, configMAC_ADDR2, configMAC_ADDR3, configMAC_ADDR4, configMAC_ADDR5\r
140 };\r
141 \r
142         /* Enable the ENET clock. */\r
143         SIM_SCGC2 |= SIM_SCGC2_ENET_MASK;\r
144 \r
145         /* Allow concurrent access to MPU controller to avoid bus errors. */\r
146         MPU_CESR = 0;\r
147 \r
148         prvInitialiseDescriptors();\r
149 \r
150         /* Reset and enable. */\r
151         ENET_ECR = ENET_ECR_RESET_MASK;\r
152         \r
153         /* Wait at least 8 clock cycles */\r
154         vTaskDelay( 2 );\r
155         \r
156         /* Start the MII interface*/\r
157         mii_init( 0, periph_clk_khz / 1000L );\r
158 \r
159         /* Configure the transmit interrupt. */\r
160         set_irq_priority( emacTX_INTERRUPT_NO, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY );\r
161         enable_irq( emacTX_INTERRUPT_NO );\r
162 \r
163         /* Configure the receive interrupt. */\r
164         set_irq_priority( emacRX_INTERRUPT_NO, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY );\r
165         enable_irq( emacRX_INTERRUPT_NO );\r
166 \r
167         /* Configure the error interrupt. */\r
168         set_irq_priority( emacERROR_INTERRUPT_NO, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY );\r
169         enable_irq( emacERROR_INTERRUPT_NO );\r
170 \r
171         /* Configure the pins to the PHY - RMII mode used. */\r
172         PORTB_PCR0  = PORT_PCR_MUX( 4 ); /* RMII0_MDIO / MII0_MDIO. */\r
173         PORTB_PCR1  = PORT_PCR_MUX( 4 ); /* RMII0_MDC / MII0_MDC */\r
174         PORTA_PCR14 = PORT_PCR_MUX( 4 ); /* RMII0_CRS_DV / MII0_RXDV */\r
175         PORTA_PCR12 = PORT_PCR_MUX( 4 ); /* RMII0_RXD1 / MII0_RXD1 */\r
176         PORTA_PCR13 = PORT_PCR_MUX( 4 ); /* RMII0_RXD0/MII0_RXD0 */\r
177         PORTA_PCR15 = PORT_PCR_MUX( 4 ); /* RMII0_TXEN/MII0_TXEN */\r
178         PORTA_PCR16 = PORT_PCR_MUX( 4 ); /* RMII0_TXD0/MII0_TXD0 */\r
179         PORTA_PCR17 = PORT_PCR_MUX( 4 ); /* RMII0_TXD1/MII0_TXD1 */\r
180 \r
181         /* Is there communication with the PHY? */\r
182         do\r
183         {\r
184                 vTaskDelay( emacLINK_DELAY );\r
185                 iData = 0xFFFF;\r
186                 mii_read( 0, configPHY_ADDRESS, PHY_PHYIDR1, &iData );\r
187         \r
188         } while( iData == 0xFFFF );\r
189 \r
190         /* Start to auto negotiate. */\r
191         mii_write( 0, configPHY_ADDRESS, PHY_BMCR, ( PHY_BMCR_AN_RESTART | PHY_BMCR_AN_ENABLE ) );\r
192         \r
193         /* Wait for auto negotiate to complete. */\r
194         do\r
195         {\r
196                 vTaskDelay( emacLINK_DELAY );\r
197                 mii_read( 0, configPHY_ADDRESS, PHY_BMSR, &iData );\r
198         \r
199         } while( !( iData & PHY_BMSR_AN_COMPLETE ) );\r
200 \r
201         /* A link has been established.  What was negotiated? */\r
202         iData = 0;\r
203         mii_read( 0, configPHY_ADDRESS, emacPHY_STATUS, &iData );\r
204 \r
205         /* Clear the Individual and Group Address Hash registers */\r
206         ENET_IALR = 0;\r
207         ENET_IAUR = 0;\r
208         ENET_GALR = 0;\r
209         ENET_GAUR = 0;\r
210 \r
211         /* Set the Physical Address for the selected ENET */\r
212         enet_set_address( 0, ucMACAddress );\r
213 \r
214         ENET_RCR = ENET_RCR_MAX_FL( UIP_BUFSIZE ) | ENET_RCR_MII_MODE_MASK | ENET_RCR_CRCFWD_MASK | ENET_RCR_RMII_MODE_MASK;\r
215 \r
216         /* Clear the control registers. */\r
217         ENET_TCR = 0;\r
218 \r
219         if( iData & emacPHY_DUPLEX_STATUS )\r
220         {\r
221                 /* Full duplex */\r
222                 ENET_RCR &= ( unsigned long )~ENET_RCR_DRT_MASK;\r
223                 ENET_TCR |= ENET_TCR_FDEN_MASK;\r
224         }\r
225         else\r
226         {\r
227                 /* Half duplex */\r
228                 ENET_RCR |= ENET_RCR_DRT_MASK;\r
229                 ENET_TCR &= (unsigned long)~ENET_TCR_FDEN_MASK;\r
230         }\r
231 \r
232         if( iData & emacPHY_SPEED_STATUS )\r
233         {\r
234                 /* 10Mbps */\r
235                 ENET_RCR |= ENET_RCR_RMII_10T_MASK;\r
236         }\r
237 \r
238     ENET_ECR = ENET_ECR_EN1588_MASK;\r
239 \r
240         /* Store and forward checksum. */\r
241         ENET_TFWR = ENET_TFWR_STRFWD_MASK;\r
242 \r
243         /* Set Rx Buffer Size */\r
244         ENET_MRBR = ( unsigned short ) UIP_BUFSIZE;\r
245         \r
246         /* Point to the start of the circular Rx buffer descriptor queue */\r
247         ENET_RDSR = ( unsigned long ) &( xRxDescriptors[ 0 ] );\r
248         \r
249         /* Point to the start of the circular Tx buffer descriptor queue */\r
250         ENET_TDSR = ( unsigned long ) &( xTxDescriptors[ 0 ] );\r
251         \r
252         /* Clear all ENET interrupt events */\r
253         ENET_EIR = ( unsigned long ) -1;\r
254         \r
255         /* Enable interrupts. */\r
256         ENET_EIMR = 0\r
257                         /*rx irqs*/\r
258                         | ENET_EIMR_RXF_MASK/* only for complete frame, not partial buffer descriptor | ENET_EIMR_RXB_MASK*/\r
259                         /*xmit irqs*/\r
260                         | ENET_EIMR_TXF_MASK/* only for complete frame, not partial buffer descriptor | ENET_EIMR_TXB_MASK*/\r
261                         /*enet irqs*/\r
262                         | 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
263                         ;\r
264         \r
265         /* Enable the MAC itself. */\r
266         ENET_ECR |= ENET_ECR_ETHEREN_MASK;\r
267         \r
268         /* Indicate that there have been empty receive buffers produced */\r
269         ENET_RDAR = ENET_RDAR_RDAR_MASK;\r
270 }\r
271 /*-----------------------------------------------------------*/\r
272 \r
273 static void prvInitialiseDescriptors( void )\r
274 {\r
275 volatile NBUF *pxDescriptor;\r
276 long x;\r
277 \r
278         for( x = 0; x < emacNUM_BUFFERS; x++ )\r
279         {\r
280                 /* Ensure none of the buffers are shown as in use at the start. */\r
281                 ucBufferInUse[ x ] = pdFALSE;\r
282         }\r
283 \r
284         /* Initialise the Rx descriptors. */\r
285         for( x = 0; x < emacNUM_RX_DESCRIPTORS; x++ )\r
286         {\r
287                 pxDescriptor = &( xRxDescriptors[ x ] );\r
288                 pxDescriptor->data = ( uint8_t* ) &( xEthernetBuffers[ x ][ 0 ] );\r
289                 pxDescriptor->data = ( uint8_t* ) __REV( ( unsigned long ) pxDescriptor->data );\r
290                 pxDescriptor->length = 0;\r
291                 pxDescriptor->status = RX_BD_E;\r
292                 pxDescriptor->bdu = 0;\r
293                 pxDescriptor->ebd_status = RX_BD_INT;\r
294                 \r
295                 /* Mark this buffer as in use. */\r
296                 ucBufferInUse[ x ] = pdTRUE;\r
297         }\r
298 \r
299         /* The last descriptor points back to the start. */\r
300         pxDescriptor->status |= RX_BD_W;\r
301         \r
302         /* Initialise the Tx descriptors. */\r
303         for( x = 0; x < emacNUM_TX_BUFFERS; x++ )\r
304         {\r
305                 pxDescriptor = &( xTxDescriptors[ x ] );\r
306                 \r
307                 /* A buffer is not allocated to the Tx descriptor until a send is\r
308                 actually required. */\r
309                 pxDescriptor->data = NULL;\r
310                 pxDescriptor->length = 0;\r
311                 pxDescriptor->status = TX_BD_TC;\r
312                 pxDescriptor->ebd_status = TX_BD_INT;\r
313         }\r
314 \r
315         /* The last descriptor points back to the start. */\r
316         pxDescriptor->status |= TX_BD_W;\r
317         \r
318         /* Use the first Rx descriptor to start with. */\r
319         ulRxDescriptorIndex = 0UL;\r
320         pxCurrentRxDesc = &( xRxDescriptors[ 0 ] );\r
321 }\r
322 /*-----------------------------------------------------------*/\r
323 \r
324 void vEMACWrite( void )\r
325 {\r
326 long x;\r
327 \r
328         /* Wait until the second transmission of the last packet has completed. */\r
329         for( x = 0; x < emacTX_WAIT_ATTEMPTS; x++ )\r
330         {\r
331                 if( ( xTxDescriptors[ 1 ].status & TX_BD_R ) != 0 )\r
332                 {\r
333                         /* Descriptor is still active. */\r
334                         vTaskDelay( emacTX_WAIT_DELAY_ms );\r
335                 }\r
336                 else\r
337                 {\r
338                         break;\r
339                 }\r
340         }\r
341         \r
342         /* Is the descriptor free after waiting for it? */\r
343         if( ( xTxDescriptors[ 1 ].status & TX_BD_R ) != 0 )\r
344         {\r
345                 /* Something has gone wrong. */\r
346                 prvResetEverything();\r
347         }\r
348         \r
349         /* Setup both descriptors to transmit the frame. */\r
350         xTxDescriptors[ 0 ].data = ( uint8_t * ) __REV( ( unsigned long ) uip_buf );\r
351         xTxDescriptors[ 0 ].length = __REVSH( uip_len );\r
352         xTxDescriptors[ 1 ].data = ( uint8_t * ) __REV( ( unsigned long ) uip_buf );\r
353         xTxDescriptors[ 1 ].length = __REVSH( uip_len );\r
354 \r
355         /* uip_buf is being sent by the Tx descriptor.  Allocate a new buffer\r
356         for use by the stack. */\r
357         uip_buf = prvGetNextBuffer();\r
358 \r
359         /* Clear previous settings and go. */\r
360         xTxDescriptors[ 0 ].status |= ( TX_BD_R | TX_BD_L );\r
361         xTxDescriptors[ 1 ].status |= ( TX_BD_R | TX_BD_L );\r
362 \r
363         /* Start the Tx. */\r
364         ENET_TDAR = ENET_TDAR_TDAR_MASK;\r
365 }\r
366 /*-----------------------------------------------------------*/\r
367 \r
368 static unsigned char *prvGetNextBuffer( void )\r
369 {\r
370 long x;\r
371 unsigned char *pucReturn = NULL;\r
372 unsigned long ulAttempts = 0;\r
373 \r
374         while( pucReturn == NULL )\r
375         {\r
376                 /* Look through the buffers to find one that is not in use by\r
377                 anything else. */\r
378                 for( x = 0; x < emacNUM_BUFFERS; x++ )\r
379                 {\r
380                         if( ucBufferInUse[ x ] == pdFALSE )\r
381                         {\r
382                                 ucBufferInUse[ x ] = pdTRUE;\r
383                                 pucReturn = ( unsigned char * ) &( xEthernetBuffers[ x ][ 0 ] );\r
384                                 break;\r
385                         }\r
386                 }\r
387 \r
388                 /* Was a buffer found? */\r
389                 if( pucReturn == NULL )\r
390                 {\r
391                         ulAttempts++;\r
392 \r
393                         if( ulAttempts >= emacBUFFER_WAIT_ATTEMPTS )\r
394                         {\r
395                                 break;\r
396                         }\r
397 \r
398                         /* Wait then look again. */\r
399                         vTaskDelay( emacBUFFER_WAIT_DELAY_ms );\r
400                 }\r
401         }\r
402 \r
403         return pucReturn;\r
404 }\r
405 /*-----------------------------------------------------------*/\r
406 \r
407 static void prvResetEverything( void )\r
408 {\r
409         /* Temporary code just to see if this gets called.  This function has not\r
410         been implemented. */\r
411         portDISABLE_INTERRUPTS();\r
412         for( ;; );\r
413 }\r
414 /*-----------------------------------------------------------*/\r
415 \r
416 unsigned short usEMACRead( void )\r
417 {\r
418 unsigned short usBytesReceived;\r
419 \r
420         usBytesReceived = prvCheckRxStatus();\r
421         usBytesReceived = __REVSH( usBytesReceived );\r
422 \r
423         if( usBytesReceived > 0 )\r
424         {\r
425                 /* Mark the pxDescriptor buffer as free as uip_buf is going to be set to\r
426                 the buffer that contains the received data. */\r
427                 prvReturnBuffer( uip_buf );\r
428 \r
429                 /* Point uip_buf to the data about to be processed. */\r
430                 uip_buf = ( void * ) pxCurrentRxDesc->data;\r
431                 uip_buf = ( void * ) __REV( ( unsigned long ) uip_buf );\r
432                 \r
433                 /* Allocate a new buffer to the descriptor, as uip_buf is now using it's\r
434                 old descriptor. */\r
435                 pxCurrentRxDesc->data = ( uint8_t * ) prvGetNextBuffer();\r
436                 pxCurrentRxDesc->data = ( uint8_t* ) __REV( ( unsigned long ) pxCurrentRxDesc->data );\r
437 \r
438                 /* Prepare the descriptor to go again. */\r
439                 pxCurrentRxDesc->status |= RX_BD_E;\r
440 \r
441                 /* Move onto the next buffer in the ring. */\r
442                 ulRxDescriptorIndex++;\r
443                 if( ulRxDescriptorIndex >= emacNUM_RX_DESCRIPTORS )\r
444                 {\r
445                         ulRxDescriptorIndex = 0UL;\r
446                 }\r
447                 pxCurrentRxDesc = &( xRxDescriptors[ ulRxDescriptorIndex ] );\r
448                 \r
449                 /* Restart Ethernet if it has stopped */\r
450                 ENET_RDAR = ENET_RDAR_RDAR_MASK;\r
451         }\r
452 \r
453         return usBytesReceived;\r
454 }\r
455 /*-----------------------------------------------------------*/\r
456 \r
457 static void prvReturnBuffer( unsigned char *pucBuffer )\r
458 {\r
459 unsigned long ul;\r
460 \r
461         /* Return a buffer to the pool of free buffers. */\r
462         for( ul = 0; ul < emacNUM_BUFFERS; ul++ )\r
463         {\r
464                 if( &( xEthernetBuffers[ ul ][ 0 ] ) == ( void * ) pucBuffer )\r
465                 {\r
466                         ucBufferInUse[ ul ] = pdFALSE;\r
467                         break;\r
468                 }\r
469         }\r
470 }\r
471 /*-----------------------------------------------------------*/\r
472 \r
473 static unsigned short prvCheckRxStatus( void )\r
474 {\r
475 unsigned long usReturn = 0;\r
476 \r
477         if( ( pxCurrentRxDesc->status & RX_BD_E ) != 0 )\r
478         {\r
479                 /* Current descriptor is still active. */\r
480         }\r
481         else\r
482         {\r
483                 /* The descriptor contains a frame.  Because of the size of the buffers\r
484                 the frame should always be complete. */\r
485                 usReturn = pxCurrentRxDesc->length;\r
486         }\r
487         \r
488         return usReturn;\r
489 }\r
490 /*-----------------------------------------------------------*/\r
491 \r
492 void vEMAC_TxISRHandler( void )\r
493 {\r
494         /* Clear the interrupt. */\r
495         ENET_EIR = ENET_EIR_TXF_MASK;\r
496 \r
497         /* Check the buffers have not already been freed in the first of the\r
498         two Tx interrupts - which could potentially happen if the second Tx completed\r
499         during the interrupt for the first Tx. */\r
500         if( xTxDescriptors[ 0 ].data != NULL )\r
501         {\r
502                 if( ( ( xTxDescriptors[ 0 ].status & TX_BD_R ) == 0 ) && ( ( xTxDescriptors[ 0 ].status & TX_BD_R ) == 0 ) )\r
503                 {\r
504                         configASSERT( xTxDescriptors[ 0 ].data == xTxDescriptors[ 1 ].data );\r
505                         \r
506                         xTxDescriptors[ 0 ].data = ( uint8_t* ) __REV( ( unsigned long ) xTxDescriptors[ 0 ].data );\r
507                         prvReturnBuffer( xTxDescriptors[ 0 ].data );\r
508                         \r
509                         /* Just to mark the fact that the buffer has already been released. */\r
510                         xTxDescriptors[ 0 ].data = NULL;\r
511                 }\r
512         }\r
513 }\r
514 /*-----------------------------------------------------------*/\r
515 \r
516 void vEMAC_RxISRHandler( void )\r
517 {\r
518 const unsigned long ulRxEvent = uipETHERNET_RX_EVENT;\r
519 long lHigherPriorityTaskWoken = pdFALSE;\r
520 extern QueueHandle_t xEMACEventQueue;\r
521 \r
522         /* Clear the interrupt. */\r
523         ENET_EIR = ENET_EIR_RXF_MASK;\r
524 \r
525         /* An Ethernet Rx event has occurred. */\r
526         xQueueSendFromISR( xEMACEventQueue, &ulRxEvent, &lHigherPriorityTaskWoken );\r
527         portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );\r
528 }\r
529 /*-----------------------------------------------------------*/\r
530 \r
531 void vEMAC_ErrorISRHandler( void )\r
532 {\r
533         /* Clear the interrupt. */\r
534         ENET_EIR = ENET_EIR & ENET_EIMR;\r
535 \r
536         /* Attempt recovery.  Not very sophisticated. */\r
537         prvInitialiseDescriptors();\r
538         ENET_RDAR = ENET_RDAR_RDAR_MASK;\r
539 }\r
540 /*-----------------------------------------------------------*/\r
541 \r
542 \r