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/] [AVR32_UC3/] [serial/] [serial.c] - Blame information for rev 623

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

Line No. Rev Author Line
1 589 jeremybenn
/*This file has been prepared for Doxygen automatic documentation generation.*/
2
/*! \file *********************************************************************
3
 *
4
 * \brief FreeRTOS Serial Port management example for AVR32 UC3.
5
 *
6
 * - Compiler:           IAR EWAVR32 and GNU GCC for AVR32
7
 * - Supported devices:  All AVR32 devices can be used.
8
 * - AppNote:
9
 *
10
 * \author               Atmel Corporation: http://www.atmel.com \n
11
 *                       Support and FAQ: http://support.atmel.no/
12
 *
13
 *****************************************************************************/
14
 
15
/* Copyright (c) 2007, Atmel Corporation All rights reserved.
16
 *
17
 * Redistribution and use in source and binary forms, with or without
18
 * modification, are permitted provided that the following conditions are met:
19
 *
20
 * 1. Redistributions of source code must retain the above copyright notice,
21
 * this list of conditions and the following disclaimer.
22
 *
23
 * 2. Redistributions in binary form must reproduce the above copyright notice,
24
 * this list of conditions and the following disclaimer in the documentation
25
 * and/or other materials provided with the distribution.
26
 *
27
 * 3. The name of ATMEL may not be used to endorse or promote products derived
28
 * from this software without specific prior written permission.
29
 *
30
 * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
31
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
32
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
33
 * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
34
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
35
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
36
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
37
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
39
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40
 */
41
 
42
 
43
/*
44
  BASIC INTERRUPT DRIVEN SERIAL PORT DRIVER FOR USART.
45
*/
46
 
47
/* Scheduler includes. */
48
#include "FreeRTOS.h"
49
#include "queue.h"
50
#include "task.h"
51
 
52
/* Demo application includes. */
53
#include "serial.h"
54
#include <avr32/io.h>
55
#include "board.h"
56
#include "gpio.h"
57
 
58
/*-----------------------------------------------------------*/
59
 
60
/* Constants to setup and access the USART. */
61
#define serINVALID_COMPORT_HANDLER        ( ( xComPortHandle ) 0 )
62
#define serINVALID_QUEUE                  ( ( xQueueHandle ) 0 )
63
#define serHANDLE                         ( ( xComPortHandle ) 1 )
64
#define serNO_BLOCK                       ( ( portTickType ) 0 )
65
 
66
/*-----------------------------------------------------------*/
67
 
68
/* Queues used to hold received characters, and characters waiting to be
69
transmitted. */
70
static xQueueHandle xRxedChars;
71
static xQueueHandle xCharsForTx;
72
 
73
/*-----------------------------------------------------------*/
74
 
75
/* Forward declaration. */
76
static void vprvSerialCreateQueues( unsigned portBASE_TYPE uxQueueLength,
77
                                                                        xQueueHandle *pxRxedChars,
78
                                                                        xQueueHandle *pxCharsForTx );
79
 
80
/*-----------------------------------------------------------*/
81
 
82
#if __GNUC__
83
        __attribute__((__noinline__))
84
#elif __ICCAVR32__
85
        #pragma optimize = no_inline
86
#endif
87
 
