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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [RX600_RX62N-RSK_IAR/] [webserver/] [EMAC.c] - Blame information for rev 589

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 <iorx62n.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
#pragma data_alignment=32
100
volatile ethfifo xRxDescriptors[ emacNUM_RX_DESCRIPTORS ];
101
 
102
#pragma data_alignment=32
103
volatile ethfifo xTxDescriptors[ emacNUM_TX_BUFFERS ];
104
 
105
#pragma data_alignment=32
106
char xEthernetBuffers[ emacNUM_BUFFERS ][ UIP_BUFSIZE ];
107
 
108
 
109
/* Used to indicate which buffers are free and which are in use.  If an index
110
contains 0 then the corresponding buffer in xEthernetBuffers is free, otherwise
111
the buffer is in use or about to be used. */
112
static unsigned char ucBufferInUse[ emacNUM_BUFFERS ];
113
 
114
/*-----------------------------------------------------------*/
115
 
116
/*
117
 * Initialise both the Rx and Tx descriptors.
118
 */
119
static void prvInitialiseDescriptors( void );
120
 
121
/*
122
 * Return a pointer to a free buffer within xEthernetBuffers.
123
 */
124
static unsigned char *prvGetNextBuffer( void );
125
 
126
/*
127
 * Return a buffer to the list of free buffers.
128
 */
129
static void prvReturnBuffer( unsigned char *pucBuffer );
130
 
131
/*
132
 * Examine the status of the next Rx FIFO to see if it contains new data.
133
 */
134
static unsigned long prvCheckRxFifoStatus( void );
135
 
136
/*
137
 * Setup the microcontroller for communication with the PHY.
138
 */
139
static void prvResetMAC( void );
140
 
141
/*
142
 * Configure the Ethernet interface peripherals.
143
 */
144
static void prvConfigureEtherCAndEDMAC( void );
145
 
146
/*
147
 * Something has gone wrong with the descriptor usage.  Reset all the buffers
148
 * and descriptors.
149
 */
150
static void prvResetEverything( void );
151
 
152
/*-----------------------------------------------------------*/
153
 
154
/* Points to the Rx descriptor currently in use. */
155
static volatile ethfifo *pxCurrentDesc = NULL;
156
 
157
/* The buffer used by the uIP stack to both receive and send.  This points to
158
one of the Ethernet buffers when its actually in use. */
159
unsigned char *uip_buf = NULL;
160
 
161
/*-----------------------------------------------------------*/
162
 
163
void vInitEmac( void )
164
{
165
        /* Software reset. */
166
        prvResetMAC();
167
 
168
        /* Set the Rx and Tx descriptors into their initial state. */
169
        prvInitialiseDescriptors();
170
 
171
        /* Set the MAC address into the ETHERC */
172
        ETHERC.MAHR =   ( ( unsigned long ) configMAC_ADDR0 << 24UL ) |
173
                                        ( ( unsigned long ) configMAC_ADDR1 << 16UL ) |
174
                                        ( ( unsigned long ) configMAC_ADDR2 << 8UL ) |
175
                                        ( unsigned long ) configMAC_ADDR3;
176
 
177
        ETHERC.MALR.BIT.MA = ( ( unsigned long ) configMAC_ADDR4 << 8UL ) |
178
                                                 ( unsigned long ) configMAC_ADDR5;
179
 
180
        /* Perform rest of interface hardware configuration. */
181
        prvConfigureEtherCAndEDMAC();
182
 
183
        /* Nothing received yet, so uip_buf points nowhere. */
184
        uip_buf = NULL;
185
 
186
        /* Initialize the PHY */
187
        phy_init();
188
}
189
/*-----------------------------------------------------------*/
190
 
191
void vEMACWrite( void )
192
{
193
long x;
194
 
195
        /* Wait until the second transmission of the last packet has completed. */
196
        for( x = 0; x < emacTX_WAIT_ATTEMPTS; x++ )
197
        {
198
                if( ( xTxDescriptors[ 1 ].status & ACT ) != 0 )
199
                {
200
                        /* Descriptor is still active. */
201
                        vTaskDelay( emacTX_WAIT_DELAY_ms );
202
                }
203
                else
204
                {
205
                        break;
206
                }
207
        }
208
 
209
        /* Is the descriptor free after waiting for it? */
210
        if( ( xTxDescriptors[ 1 ].status & ACT ) != 0 )
211
        {
212
                /* Something has gone wrong. */
213
                prvResetEverything();
214
        }
215
 
216
        /* Setup both descriptors to transmit the frame. */
217
        xTxDescriptors[ 0 ].buf_p = ( char * ) uip_buf;
218
        xTxDescriptors[ 0 ].bufsize = uip_len;
219
        xTxDescriptors[ 1 ].buf_p = ( char * ) uip_buf;
220
        xTxDescriptors[ 1 ].bufsize = uip_len;
221
 
222
        /* uip_buf is being sent by the Tx descriptor.  Allocate a new buffer
223
        for use by the stack. */
224
        uip_buf = prvGetNextBuffer();
225
 
226
        /* Clear previous settings and go. */
227
        xTxDescriptors[0].status &= ~( FP1 | FP0 );
228
        xTxDescriptors[0].status |= ( FP1 | FP0 | ACT );
229
        xTxDescriptors[1].status &= ~( FP1 | FP0 );
230
        xTxDescriptors[1].status |= ( FP1 | FP0 | ACT );
231
 
232
        EDMAC.EDTRR.LONG = 0x00000001;
233
}
234
/*-----------------------------------------------------------*/
235
 
