OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [RX600_RX62N-RDK_GNURX/] [RTOSDemo/] [webserver/] [EMAC.c] - Blame information for rev 779

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

Line No. Rev Author Line
1 585 jeremybenn
/*
2
    FreeRTOS V6.1.1 - Copyright (C) 2011 Real Time Engineers Ltd.
3
 
4
    ***************************************************************************
5
    *                                                                         *
6
    * If you are:                                                             *
7
    *                                                                         *
8
    *    + New to FreeRTOS,                                                   *
9
    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
10
    *    + Looking for basic training,                                        *
11
    *    + Wanting to improve your FreeRTOS skills and productivity           *
12
    *                                                                         *
13
    * then take a look at the FreeRTOS books - available as PDF or paperback  *
14
    *                                                                         *
15
    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
16
    *                  http://www.FreeRTOS.org/Documentation                  *
17
    *                                                                         *
18
    * A pdf reference manual is also available.  Both are usually delivered   *
19
    * to your inbox within 20 minutes to two hours when purchased between 8am *
20
    * and 8pm GMT (although please allow up to 24 hours in case of            *
21
    * exceptional circumstances).  Thank you for your support!                *
22
    *                                                                         *
23
    ***************************************************************************
24
 
25
    This file is part of the FreeRTOS distribution.
26
 
27
    FreeRTOS is free software; you can redistribute it and/or modify it under
28
    the terms of the GNU General Public License (version 2) as published by the
29
    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
30
    ***NOTE*** The exception to the GPL is included to allow you to distribute
31
    a combined work that includes FreeRTOS without being obliged to provide the
32
    source code for proprietary components outside of the FreeRTOS kernel.
33
    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
34
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
35
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
36
    more details. You should have received a copy of the GNU General Public
37
    License and the FreeRTOS license exception along with FreeRTOS; if not it
38
    can be viewed here: http://www.freertos.org/a00114.html and also obtained
39
    by writing to Richard Barry, contact details for whom are available on the
40
    FreeRTOS WEB site.
41
 
42
    1 tab == 4 spaces!
43
 
44
    http://www.FreeRTOS.org - Documentation, latest information, license and
45
    contact details.
46
 
47
    http://www.SafeRTOS.com - A version that is certified for use in safety
48
    critical systems.
49
 
50
    http://www.OpenRTOS.com - Commercial support, development, porting,
51
    licensing and training services.
52
*/
53
 
54
/* Hardware specific includes. */
55
#include "iodefine.h"
56
#include "typedefine.h"
57
#include "r_ether.h"
58
#include "phy.h"
59
 
60
/* FreeRTOS includes. */
61
#include "FreeRTOS.h"
62
#include "task.h"
63
#include "semphr.h"
64
 
65
/* uIP includes. */
66
#include "net/uip.h"
67
 
68
/* The time to wait between attempts to obtain a free buffer. */
69
#define emacBUFFER_WAIT_DELAY_ms                ( 3 / portTICK_RATE_MS )
70
 
71
/* The number of times emacBUFFER_WAIT_DELAY_ms should be waited before giving
72
up on attempting to obtain a free buffer all together. */
73
#define emacBUFFER_WAIT_ATTEMPTS        ( 30 )
74
 
75
/* The number of Rx descriptors. */
76
#define emacNUM_RX_DESCRIPTORS  8
77
 
78
/* The number of Tx descriptors.  When using uIP there is not point in having
79
more than two. */
80
#define emacNUM_TX_BUFFERS      2
81
 
82
/* The total number of EMAC buffers to allocate. */
83
#define emacNUM_BUFFERS         ( emacNUM_RX_DESCRIPTORS + emacNUM_TX_BUFFERS )
84
 
85
/* The time to wait for the Tx descriptor to become free. */
86
#define emacTX_WAIT_DELAY_ms ( 10 / portTICK_RATE_MS )
87
 