88
static portBASE_TYPE prvUSART_ISR_NonNakedBehaviour( void )
89
{
90
        /* Now we can declare the local variables. */
91
        signed portCHAR     cChar;
92
        portBASE_TYPE     xHigherPriorityTaskWoken = pdFALSE;
93
        unsigned portLONG     ulStatus;
94
        volatile avr32_usart_t  *usart = serialPORT_USART;
95
        portBASE_TYPE retstatus;
96
 
97
        /* What caused the interrupt? */
98
        ulStatus = usart->csr & usart->imr;
99
 
100
        if (ulStatus & AVR32_USART_CSR_TXRDY_MASK)
101
        {
102
                /* The interrupt was caused by the THR becoming empty.  Are there any
103
                more characters to transmit?
104
                Because FreeRTOS is not supposed to run with nested interrupts, put all OS
105
                calls in a critical section . */
106
                portENTER_CRITICAL();
107
                        retstatus = xQueueReceiveFromISR( xCharsForTx, &cChar, &xHigherPriorityTaskWoken );
108
                portEXIT_CRITICAL();
109
 
110
                if (retstatus == pdTRUE)
111
                {
112
                        /* A character was retrieved from the queue so can be sent to the
113
                         THR now. */
114
                        usart->thr = cChar;
115
                }
116
                else
117
                {
118
                        /* Queue empty, nothing to send so turn off the Tx interrupt. */
119
                        usart->idr = AVR32_USART_IDR_TXRDY_MASK;
120
                }
121
        }
122
 
123
        if (ulStatus & AVR32_USART_CSR_RXRDY_MASK)
124
        {
125
                /* The interrupt was caused by the receiver getting data. */
126
                cChar = usart->rhr; //TODO
127
 
128
                /* Because FreeRTOS is not supposed to run with nested interrupts, put all OS
129
                calls in a critical section . */
130
                portENTER_CRITICAL();
131
                        xQueueSendFromISR(xRxedChars, &cChar, &xHigherPriorityTaskWoken);
132
                portEXIT_CRITICAL();
133
        }
134
 
135
        /* The return value will be used by portEXIT_SWITCHING_ISR() to know if it
136
        should perform a vTaskSwitchContext(). */
137
        return ( xHigherPriorityTaskWoken );
138
}
139
/*-----------------------------------------------------------*/
140
 
141
/*
142
 * USART interrupt service routine.
143
 */
144
#if __GNUC__
145
        __attribute__((__naked__))
146
#elif __ICCAVR32__
147
        #pragma shadow_registers = full   // Naked.
148
#endif
149
 
150
static void vUSART_ISR( void )
151
{
152
        /* This ISR can cause a context switch, so the first statement must be a
153
        call to the portENTER_SWITCHING_ISR() macro.  This must be BEFORE any
154
        variable declarations. */
155
        portENTER_SWITCHING_ISR();
156
 
157
        prvUSART_ISR_NonNakedBehaviour();
158
 
159
        /* Exit the ISR.  If a task was woken by either a character being received
160
        or transmitted then a context switch will occur. */
161
        portEXIT_SWITCHING_ISR();
162
}
163
/*-----------------------------------------------------------*/
164
 
165
 
166
/*
167
 * Init the serial port for the Minimal implementation.
168
 */
