OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [ColdFire_MCF51CN128_CodeWarrior/] [Sources/] [FEC.c] - Blame information for rev 649

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 jeremybenn
/*
2
    This file is part of the FreeRTOS.org distribution.
3
 
4
    FreeRTOS.org is free software; you can redistribute it and/or modify it
5
    under the terms of the GNU General Public License (version 2) as published
6
    by the Free Software Foundation and modified by the FreeRTOS exception.
7
 
8
    FreeRTOS.org is distributed in the hope that it will be useful,    but WITHOUT
9
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11
    more details.
12
 
13
    You should have received a copy of the GNU General Public License along
14
    with FreeRTOS.org; if not, write to the Free Software Foundation, Inc., 59
15
    Temple Place, Suite 330, Boston, MA  02111-1307  USA.
16
 
17
    A special exception to the GPL is included to allow you to distribute a
18
    combined work that includes FreeRTOS.org without being obliged to provide
19
    the source code for any proprietary components.  See the licensing section
20
    of http://www.FreeRTOS.org for full details.
21
 
22
 
23
    ***************************************************************************
24
    *                                                                         *
25
    * Get the FreeRTOS eBook!  See http://www.FreeRTOS.org/Documentation      *
26
    *                                                                         *
27
    * This is a concise, step by step, 'hands on' guide that describes both   *
28
    * general multitasking concepts and FreeRTOS specifics. It presents and   *
29
    * explains numerous examples that are written using the FreeRTOS API.     *
30
    * Full source code for all the examples is provided in an accompanying    *
31
    * .zip file.                                                              *
32
    *                                                                         *
33
    ***************************************************************************
34
 
35
    1 tab == 4 spaces!
36
 
37
    Please ensure to read the configuration and relevant port sections of the
38
    online documentation.
39
 
40
    http://www.FreeRTOS.org - Documentation, latest information, license and
41
    contact details.
42
 
43
    http://www.SafeRTOS.com - A version that is certified for use in safety
44
    critical systems.
45
 
46
    http://www.OpenRTOS.com - Commercial support, development, porting,
47
    licensing and training services.
48
*/
49
 
50
 
51
/* Kernel includes. */
52
#include "FreeRTOS.h"
53
#include "semphr.h"
54
#include "task.h"
55
 
56
/* Demo includes. */
57
#include "FEC.h"
58
#include "fecbd.h"
59
#include "mii.h"
60
#include "eth_phy.h"
61
#include "eth.h"
62
 
63
/* uIP includes. */
64
#include "uip.h"
65
#include "uip_arp.h"
66
 
67
/*-----------------------------------------------------------*/
68
 
69
/* FEC hardware specifics. */
70
#define MCF_FEC_MSCR_MII_SPEED(x)                       (((x)&0x3F)<<0x1)
71
#define MCF_FEC_RDAR_R_DES_ACTIVE           ( 0x1000000 )
72
#define MCF_FEC_TDAR_X_DES_ACTIVE           ( 0x1000000 )
73
 
74
/* PHY hardware specifics. */
75
#define PHY_STATUS                                                      ( 16 )
76
#define PHY_DUPLEX_STATUS                                       ( 4 )
77
 
78
/* Delay between polling the PHY to see if a link has been established. */
79
#define fecLINK_DELAY                                           ( 500 / portTICK_RATE_MS )
80
 
81
/* Very short delay to use when waiting for the Tx to finish with a buffer if
82
we run out of Rx buffers. */
83
#define fecMINIMAL_DELAY                                        ( 3 / portTICK_RATE_MS )
84
 
85
/* Don't block to wait for a buffer more than this many times. */
86
#define uipBUFFER_WAIT_ATTEMPTS ( 30 )
87
 
88
/* The Tx re-uses the Rx buffers and only has one descriptor. */
89
#define fecNUM_TX_DESCRIPTORS                           ( 1 )
90
 
