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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [WizNET_DEMO_TERN_186/] [serial/] [serial.c] - Blame information for rev 860

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
 
55
#include <stdlib.h>
56
#include <embedded.h>
57
#include "FreeRTOS.h"
58
#include "portasm.h"
59
#include "queue.h"
60
#include "task.h"
61
#include "semphr.h"
62
 
63
#define serMAX_PORTS                    ( ( unsigned short ) 2 )
64
 
65
#define serPORT_0_INT_REG               ( 0xff44 )
66
#define serPORT_0_BAUD_REG              ( 0xff88 )
67
#define serPORT_0_RX_REG                ( 0xff86 )
68
#define serPORT_0_TX_REG                ( 0xff84 )
69
#define serPORT_0_STATUS_REG    ( 0xff82 )
70
#define serPORT_0_CTRL_REG              ( 0xff80 )
71
#define serPORT_0_IRQ                   ( 0x14 )
72
 
73
#define serPORT_1_INT_REG               ( 0xff42 )
74
#define serPORT_1_BAUD_REG              ( 0xff18 )
75
#define serPORT_1_RX_REG                ( 0xff16 )
76
#define serPORT_1_TX_REG                ( 0xff14 )
77
#define serPORT_1_STATUS_REG    ( 0xff12 )
78
#define serPORT_1_CTRL_REG              ( 0xff10 )
79
#define serPORT_1_IRQ                   ( 0x11 )
80
 
81
#define serTX_EMPTY                             ( ( unsigned short ) 0x40 )
82
#define serRX_READY                             ( ( unsigned short ) 0x80 )
83
 
84
#define serRESET_PIC( usEOI_TYPE )      portOUTPUT_WORD( ( unsigned short ) 0xff22, usEOI_TYPE )
85
#define serTX_HOLD_EMPTY_INT            ( ( unsigned short ) 0x100 )
86
 
87
#define serENABLE_INTERRUPTS            ( ( unsigned short ) 0x80 )
88
#define serMODE                                         ( ( unsigned short ) 0x01 )
89
#define serENABLE_TX_MACHINES           ( ( unsigned short ) 0x40 )
90
#define serENABLE_RX_MACHINES           ( ( unsigned short ) 0x20 )
91
#define serINTERRUPT_MASK                       ( ( unsigned short ) 0x08 )
92
#define serCLEAR_ALL_STATUS_BITS        ( ( unsigned short ) 0x00 )
93
#define serINTERRUPT_PRIORITY           ( ( unsigned short ) 0x01 ) /*< Just below the scheduler priority. */
94
 
95
#define serDONT_BLOCK                           ( ( portTickType ) 0 )
96
 
97
typedef enum
98
{
99
        serCOM1 = 0,
100
        serCOM2,
101
        serCOM3,
102
        serCOM4,
103
        serCOM5,
104
        serCOM6,
105
        serCOM7,
106
        serCOM8
107
} eCOMPort;
108
 
109
typedef enum
110
{
111
        serNO_PARITY,
112
        serODD_PARITY,
113
        serEVEN_PARITY,
114
        serMARK_PARITY,
115
        serSPACE_PARITY
116
} eParity;
117
 
118
typedef enum
119
{
120
        serSTOP_1,
121
        serSTOP_2
122
} eStopBits;
123
 
124
typedef enum
125
{
126
        serBITS_5,
127
        serBITS_6,
128
        serBITS_7,
129
        serBITS_8
130
} eDataBits;
131
 
132
typedef enum
133
{
134
        ser50 = 0,
135
        ser75,
136
        ser110,
137
        ser134,
138
        ser150,
139
        ser200,
140
        ser300,
141
        ser600,
142
        ser1200,
143
        ser1800,
144
        ser2400,
145
        ser4800,
146
        ser9600,
147
        ser19200,
148
        ser38400,
149
        ser57600,
150
        ser115200
151
} eBaud;
152
 
153
typedef struct xCOM_PORT
154
{
155
        /* Hardware parameters for this port. */
156
        short sTxInterruptOn;
157
        unsigned short usIntReg;
158
        unsigned short usBaudReg;
159
        unsigned short usRxReg;
160
        unsigned short usTxReg;
161
        unsigned short usStatusReg;
162
        unsigned short usCtrlReg;
163
 
164
        unsigned short usIRQVector;
165
 
166
        /* Queues used for communications with com test task. */
167
        xQueueHandle xRxedChars;
168
        xQueueHandle xCharsForTx;
169
 
170
        /* This semaphore does nothing useful except test a feature of the
171
        scheduler. */
172
        xSemaphoreHandle xTestSem;
173
 
174
} xComPort;
175
 
