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

Subversion Repositories openrisc

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

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

Line No. Rev Author Line
1 577 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
/*
56
        BASIC INTERRUPT DRIVEN SERIAL PORT DRIVER FOR UART0.
57
 
58
        Note this driver is used to test the FreeRTOS port.  It is NOT intended to
59
        be an example of an efficient implementation!
60
*/
61
 
62
/* Standard includes. */
63
#include <stdlib.h>
64
 
65
/* Scheduler includes. */
66
#include "FreeRTOS.h"
67
#include "queue.h"
68
#include "task.h"
69
 
70
/* Demo application includes. */
71
#include "serial.h"
72
 
73
/*-----------------------------------------------------------*/
74
 
75
/* Constants to setup and access the UART. */
76
#define serDLAB                                                 ( ( unsigned char ) 0x80 )
77
#define serENABLE_INTERRUPTS                    ( ( unsigned char ) 0x03 )
78
#define serNO_PARITY                                    ( ( unsigned char ) 0x00 )
79
#define ser1_STOP_BIT                                   ( ( unsigned char ) 0x00 )
80
#define ser8_BIT_CHARS                                  ( ( unsigned char ) 0x03 )
81
#define serFIFO_ON                                              ( ( unsigned char ) 0x01 )
82
#define serCLEAR_FIFO                                   ( ( unsigned char ) 0x06 )
83
#define serWANTED_CLOCK_SCALING                 ( ( unsigned long ) 16 )
84
 
85
/* Constants to setup and access the VIC. */
86
#define serU1VIC_CHANNEL                                ( ( unsigned long ) 0x0007 )
87
#define serU1VIC_CHANNEL_BIT                    ( ( unsigned long ) 0x0080 )
88
#define serU1VIC_ENABLE                                 ( ( unsigned long ) 0x0020 )
89
 
90
/* Misc. */
91
#define serINVALID_QUEUE                                ( ( xQueueHandle ) 0 )
92
#define serHANDLE                                               ( ( xComPortHandle ) 1 )
93
#define serNO_BLOCK                                             ( ( portTickType ) 0 )
94
 
95
/* Constant to access the VIC. */
96
#define serCLEAR_VIC_INTERRUPT                  ( ( unsigned long ) 0 )
97
 
98
/* Constants to determine the ISR source. */
99
#define serSOURCE_THRE                                  ( ( unsigned char ) 0x02 )
100
#define serSOURCE_RX_TIMEOUT                    ( ( unsigned char ) 0x0c )
101
#define serSOURCE_ERROR                                 ( ( unsigned char ) 0x06 )
102
#define serSOURCE_RX                                    ( ( unsigned char ) 0x04 )
103
#define serINTERRUPT_SOURCE_MASK                ( ( unsigned char ) 0x0f )
104
#define serINTERRUPT_IS_PENDING                 ( ( unsigned char ) 0x01 )
105
 
106
/*-----------------------------------------------------------*/
107
 
108
/*
109
 * The asm wrapper for the interrupt service routine.
110
 */
111
extern void vUART_ISREntry( void );
112
 
113
/*
114
 * The C function called from the asm wrapper.
115
 */
116
void vUART_ISRHandler( void );
117
 
118
/*-----------------------------------------------------------*/
119
 
120
/* Queues used to hold received characters, and characters waiting to be
121
transmitted. */
122
static xQueueHandle xRxedChars;
123
static xQueueHandle xCharsForTx;
124
 
125
/* Communication flag between the interrupt service routine and serial API. */
126
static volatile long lTHREEmpty;
127
 
128
/*-----------------------------------------------------------*/
129
 
130
xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned portBASE_TYPE uxQueueLength )
131
{
132
unsigned long ulDivisor, ulWantedClock;
133
xComPortHandle xReturn = serHANDLE;
134
 
135
        /* Create the queues used to hold Rx and Tx characters. */
136
        xRxedChars = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed char ) );