91
/* The total number of buffers available, which should be greater than the
92
number of Rx descriptors. */
93
#define fecNUM_BUFFERS                                          ( configNUM_FEC_RX_DESCRIPTORS + 2 )
94
 
95
/*-----------------------------------------------------------*/
96
 
97
/*
98
 * Return an unused buffer to the pool of free buffers.
99
 */
100
static void prvReturnBuffer( unsigned char *pucBuffer );
101
 
102
/*
103
 * Find and return the next buffer that is not in use by anything else.
104
 */
105
static unsigned char *prvGetFreeBuffer( void );
106
/*-----------------------------------------------------------*/
107
 
108
/* The semaphore used to wake the uIP task when data arrives. */
109
xSemaphoreHandle xFECSemaphore = NULL;
110
 
111
/* The buffer used by the uIP stack.  In this case the pointer is used to
112
point to one of the Rx buffers to avoid having to copy the Rx buffer into
113
the uIP buffer. */
114
unsigned char *uip_buf;
115
 
116
/* The DMA descriptors.  These are char arrays to allow us to align them
117
correctly. */
118
static unsigned char xFECTxDescriptors_unaligned[ ( fecNUM_TX_DESCRIPTORS * sizeof( FECBD ) ) + 16 ];
119
static unsigned char xFECRxDescriptors_unaligned[ ( configNUM_FEC_RX_DESCRIPTORS * sizeof( FECBD ) ) + 16 ];
120
static FECBD *pxFECTxDescriptor;
121
static FECBD *xFECRxDescriptors;
122
 
123
/* The DMA buffer.  This is a char arrays to allow it to be aligned correctly. */
124
static unsigned char ucFECRxBuffers[ ( fecNUM_BUFFERS * configFEC_BUFFER_SIZE ) + 16 ];
125
 
126
/* Index to the next descriptor to be inspected for received data. */
127
static unsigned long ulNextRxDescriptor = 0;
128
 
129
/* Contains the start address of each Rx buffer, after it has been correctly
130
aligned. */
131
static unsigned char *pucAlignedBufferStartAddresses[ fecNUM_BUFFERS ] = { 0 };
132
 
133
/* Each ucBufferInUse index corresponds to a position in the same index in the
134
pucAlignedBufferStartAddresses array.  If the index contains a 1 then the
135
buffer within pucAlignedBufferStartAddresses is in use, if it contains a 0 then
136
the buffer is free. */
137
static unsigned char ucBufferInUse[ fecNUM_BUFFERS ] = { 0 };
138
 
139
/*-----------------------------------------------------------*/
140
 
141
/********************************************************************/
142
/*
143
 * Write a value to a PHY's MII register.
144
 *
145
 * Parameters:
146
 *  ch          FEC channel
147
 *  phy_addr    Address of the PHY.
148
 *  reg_addr    Address of the register in the PHY.
149
 *  data        Data to be written to the PHY register.
150
 *
151
 * Return Values:
152
 *  0 on failure
153
 *  1 on success.
154
 *
155
 * Please refer to your PHY manual for registers and their meanings.
156
 * mii_write() polls for the FEC's MII interrupt event and clears it.
157
 * If after a suitable amount of time the event isn't triggered, a
158
 * value of 0 is returned.
159
 */
160
static int fec_mii_write( int phy_addr, int reg_addr, int data )
161
{
162
int timeout;
163
unsigned long eimr;
164
 
165
        /* Clear the MII interrupt bit */
166
        EIR = EIR_MII;
167
 
168
        /* Mask the MII interrupt */
169
        eimr = EIMR;
170
        EIMR &= ~EIMR_MII;
171
 
172
        /* Write to the MII Management Frame Register to kick-off the MII write */
173
        MMFR = ( unsigned long ) ( FEC_MMFR_ST_01 | FEC_MMFR_OP_WRITE | FEC_MMFR_PA(phy_addr) | FEC_MMFR_RA(reg_addr) | FEC_MMFR_TA_10 | FEC_MMFR_DATA( data ) );
174
 
175
        /* Poll for the MII interrupt (interrupt should be masked) */
176
        for (timeout = 0; timeout < FEC_MII_TIMEOUT; timeout++)
177
        {
178
                if( EIR & EIR_MII)
179
                {
180
                        break;
181
                }
182
        }
183
 
184
        if( timeout == FEC_MII_TIMEOUT )
185
        {
186
                return 0;
187
        }
188
 
189
        /* Clear the MII interrupt bit */
190
        EIR = EIR_MII;
191
 
192
        /* Restore the EIMR */
193
        EIMR = eimr;
194
 
195
        return 1;
196
}
197
 
