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