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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [lwIP_AVR32_UC3/] [SERIAL/] [serial.c] - Blame information for rev 583

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 583 jeremybenn
/*This file has been prepared for Doxygen automatic documentation generation.*/
2
/*! \file *********************************************************************
3
 *
4
 * \brief FreeRTOS serial port 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 USART0.
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
static portBASE_TYPE prvUSART0_ISR_NonNakedBehaviour( void )
88
{
89
  /* Now we can declare the local variables. */
90
  signed portCHAR     cChar;
91
  portBASE_TYPE     xHigherPriorityTaskWoken = pdFALSE;
92
  unsigned portLONG     ulStatus;
93
  volatile avr32_usart_t  *usart0 = &AVR32_USART0;
94
  portBASE_TYPE retstatus;
95
 
96
  /* What caused the interrupt? */
97
  ulStatus = usart0->csr & usart0->imr;
98
 
99
  if (ulStatus & AVR32_USART_CSR_TXRDY_MASK)
100
  {
101
    /* The interrupt was caused by the THR becoming empty.  Are there any
102
       more characters to transmit? */
103
    /* Because FreeRTOS is not supposed to run with nested interrupts, put all OS
104
      calls in a critical section . */
105
    portENTER_CRITICAL();
106
    retstatus = xQueueReceiveFromISR(xCharsForTx, &cChar, &xHigherPriorityTaskWoken);
107
    portEXIT_CRITICAL();
108
    if (retstatus == pdTRUE)
109
    {
110
      /* A character was retrieved from the queue so can be sent to the
111
         THR now. */
112
      usart0->thr = cChar;
113
    }
114
    else
115
    {
116
      /* Queue empty, nothing to send so turn off the Tx interrupt. */
117
      usart0->idr = AVR32_USART_IDR_TXRDY_MASK;
118
    }
119
  }
120
 
121
  if (ulStatus & AVR32_USART_CSR_RXRDY_MASK)
122
  {
123
    /* The interrupt was caused by the receiver getting data. */
124
    cChar = usart0->rhr; //TODO
125
 
126
    /* Because FreeRTOS is not supposed to run with nested interrupts, put all OS
127
      calls in a critical section . */
128
    portENTER_CRITICAL();
129
        xQueueSendFromISR(xRxedChars, &cChar, &xHigherPriorityTaskWoken);
130
    portEXIT_CRITICAL();
131
  }
132
 
133
  /* The return value will be used by portEXIT_SWITCHING_ISR() to know if it
134
  should perform a vTaskSwitchContext(). */
135
  return ( xHigherPriorityTaskWoken );
136
}
137
 
138
 
139
/*
140
 * USART0 interrupt service routine.
141
 */
142
#if __GNUC__
143
__attribute__((__naked__))
144
#elif __ICCAVR32__
145
#pragma shadow_registers = full   // Naked.
146
#endif
147
static void vUSART0_ISR( void )
148
{
149
 
150
 /* This ISR can cause a context switch, so the first statement must be a
151
  call to the portENTER_SWITCHING_ISR() macro.  This must be BEFORE any
152
  variable declarations. */
153
  portENTER_SWITCHING_ISR();
154
  prvUSART0_ISR_NonNakedBehaviour();
155
 /* Exit the ISR.  If a task was woken by either a character being received
156
  or transmitted then a context switch will occur. */
157
  portEXIT_SWITCHING_ISR();
158
}
159
/*-----------------------------------------------------------*/
160
 
161
 
162
 
163
/*
164
 * Init the serial port for the Minimal implementation.
165
 */