198
/********************************************************************/
199
/*
200
 * Read a value from a PHY's MII register.
201
 *
202
 * Parameters:
203
 *  ch          FEC channel
204
 *  phy_addr    Address of the PHY.
205
 *  reg_addr    Address of the register in the PHY.
206
 *  data        Pointer to storage for the Data to be read
207
 *              from the PHY register (passed by reference)
208
 *
209
 * Return Values:
210
 *  0 on failure
211
 *  1 on success.
212
 *
213
 * Please refer to your PHY manual for registers and their meanings.
214
 * mii_read() polls for the FEC's MII interrupt event and clears it.
215
 * If after a suitable amount of time the event isn't triggered, a
216
 * value of 0 is returned.
217
 */
218
static int fec_mii_read( int phy_addr, int reg_addr, unsigned short* data )
219
{
220
int timeout;
221
unsigned long eimr;
222
 
223
        /* Clear the MII interrupt bit */
224
        EIR = 0xffffffff;
225
 
226
        /* Mask the MII interrupt */
227
        eimr = EIMR;
228
        EIMR &= ~EIMR_MII;
229
 
230
        /* Write to the MII Management Frame Register to kick-off the MII read */
231
        MMFR = ( unsigned long ) ( FEC_MMFR_ST_01 | FEC_MMFR_OP_READ | FEC_MMFR_PA(phy_addr) | FEC_MMFR_RA(reg_addr) | FEC_MMFR_TA_10 );
232
 
233
        /* Poll for the MII interrupt (interrupt should be masked) */
234
        for (timeout = 0; timeout < FEC_MII_TIMEOUT; timeout++)
235
        {
236
                if (EIR)
237
                {
238
                        break;
239
                }
240
        }
241
 
242
        if(timeout == FEC_MII_TIMEOUT)
243
        {
244
                return 0;
245
        }
246
 
247
        /* Clear the MII interrupt bit */
248
        EIR = EIR_MII;
249
 
250
        /* Restore the EIMR */
251
        EIMR = eimr;
252
 
253
        *data = (unsigned short)(MMFR & 0x0000FFFF);
254
 
255
        return 1;
256
}
257
 
258
 
259
/********************************************************************/
260
/*
261
 * Generate the hash table settings for the given address
262
 *
263
 * Parameters:
264
 *  addr    48-bit (6 byte) Address to generate the hash for
265
 *
266
 * Return Value:
267
 *  The 6 most significant bits of the 32-bit CRC result
268
 */
269
static unsigned char fec_hash_address( const unsigned char* addr )
270
{
271
unsigned long crc;
272
unsigned char byte;
273
int i, j;
274
 
275
        crc = 0xFFFFFFFF;
276
        for(i=0; i<6; ++i)
277
        {
278
                byte = addr[i];
279
                for(j=0; j<8; ++j)
280
                {
281
                        if((byte & 0x01)^(crc & 0x01))
282
                        {
283
                                crc >>= 1;
284
                                crc = crc ^ 0xEDB88320;
285
                        }
286
                        else
287
                        {
288
                                crc >>= 1;
289
                        }
290
 
291
                        byte >>= 1;
292
                }
293
        }
294
 
295
        return (unsigned char)(crc >> 26);
296
}
297
 
