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
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
19 Refere to the header file uart.h for a description of the routines.
20 See also example test_uart.c.
23 Based on Atmel Application Note AVR306
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
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 *************************************************************************/
40 #include <avr/interrupt.h>
41 #include <avr/pgmspace.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
56 #if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK )
57 #error TX buffer size is not a power of 2
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 */
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 */
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 */
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 */
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 */
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__)
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
193 #error "no UART definition for MCU available"
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
)
208 //unsigned char lastRxError;
211 /* read UART status register and UART data register */
212 //usr = UART0_STATUS;
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)) );
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 */
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()
259 **************************************************************************/
260 void uart_init(unsigned int baudrate
)
265 #if defined( AT90_UART )
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)
274 if ( baudrate
& 0x8000 )
276 UART0_STATUS
= (1<<U2X
); //Enable 2x speed
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 */
287 UCSRC
= (1<<URSEL
)|(3<<UCSZ0
);
292 #elif defined (ATMEGA_USART0 )
294 if ( baudrate
& 0x8000 )
296 UART0_STATUS
= (1<<U2X0
); //Enable 2x speed
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 */
307 UCSR0C
= (1<<URSEL0
)|(3<<UCSZ00
);
309 UCSR0C
= (3<<UCSZ00
);
312 #elif defined ( ATMEGA_UART )
314 if ( baudrate
& 0x8000 )
316 UART0_STATUS
= (1<<U2X
); //Enable 2x speed
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
);
329 /*************************************************************************
330 Function: uart_putc()
331 Purpose: write byte to ringbuffer for transmitting via UART
332 Input: byte to be transmitted
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
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
371 **************************************************************************/
372 void uart_puts(const char *s
)
380 /*************************************************************************
381 Function: uart_puts_p()
382 Purpose: transmit string from program memory to UART
383 Input: program memory string to be transmitted
385 **************************************************************************/
386 void uart_puts_p(const char *progmem_s
)
390 while ( (c
= pgm_read_byte(progmem_s
++)) )