137
        xCharsForTx = xQueueCreate( uxQueueLength + 1, ( unsigned portBASE_TYPE ) sizeof( signed char ) );
138
 
139
        /* Initialise the THRE empty flag. */
140
        lTHREEmpty = pdTRUE;
141
 
142
        if(
143
                ( xRxedChars != serINVALID_QUEUE ) &&
144
                ( xCharsForTx != serINVALID_QUEUE ) &&
145
                ( ulWantedBaud != ( unsigned long ) 0 )
146
          )
147
        {
148
                portENTER_CRITICAL()
149
                {
150
                        /* Setup the baud rate:  Calculate the divisor value. */
151
                        ulWantedClock = ulWantedBaud * serWANTED_CLOCK_SCALING;
152
                        ulDivisor = configCPU_CLOCK_HZ / ulWantedClock;
153
 
154
                        /* Set the DLAB bit so we can access the divisor. */
155
                        U1LCR |= serDLAB;
156
 
157
                        /* Setup the divisor. */
158
                        U1DLL = ( unsigned char ) ( ulDivisor & ( unsigned long ) 0xff );
159
                        ulDivisor >>= 8;
160
                        U1DLM = ( unsigned char ) ( ulDivisor & ( unsigned long ) 0xff );
161
 
162
                        /* Turn on the FIFO's and clear the buffers. */
163
                        U1FCR = ( serFIFO_ON | serCLEAR_FIFO );
164
 
165
                        /* Setup transmission format. */
166
                        U1LCR = serNO_PARITY | ser1_STOP_BIT | ser8_BIT_CHARS;
167
 
168
                        /* Setup the VIC for the UART. */
169
                        VICIntSelect &= ~( serU1VIC_CHANNEL_BIT );
170
                        VICIntEnable |= serU1VIC_CHANNEL_BIT;
171
                        VICVectAddr1 = ( unsigned long ) vUART_ISREntry;
172
                        VICVectCntl1 = serU1VIC_CHANNEL | serU1VIC_ENABLE;
173
 
174
                        /* Enable UART0 interrupts. */
175
                        U1IER |= serENABLE_INTERRUPTS;
176
                }
177
                portEXIT_CRITICAL();
178
        }
179
        else
180
        {
181
                xReturn = ( xComPortHandle ) 0;
182
        }
183
 
184
        return xReturn;
185
}
186
/*-----------------------------------------------------------*/
187
 
188
signed portBASE_TYPE xSerialGetChar( xComPortHandle pxPort, signed char *pcRxedChar, portTickType xBlockTime )
189
{
190
        /* The port handle is not required as this driver only supports UART0. */
191
        ( void ) pxPort;
192
 
193
        /* Get the next character from the buffer.  Return false if no characters
194
        are available, or arrive before xBlockTime expires. */
195
        if( xQueueReceive( xRxedChars, pcRxedChar, xBlockTime ) )
196
        {
197
                return pdTRUE;
198
        }
199
        else
200
        {
201
                return pdFALSE;
202
        }
203
}
204
/*-----------------------------------------------------------*/
205
 
206
void vSerialPutString( xComPortHandle pxPort, const signed char * const pcString, unsigned short usStringLength )
207
{
208
signed char *pxNext;
209
 
210
        /* NOTE: This implementation does not handle the queue being full as no
211
        block time is used! */
212
 
213
        /* The port handle is not required as this driver only supports UART0. */
214
        ( void ) pxPort;
215
        ( void ) usStringLength;
216
 
217
        /* Send each character in the string, one at a time. */
218
        pxNext = ( signed char * ) pcString;
219
        while( *pxNext )
220
        {
221
                xSerialPutChar( pxPort, *pxNext, serNO_BLOCK );
222
                pxNext++;
223
        }
224
}
225
/*-----------------------------------------------------------*/
226
 