298
/********************************************************************/
299
/*
300
 * Set the Physical (Hardware) Address and the Individual Address
301
 * Hash in the selected FEC
302
 *
303
 * Parameters:
304
 *  ch  FEC channel
305
 *  pa  Physical (Hardware) Address for the selected FEC
306
 */
307
static void fec_set_address( const unsigned char *pa )
308
{
309
        unsigned char crc;
310
 
311
        /*
312
        * Set the Physical Address
313
        */
314
        PALR = (unsigned long)((pa[0]<<24) | (pa[1]<<16) | (pa[2]<<8) | pa[3]);
315
        PAUR = (unsigned long)((pa[4]<<24) | (pa[5]<<16));
316
 
317
        /*
318
        * Calculate and set the hash for given Physical Address
319
        * in the  Individual Address Hash registers
320
        */
321
        crc = fec_hash_address(pa);
322
        if(crc >= 32)
323
        {
324
                IAUR |= (unsigned long)(1 << (crc - 32));
325
        }
326
        else
327
        {
328
                IALR |= (unsigned long)(1 << crc);
329
        }
330
}
331
/*-----------------------------------------------------------*/
332
 
333
static void prvInitialiseFECBuffers( void )
334
{
335
unsigned portBASE_TYPE ux;
336
unsigned char *pcBufPointer;
337
 
338
        /* Set the pointer to a correctly aligned address. */
339
        pcBufPointer = &( xFECTxDescriptors_unaligned[ 0 ] );
340
        while( ( ( unsigned long ) pcBufPointer & 0x0fUL ) != 0 )
341
        {
342
                pcBufPointer++;
343
        }
344
 
345
        pxFECTxDescriptor = ( FECBD * ) pcBufPointer;
346
 
347
        /* Likewise the pointer to the Rx descriptor. */
348
        pcBufPointer = &( xFECRxDescriptors_unaligned[ 0 ] );
349
        while( ( ( unsigned long ) pcBufPointer & 0x0fUL ) != 0 )
350
        {
351
                pcBufPointer++;
352
        }
353
 
354
        xFECRxDescriptors = ( FECBD * ) pcBufPointer;
355
 
356
        /* There is no Tx buffer as the Rx buffer is reused. */
357
        pxFECTxDescriptor->length = 0;
358
        pxFECTxDescriptor->status = 0;
359
 
360
        /* Align the Rx buffers. */
361
        pcBufPointer = &( ucFECRxBuffers[ 0 ] );
362
        while( ( ( unsigned long ) pcBufPointer & 0x0fUL ) != 0 )
363
        {
364
                pcBufPointer++;
365
        }
366
 
367
        /* Then fill in the Rx descriptors. */
368
        for( ux = 0; ux < configNUM_FEC_RX_DESCRIPTORS; ux++ )
369
        {
370
            xFECRxDescriptors[ ux ].status = RX_BD_E;
371
            xFECRxDescriptors[ ux ].length = configFEC_BUFFER_SIZE;
372
            xFECRxDescriptors[ ux ].data = pcBufPointer;
373
 
374
                /* Note the start address of the buffer now that it is correctly
375
                aligned. */
376
                pucAlignedBufferStartAddresses[ ux ] = pcBufPointer;
377
 
378
                /* The buffer is in use by the descriptor. */
379
                ucBufferInUse[ ux ] = pdTRUE;
380
 
381
            pcBufPointer += configFEC_BUFFER_SIZE;
382
        }
383
 
384
        /* Note the start address of the last buffer as one more buffer is
385
        allocated than there are Rx descriptors. */
386
        pucAlignedBufferStartAddresses[ ux ] = pcBufPointer;
387
 
388
        /* Set uip_buf to point to the last buffer. */
389
        uip_buf = pcBufPointer;
390
        ucBufferInUse[ ux ] = pdTRUE;
391
 
392
        /* Set the wrap bit in the last descriptors to form a ring. */
393
        xFECRxDescriptors[ configNUM_FEC_RX_DESCRIPTORS - 1 ].status |= RX_BD_W;
394
 
395
        /* We start with descriptor 0. */
396
        ulNextRxDescriptor = 0;
397
}
398
/*-----------------------------------------------------------*/
399
 
