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