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