169
xComPortHandle xSerialPortInitMinimal( unsigned portLONG ulWantedBaud, unsigned portBASE_TYPE uxQueueLength )
170
{
171
static const gpio_map_t USART_GPIO_MAP =
172
{
173
        { serialPORT_USART_RX_PIN, serialPORT_USART_RX_FUNCTION },
174
        { serialPORT_USART_TX_PIN, serialPORT_USART_TX_FUNCTION }
175
};
176
 
177
xComPortHandle    xReturn = serHANDLE;
178
volatile avr32_usart_t  *usart = serialPORT_USART;
179
int cd; /* USART Clock Divider. */
180
 
181
        /* Create the rx and tx queues. */
182
        vprvSerialCreateQueues( uxQueueLength, &xRxedChars, &xCharsForTx );
183
 
184
        /* Configure USART. */
185
        if( ( xRxedChars != serINVALID_QUEUE ) &&
186
          ( xCharsForTx != serINVALID_QUEUE ) &&
187
          ( ulWantedBaud != ( unsigned portLONG ) 0 ) )
188
        {
189
                portENTER_CRITICAL();
190
                {
191
                        /**
192
                        ** Reset USART.
193
                        **/
194
                        /* Disable all USART interrupt sources to begin... */
195
                        usart->idr = 0xFFFFFFFF;
196
 
197
                        /* Reset mode and other registers that could cause unpredictable
198
                         behaviour after reset */
199
                        usart->mr = 0; /* Reset Mode register. */
200
                        usart->rtor = 0; /* Reset Receiver Time-out register. */
201
                        usart->ttgr = 0; /* Reset Transmitter Timeguard register. */
202
 
203
                        /* Shutdown RX and TX, reset status bits, reset iterations in CSR, reset NACK
204
                         and turn off DTR and RTS */
205
                        usart->cr = AVR32_USART_CR_RSTRX_MASK   |
206
                                           AVR32_USART_CR_RSTTX_MASK   |
207
                                           AVR32_USART_CR_RXDIS_MASK   |
208
                                           AVR32_USART_CR_TXDIS_MASK   |
209
                                           AVR32_USART_CR_RSTSTA_MASK  |
210
                                           AVR32_USART_CR_RSTIT_MASK   |
211
                                           AVR32_USART_CR_RSTNACK_MASK |
212
                                           AVR32_USART_CR_DTRDIS_MASK  |
213
                                           AVR32_USART_CR_RTSDIS_MASK;
214
 
215
                        /**
216
                        ** Configure USART.
217
                        **/
218
                        /* Enable USART RXD & TXD pins. */
219
                        gpio_enable_module( USART_GPIO_MAP, sizeof( USART_GPIO_MAP ) / sizeof( USART_GPIO_MAP[0] ) );
220
 
221
                        /* Set the USART baudrate to be as close as possible to the wanted baudrate. */
222
                        /*
223
                        *             ** BAUDRATE CALCULATION **
224
                        *
225
                        *                 Selected Clock                       Selected Clock
226
                        *     baudrate = ----------------   or     baudrate = ----------------
227
                        *                    16 x CD                              8 x CD
228
                        *
229
                        *       (with 16x oversampling)              (with 8x oversampling)
230
                        */
231
 
232
                        if( ulWantedBaud < ( configCPU_CLOCK_HZ / 16 ) )
233
                        {
234
                                /* Use 8x oversampling */
235
                                usart->mr |= (1<<AVR32_USART_MR_OVER_OFFSET);
236
                                cd = configCPU_CLOCK_HZ / (8*ulWantedBaud);
237
 
238
                                if( cd < 2 )
239
                                {
240
                                        return serINVALID_COMPORT_HANDLER;
241
                                }
242
 
243
                                usart->brgr = (cd << AVR32_USART_BRGR_CD_OFFSET);
244
                        }
245
                        else
246
                        {
247
                                /* Use 16x oversampling */
248
                                usart->mr &= ~(1<<AVR32_USART_MR_OVER_OFFSET);
249
                                cd = configCPU_CLOCK_HZ / (16*ulWantedBaud);
250
 
251
                                if( cd > 65535 )
252
                                {
253
                                        /* Baudrate is too low */
254
                                        return serINVALID_COMPORT_HANDLER;
255
                                }
256
                        }
257
 
258
                        usart->brgr = (cd << AVR32_USART_BRGR_CD_OFFSET);
259
 
260
                        /* Set the USART Mode register: Mode=Normal(0), Clk selection=MCK(0),
261
                        CHRL=8,  SYNC=0(asynchronous), PAR=None, NBSTOP=1, CHMODE=0, MSBF=0,
262
                        MODE9=0, CKLO=0, OVER(previously done when setting the baudrate),
263
                        other fields not used in this mode. */
264
                        usart->mr |= ((8-5) << AVR32_USART_MR_CHRL_OFFSET  ) |
265
                                        (   4  << AVR32_USART_MR_PAR_OFFSET   ) |
266
                                        (   1  << AVR32_USART_MR_NBSTOP_OFFSET);
267
 
268
                        /* Write the Transmit Timeguard Register */
269
                        usart->ttgr = 0;
270
 
271
 
272
                        /* Register the USART interrupt handler to the interrupt controller and
273
                         enable the USART interrupt. */
274
                        INTC_register_interrupt((__int_handler)&vUSART_ISR, serialPORT_USART_IRQ, INT1);
275
 
276
                        /* Enable USART interrupt sources (but not Tx for now)... */
277
                        usart->ier = AVR32_USART_IER_RXRDY_MASK;
278
 
279
                        /* Enable receiver and transmitter... */
280
                        usart->cr |= AVR32_USART_CR_TXEN_MASK | AVR32_USART_CR_RXEN_MASK;
281
                }
282
                portEXIT_CRITICAL();
283
        }
284
        else
285
        {
286
                xReturn = serINVALID_COMPORT_HANDLER;
287
        }
288
 
289
        return xReturn;
290
}
291
/*-----------------------------------------------------------*/
292
 