236
unsigned long ulEMACRead( void )
237
{
238
unsigned long ulBytesReceived;
239
 
240
        ulBytesReceived = prvCheckRxFifoStatus();
241
 
242
        if( ulBytesReceived > 0 )
243
        {
244
                pxCurrentDesc->status &= ~( FP1 | FP0 );
245
                pxCurrentDesc->status |= ACT;
246
 
247
                if( EDMAC.EDRRR.LONG == 0x00000000L )
248
                {
249
                        /* Restart Ethernet if it has stopped */
250
                        EDMAC.EDRRR.LONG = 0x00000001L;
251
                }
252
 
253
                /* Mark the pxDescriptor buffer as free as uip_buf is going to be set to
254
                the buffer that contains the received data. */
255
                prvReturnBuffer( uip_buf );
256
 
257
                uip_buf = ( void * ) pxCurrentDesc->buf_p;
258
 
259
                /* Move onto the next buffer in the ring. */
260
                pxCurrentDesc = pxCurrentDesc->next;
261
        }
262
 
263
        return ulBytesReceived;
264
}
265
/*-----------------------------------------------------------*/
266
 
267
long lEMACWaitForLink( void )
268
{
269
long lReturn;
270
 
271
        /* Set the link status. */
272
        switch( phy_set_autonegotiate() )
273
        {
274
                /* Half duplex link */
275
                case PHY_LINK_100H:
276
                                                                ETHERC.ECMR.BIT.DM = 0;
277
                                                                ETHERC.ECMR.BIT.RTM = 1;
278
                                                                lReturn = pdPASS;
279
                                                                break;
280
 
281
                case PHY_LINK_10H:
282
                                                                ETHERC.ECMR.BIT.DM = 0;
283
                                                                ETHERC.ECMR.BIT.RTM = 0;
284
                                                                lReturn = pdPASS;
285
                                                                break;
286
 
287
 
288
                /* Full duplex link */
289
                case PHY_LINK_100F:
290
                                                                ETHERC.ECMR.BIT.DM = 1;
291
                                                                ETHERC.ECMR.BIT.RTM = 1;
292
                                                                lReturn = pdPASS;
293
                                                                break;
294
 
295
                case PHY_LINK_10F:
296
                                                                ETHERC.ECMR.BIT.DM = 1;
297
                                                                ETHERC.ECMR.BIT.RTM = 0;
298
                                                                lReturn = pdPASS;
299
                                                                break;
300
 
301
                default:
302
                                                                lReturn = pdFAIL;
303
                                                                break;
304
        }
305
 
306
        if( lReturn == pdPASS )
307
        {
308
                /* Enable receive and transmit. */
309
                ETHERC.ECMR.BIT.RE = 1;
310
                ETHERC.ECMR.BIT.TE = 1;
311
 
312
                /* Enable EDMAC receive */
313
                EDMAC.EDRRR.LONG = 0x1;
314
        }
315
 
316
        return lReturn;
317
}
318
/*-----------------------------------------------------------*/
319
 