400
void vInitFEC( void )
401
{
402
unsigned short usData;
403
struct uip_eth_addr xAddr;
404
const unsigned char ucMACAddress[6] =
405
{
406
        configMAC_0, configMAC_1,configMAC_2,configMAC_3,configMAC_4,configMAC_5
407
};
408
 
409
        prvInitialiseFECBuffers();
410
 
411
        /* Create the semaphore used to wake the uIP task when data arrives. */
412
        vSemaphoreCreateBinary( xFECSemaphore );
413
 
414
        /* Set the MAC address within the stack. */
415
        for( usData = 0; usData < 6; usData++ )
416
        {
417
                xAddr.addr[ usData ] = ucMACAddress[ usData ];
418
        }
419
        uip_setethaddr( xAddr );
420
 
421
        /* Set the Reset bit and clear the Enable bit */
422
        ECR_RESET = 1;
423
 
424
        /* Enable the clock. */
425
        SCGC4 |= SCGC4_FEC_MASK;
426
 
427
        /* Wait at least 8 clock cycles */
428
        for( usData = 0; usData < 10; usData++ )
429
        {
430
                asm( "NOP" );
431
        }
432
 
433
        /* Set MII speed to 2.5MHz. */
434
        MSCR = MCF_FEC_MSCR_MII_SPEED( ( ( configCPU_CLOCK_HZ / 1000000 ) / 5 ) + 1 );
435
 
436
        /*
437
         * Make sure the external interface signals are enabled
438
         */
439
    PTCPF2_C0 = 1;
440
    PTCPF2_C1 = 1;
441
    PTCPF2_C2 = 1;
442
    PTAPF1 = 0x55;
443
    PTAPF2 = 0x55;
444
    PTBPF1 = 0x55;
445
    PTBPF2 = 0x55;
446
 
447
    /* Set all pins to full drive with no filter. */
448
    PTADS = 0x06;
449
    PTAIFE = 0x06;
450
    PTBDS = 0xf4;
451
    PTBIFE = 0xf4;
452
    PTCDS = 0;
453
    PTCIFE = 0;
454
 
455
 
456
        /* Can we talk to the PHY? */
457
        do
458
        {
459
                vTaskDelay( fecLINK_DELAY );
460
                usData = 0xffff;
461
                fec_mii_read( configPHY_ADDRESS, PHY_PHYIDR1, &usData );
462
 
463
        } while( usData == 0xffff );
464
 
465
        /* Start auto negotiate. */
466
        fec_mii_write( configPHY_ADDRESS, PHY_BMCR, ( PHY_BMCR_AN_RESTART | PHY_BMCR_AN_ENABLE ) );
467
 
468
        /* Wait for auto negotiate to complete. */
469
        do
470
        {
471
                vTaskDelay( fecLINK_DELAY );
472
                fec_mii_read( configPHY_ADDRESS, PHY_BMSR, &usData );
473
 
474
        } while( !( usData & PHY_BMSR_AN_COMPLETE ) );
475
 
476
        /* When we get here we have a link - find out what has been negotiated. */
477
        usData = 0;
478
        fec_mii_read( configPHY_ADDRESS, PHY_STATUS, &usData );
479
 
480
        /* Setup half or full duplex. */
481
        if( usData & PHY_DUPLEX_STATUS )
482
        {
483
                RCR &= (unsigned long)~RCR_DRT;
484
                TCR |= TCR_FDEN;
485
        }
486
        else
487
        {
488
                RCR |= RCR_DRT;
489
                TCR &= (unsigned long)~TCR_FDEN;
490
        }
491
 
492
        /* Clear the Individual and Group Address Hash registers */
493
        IALR = 0;
494
        IAUR = 0;
495
        GALR = 0;
496
        GAUR = 0;
497
 
498
        /* Set the Physical Address for the selected FEC */
499
        fec_set_address( ucMACAddress );
500
 
501
        /* Set Rx Buffer Size */
502
        EMRBR = (unsigned short) configFEC_BUFFER_SIZE;
503
 
504
        /* Point to the start of the circular Rx buffer descriptor queue */
505
        ERDSR = ( volatile unsigned long ) &( xFECRxDescriptors[ 0 ] );
506
 
507
        /* Point to the start of the circular Tx buffer descriptor queue */
508
        ETSDR = ( volatile unsigned long ) pxFECTxDescriptor;
509
 
510
        /* Clear all FEC interrupt events */
511
        EIR = ( unsigned long ) -1;
512
 
513
        /* Various mode/status setup. */
514
        RCR = 0;
515
        RCR_MAX_FL = configFEC_BUFFER_SIZE;
516
        RCR_MII_MODE = 1;
517
 
518
        #if( configUSE_PROMISCUOUS_MODE == 1 )
519
        {
520
                RCR |= RCR_PROM;
521
        }
522
        #endif
523
 
524
        /* Enable interrupts. */
525
        EIMR = EIR_TXF_MASK | EIMR_RXF_MASK | EIMR_RXB_MASK | EIMR_UN_MASK | EIMR_RL_MASK | EIMR_LC_MASK | EIMR_BABT_MASK | EIMR_BABR_MASK | EIMR_HBERR_MASK;
526
 
527
        /* Enable the MAC itself. */
528
    ECR = ECR_ETHER_EN_MASK;
529
 
530
    /* Indicate that there have been empty receive buffers produced */
531
    RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;
532
}
533
/*-----------------------------------------------------------*/
534
 