176
static xComPort xPorts[ serMAX_PORTS ] =
177
{
178
        { pdFALSE, serPORT_0_INT_REG, serPORT_0_BAUD_REG, serPORT_0_RX_REG, serPORT_0_TX_REG, serPORT_0_STATUS_REG, serPORT_0_CTRL_REG, serPORT_0_IRQ, NULL, NULL, NULL },
179
        { pdFALSE, serPORT_1_INT_REG, serPORT_1_BAUD_REG, serPORT_1_RX_REG, serPORT_1_TX_REG, serPORT_1_STATUS_REG, serPORT_1_CTRL_REG, serPORT_1_IRQ, NULL, NULL, NULL }
180
};
181
 
182
typedef xComPort * xComPortHandle;
183
 
184
/**
185
 * Lookup the baud rate from the enum.
186
 */
187
static unsigned long prvBaud( eBaud eWantedBaud );
188
 
189
/* These prototypes are repeated here so we don't have to include the serial header.  This allows
190
the xComPortHandle structure details to be private to this file. */
191
xComPortHandle xSerialPortInit( eCOMPort ePort, eBaud eWantedBaud, eParity eWantedParity, eDataBits eWantedDataBits, eStopBits eWantedStopBits, unsigned portBASE_TYPE uxBufferLength );
192
portBASE_TYPE xSerialGetChar( xComPortHandle pxPort, char *pcRxedChar, portTickType xBlockTime );
193
portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, char cOutChar, portTickType xBlockTime );
194
void vSerialClose( xComPortHandle xPort );
195
short sSerialWaitForSemaphore( xComPortHandle xPort );
196
/*-----------------------------------------------------------*/
197
 
198
static short xComPortISR( xComPort * const pxPort );
199
 
200
#define vInterruptOn( pxPort, usInterrupt )                                                                             \
201
{                                                                                                                                                               \
202
unsigned short usIn;                                                                                                            \
203
                                                                                                                                                                \
204
        portENTER_CRITICAL();                                                                                                           \
205
        {                                                                                                                                                       \
206
                if( pxPort->sTxInterruptOn == pdFALSE )                                                                 \
207
                {                                                                                                                                               \
208
                        usIn = portINPUT_WORD( pxPort->usCtrlReg );                                                     \
209
                        portOUTPUT_WORD( pxPort->usCtrlReg, usIn | usInterrupt );                       \
210
                                                                                                                                                                \
211
                        pxPort->sTxInterruptOn = pdTRUE;                                                                        \
212
                }                                                                                                                                               \
213
        }                                                                                                                                                       \
214
        portEXIT_CRITICAL();                                                                                                            \
215
}
216
/*-----------------------------------------------------------*/
217
 
218
#define vInterruptOff( pxPort, usInterrupt )                                                                    \
219
{                                                                                                                                                               \
220
        unsigned short usIn = portINPUT_WORD( pxPort->usCtrlReg );                              \
221
        if( usIn & usInterrupt )                                                                                                        \
222
        {                                                                                                                                                       \
223
                portOUTPUT_WORD( pxPort->usCtrlReg, usIn & ~usInterrupt);                               \
224
                pxPort->sTxInterruptOn = pdFALSE;                                                                               \
225
        }                                                                                                                                                       \
226
}
227
/*-----------------------------------------------------------*/
228
 
229
 
230
/* Define an interrupt handler for each port */
231
#define COM_IRQ_WRAPPER(N)                                                                              \
232
        static void __interrupt COM_IRQ##N##_WRAPPER( void )            \