88
/* The total number of times to wait emacTX_WAIT_DELAY_ms for the Tx descriptor to
89
become free. */
90
#define emacTX_WAIT_ATTEMPTS ( 50 )
91
 
92
/* Only Rx end and Tx end interrupts are used by this driver. */
93
#define emacTX_END_INTERRUPT    ( 1UL << 21UL )
94
#define emacRX_END_INTERRUPT    ( 1UL << 18UL )
95
 
96
/*-----------------------------------------------------------*/
97
 
98
/* The buffers and descriptors themselves.  */
99
static volatile ethfifo xRxDescriptors[ emacNUM_RX_DESCRIPTORS ] __attribute__((aligned(16)));
100
static volatile ethfifo xTxDescriptors[ emacNUM_TX_BUFFERS ] __attribute__((aligned(16)));
101
static char xEthernetBuffers[ emacNUM_BUFFERS ][ UIP_BUFSIZE ] __attribute__((aligned(16)));
102
 
103
/* Used to indicate which buffers are free and which are in use.  If an index
104
contains 0 then the corresponding buffer in xEthernetBuffers is free, otherwise
105
the buffer is in use or about to be used. */
106
static unsigned char ucBufferInUse[ emacNUM_BUFFERS ];
107
 
108
/*-----------------------------------------------------------*/
109
 
110
/*
111
 * Initialise both the Rx and Tx descriptors.
112
 */
113
static void prvInitialiseDescriptors( void );
114
 
115
/*
116
 * Return a pointer to a free buffer within xEthernetBuffers.
117
 */
118
static unsigned char *prvGetNextBuffer( void );
119
 
120
/*
121
 * Return a buffer to the list of free buffers.
122
 */
123
static void prvReturnBuffer( unsigned char *pucBuffer );
124
 
125
/*
126
 * Examine the status of the next Rx FIFO to see if it contains new data.
127
 */
128
static unsigned long prvCheckRxFifoStatus( void );
129
 
130
/*
131
 * Setup the microcontroller for communication with the PHY.
132
 */
133
static void prvResetMAC( void );
134
 
135
/*
136
 * Configure the Ethernet interface peripherals.
137
 */
138
static void prvConfigureEtherCAndEDMAC( void );
139
 
140
/*
141
 * Something has gone wrong with the descriptor usage.  Reset all the buffers
142
 * and descriptors.
143
 */
144
static void prvResetEverything( void );
145
 
146
/*
147
 * Handler for the EMAC peripheral.  See the documentation for this
148
 * port on http://www.FreeRTOS.org for more information on defining interrupt
149
 * handlers.
150
 */
151
void vEMAC_ISR_Handler( void ) __attribute__((interrupt));
152
 
153
/*-----------------------------------------------------------*/
154
 
155
/* Points to the Rx descriptor currently in use. */
156
static ethfifo *pxCurrentRxDesc = NULL;
157
 
158
/* The buffer used by the uIP stack to both receive and send.  This points to
159
one of the Ethernet buffers when its actually in use. */
160
unsigned char *uip_buf = NULL;
161
 
162
/*-----------------------------------------------------------*/
163
 
164
void vInitEmac( void )
165
{
166
        /* Software reset. */
167
        prvResetMAC();
168
 
169
        /* Set the Rx and Tx descriptors into their initial state. */
170
        prvInitialiseDescriptors();
171
 
172
        /* Set the MAC address into the ETHERC */
173
        ETHERC.MAHR =   ( ( unsigned long ) configMAC_ADDR0 << 24UL ) |
174
                                        ( ( unsigned long ) configMAC_ADDR1 << 16UL ) |
175
                                        ( ( unsigned long ) configMAC_ADDR2 << 8UL ) |
176
                                        ( unsigned long ) configMAC_ADDR3;
177
 
178
        ETHERC.MALR.BIT.MA = ( ( unsigned long ) configMAC_ADDR4 << 8UL ) |
179
                                                 ( unsigned long ) configMAC_ADDR5;
180
 
181
        /* Perform rest of interface hardware configuration. */
182
        prvConfigureEtherCAndEDMAC();
183
 
184
        /* Nothing received yet, so uip_buf points nowhere. */
185
        uip_buf = NULL;
186
 
187
        /* Initialize the PHY */
188
        phy_init();
189
}
190
/*-----------------------------------------------------------*/
191
 