535
unsigned long ulFECRx( void )
536
{
537
unsigned long ulLen = 0UL;
538
 
539
        /* Is a buffer ready? */
540
        if( ( xFECRxDescriptors[ ulNextRxDescriptor ].status & RX_BD_E ) == 0 )
541
        {
542
                /* uip_buf is about to be set to a new buffer, so return the buffer it
543
                is already pointing to. */
544
                prvReturnBuffer( uip_buf );
545
 
546
                /* Obtain the size of the packet and put it into the "len" variable. */
547
                ulLen = xFECRxDescriptors[ ulNextRxDescriptor ].length;
548
                uip_buf = xFECRxDescriptors[ ulNextRxDescriptor ].data;
549
 
550
                /* The buffer that this descriptor was using is now in use by the
551
                TCP/IP stack, so allocate it a new buffer. */
552
                xFECRxDescriptors[ ulNextRxDescriptor ].data = prvGetFreeBuffer();
553
 
554
                /* Doing this here could cause corruption! */
555
                xFECRxDescriptors[ ulNextRxDescriptor ].status |= RX_BD_E;
556
 
557
                portENTER_CRITICAL();
558
                {
559
                        ulNextRxDescriptor++;
560
                        if( ulNextRxDescriptor >= configNUM_FEC_RX_DESCRIPTORS )
561
                        {
562
                                ulNextRxDescriptor = 0;
563
                        }
564
                }
565
                portEXIT_CRITICAL();
566
 
567
                /* Tell the DMA a new buffer is available. */
568
                RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;
569
        }
570
 
571
    return ulLen;
572
}
573
/*-----------------------------------------------------------*/
574
 