320
static void prvInitialiseDescriptors( void )
321
{
322
volatile ethfifo *pxDescriptor;
323
long x;
324
 
325
        for( x = 0; x < emacNUM_BUFFERS; x++ )
326
        {
327
                /* Ensure none of the buffers are shown as in use at the start. */
328
                ucBufferInUse[ x ] = pdFALSE;
329
        }
330
 
331
        /* Initialise the Rx descriptors. */
332
        for( x = 0; x < emacNUM_RX_DESCRIPTORS; x++ )
333
        {
334
                pxDescriptor = &( xRxDescriptors[ x ] );
335
                pxDescriptor->buf_p = &( xEthernetBuffers[ x ][ 0 ] );
336
 
337
                pxDescriptor->bufsize = UIP_BUFSIZE;
338
                pxDescriptor->size = 0;
339
                pxDescriptor->status = ACT;
340
                pxDescriptor->next = ( ethfifo * ) &xRxDescriptors[ x + 1 ];
341
 
342
                /* Mark this buffer as in use. */
343
                ucBufferInUse[ x ] = pdTRUE;
344
        }
345
 
346
        /* The last descriptor points back to the start. */
347
        pxDescriptor->status |= DL;
348
        pxDescriptor->next = ( ethfifo * ) &xRxDescriptors[ 0 ];
349
 
350
        /* Initialise the Tx descriptors. */
351
        for( x = 0; x < emacNUM_TX_BUFFERS; x++ )
352
        {
353
                pxDescriptor = &( xTxDescriptors[ x ] );
354
 
355
                /* A buffer is not allocated to the Tx descriptor until a send is
356
                actually required. */
357
                pxDescriptor->buf_p = NULL;
358
 
359
                pxDescriptor->bufsize = UIP_BUFSIZE;
360
                pxDescriptor->size = 0;
361
                pxDescriptor->status = 0;
362
                pxDescriptor->next = ( ethfifo * ) &xTxDescriptors[ x + 1 ];
363
        }
364
 
365
        /* The last descriptor points back to the start. */
366
        pxDescriptor->status |= DL;
367
        pxDescriptor->next = ( ethfifo * ) &( xTxDescriptors[ 0 ] );
368
 
369
        /* Use the first Rx descriptor to start with. */
370
        pxCurrentDesc = &( xRxDescriptors[ 0 ] );
371
}
372
/*-----------------------------------------------------------*/
373
 
374
static unsigned char *prvGetNextBuffer( void )
375
{
376
long x;
377
unsigned char *pucReturn = NULL;
378
unsigned long ulAttempts = 0;
379
 
380
        while( pucReturn == NULL )
381
        {
382
                /* Look through the buffers to find one that is not in use by
383
                anything else. */
384
                for( x = 0; x < emacNUM_BUFFERS; x++ )
385
                {
386
                        if( ucBufferInUse[ x ] == pdFALSE )
387
                        {
388
                                ucBufferInUse[ x ] = pdTRUE;
389
                                pucReturn = ( unsigned char * ) &( xEthernetBuffers[ x ][ 0 ] );
390
                                break;
391
                        }
392
                }
393
 
394
                /* Was a buffer found? */
395
                if( pucReturn == NULL )
396
                {
397
                        ulAttempts++;
398
 
399
                        if( ulAttempts >= emacBUFFER_WAIT_ATTEMPTS )
400
                        {
401
                                break;
402
                        }
403
 
404
                        /* Wait then look again. */
405
                        vTaskDelay( emacBUFFER_WAIT_DELAY_ms );
406
                }
407
        }
408
 
409
        return pucReturn;
410
}
411
/*-----------------------------------------------------------*/
412
 
413
static void prvReturnBuffer( unsigned char *pucBuffer )
414
{
415
unsigned long ul;
416
 
417
        /* Return a buffer to the pool of free buffers. */
418
        for( ul = 0; ul < emacNUM_BUFFERS; ul++ )
419
        {
420
                if( &( xEthernetBuffers[ ul ][ 0 ] ) == ( void * ) pucBuffer )
421
                {
422
                        ucBufferInUse[ ul ] = pdFALSE;
423
                        break;
424
                }
425
        }
426
}
427
/*-----------------------------------------------------------*/
428
 
429
static void prvResetEverything( void )
430
{
431
        /* Temporary code just to see if this gets called.  This function has not
432
        been implemented. */
433
        portDISABLE_INTERRUPTS();
434
        for( ;; );
435
}
436
/*-----------------------------------------------------------*/
437
 
438
static unsigned long prvCheckRxFifoStatus( void )
439
{
440
unsigned long ulReturn = 0;
441
 
442
        if( ( pxCurrentDesc->status & ACT ) != 0 )
443
        {
444
                /* Current descriptor is still active. */
445
        }
446
        else if( ( pxCurrentDesc->status & FE ) != 0 )
447
        {
448
                /* Frame error.  Clear the error. */
449
                pxCurrentDesc->status &= ~( FP1 | FP0 | FE );
450
                pxCurrentDesc->status &= ~( RMAF | RRF | RTLF | RTSF | PRE | CERF );
451
                pxCurrentDesc->status |= ACT;
452
                pxCurrentDesc = pxCurrentDesc->next;
453
 
454
                if( EDMAC.EDRRR.LONG == 0x00000000UL )
455
                {
456
                        /* Restart Ethernet if it has stopped. */
457
                        EDMAC.EDRRR.LONG = 0x00000001UL;
458
                }
459
        }
460
        else
461
        {
462
                /* The descriptor contains a frame.  Because of the size of the buffers
463
                the frame should always be complete. */
464
                if( ( pxCurrentDesc->status & FP0 ) == FP0 )
465
                {
466
                        ulReturn = pxCurrentDesc->size;
467
                }
468
                else
469
                {
470
                        /* Do not expect to get here. */
471
                        prvResetEverything();
472
                }
473
        }
474
 
475
        return ulReturn;
476
}
477
/*-----------------------------------------------------------*/
478
 
