Improved error handling during code generation
[cerebrum.git] / avr / uart.c
blob0a27e035dba0f093440366da981bc9b97d898f3a
1 /*************************************************************************
2 Title: Interrupt UART library with receive/transmit circular buffers
3 Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury
4 File: $Id: uart.c,v 1.6.2.2 2009/11/29 08:56:12 Peter Exp $
5 Software: AVR-GCC 4.1, AVR Libc 1.4.6 or higher
6 Hardware: any AVR with built-in UART,
7 License: GNU General Public License
9 DESCRIPTION:
10 An interrupt is generated when the UART has finished transmitting or
11 receiving a byte. The interrupt handling routines use circular buffers
12 for buffering received and transmitted data.
14 The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE variables define
15 the buffer size in bytes. Note that these variables must be a
16 power of 2.
18 USAGE:
19 Refere to the header file uart.h for a description of the routines.
20 See also example test_uart.c.
22 NOTES:
23 Based on Atmel Application Note AVR306
25 LICENSE:
26 Copyright (C) 2006 Peter Fleury
28 This program is free software; you can redistribute it and/or modify
29 it under the terms of the GNU General Public License as published by
30 the Free Software Foundation; either version 2 of the License, or
31 any later version.
33 This program is distributed in the hope that it will be useful,
34 but WITHOUT ANY WARRANTY; without even the implied warranty of
35 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36 GNU General Public License for more details.
38 *************************************************************************/
39 #include <avr/io.h>
40 #include <avr/interrupt.h>
41 #include <avr/pgmspace.h>
42 #include "uart.h"
43 #include "comm_handle.h"
46 * constants and macros
49 /* size of RX/TX buffers */
50 #define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1)
51 #define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1)
53 #if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK )
54 #error RX buffer size is not a power of 2
55 #endif
56 #if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK )
57 #error TX buffer size is not a power of 2
58 #endif
60 //FIXME the following defines still need fixing of the interrupt stuff for most AVRs
61 #if defined(__AVR_AT90S2313__) \
62 || defined(__AVR_AT90S4414__) || defined(__AVR_AT90S4434__) \
63 || defined(__AVR_AT90S8515__) || defined(__AVR_AT90S8535__) \
64 || defined(__AVR_ATmega103__)
65 /* old AVR classic or ATmega103 with one UART */
66 #define AT90_UART
67 #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV
68 #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA
69 #define UART0_STATUS USR
70 #define UART0_CONTROL UCR
71 #define UART0_DATA UDR
72 #define UART0_UDRIE UDRIE
73 #elif defined(__AVR_AT90S2333__) || defined(__AVR_AT90S4433__)
74 /* old AVR classic with one UART */
75 #define AT90_UART
76 #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV
77 #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA
78 #define UART0_STATUS UCSRA
79 #define UART0_CONTROL UCSRB
80 #define UART0_DATA UDR
81 #define UART0_UDRIE UDRIE
82 #elif defined(__AVR_ATmega8__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) \
83 || defined(__AVR_ATmega8515__) || defined(__AVR_ATmega8535__) \
84 || defined(__AVR_ATmega323__)
85 /* ATmega with one USART */
86 #define ATMEGA_USART
87 #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV
88 #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA
89 #define UART0_STATUS UCSRA
90 #define UART0_CONTROL UCSRB
91 #define UART0_DATA UDR
92 #define UART0_UDRIE UDRIE
93 #elif defined(__AVR_ATmega163__)
94 /* ATmega163 with one UART */
95 #define ATMEGA_UART
96 #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV
97 #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA
98 #define UART0_STATUS UCSRA
99 #define UART0_CONTROL UCSRB
100 #define UART0_DATA UDR
101 #define UART0_UDRIE UDRIE
102 #elif defined(__AVR_ATmega162__)
103 /* ATmega with two USART */
104 #define ATMEGA_USART0
105 #define ATMEGA_USART1
106 #define UART0_RECEIVE_INTERRUPT SIG_USART0_RECV
107 #define UART0_TRANSMIT_INTERRUPT SIG_USART0_DATA
108 #define UART0_STATUS UCSR0A
109 #define UART0_CONTROL UCSR0B
110 #define UART0_DATA UDR0
111 #define UART0_UDRIE UDRIE0
112 #elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__)
113 /* ATmega with two USART */
114 #define ATMEGA_USART0
115 #define ATMEGA_USART1
116 #define UART0_RECEIVE_INTERRUPT SIG_UART0_RECV
117 #define UART0_TRANSMIT_INTERRUPT SIG_UART0_DATA
118 #define UART0_STATUS UCSR0A
119 #define UART0_CONTROL UCSR0B
120 #define UART0_DATA UDR0
121 #define UART0_UDRIE UDRIE0
122 #elif defined(__AVR_ATmega161__)
123 /* ATmega with UART */
124 #error "AVR ATmega161 currently not supported by this libaray !"
125 #elif defined(__AVR_ATmega169__)
126 /* ATmega with one USART */
127 #define ATMEGA_USART
128 #define UART0_RECEIVE_INTERRUPT SIG_USART_RECV
129 #define UART0_TRANSMIT_INTERRUPT SIG_USART_DATA
130 #define UART0_STATUS UCSRA
131 #define UART0_CONTROL UCSRB
132 #define UART0_DATA UDR
133 #define UART0_UDRIE UDRIE
134 #elif defined(__AVR_ATmega48__) ||defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega48P__) || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
135 /* ATmega with one USART */
136 #define ATMEGA_USART0
137 #define UART0_RECEIVE_INTERRUPT USART_RX_vect
138 #define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect
139 #define UART0_STATUS UCSR0A
140 #define UART0_CONTROL UCSR0B
141 #define UART0_DATA UDR0
142 #define UART0_UDRIE UDRIE0
143 #elif defined(__AVR_ATtiny2313__)
144 #define ATMEGA_USART
145 #define UART0_RECEIVE_INTERRUPT SIG_USART0_RX
146 #define UART0_TRANSMIT_INTERRUPT SIG_USART0_UDRE
147 #define UART0_STATUS UCSRA
148 #define UART0_CONTROL UCSRB
149 #define UART0_DATA UDR
150 #define UART0_UDRIE UDRIE
151 #elif defined(__AVR_ATmega329__) ||defined(__AVR_ATmega3290__) ||\
152 defined(__AVR_ATmega649__) ||defined(__AVR_ATmega6490__) ||\
153 defined(__AVR_ATmega325__) ||defined(__AVR_ATmega3250__) ||\
154 defined(__AVR_ATmega645__) ||defined(__AVR_ATmega6450__)
155 /* ATmega with one USART */
156 #define ATMEGA_USART0
157 #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV
158 #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA
159 #define UART0_STATUS UCSR0A
160 #define UART0_CONTROL UCSR0B
161 #define UART0_DATA UDR0
162 #define UART0_UDRIE UDRIE0
163 #elif defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega640__)
164 /* ATmega with two USART */
165 #define ATMEGA_USART0
166 #define ATMEGA_USART1
167 #define UART0_RECEIVE_INTERRUPT USART0_RX_vect
168 #define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
169 #define UART0_STATUS UCSR0A
170 #define UART0_CONTROL UCSR0B
171 #define UART0_DATA UDR0
172 #define UART0_UDRIE UDRIE0
173 #elif defined(__AVR_ATmega644__)
174 /* ATmega with one USART */
175 #define ATMEGA_USART0
176 #define UART0_RECEIVE_INTERRUPT SIG_USART_RECV
177 #define UART0_TRANSMIT_INTERRUPT SIG_USART_DATA
178 #define UART0_STATUS UCSR0A
179 #define UART0_CONTROL UCSR0B
180 #define UART0_DATA UDR0
181 #define UART0_UDRIE UDRIE0
182 #elif defined(__AVR_ATmega164P__) || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega644P__)
183 /* ATmega with two USART */
184 #define ATMEGA_USART0
185 #define ATMEGA_USART1
186 #define UART0_RECEIVE_INTERRUPT SIG_USART_RECV
187 #define UART0_TRANSMIT_INTERRUPT SIG_USART_DATA
188 #define UART0_STATUS UCSR0A
189 #define UART0_CONTROL UCSR0B
190 #define UART0_DATA UDR0
191 #define UART0_UDRIE UDRIE0
192 #else
193 #error "no UART definition for MCU available"
194 #endif
198 * module global variables
200 static volatile unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE];
201 static volatile unsigned char UART_TxHead;
202 static volatile unsigned char UART_TxTail;
204 ISR(UART0_RECEIVE_INTERRUPT)
206 unsigned char data;
207 //unsigned char usr;
208 //unsigned char lastRxError;
211 /* read UART status register and UART data register */
212 //usr = UART0_STATUS;
213 data = UART0_DATA;
216 #if defined( AT90_UART )
217 lastRxError = (usr & (_BV(FE)|_BV(DOR)) );
218 #elif defined( ATMEGA_USART )
219 lastRxError = (usr & (_BV(FE)|_BV(DOR)) );
220 #elif defined( ATMEGA_USART0 )
221 lastRxError = (usr & (_BV(FE0)|_BV(DOR0)) );
222 #elif defined ( ATMEGA_UART )
223 lastRxError = (usr & (_BV(FE)|_BV(DOR)) );
224 #endif
227 //uart_putc(data);
228 comm_handle(data);
232 ISR(UART0_TRANSMIT_INTERRUPT)
233 /*************************************************************************
234 Function: UART Data Register Empty interrupt
235 Purpose: called when the UART is ready to transmit the next byte
236 **************************************************************************/
238 unsigned char tmptail;
241 if ( UART_TxHead != UART_TxTail) {
242 /* calculate and store new buffer index */
243 tmptail = (UART_TxTail + 1) & UART_TX_BUFFER_MASK;
244 UART_TxTail = tmptail;
245 /* get one byte from buffer and write it to UART */
246 UART0_DATA = UART_TxBuf[tmptail]; /* start transmission */
247 }else{
248 /* tx buffer empty, disable UDRE interrupt */
249 UART0_CONTROL &= ~_BV(UART0_UDRIE);
254 /*************************************************************************
255 Function: uart_init()
256 Purpose: initialize UART and set baudrate
257 Input: baudrate using macro UART_BAUD_SELECT()
258 Returns: none
259 **************************************************************************/
260 void uart_init(unsigned int baudrate)
262 UART_TxHead = 0;
263 UART_TxTail = 0;
265 #if defined( AT90_UART )
266 /* set baud rate */
267 UBRR = (unsigned char)baudrate;
269 /* enable UART receiver and transmmitter and receive complete interrupt */
270 UART0_CONTROL = _BV(RXCIE)|_BV(RXEN)|_BV(TXEN);
272 #elif defined (ATMEGA_USART)
273 /* Set baud rate */
274 if ( baudrate & 0x8000 )
276 UART0_STATUS = (1<<U2X); //Enable 2x speed
277 baudrate &= ~0x8000;
279 UBRRH = (unsigned char)(baudrate>>8);
280 UBRRL = (unsigned char) baudrate;
282 /* Enable USART receiver and transmitter and receive complete interrupt */
283 UART0_CONTROL = _BV(RXCIE)|(1<<RXEN)|(1<<TXEN);
285 /* Set frame format: asynchronous, 8data, no parity, 1stop bit */
286 #ifdef URSEL
287 UCSRC = (1<<URSEL)|(3<<UCSZ0);
288 #else
289 UCSRC = (3<<UCSZ0);
290 #endif
292 #elif defined (ATMEGA_USART0 )
293 /* Set baud rate */
294 if ( baudrate & 0x8000 )
296 UART0_STATUS = (1<<U2X0); //Enable 2x speed
297 baudrate &= ~0x8000;
299 UBRR0H = (unsigned char)(baudrate>>8);
300 UBRR0L = (unsigned char) baudrate;
302 /* Enable USART receiver and transmitter and receive complete interrupt */
303 UART0_CONTROL = _BV(RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
305 /* Set frame format: asynchronous, 8data, no parity, 1stop bit */
306 #ifdef URSEL0
307 UCSR0C = (1<<URSEL0)|(3<<UCSZ00);
308 #else
309 UCSR0C = (3<<UCSZ00);
310 #endif
312 #elif defined ( ATMEGA_UART )
313 /* set baud rate */
314 if ( baudrate & 0x8000 )
316 UART0_STATUS = (1<<U2X); //Enable 2x speed
317 baudrate &= ~0x8000;
319 UBRRHI = (unsigned char)(baudrate>>8);
320 UBRR = (unsigned char) baudrate;
322 /* Enable UART receiver and transmitter and receive complete interrupt */
323 UART0_CONTROL = _BV(RXCIE)|(1<<RXEN)|(1<<TXEN);
325 #endif
327 }/* uart_init */
329 /*************************************************************************
330 Function: uart_putc()
331 Purpose: write byte to ringbuffer for transmitting via UART
332 Input: byte to be transmitted
333 Returns: none
334 **************************************************************************/
335 void uart_putc(unsigned char data)
337 unsigned char tmphead;
339 tmphead = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;
341 while ( tmphead == UART_TxTail );/* wait for free space in buffer */
343 UART_TxBuf[tmphead] = data;
344 UART_TxHead = tmphead;
346 /* enable UDRE interrupt */
347 UART0_CONTROL |= _BV(UART0_UDRIE);
350 void uart_putc_nonblocking(unsigned char data){
351 unsigned char tmphead;
353 tmphead = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;
355 if(tmphead == UART_TxTail) //if there is no free space in buffer
356 return;
358 UART_TxBuf[tmphead] = data;
359 UART_TxHead = tmphead;
361 //enable UDRE interrupt
362 UART0_CONTROL |= _BV(UART0_UDRIE);
366 /*************************************************************************
367 Function: uart_puts()
368 Purpose: transmit string to UART
369 Input: string to be transmitted
370 Returns: none
371 **************************************************************************/
372 void uart_puts(const char *s )
374 while (*s)
375 uart_putc(*s++);
377 }/* uart_puts */
380 /*************************************************************************
381 Function: uart_puts_p()
382 Purpose: transmit string from program memory to UART
383 Input: program memory string to be transmitted
384 Returns: none
385 **************************************************************************/
386 void uart_puts_p(const char *progmem_s )
388 register char c;
390 while ( (c = pgm_read_byte(progmem_s++)) )
391 uart_putc(c);
393 }/* uart_puts_p */