575
void vFECTx( void )
576
{
577
        /* When we get here the Tx descriptor should show as having completed. */
578
        while( pxFECTxDescriptor->status & TX_BD_R )
579
        {
580
                vTaskDelay( fecMINIMAL_DELAY );
581
        }
582
 
583
        portENTER_CRITICAL();
584
        {
585
                /* To maintain the zero copy implementation, point the Tx descriptor
586
                to the data from the Rx buffer. */
587
                pxFECTxDescriptor->data = uip_buf;
588
 
589
                /* Setup the buffer descriptor for transmission */
590
                pxFECTxDescriptor->length = uip_len;
591
 
592
                /* NB this assumes only one Tx descriptor! */
593
                pxFECTxDescriptor->status = ( TX_BD_R | TX_BD_L | TX_BD_TC | TX_BD_W );
594
        }
595
        portEXIT_CRITICAL();
596
 
597
        /* Continue the Tx DMA task (in case it was waiting for a new TxBD) */
598
        TDAR = MCF_FEC_TDAR_X_DES_ACTIVE;
599
 
600
        /* uip_buf is being used by the Tx descriptor.  Allocate a new buffer to
601
        uip_buf. */
602
        uip_buf = prvGetFreeBuffer();
603
}
604
/*-----------------------------------------------------------*/
605
 
606
static void prvReturnBuffer( unsigned char *pucBuffer )
607
{
608
unsigned long ul;
609
 
610
        /* Mark a buffer as free for use. */
611
        for( ul = 0; ul < fecNUM_BUFFERS; ul++ )
612
        {
613
                if( pucAlignedBufferStartAddresses[ ul ] == pucBuffer )
614
                {
615
                        ucBufferInUse[ ul ] = pdFALSE;
616
                        break;
617
                }
618
        }
619
}
620
/*-----------------------------------------------------------*/
621
 
622
static unsigned char *prvGetFreeBuffer( void )
623
{
624
portBASE_TYPE x;
625
unsigned char *pucReturn = NULL;
626
unsigned long ulAttempts = 0;
627
 
628
        while( pucReturn == NULL )
629
        {
630
                /* Look through the buffers to find one that is not in use by
631
                anything else. */
632
                for( x = 0; x < fecNUM_BUFFERS; x++ )
633
                {
634
                        if( ucBufferInUse[ x ] == pdFALSE )
635
                        {
636
                                ucBufferInUse[ x ] = pdTRUE;
637
                                pucReturn = pucAlignedBufferStartAddresses[ x ];
638
                                break;
639
                        }
640
                }
641
 
642
                /* Was a buffer found? */
643
                if( pucReturn == NULL )
644
                {
645
                        ulAttempts++;
646
 
647
                        if( ulAttempts >= uipBUFFER_WAIT_ATTEMPTS )
648
                        {
649
                                break;
650
                        }
651
 
652
                        /* Wait then look again. */
653
                        vTaskDelay( fecMINIMAL_DELAY );
654
                }
655
        }
656
 
657
        return pucReturn;
658
}
659
/*-----------------------------------------------------------*/
660
 
661
void interrupt 86 vFECISRHandler( void )
662
{
663
unsigned long ulEvent;
664
portBASE_TYPE xHighPriorityTaskWoken = pdFALSE;
665
 
666
        /* Determine the cause of the interrupt. */
667
        ulEvent = EIR & EIMR;
668
        EIR = ulEvent;
669
 
670
        if( ulEvent & EIR_RXF_MASK )
671
        {
672
                /* A packet has been received.  Wake the handler task in case it is
673
                blocked. */
674
                xSemaphoreGiveFromISR( xFECSemaphore, &xHighPriorityTaskWoken );
675
        }
676
 
677
        if( ulEvent & EIR_TXF_MASK )
678
        {
679
                /* The Tx has completed.  Mark the buffer it was using as free again. */
680
                prvReturnBuffer( pxFECTxDescriptor->data );
681
                pxFECTxDescriptor->data = NULL;
682
        }
683
 
684
        if (ulEvent & ( EIR_UN_MASK | EIR_RL_MASK | EIR_LC_MASK | EIR_EBERR_MASK | EIR_BABT_MASK | EIR_BABR_MASK | EIR_HBERR_MASK ) )
685
        {
686
                /* Sledge hammer error handling. */
687
                prvInitialiseFECBuffers();
688
                RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;
689
        }
690
 
691
        portEND_SWITCHING_ISR( xHighPriorityTaskWoken );
692
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.