293
signed portBASE_TYPE xSerialGetChar( xComPortHandle pxPort, signed portCHAR *pcRxedChar, portTickType xBlockTime )
294
{
295
        /* The port handle is not required as this driver only supports UART0. */
296
        ( void ) pxPort;
297
 
298
        /* Get the next character from the buffer.  Return false if no characters
299
        are available, or arrive before xBlockTime expires. */
300
        if( xQueueReceive( xRxedChars, pcRxedChar, xBlockTime ) )
301
        {
302
                return pdTRUE;
303
        }
304
        else
305
        {
306
                return pdFALSE;
307
        }
308
}
309
/*-----------------------------------------------------------*/
310
 
311
void vSerialPutString( xComPortHandle pxPort, const signed portCHAR * const pcString, unsigned portSHORT usStringLength )
312
{
313
signed portCHAR *pxNext;
314
 
315
        /* NOTE: This implementation does not handle the queue being full as no
316
        block time is used! */
317
 
318
        /* The port handle is not required as this driver only supports UART0. */
319
        ( void ) pxPort;
320
 
321
        /* Send each character in the string, one at a time. */
322
        pxNext = ( signed portCHAR * ) pcString;
323
        while( *pxNext )
324
        {
325
                xSerialPutChar( pxPort, *pxNext, serNO_BLOCK );
326
                pxNext++;
327
        }
328
}
329
/*-----------------------------------------------------------*/
330
 
331
signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed portCHAR cOutChar, portTickType xBlockTime )
332
{
333
volatile avr32_usart_t  *usart = serialPORT_USART;
334
 
335
        /* Place the character in the queue of characters to be transmitted. */
336
        if( xQueueSend( xCharsForTx, &cOutChar, xBlockTime ) != pdPASS )
337
        {
338
                return pdFAIL;
339
        }
340
 
341
        /* Turn on the Tx interrupt so the ISR will remove the character from the
342
        queue and send it.   This does not need to be in a critical section as
343
        if the interrupt has already removed the character the next interrupt
344
        will simply turn off the Tx interrupt again. */
345
        usart->ier = (1 << AVR32_USART_IER_TXRDY_OFFSET);
346
 
347
        return pdPASS;
348
}
349
/*-----------------------------------------------------------*/
350
 
351
void vSerialClose( xComPortHandle xPort )
352
{
353
  /* Not supported as not required by the demo application. */
354
}
355
/*-----------------------------------------------------------*/
356
 
357
/*###########################################################*/
358
 
359
/*
360
 * Create the rx and tx queues.
361
 */
362
static void vprvSerialCreateQueues(  unsigned portBASE_TYPE uxQueueLength, xQueueHandle *pxRxedChars, xQueueHandle *pxCharsForTx )
363
{
364
        /* Create the queues used to hold Rx and Tx characters. */
365
        xRxedChars = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed portCHAR ) );
366
        xCharsForTx = xQueueCreate( uxQueueLength + 1, ( unsigned portBASE_TYPE ) sizeof( signed portCHAR ) );
367
 
368
        /* Pass back a reference to the queues so the serial API file can
369
        post/receive characters. */
370
        *pxRxedChars = xRxedChars;
371
        *pxCharsForTx = xCharsForTx;
372
}
373
/*-----------------------------------------------------------*/

powered by: WebSVN 2.1.0

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