]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_Kinetis_K60_Tower_IAR/webserver/EMAC.c
2e718354f4cc0041b8cf9af6e7e479f2f2336113
[freertos] / FreeRTOS / Demo / CORTEX_Kinetis_K60_Tower_IAR / webserver / EMAC.c
1 /*\r
2     FreeRTOS V8.2.2 - Copyright (C) 2015 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 /* Freescale includes. */\r
71 #include "common.h"\r
72 #include "eth_phy.h"\r
73 #include "enet.h"\r
74 #include "mii.h"\r
75 \r
76 /* FreeRTOS includes. */\r
77 #include "FreeRTOS.h"\r
78 #include "task.h"\r
79 #include "queue.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 /* Constants used for set up and initialisation. */\r
109 #define emacTX_INTERRUPT_NO                     ( 76 )\r
110 #define emacRX_INTERRUPT_NO                     ( 77 )\r
111 #define emacERROR_INTERRUPT_NO          ( 78 )\r
112 #define emacLINK_DELAY                          ( 500 / portTICK_PERIOD_MS )\r
113 #define emacPHY_STATUS                          ( 0x1F )\r
114 #define emacPHY_DUPLEX_STATUS           ( 4 << 2 )\r
115 #define emacPHY_SPEED_STATUS            ( 1 << 2 )\r
116 \r
117 /*-----------------------------------------------------------*/\r
118 \r
119 /*\r
120  * Initialise both the Rx and Tx descriptors.\r
121  */\r
122 static void prvInitialiseDescriptors( void );\r
123 \r
124 /*\r
125  * Return a pointer to a free buffer within xEthernetBuffers.\r
126  */\r
127 static unsigned char *prvGetNextBuffer( void );\r
128 \r
129 /*\r
130  * Return a buffer to the list of free buffers.\r
131  */\r
132 static void prvReturnBuffer( unsigned char *pucBuffer );\r
133 \r
134 /*\r
135  * Examine the status of the next Rx descriptor to see if it contains new data.\r
136  */\r
137 static unsigned short prvCheckRxStatus( void );\r
138 \r
139 /*\r
140  * Something has gone wrong with the descriptor usage.  Reset all the buffers\r
141  * and descriptors.\r
142  */\r
143 static void prvResetEverything( void );\r
144 \r
145 /*-----------------------------------------------------------*/\r
146 \r
147 /* The buffers and descriptors themselves.  */\r
148 #pragma data_alignment=16\r
149 volatile NBUF xRxDescriptors[ emacNUM_RX_DESCRIPTORS ];\r
150 \r
151 #pragma data_alignment=16\r
152 volatile NBUF xTxDescriptors[ emacNUM_TX_BUFFERS ];\r
153 \r
154 #pragma data_alignment=16\r
155 char xEthernetBuffers[ emacNUM_BUFFERS ][ UIP_BUFSIZE ];\r
156 \r
157 /* Used to indicate which buffers are free and which are in use.  If an index\r
158 contains 0 then the corresponding buffer in xEthernetBuffers is free, otherwise\r
159 the buffer is in use or about to be used. */\r
160 static unsigned char ucBufferInUse[ emacNUM_BUFFERS ];\r
161 \r
162 /* Points to the Rx descriptor currently in use. */\r
163 static volatile NBUF *pxCurrentRxDesc = NULL;\r
164 \r
165 /* pxCurrentRxDesc points to descriptor within the xRxDescriptors array that\r
166 has an index defined by ulRxDescriptorIndex. */\r
167 static unsigned long ulRxDescriptorIndex = 0UL;\r
168 \r
169 /* The buffer used by the uIP stack to both receive and send.  This points to\r
170 one of the Ethernet buffers when its actually in use. */\r
171 unsigned char *uip_buf = NULL;\r
172 \r
173 /*-----------------------------------------------------------*/\r
174 \r
175 void vEMACInit( void )\r
176 {\r
177 int iData;\r
178 extern int periph_clk_khz;\r
179 const unsigned char ucMACAddress[] =\r
180 {\r
181         configMAC_ADDR0, configMAC_ADDR1, configMAC_ADDR2, configMAC_ADDR3, configMAC_ADDR4, configMAC_ADDR5\r
182 };\r
183 \r
184         /* Enable the ENET clock. */\r
185         SIM_SCGC2 |= SIM_SCGC2_ENET_MASK;\r
186 \r
187         /* Allow concurrent access to MPU controller to avoid bus errors. */\r
188         MPU_CESR = 0;\r
189 \r
190         prvInitialiseDescriptors();\r
191 \r
192         /* Reset and enable. */\r
193         ENET_ECR = ENET_ECR_RESET_MASK;\r
194         \r
195         /* Wait at least 8 clock cycles */\r
196         vTaskDelay( 2 );\r
197         \r
198         /* Start the MII interface*/\r
199         mii_init( 0, periph_clk_khz / 1000L );\r
200 \r
201         /* Configure the transmit interrupt. */\r
202         set_irq_priority( emacTX_INTERRUPT_NO, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY );\r
203         enable_irq( emacTX_INTERRUPT_NO );\r
204 \r
205         /* Configure the receive interrupt. */\r
206         set_irq_priority( emacRX_INTERRUPT_NO, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY );\r
207         enable_irq( emacRX_INTERRUPT_NO );\r
208 \r
209         /* Configure the error interrupt. */\r
210         set_irq_priority( emacERROR_INTERRUPT_NO, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY );\r
211         enable_irq( emacERROR_INTERRUPT_NO );\r
212 \r
213         /* Configure the pins to the PHY - RMII mode used. */\r
214         PORTB_PCR0  = PORT_PCR_MUX( 4 ); /* RMII0_MDIO / MII0_MDIO. */\r
215         PORTB_PCR1  = PORT_PCR_MUX( 4 ); /* RMII0_MDC / MII0_MDC */\r
216         PORTA_PCR14 = PORT_PCR_MUX( 4 ); /* RMII0_CRS_DV / MII0_RXDV */\r
217         PORTA_PCR12 = PORT_PCR_MUX( 4 ); /* RMII0_RXD1 / MII0_RXD1 */\r
218         PORTA_PCR13 = PORT_PCR_MUX( 4 ); /* RMII0_RXD0/MII0_RXD0 */\r
219         PORTA_PCR15 = PORT_PCR_MUX( 4 ); /* RMII0_TXEN/MII0_TXEN */\r
220         PORTA_PCR16 = PORT_PCR_MUX( 4 ); /* RMII0_TXD0/MII0_TXD0 */\r
221         PORTA_PCR17 = PORT_PCR_MUX( 4 ); /* RMII0_TXD1/MII0_TXD1 */\r
222 \r
223         /* Is there communication with the PHY? */\r
224         do\r
225         {\r
226                 vTaskDelay( emacLINK_DELAY );\r
227                 iData = 0xFFFF;\r
228                 mii_read( 0, configPHY_ADDRESS, PHY_PHYIDR1, &iData );\r
229         \r
230         } while( iData == 0xFFFF );\r
231 \r
232         /* Start to auto negotiate. */\r
233         mii_write( 0, configPHY_ADDRESS, PHY_BMCR, ( PHY_BMCR_AN_RESTART | PHY_BMCR_AN_ENABLE ) );\r
234         \r
235         /* Wait for auto negotiate to complete. */\r
236         do\r
237         {\r
238                 vTaskDelay( emacLINK_DELAY );\r
239                 mii_read( 0, configPHY_ADDRESS, PHY_BMSR, &iData );\r
240         \r
241         } while( !( iData & PHY_BMSR_AN_COMPLETE ) );\r
242 \r
243         /* A link has been established.  What was negotiated? */\r
244         iData = 0;\r
245         mii_read( 0, configPHY_ADDRESS, emacPHY_STATUS, &iData );\r
246 \r
247         /* Clear the Individual and Group Address Hash registers */\r
248         ENET_IALR = 0;\r
249         ENET_IAUR = 0;\r
250         ENET_GALR = 0;\r
251         ENET_GAUR = 0;\r
252 \r
253         /* Set the Physical Address for the selected ENET */\r
254         enet_set_address( 0, ucMACAddress );\r
255 \r
256         ENET_RCR = ENET_RCR_MAX_FL( UIP_BUFSIZE ) | ENET_RCR_MII_MODE_MASK | ENET_RCR_CRCFWD_MASK | ENET_RCR_RMII_MODE_MASK;\r
257 \r
258         /* Clear the control registers. */\r
259         ENET_TCR = 0;\r
260 \r
261         if( iData & emacPHY_DUPLEX_STATUS )\r
262         {\r
263                 /* Full duplex */\r
264                 ENET_RCR &= ( unsigned long )~ENET_RCR_DRT_MASK;\r
265                 ENET_TCR |= ENET_TCR_FDEN_MASK;\r
266         }\r
267         else\r
268         {\r
269                 /* Half duplex */\r
270                 ENET_RCR |= ENET_RCR_DRT_MASK;\r
271                 ENET_TCR &= (unsigned long)~ENET_TCR_FDEN_MASK;\r
272         }\r
273 \r
274         if( iData & emacPHY_SPEED_STATUS )\r
275         {\r
276                 /* 10Mbps */\r
277                 ENET_RCR |= ENET_RCR_RMII_10T_MASK;\r
278         }\r
279 \r
280     ENET_ECR = ENET_ECR_EN1588_MASK;\r
281 \r
282         /* Store and forward checksum. */\r
283         ENET_TFWR = ENET_TFWR_STRFWD_MASK;\r
284 \r
285         /* Set Rx Buffer Size */\r
286         ENET_MRBR = ( unsigned short ) UIP_BUFSIZE;\r
287         \r
288         /* Point to the start of the circular Rx buffer descriptor queue */\r
289         ENET_RDSR = ( unsigned long ) &( xRxDescriptors[ 0 ] );\r
290         \r
291         /* Point to the start of the circular Tx buffer descriptor queue */\r
292         ENET_TDSR = ( unsigned long ) &( xTxDescriptors[ 0 ] );\r
293         \r
294         /* Clear all ENET interrupt events */\r
295         ENET_EIR = ( unsigned long ) -1;\r
296         \r
297         /* Enable interrupts. */\r
298         ENET_EIMR = 0\r
299                         /*rx irqs*/\r
300                         | ENET_EIMR_RXF_MASK/* only for complete frame, not partial buffer descriptor | ENET_EIMR_RXB_MASK*/\r
301                         /*xmit irqs*/\r
302                         | ENET_EIMR_TXF_MASK/* only for complete frame, not partial buffer descriptor | ENET_EIMR_TXB_MASK*/\r
303                         /*enet irqs*/\r
304                         | 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
305                         ;\r
306         \r
307         /* Enable the MAC itself. */\r
308         ENET_ECR |= ENET_ECR_ETHEREN_MASK;\r
309         \r
310         /* Indicate that there have been empty receive buffers produced */\r
311         ENET_RDAR = ENET_RDAR_RDAR_MASK;\r
312 }\r
313 /*-----------------------------------------------------------*/\r
314 \r
315 static void prvInitialiseDescriptors( void )\r
316 {\r
317 volatile NBUF *pxDescriptor;\r
318 long x;\r
319 \r
320         for( x = 0; x < emacNUM_BUFFERS; x++ )\r
321         {\r
322                 /* Ensure none of the buffers are shown as in use at the start. */\r
323                 ucBufferInUse[ x ] = pdFALSE;\r
324         }\r
325 \r
326         /* Initialise the Rx descriptors. */\r
327         for( x = 0; x < emacNUM_RX_DESCRIPTORS; x++ )\r
328         {\r
329                 pxDescriptor = &( xRxDescriptors[ x ] );\r
330                 pxDescriptor->data = ( uint8_t* ) &( xEthernetBuffers[ x ][ 0 ] );\r
331                 pxDescriptor->data = ( uint8_t* ) __REV( ( unsigned long ) pxDescriptor->data );\r
332                 pxDescriptor->length = 0;\r
333                 pxDescriptor->status = RX_BD_E;\r
334                 pxDescriptor->bdu = 0;\r
335                 pxDescriptor->ebd_status = RX_BD_INT;\r
336                 \r
337                 /* Mark this buffer as in use. */\r
338                 ucBufferInUse[ x ] = pdTRUE;\r
339         }\r
340 \r
341         /* The last descriptor points back to the start. */\r
342         pxDescriptor->status |= RX_BD_W;\r
343         \r
344         /* Initialise the Tx descriptors. */\r
345         for( x = 0; x < emacNUM_TX_BUFFERS; x++ )\r
346         {\r
347                 pxDescriptor = &( xTxDescriptors[ x ] );\r
348                 \r
349                 /* A buffer is not allocated to the Tx descriptor until a send is\r
350                 actually required. */\r
351                 pxDescriptor->data = NULL;\r
352                 pxDescriptor->length = 0;\r
353                 pxDescriptor->status = TX_BD_TC;\r
354                 pxDescriptor->ebd_status = TX_BD_INT;\r
355         }\r
356 \r
357         /* The last descriptor points back to the start. */\r
358         pxDescriptor->status |= TX_BD_W;\r
359         \r
360         /* Use the first Rx descriptor to start with. */\r
361         ulRxDescriptorIndex = 0UL;\r
362         pxCurrentRxDesc = &( xRxDescriptors[ 0 ] );\r
363 }\r
364 /*-----------------------------------------------------------*/\r
365 \r
366 void vEMACWrite( void )\r
367 {\r
368 long x;\r
369 \r
370         /* Wait until the second transmission of the last packet has completed. */\r
371         for( x = 0; x < emacTX_WAIT_ATTEMPTS; x++ )\r
372         {\r
373                 if( ( xTxDescriptors[ 1 ].status & TX_BD_R ) != 0 )\r
374                 {\r
375                         /* Descriptor is still active. */\r
376                         vTaskDelay( emacTX_WAIT_DELAY_ms );\r
377                 }\r
378                 else\r
379                 {\r
380                         break;\r
381                 }\r
382         }\r
383         \r
384         /* Is the descriptor free after waiting for it? */\r
385         if( ( xTxDescriptors[ 1 ].status & TX_BD_R ) != 0 )\r
386         {\r
387                 /* Something has gone wrong. */\r
388                 prvResetEverything();\r
389         }\r
390         \r
391         /* Setup both descriptors to transmit the frame. */\r
392         xTxDescriptors[ 0 ].data = ( uint8_t * ) __REV( ( unsigned long ) uip_buf );\r
393         xTxDescriptors[ 0 ].length = __REVSH( uip_len );\r
394         xTxDescriptors[ 1 ].data = ( uint8_t * ) __REV( ( unsigned long ) uip_buf );\r
395         xTxDescriptors[ 1 ].length = __REVSH( uip_len );\r
396 \r
397         /* uip_buf is being sent by the Tx descriptor.  Allocate a new buffer\r
398         for use by the stack. */\r
399         uip_buf = prvGetNextBuffer();\r
400 \r
401         /* Clear previous settings and go. */\r
402         xTxDescriptors[ 0 ].status |= ( TX_BD_R | TX_BD_L );\r
403         xTxDescriptors[ 1 ].status |= ( TX_BD_R | TX_BD_L );\r
404 \r
405         /* Start the Tx. */\r
406         ENET_TDAR = ENET_TDAR_TDAR_MASK;\r
407 }\r
408 /*-----------------------------------------------------------*/\r
409 \r
410 static unsigned char *prvGetNextBuffer( void )\r
411 {\r
412 long x;\r
413 unsigned char *pucReturn = NULL;\r
414 unsigned long ulAttempts = 0;\r
415 \r
416         while( pucReturn == NULL )\r
417         {\r
418                 /* Look through the buffers to find one that is not in use by\r
419                 anything else. */\r
420                 for( x = 0; x < emacNUM_BUFFERS; x++ )\r
421                 {\r
422                         if( ucBufferInUse[ x ] == pdFALSE )\r
423                         {\r
424                                 ucBufferInUse[ x ] = pdTRUE;\r
425                                 pucReturn = ( unsigned char * ) &( xEthernetBuffers[ x ][ 0 ] );\r
426                                 break;\r
427                         }\r
428                 }\r
429 \r
430                 /* Was a buffer found? */\r
431                 if( pucReturn == NULL )\r
432                 {\r
433                         ulAttempts++;\r
434 \r
435                         if( ulAttempts >= emacBUFFER_WAIT_ATTEMPTS )\r
436                         {\r
437                                 break;\r
438                         }\r
439 \r
440                         /* Wait then look again. */\r
441                         vTaskDelay( emacBUFFER_WAIT_DELAY_ms );\r
442                 }\r
443         }\r
444 \r
445         return pucReturn;\r
446 }\r
447 /*-----------------------------------------------------------*/\r
448 \r
449 static void prvResetEverything( void )\r
450 {\r
451         /* Temporary code just to see if this gets called.  This function has not\r
452         been implemented. */\r
453         portDISABLE_INTERRUPTS();\r
454         for( ;; );\r
455 }\r
456 /*-----------------------------------------------------------*/\r
457 \r
458 unsigned short usEMACRead( void )\r
459 {\r
460 unsigned short usBytesReceived;\r
461 \r
462         usBytesReceived = prvCheckRxStatus();\r
463         usBytesReceived = __REVSH( usBytesReceived );\r
464 \r
465         if( usBytesReceived > 0 )\r
466         {\r
467                 /* Mark the pxDescriptor buffer as free as uip_buf is going to be set to\r
468                 the buffer that contains the received data. */\r
469                 prvReturnBuffer( uip_buf );\r
470 \r
471                 /* Point uip_buf to the data about to be processed. */\r
472                 uip_buf = ( void * ) pxCurrentRxDesc->data;\r
473                 uip_buf = ( void * ) __REV( ( unsigned long ) uip_buf );\r
474                 \r
475                 /* Allocate a new buffer to the descriptor, as uip_buf is now using it's\r
476                 old descriptor. */\r
477                 pxCurrentRxDesc->data = ( uint8_t * ) prvGetNextBuffer();\r
478                 pxCurrentRxDesc->data = ( uint8_t* ) __REV( ( unsigned long ) pxCurrentRxDesc->data );\r
479 \r
480                 /* Prepare the descriptor to go again. */\r
481                 pxCurrentRxDesc->status |= RX_BD_E;\r
482 \r
483                 /* Move onto the next buffer in the ring. */\r
484                 ulRxDescriptorIndex++;\r
485                 if( ulRxDescriptorIndex >= emacNUM_RX_DESCRIPTORS )\r
486                 {\r
487                         ulRxDescriptorIndex = 0UL;\r
488                 }\r
489                 pxCurrentRxDesc = &( xRxDescriptors[ ulRxDescriptorIndex ] );\r
490                 \r
491                 /* Restart Ethernet if it has stopped */\r
492                 ENET_RDAR = ENET_RDAR_RDAR_MASK;\r
493         }\r
494 \r
495         return usBytesReceived;\r
496 }\r
497 /*-----------------------------------------------------------*/\r
498 \r
499 static void prvReturnBuffer( unsigned char *pucBuffer )\r
500 {\r
501 unsigned long ul;\r
502 \r
503         /* Return a buffer to the pool of free buffers. */\r
504         for( ul = 0; ul < emacNUM_BUFFERS; ul++ )\r
505         {\r
506                 if( &( xEthernetBuffers[ ul ][ 0 ] ) == ( void * ) pucBuffer )\r
507                 {\r
508                         ucBufferInUse[ ul ] = pdFALSE;\r
509                         break;\r
510                 }\r
511         }\r
512 }\r
513 /*-----------------------------------------------------------*/\r
514 \r
515 static unsigned short prvCheckRxStatus( void )\r
516 {\r
517 unsigned long usReturn = 0;\r
518 \r
519         if( ( pxCurrentRxDesc->status & RX_BD_E ) != 0 )\r
520         {\r
521                 /* Current descriptor is still active. */\r
522         }\r
523         else\r
524         {\r
525                 /* The descriptor contains a frame.  Because of the size of the buffers\r
526                 the frame should always be complete. */\r
527                 usReturn = pxCurrentRxDesc->length;\r
528         }\r
529         \r
530         return usReturn;\r
531 }\r
532 /*-----------------------------------------------------------*/\r
533 \r
534 void vEMAC_TxISRHandler( void )\r
535 {\r
536         /* Clear the interrupt. */\r
537         ENET_EIR = ENET_EIR_TXF_MASK;\r
538 \r
539         /* Check the buffers have not already been freed in the first of the\r
540         two Tx interrupts - which could potentially happen if the second Tx completed\r
541         during the interrupt for the first Tx. */\r
542         if( xTxDescriptors[ 0 ].data != NULL )\r
543         {\r
544                 if( ( ( xTxDescriptors[ 0 ].status & TX_BD_R ) == 0 ) && ( ( xTxDescriptors[ 0 ].status & TX_BD_R ) == 0 ) )\r
545                 {\r
546                         configASSERT( xTxDescriptors[ 0 ].data == xTxDescriptors[ 1 ].data );\r
547                         \r
548                         xTxDescriptors[ 0 ].data = ( uint8_t* ) __REV( ( unsigned long ) xTxDescriptors[ 0 ].data );\r
549                         prvReturnBuffer( xTxDescriptors[ 0 ].data );\r
550                         \r
551                         /* Just to mark the fact that the buffer has already been released. */\r
552                         xTxDescriptors[ 0 ].data = NULL;\r
553                 }\r
554         }\r
555 }\r
556 /*-----------------------------------------------------------*/\r
557 \r
558 void vEMAC_RxISRHandler( void )\r
559 {\r
560 const unsigned long ulRxEvent = uipETHERNET_RX_EVENT;\r
561 long lHigherPriorityTaskWoken = pdFALSE;\r
562 extern QueueHandle_t xEMACEventQueue;\r
563 \r
564         /* Clear the interrupt. */\r
565         ENET_EIR = ENET_EIR_RXF_MASK;\r
566 \r
567         /* An Ethernet Rx event has occurred. */\r
568         xQueueSendFromISR( xEMACEventQueue, &ulRxEvent, &lHigherPriorityTaskWoken );\r
569         portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );\r
570 }\r
571 /*-----------------------------------------------------------*/\r
572 \r
573 void vEMAC_ErrorISRHandler( void )\r
574 {\r
575         /* Clear the interrupt. */\r
576         ENET_EIR = ENET_EIR & ENET_EIMR;\r
577 \r
578         /* Attempt recovery.  Not very sophisticated. */\r
579         prvInitialiseDescriptors();\r
580         ENET_RDAR = ENET_RDAR_RDAR_MASK;\r
581 }\r
582 /*-----------------------------------------------------------*/\r
583 \r
584 \r