192
void vEMACWrite( void )
193
{
194
long x;
195
 
196
        /* Wait until the second transmission of the last packet has completed. */
197
        for( x = 0; x < emacTX_WAIT_ATTEMPTS; x++ )
198
        {
199
                if( ( xTxDescriptors[ 1 ].status & ACT ) != 0 )
200
                {
201
                        /* Descriptor is still active. */
202
                        vTaskDelay( emacTX_WAIT_DELAY_ms );
203
                }
204
                else
205
                {
206
                        break;
207
                }
208
        }
209
 
210
        /* Is the descriptor free after waiting for it? */
211
        if( ( xTxDescriptors[ 1 ].status & ACT ) != 0 )
212
        {
213
                /* Something has gone wrong. */
214
                prvResetEverything();
215
        }
216
 
217
        /* Setup both descriptors to transmit the frame. */
218
        xTxDescriptors[ 0 ].buf_p = ( char * ) uip_buf;
219
        xTxDescriptors[ 0 ].bufsize = uip_len;
220
        xTxDescriptors[ 1 ].buf_p = ( char * ) uip_buf;
221
        xTxDescriptors[ 1 ].bufsize = uip_len;
222
 
223
        /* uip_buf is being sent by the Tx descriptor.  Allocate a new buffer
224
        for use by the stack. */
225
        uip_buf = prvGetNextBuffer();
226
 
227
        /* Clear previous settings and go. */
228
        xTxDescriptors[0].status &= ~( FP1 | FP0 );
229
        xTxDescriptors[0].status |= ( FP1 | FP0 | ACT );
230
        xTxDescriptors[1].status &= ~( FP1 | FP0 );
231
        xTxDescriptors[1].status |= ( FP1 | FP0 | ACT );
232
 
233
        EDMAC.EDTRR.LONG = 0x00000001;
234
}
235
/*-----------------------------------------------------------*/
236
 
237
unsigned long ulEMACRead( void )
238
{
239
unsigned long ulBytesReceived;
240
 
241
        ulBytesReceived = prvCheckRxFifoStatus();
242
 
243
        if( ulBytesReceived > 0 )
244
        {
245
                pxCurrentRxDesc->status &= ~( FP1 | FP0 );
246
                pxCurrentRxDesc->status |= ACT;
247
 
248
                if( EDMAC.EDRRR.LONG == 0x00000000L )
249
                {
250
                        /* Restart Ethernet if it has stopped */
251
                        EDMAC.EDRRR.LONG = 0x00000001L;
252
                }
253
 
254
                /* Mark the pxDescriptor buffer as free as uip_buf is going to be set to
255
                the buffer that contains the received data. */
256
                prvReturnBuffer( uip_buf );
257
 
258
                uip_buf = ( void * ) pxCurrentRxDesc->buf_p;
259
 
260
                /* Move onto the next buffer in the ring. */
261
                pxCurrentRxDesc = pxCurrentRxDesc->next;
262
        }
263
 
264
        return ulBytesReceived;
265
}
266
/*-----------------------------------------------------------*/
267
 