227
signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed char cOutChar, portTickType xBlockTime )
228
{
229
signed portBASE_TYPE xReturn;
230
 
231
        /* The port handle is not required as this driver only supports UART0. */
232
        ( void ) pxPort;
233
 
234
        portENTER_CRITICAL();
235
        {
236
                /* Is there space to write directly to the UART? */
237
                if( lTHREEmpty == ( long ) pdTRUE )
238
                {
239
                        /* We wrote the character directly to the UART, so was
240
                        successful. */
241
                        lTHREEmpty = pdFALSE;
242
                        U1THR = cOutChar;
243
                        xReturn = pdPASS;
244
                }
245
                else
246
                {
247
                        /* We cannot write directly to the UART, so queue the character.
248
                        Block for a maximum of xBlockTime if there is no space in the
249
                        queue.  It is ok to block within a critical section as each
250
                        task has it's own critical section management. */
251
                        xReturn = xQueueSend( xCharsForTx, &cOutChar, xBlockTime );
252
 
253
                        /* Depending on queue sizing and task prioritisation:  While we
254
                        were blocked waiting to post interrupts were not disabled.  It is
255
                        possible that the serial ISR has emptied the Tx queue, in which
256
                        case we need to start the Tx off again. */
257
                        if( lTHREEmpty == ( long ) pdTRUE )
258
                        {
259
                                xQueueReceive( xCharsForTx, &cOutChar, serNO_BLOCK );
260
                                lTHREEmpty = pdFALSE;
261
                                U1THR = cOutChar;
262
                        }
263
                }
264
        }
265
        portEXIT_CRITICAL();
266
 
267
        return xReturn;
268
}
269
/*-----------------------------------------------------------*/
270
 
271
void vUART_ISRHandler( void )
272
{
273
signed char cChar;
274
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
275
unsigned char ucInterrupt;
276
 
277
        ucInterrupt = U1IIR;
278
 
279
        /* The interrupt pending bit is active low. */
280
        while( ( ucInterrupt & serINTERRUPT_IS_PENDING ) == 0 )
281
        {
282
                /* What caused the interrupt? */
283
                switch( ucInterrupt & serINTERRUPT_SOURCE_MASK )
284
                {
285
                        case serSOURCE_ERROR :  /* Not handling this, but clear the interrupt. */
286
                                                                        cChar = U1LSR;
287
                                                                        break;
288
 
289
                        case serSOURCE_THRE     :       /* The THRE is empty.  If there is another
290
                                                                        character in the Tx queue, send it now. */
291
                                                                        if( xQueueReceiveFromISR( xCharsForTx, &cChar, &xHigherPriorityTaskWoken ) == pdTRUE )
292
                                                                        {
293
                                                                                U1THR = cChar;
294
                                                                        }
295
                                                                        else
296
                                                                        {
297
                                                                                /* There are no further characters
298
                                                                                queued to send so we can indicate
299
                                                                                that the THRE is available. */
300
                                                                                lTHREEmpty = pdTRUE;
301
                                                                        }
302
                                                                        break;
303
 
304
                        case serSOURCE_RX_TIMEOUT :
305
                        case serSOURCE_RX       :       /* A character was received.  Place it in
306
                                                                        the queue of received characters. */
307
                                                                        cChar = U1RBR;
308
                                                                        xQueueSendFromISR( xRxedChars, &cChar, &xHigherPriorityTaskWoken );
309
                                                                        break;
310
 
311
                        default                         :       /* There is nothing to do, leave the ISR. */
312
                                                                        break;
313
                }
314
 
315
                ucInterrupt = U1IIR;
316
        }
317
 
318
        /* Clear the ISR in the VIC. */
319
        VICVectAddr = serCLEAR_VIC_INTERRUPT;
320
 
321
        /* Exit the ISR.  If a task was woken by either a character being received
322
        or transmitted then a context switch will occur. */
323
        portEXIT_SWITCHING_ISR( xHigherPriorityTaskWoken );
324
}
325
/*-----------------------------------------------------------*/
326
 
327
 
328
 
329
 
330
 
331
 
332
 

powered by: WebSVN 2.1.0

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