166
xComPortHandle xSerialPortInitMinimal( unsigned portLONG ulWantedBaud, unsigned portBASE_TYPE uxQueueLength )
167
{
168
  static const gpio_map_t USART0_GPIO_MAP =
169
  {
170
    { AVR32_USART0_RXD_0_PIN, AVR32_USART0_RXD_0_FUNCTION },
171
    { AVR32_USART0_TXD_0_PIN, AVR32_USART0_TXD_0_FUNCTION }
172
  };
173
 
174
  xComPortHandle    xReturn = serHANDLE;
175
  volatile avr32_usart_t  *usart0 = &AVR32_USART0;
176
  int                           cd; /* USART0 Clock Divider. */
177
 
178
  /* Create the rx and tx queues. */
179
  vprvSerialCreateQueues( uxQueueLength, &xRxedChars, &xCharsForTx );
180
 
181
  /* Configure USART0. */
182
  if( ( xRxedChars != serINVALID_QUEUE ) &&
183
      ( xCharsForTx != serINVALID_QUEUE ) &&
184
      ( ulWantedBaud != ( unsigned portLONG ) 0 ) )
185
  {
186
    portENTER_CRITICAL();
187
    {
188
      /**
189
       ** Reset USART0.
190
       **/
191
      /* Disable all USART0 interrupt sources to begin... */
192
      usart0->idr = 0xFFFFFFFF;
193
 
194
      /* Reset mode and other registers that could cause unpredictable
195
         behaviour after reset */
196
      usart0->mr = 0; /* Reset Mode register. */
197
      usart0->rtor = 0; /* Reset Receiver Time-out register. */
198
      usart0->ttgr = 0; /* Reset Transmitter Timeguard register. */
199
 
200
      /* Shutdown RX and TX, reset status bits, reset iterations in CSR, reset NACK
201
         and turn off DTR and RTS */
202
      usart0->cr = AVR32_USART_CR_RSTRX_MASK   |
203
                   AVR32_USART_CR_RSTTX_MASK   |
204
                   AVR32_USART_CR_RXDIS_MASK   |
205
                   AVR32_USART_CR_TXDIS_MASK   |
206
                   AVR32_USART_CR_RSTSTA_MASK  |
207
                   AVR32_USART_CR_RSTIT_MASK   |
208
                   AVR32_USART_CR_RSTNACK_MASK |
209
                   AVR32_USART_CR_DTRDIS_MASK  |
210
                   AVR32_USART_CR_RTSDIS_MASK;
211
 
212
      /**
213
       ** Configure USART0.
214
       **/
215
      /* Enable USART0 RXD & TXD pins. */
216
      gpio_enable_module( USART0_GPIO_MAP, sizeof( USART0_GPIO_MAP ) / sizeof( USART0_GPIO_MAP[0] ) );
217
 
218
      /* Set the USART0 baudrate to be as close as possible to the wanted baudrate. */
219
      /*
220
       *             ** BAUDRATE CALCULATION **
221
       *
222
       *                 Selected Clock                       Selected Clock
223
       *     baudrate = ----------------   or     baudrate = ----------------
224
       *                    16 x CD                              8 x CD
225
       *
226
       *       (with 16x oversampling)              (with 8x oversampling)
227
       */
228
      if ( ulWantedBaud < (configCPU_CLOCK_HZ/16)  ){
229
        /* Use 8x oversampling */
230
        usart0->mr |= (1<<AVR32_USART_MR_OVER_OFFSET);
231
        cd = configCPU_CLOCK_HZ / (8*ulWantedBaud);
232
 
233
        if (cd < 2) {
234
          return serINVALID_COMPORT_HANDLER;
235
        }
236
        usart0->brgr = (cd << AVR32_USART_BRGR_CD_OFFSET);
237
      } else {
238
        /* Use 16x oversampling */
239
        usart0->mr &= ~(1<<AVR32_USART_MR_OVER_OFFSET);
240
        cd =  configCPU_CLOCK_HZ / (16*ulWantedBaud);
241
 
242
        if (cd > 65535) {
243
          /* Baudrate is too low */
244
          return serINVALID_COMPORT_HANDLER;
245
        }
246
      }
247
      usart0->brgr = (cd << AVR32_USART_BRGR_CD_OFFSET);
248
 
249
      /* Set the USART0 Mode register: Mode=Normal(0), Clk selection=MCK(0),
250
         CHRL=8,  SYNC=0(asynchronous), PAR=None, NBSTOP=1, CHMODE=0, MSBF=0,
251
         MODE9=0, CKLO=0, OVER(previously done when setting the baudrate),
252
         other fields not used in this mode. */
253
      usart0->mr |= ((8-5) << AVR32_USART_MR_CHRL_OFFSET  ) |
254
                    (   4  << AVR32_USART_MR_PAR_OFFSET   ) |
255
                    (   1  << AVR32_USART_MR_NBSTOP_OFFSET);
256
 
257
      /* Write the Transmit Timeguard Register */
258
      usart0->ttgr = 0;
259
 
260
      // Register the USART0 interrupt handler to the interrupt controller and
261
      // enable the USART0 interrupt.
262
      INTC_register_interrupt((__int_handler)&vUSART0_ISR, AVR32_USART0_IRQ, INT1);
263
 
264
      /* Enable USART0 interrupt sources (but not Tx for now)... */
265
      usart0->ier = AVR32_USART_IER_RXRDY_MASK;
266
 
267
      /* Enable receiver and transmitter... */
268
      usart0->cr |= AVR32_USART_CR_TXEN_MASK | AVR32_USART_CR_RXEN_MASK;
269
    }
270
    portEXIT_CRITICAL();
271
  }
272
  else
273
  {
274
    xReturn = serINVALID_COMPORT_HANDLER;
275
  }
276
 
277
  return xReturn;
278
}
279
/*-----------------------------------------------------------*/
280
 