268
long lEMACWaitForLink( void )
269
{
270
long lReturn;
271
 
272
        /* Set the link status. */
273
        switch( phy_set_autonegotiate() )
274
        {
275
                /* Half duplex link */
276
                case PHY_LINK_100H:
277
                                                                ETHERC.ECMR.BIT.DM = 0;
278
                                                                ETHERC.ECMR.BIT.RTM = 1;
279
                                                                lReturn = pdPASS;
280
                                                                break;
281
 
282
                case PHY_LINK_10H:
283
                                                                ETHERC.ECMR.BIT.DM = 0;
284
                                                                ETHERC.ECMR.BIT.RTM = 0;
285
                                                                lReturn = pdPASS;
286
                                                                break;
287
 
288
 
289
                /* Full duplex link */
290
                case PHY_LINK_100F:
291
                                                                ETHERC.ECMR.BIT.DM = 1;
292
                                                                ETHERC.ECMR.BIT.RTM = 1;
293
                                                                lReturn = pdPASS;
294
                                                                break;
295
 
296
                case PHY_LINK_10F:
297
                                                                ETHERC.ECMR.BIT.DM = 1;
298
                                                                ETHERC.ECMR.BIT.RTM = 0;
299
                                                                lReturn = pdPASS;
300
                                                                break;
301
 
302
                default:
303
                                                                lReturn = pdFAIL;
304
                                                                break;
305
        }
306
 
307
        if( lReturn == pdPASS )
308
        {
309
                /* Enable receive and transmit. */
310
                ETHERC.ECMR.BIT.RE = 1;
311
                ETHERC.ECMR.BIT.TE = 1;
312
 
313
                /* Enable EDMAC receive */
314
                EDMAC.EDRRR.LONG = 0x1;
315
        }
316
 
317
        return lReturn;
318
}
319
/*-----------------------------------------------------------*/
320
 
321
static void prvInitialiseDescriptors( void )
322
{
323
volatile ethfifo *pxDescriptor;
324
long x;
325
 
326
        for( x = 0; x < emacNUM_BUFFERS; x++ )
327
        {
328
                /* Ensure none of the buffers are shown as in use at the start. */
329
                ucBufferInUse[ x ] = pdFALSE;
330
        }
331
 
332
        /* Initialise the Rx descriptors. */
333
        for( x = 0; x < emacNUM_RX_DESCRIPTORS; x++ )
334
        {
335
                pxDescriptor = &( xRxDescriptors[ x ] );
336
                pxDescriptor->buf_p = &( xEthernetBuffers[ x ][ 0 ] );
337
 
338
                pxDescriptor->bufsize = UIP_BUFSIZE;
339
                pxDescriptor->size = 0;
340
                pxDescriptor->status = ACT;
341
                pxDescriptor->next = ( struct Descriptor * ) &xRxDescriptors[ x + 1 ];
342
 
343
                /* Mark this buffer as in use. */
344
                ucBufferInUse[ x ] = pdTRUE;
345
        }
346
 
347
        /* The last descriptor points back to the start. */
348
        pxDescriptor->status |= DL;
349
        pxDescriptor->next = ( struct Descriptor * ) &xRxDescriptors[ 0 ];
350
 
351
        /* Initialise the Tx descriptors. */
352
        for( x = 0; x < emacNUM_TX_BUFFERS; x++ )
353
        {
354
                pxDescriptor = &( xTxDescriptors[ x ] );
355
 
356
                /* A buffer is not allocated to the Tx descriptor until a send is
357
                actually required. */
358
                pxDescriptor->buf_p = NULL;
359
 
360
                pxDescriptor->bufsize = UIP_BUFSIZE;
361
                pxDescriptor->size = 0;
362
                pxDescriptor->status = 0;
363
                pxDescriptor->next = ( struct Descriptor * ) &xTxDescriptors[ x + 1 ];
364
        }
365
 
366
        /* The last descriptor points back to the start. */
367
        pxDescriptor->status |= DL;
368
        pxDescriptor->next = ( struct Descriptor * ) &( xTxDescriptors[ 0 ] );
369
 
370
        /* Use the first Rx descriptor to start with. */
371
        pxCurrentRxDesc = ( struct Descriptor * ) &( xRxDescriptors[ 0 ] );
372
}
373
/*-----------------------------------------------------------*/
374
 