479
static void prvResetMAC( void )
480
{
481
        /* Ensure the EtherC and EDMAC are enabled. */
482
        SYSTEM.MSTPCRB.BIT.MSTPB15 = 0;
483
        vTaskDelay( 100 / portTICK_RATE_MS );
484
 
485
        EDMAC.EDMR.BIT.SWR = 1;
486
 
487
        /* Crude wait for reset to complete. */
488
        vTaskDelay( 500 / portTICK_RATE_MS );
489
}
490
/*-----------------------------------------------------------*/
491
 
492
static void prvConfigureEtherCAndEDMAC( void )
493
{
494
        /* Initialisation code taken from Renesas example project. */
495
 
496
        /* TODO:    Check   bit 5   */
497
        ETHERC.ECSR.LONG = 0x00000037;                          /* Clear all ETHERC statuS BFR, PSRTO, LCHNG, MPD, ICD */
498
 
499
        /* Set the EDMAC interrupt priority. */
500
        _IPR( _ETHER_EINT ) = configKERNEL_INTERRUPT_PRIORITY;
501
 
502
        /* TODO:    Check   bit 5   */
503
        /* Enable interrupts of interest only. */
504
        EDMAC.EESIPR.LONG = emacTX_END_INTERRUPT | emacRX_END_INTERRUPT;
505
        ETHERC.RFLR.LONG = 1518;                                        /* Ether payload is 1500+ CRC */
506
        ETHERC.IPGR.LONG = 0x00000014;                          /* Intergap is 96-bit time */
507
 
508
        /* EDMAC */
509
        EDMAC.EESR.LONG = 0x47FF0F9F;                           /* Clear all ETHERC and EDMAC status bits */
510
        #if __LITTLE_ENDIAN__ == 1
511
                EDMAC.EDMR.BIT.DE = 1;
512
        #endif
513
        EDMAC.RDLAR = ( void * ) pxCurrentDesc; /* Initialaize Rx Descriptor List Address */
514
        EDMAC.TDLAR = ( void * ) &( xTxDescriptors[ 0 ] );/* Initialaize Tx Descriptor List Address */
515
        EDMAC.TRSCER.LONG = 0x00000000;                         /* Copy-back status is RFE & TFE only   */
516
        EDMAC.TFTR.LONG = 0x00000000;                           /* Threshold of Tx_FIFO */
517
        EDMAC.FDR.LONG = 0x00000000;                            /* Transmit fifo & receive fifo is 256 bytes */
518
        EDMAC.RMCR.LONG = 0x00000003;                           /* Receive function is normal mode(continued) */
519
 
520
        /* Enable the interrupt... */
521
        _IEN( _ETHER_EINT ) = 1;
522
}
523
/*-----------------------------------------------------------*/
524
 
525
#pragma vector = VECT_ETHER_EINT
526
__interrupt 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
        __enable_interrupt();
534
 
535
        /* Has a Tx end occurred? */
536
        if( ul & emacTX_END_INTERRUPT )
537
        {
538
                ++ulTxEndInts;
539
                if( ulTxEndInts >= 2 )
540
                {
541
                        /* Only return the buffer to the pool once both Txes have completed. */
542
                        prvReturnBuffer( ( void * ) xTxDescriptors[ 0 ].buf_p );
543
                        ulTxEndInts = 0;
544
                }
545
                EDMAC.EESR.LONG = emacTX_END_INTERRUPT;
546
        }
547
 
548
        /* Has an Rx end occurred? */
549
        if( ul & emacRX_END_INTERRUPT )
550
        {
551
                /* Make sure the Ethernet task is not blocked waiting for a packet. */
552
                xSemaphoreGiveFromISR( xEMACSemaphore, &lHigherPriorityTaskWoken );
553
                portYIELD_FROM_ISR( lHigherPriorityTaskWoken );
554
                EDMAC.EESR.LONG = emacRX_END_INTERRUPT;
555
        }
556
}
557
 

powered by: WebSVN 2.1.0

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