281
signed portBASE_TYPE xSerialGetChar( xComPortHandle pxPort, signed portCHAR *pcRxedChar, portTickType xBlockTime )
282
{
283
  /* The port handle is not required as this driver only supports UART0. */
284
  ( void ) pxPort;
285
 
286
  /* Get the next character from the buffer.  Return false if no characters
287
  are available, or arrive before xBlockTime expires. */
288
  if( xQueueReceive( xRxedChars, pcRxedChar, xBlockTime ) )
289
  {
290
    return pdTRUE;
291
  }
292
  else
293
  {
294
    return pdFALSE;
295
  }
296
}
297
/*-----------------------------------------------------------*/
298
 
299
void vSerialPutString( xComPortHandle pxPort, const signed portCHAR * const pcString, unsigned portSHORT usStringLength )
300
{
301
signed portCHAR *pxNext;
302
 
303
  /* NOTE: This implementation does not handle the queue being full as no
304
  block time is used! */
305
 
306
  /* The port handle is not required as this driver only supports UART0. */
307
  ( void ) pxPort;
308
 
309
  /* Send each character in the string, one at a time. */
310
  pxNext = ( signed portCHAR * ) pcString;
311
  while( *pxNext )
312
  {
313
    xSerialPutChar( pxPort, *pxNext, serNO_BLOCK );
314
    pxNext++;
315
  }
316
}
317
/*-----------------------------------------------------------*/
318
 
319
signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed portCHAR cOutChar, portTickType xBlockTime )
320
{
321
volatile avr32_usart_t  *usart0 = &AVR32_USART0;
322
 
323
  /* Place the character in the queue of characters to be transmitted. */
324
  if( xQueueSend( xCharsForTx, &cOutChar, xBlockTime ) != pdPASS )
325
  {
326
    return pdFAIL;
327
  }
328
 
329
  /* Turn on the Tx interrupt so the ISR will remove the character from the
330
  queue and send it.   This does not need to be in a critical section as
331
  if the interrupt has already removed the character the next interrupt
332
  will simply turn off the Tx interrupt again. */
333
  usart0->ier = (1 << AVR32_USART_IER_TXRDY_OFFSET);
334
 
335
  return pdPASS;
336
}
337
/*-----------------------------------------------------------*/
338
 
339
void vSerialClose( xComPortHandle xPort )
340
{
341
  /* Not supported as not required by the demo application. */
342
}
343
/*-----------------------------------------------------------*/
344
 
345
/*###########################################################*/
346
 
347
/*
348
 * Create the rx and tx queues.
349
 */
350
static void vprvSerialCreateQueues(  unsigned portBASE_TYPE uxQueueLength, xQueueHandle *pxRxedChars, xQueueHandle *pxCharsForTx )
351
{
352
  /* Create the queues used to hold Rx and Tx characters. */
353
  xRxedChars = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed portCHAR ) );
354
  xCharsForTx = xQueueCreate( uxQueueLength + 1, ( unsigned portBASE_TYPE ) sizeof( signed portCHAR ) );
355
 
356
  /* Pass back a reference to the queues so the serial API file can
357
  post/receive characters. */
358
  *pxRxedChars = xRxedChars;
359
  *pxCharsForTx = xCharsForTx;
360
}
361
/*-----------------------------------------------------------*/

powered by: WebSVN 2.1.0

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