233
        {                                                                                                                       \
234
        if( xComPortISR( &( xPorts[##N##] ) ) )                 \
235
        {                                                       \
236
                        portEND_SWITCHING_ISR();                            \
237
                }                                                       \
238
        }
239
 
240
 
241
 
242
COM_IRQ_WRAPPER( 0 )
243
COM_IRQ_WRAPPER( 1 )
244
 
245
static pxISR xISRs[ serMAX_PORTS ] =
246
{
247
        COM_IRQ0_WRAPPER,
248
        COM_IRQ1_WRAPPER
249
};
250
 
251
/*-----------------------------------------------------------*/
252
 
253
static unsigned long prvBaud( eBaud eWantedBaud )
254
{
255
        switch( eWantedBaud )
256
    {
257
                case ser50                      :       return 50UL;
258
                case ser75                      :       return 75UL;
259
                case ser110                     :       return 110UL;
260
                case ser134                     :       return 134UL;
261
                case ser150                     :       return 150UL;
262
                case ser200                     :       return 200UL;
263
                case ser300                     :       return 300UL;
264
                case ser600                     :       return 600UL;
265
                case ser1200            :       return 1200UL;
266
                case ser1800            :       return 1800UL;
267
                case ser2400            :       return 2400UL;
268
                case ser4800            :       return 4800UL;
269
                case ser19200           :       return 19200UL;
270
                case ser38400           :       return 38400UL;
271
                case ser57600           :       return 57600UL;
272
                case ser115200          :       return 115200UL;
273
                default                         :       return 9600UL;
274
    }
275
}
276
 
277
/*-----------------------------------------------------------*/
278
 
279
xComPortHandle xSerialPortInit( eCOMPort ePort, eBaud eWantedBaud, eParity eWantedParity, eDataBits eWantedDataBits, eStopBits eWantedStopBits, unsigned portBASE_TYPE uxBufferLength )
280
{
281
unsigned short usPort;
282
xComPortHandle pxPort = NULL;
283
unsigned long ulBaudDiv;
284
 
285
        /* BAUDDIV = ( Microprocessor Clock / Baud Rate ) / 16 */
286
    ulBaudDiv = ( configCPU_CLOCK_HZ / prvBaud( eWantedBaud ) ) / 16UL;
287
 
288
        /* Only n, 8, 1 is supported so these parameters are not required for this
289
        port. */
290
        ( void ) eWantedParity;
291
        ( void ) eWantedDataBits;
292
    ( void ) eWantedStopBits;
293
 
294
        /* Currently only n,8,1 is supported. */
295
 
296
        usPort = ( unsigned short ) ePort;
297
 
298
        if( usPort < serMAX_PORTS )
299
        {
300
                pxPort = &( xPorts[ usPort ] );
301
 
302
                portENTER_CRITICAL();
303
                {
304
                        unsigned short usInWord;
305
 
306
                        /* Create the queues used by the com test task. */
307
                        pxPort->xRxedChars = xQueueCreate( uxBufferLength, ( unsigned portBASE_TYPE ) sizeof( char ) );
308
                        pxPort->xCharsForTx = xQueueCreate( uxBufferLength, ( unsigned portBASE_TYPE ) sizeof( char ) );
309
 
310
                        /* Create the test semaphore.  This does nothing useful except test a feature of the scheduler. */
311
                        vSemaphoreCreateBinary( pxPort->xTestSem );
312
 
313
                        /* There is no ISR here already to restore later. */
314
                        setvect( ( short ) pxPort->usIRQVector, xISRs[ usPort ] );
315
 
316
                        usInWord = portINPUT_WORD( pxPort->usIntReg );
317
                        usInWord &= ~serINTERRUPT_MASK;
318
                        usInWord |= serINTERRUPT_PRIORITY;
319
                        portOUTPUT_WORD( pxPort->usIntReg, usInWord );
320
 
321
                        portOUTPUT_WORD( pxPort->usBaudReg, ( unsigned short ) ulBaudDiv );
322
                        portOUTPUT_WORD( pxPort->usCtrlReg, serENABLE_INTERRUPTS | serMODE | serENABLE_TX_MACHINES | serENABLE_RX_MACHINES );
323
 
324
                        portOUTPUT_WORD( pxPort->usStatusReg, serCLEAR_ALL_STATUS_BITS );
325
                }
326
                portEXIT_CRITICAL();
327
        }
328
 
329
        return pxPort;
330
} /*lint !e715 Some parameters are not used as only a subset of the serial port functionality is currently implemented. */
331
/*-----------------------------------------------------------*/
332
 
333
void vSerialPutString( xComPortHandle pxPort, const char * const pcString, unsigned short usStringLength )
334
{
335
unsigned short usByte;
336
char *pcNextChar;
337
 
338
        pcNextChar = ( char * ) pcString;
339
 
340
        for( usByte = 0; usByte < usStringLength; usByte++ )
341
        {
342
                xQueueSend( pxPort->xCharsForTx, pcNextChar, serDONT_BLOCK );
343
                pcNextChar++;
344
        }
345
 
346
        vInterruptOn( pxPort, serTX_HOLD_EMPTY_INT );
347
}
348
/*-----------------------------------------------------------*/
349
 
350
portBASE_TYPE xSerialGetChar( xComPortHandle pxPort, char *pcRxedChar, portTickType xBlockTime )
351
{
352
        /* Get the next character from the buffer, note that this routine is only
353
        called having checked that the is (at least) one to get */
354
        if( xQueueReceive( pxPort->xRxedChars, pcRxedChar, xBlockTime ) )
355
        {
356
                return pdTRUE;
357
        }
358
        else
359
        {
360
                return pdFALSE;
361
        }
362
}
363
/*-----------------------------------------------------------*/
364
 
365
portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, char cOutChar, portTickType xBlockTime )
366
{
367
        if( xQueueSend( pxPort->xCharsForTx, &cOutChar, xBlockTime ) != pdPASS )
368
        {
369
                return pdFAIL;
370
        }
371
 
372
        vInterruptOn( pxPort, serTX_HOLD_EMPTY_INT );
373
 
374
        return pdPASS;
375
}
376
/*-----------------------------------------------------------*/
377
 
378
portBASE_TYPE xSerialWaitForSemaphore( xComPortHandle xPort )
379
{
380
const portTickType xBlockTime = ( portTickType ) 0xffff;
381
 
382
        /* This function does nothing interesting, but test the
383
        semaphore from ISR mechanism. */
384
        return xSemaphoreTake( xPort->xTestSem, xBlockTime );
385
}
386
/*-----------------------------------------------------------*/
387
 
388
void vSerialClose( xComPortHandle xPort )
389
{
390
unsigned short usOutput;
391
 
392
        /* Turn off the interrupts.  We may also want to delete the queues and/or
393
        re-install the original ISR. */
394
 
395
        portENTER_CRITICAL();
396
        {
397
                usOutput = portINPUT_WORD( xPort->usCtrlReg );
398
 
399
                usOutput &= ~serENABLE_INTERRUPTS;
400
                usOutput &= ~serENABLE_TX_MACHINES;
401
                usOutput &= ~serENABLE_RX_MACHINES;
402
                portOUTPUT_WORD( xPort->usCtrlReg, usOutput );
403
 
404
                usOutput = portINPUT_WORD( xPort->usIntReg );
405
                usOutput |= serINTERRUPT_MASK;
406
                portOUTPUT_WORD( xPort->usIntReg, usOutput );
407
        }
408
        portEXIT_CRITICAL();
409
}
410
/*-----------------------------------------------------------*/
411
unsigned short usStatus;
412
static portBASE_TYPE xComPortISR( xComPort * const pxPort )
413
{
414
unsigned short usStatusRegister;
415
char cChar;
416
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
417
 
418
        /* NOTE:  THIS IS NOT AN EFFICIENT ISR AS IT IS DESIGNED SOLELY TO TEST
419
        THE SCHEDULER FUNCTIONALITY.  REAL APPLICATIONS SHOULD NOT USE THIS
420
        FUNCTION. */
421
 
422
        usStatusRegister = portINPUT_WORD( pxPort->usStatusReg );
423
 
424
        if( usStatusRegister & serRX_READY )
425
        {
426
                cChar = ( char ) portINPUT_WORD( pxPort->usRxReg );
427
                xQueueSendFromISR( pxPort->xRxedChars, &cChar, &xHigherPriorityTaskWoken );
428
 
429
                /* Also release the semaphore - this does nothing interesting and is just a test. */
430
                xSemaphoreGiveFromISR( pxPort->xTestSem, &xHigherPriorityTaskWoken );
431
        }
432
        else if( pxPort->sTxInterruptOn && ( usStatusRegister & serTX_EMPTY ) )
433
        {
434
                if( xQueueReceiveFromISR( pxPort->xCharsForTx, &cChar, &xHigherPriorityTaskWoken ) == pdTRUE )
435
                {
436
                        portOUTPUT_WORD( pxPort->usTxReg, ( unsigned short ) cChar );
437
                }
438
                else
439
                {
440
                        /* Queue empty, nothing to send */
441
                        vInterruptOff( pxPort, serTX_HOLD_EMPTY_INT );
442
                }
443
        }
444
 
445
    serRESET_PIC( pxPort->usIRQVector );
446
 
447
        /* If posting to the queue woke a task that was blocked on the queue we may
448
        want to switch to the woken task - depending on its priority relative to
449
        the task interrupted by this ISR. */
450
        return xHigherPriorityTaskWoken;
451
}
452
 
453
 
454
 
455
 
456
 

powered by: WebSVN 2.1.0

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