375
static unsigned char *prvGetNextBuffer( void )
376
{
377
long x;
378
unsigned char *pucReturn = NULL;
379
unsigned long ulAttempts = 0;
380
 
381
        while( pucReturn == NULL )
382
        {
383
                /* Look through the buffers to find one that is not in use by
384
                anything else. */
385
                for( x = 0; x < emacNUM_BUFFERS; x++ )
386
                {
387
                        if( ucBufferInUse[ x ] == pdFALSE )
388
                        {
389
                                ucBufferInUse[ x ] = pdTRUE;
390
                                pucReturn = ( unsigned char * ) &( xEthernetBuffers[ x ][ 0 ] );
391
                                break;
392
                        }
393
                }
394
 
395
                /* Was a buffer found? */
396
                if( pucReturn == NULL )
397
                {
398
                        ulAttempts++;
399
 
400
                        if( ulAttempts >= emacBUFFER_WAIT_ATTEMPTS )
401
                        {
402
                                break;
403
                        }
404
 
405
                        /* Wait then look again. */
406
                        vTaskDelay( emacBUFFER_WAIT_DELAY_ms );
407
                }
408
        }
409
 
410
        return pucReturn;
411
}
412
/*-----------------------------------------------------------*/
413
 
414
static void prvReturnBuffer( unsigned char *pucBuffer )
415
{
416
unsigned long ul;
417
 
418
        /* Return a buffer to the pool of free buffers. */
419
        for( ul = 0; ul < emacNUM_BUFFERS; ul++ )
420
        {
421
                if( &( xEthernetBuffers[ ul ][ 0 ] ) == ( void * ) pucBuffer )
422
                {
423
                        ucBufferInUse[ ul ] = pdFALSE;
424
                        break;
425
                }
426
        }
427
}
428
/*-----------------------------------------------------------*/
429
 
430
static void prvResetEverything( void )
431
{
432
        /* Temporary code just to see if this gets called.  This function has not
433
        been implemented. */
434
        portDISABLE_INTERRUPTS();
435
        for( ;; );
436
}
437
/*-----------------------------------------------------------*/
438
 
439
static unsigned long prvCheckRxFifoStatus( void )
440
{
441
unsigned long ulReturn = 0;
442
 
443
        if( ( pxCurrentRxDesc->status & ACT ) != 0 )
444
        {
445
                /* Current descriptor is still active. */
446
        }
447
        else if( ( pxCurrentRxDesc->status & FE ) != 0 )
448
        {
449
                /* Frame error.  Clear the error. */
450
                pxCurrentRxDesc->status &= ~( FP1 | FP0 | FE );
451
                pxCurrentRxDesc->status &= ~( RMAF | RRF | RTLF | RTSF | PRE | CERF );
452
                pxCurrentRxDesc->status |= ACT;
453
                pxCurrentRxDesc = pxCurrentRxDesc->next;
454
 
455
                if( EDMAC.EDRRR.LONG == 0x00000000UL )
456
                {
457
                        /* Restart Ethernet if it has stopped. */
458
                        EDMAC.EDRRR.LONG = 0x00000001UL;
459
                }
460
        }
461
        else
462
        {
463
                /* The descriptor contains a frame.  Because of the size of the buffers
464
                the frame should always be complete. */
465
                if( ( pxCurrentRxDesc->status & FP0 ) == FP0 )
466
                {
467
                        ulReturn = pxCurrentRxDesc->size;
468
                }
469
                else
470
                {
471
                        /* Do not expect to get here. */
472
                        prvResetEverything();
473
                }
474
        }
475
 
476
        return ulReturn;
477
}
478
/*-----------------------------------------------------------*/
479
 
480
static void prvResetMAC( void )
481
{
482
        /* Ensure the EtherC and EDMAC are enabled. */
483
        SYSTEM.MSTPCRB.BIT.MSTPB15 = 0;
484
        vTaskDelay( 100 / portTICK_RATE_MS );
485
 
486
        EDMAC.EDMR.BIT.SWR = 1;
487
 
488
        /* Crude wait for reset to complete. */
489
        vTaskDelay( 500 / portTICK_RATE_MS );
490
}
491
/*-----------------------------------------------------------*/
492
 
493
static void prvConfigureEtherCAndEDMAC( void )
494
{
495
        /* Initialisation code taken from Renesas example project. */
496
 
497
        /* TODO:    Check   bit 5   */
498
        ETHERC.ECSR.LONG = 0x00000037;                          /* Clear all ETHERC statuS BFR, PSRTO, LCHNG, MPD, ICD */
499
 
500
        /* Set the EDMAC interrupt priority. */
501
        _IPR( _ETHER_EINT ) = configKERNEL_INTERRUPT_PRIORITY;
502
 
503
        /* TODO:    Check   bit 5   */
504
        /* Enable interrupts of interest only. */
505
        EDMAC.EESIPR.LONG = emacTX_END_INTERRUPT | emacRX_END_INTERRUPT;
506
        ETHERC.RFLR.LONG = 1518;                                        /* Ether payload is 1500+ CRC */
507
        ETHERC.IPGR.LONG = 0x00000014;                          /* Intergap is 96-bit time */
508
 
509
        /* EDMAC */
510
        EDMAC.EESR.LONG = 0x47FF0F9F;                           /* Clear all ETHERC and EDMAC status bits */
511
        #ifdef __RX_LITTLE_ENDIAN__
512
                EDMAC.EDMR.BIT.DE = 1;
513
        #endif
514
        EDMAC.RDLAR = ( void * ) pxCurrentRxDesc;       /* Initialaize Rx Descriptor List Address */
515
        EDMAC.TDLAR = ( void * ) &( xTxDescriptors[ 0 ] );       /* Initialaize Tx Descriptor List Address */
516
        EDMAC.TRSCER.LONG = 0x00000000;                         /* Copy-back status is RFE & TFE only   */
517
        EDMAC.TFTR.LONG = 0x00000000;                           /* Threshold of Tx_FIFO */
518
        EDMAC.FDR.LONG = 0x00000000;                            /* Transmit fifo & receive fifo is 256 bytes */
519
        EDMAC.RMCR.LONG = 0x00000003;                           /* Receive function is normal mode(continued) */
520
 
521
        /* Enable the interrupt... */
522
        _IEN( _ETHER_EINT ) = 1;
523
}
524
/*-----------------------------------------------------------*/
525
 
526
void vEMAC_ISR_Handler( void )
527
{
528
unsigned long ul = EDMAC.EESR.LONG;
529
long lHigherPriorityTaskWoken = pdFALSE;
530
extern xSemaphoreHandle xEMACSemaphore;
531
static long ulTxEndInts = 0;
532
 
533
        /* Re-enabled interrupts. */
534
        __asm volatile( "SETPSW I" );
535
 
536
        /* Has a Tx end occurred? */
537
        if( ul & emacTX_END_INTERRUPT )
538
        {
539
                ++ulTxEndInts;
540
                if( ulTxEndInts >= 2 )
541
                {
542
                        /* Only return the buffer to the pool once both Txes have completed. */
543
                        prvReturnBuffer( ( void * ) xTxDescriptors[ 0 ].buf_p );
544
                        ulTxEndInts = 0;
545
                }
546
                EDMAC.EESR.LONG = emacTX_END_INTERRUPT;
547
        }
548
 
549
        /* Has an Rx end occurred? */
550
        if( ul & emacRX_END_INTERRUPT )
551
        {
552
                /* Make sure the Ethernet task is not blocked waiting for a packet. */
553
                xSemaphoreGiveFromISR( xEMACSemaphore, &lHigherPriorityTaskWoken );
554
                portYIELD_FROM_ISR( lHigherPriorityTaskWoken );
555
                EDMAC.EESR.LONG = emacRX_END_INTERRUPT;
556
        }
557
}
558
 

powered by: WebSVN 2.1.0

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