Contiki 2.5
rs232.c
1 /*
2  * Copyright (c) 2005, Swedish Institute of Computer Science
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  * @(#)$Id: rs232.c,v 1.7 2010/10/27 14:51:20 dak664 Exp $
32  */
33 
34 #include <stdio.h>
35 #include <avr/io.h>
36 #include <avr/interrupt.h>
37 #include <avr/pgmspace.h>
38 
39 #include "contiki-conf.h"
40 #include "contiki.h"
41 
42 #include "dev/slip.h"
43 #include "dev/rs232.h"
44 
45 /*ATmega32 and smaller have UBRRH/UCSRC at the same I/O address.
46  *USART_UCSRC_SEL (bit7) selects writing to UBRHH(0) or UCSRC(1).
47  *It is OR'd in below so if not defined we can just set it to zero.
48  */
49 #ifndef USART_UCSRC_SEL
50 #define USART_UCSRC_SEL 0x00
51 #endif
52 
53 #ifdef RS232_CONF_PRINTF_BUFFER_LENGTH
54 #define RS232_PRINTF_BUFFER_LENGTH RS232_CONF_PRINTF_BUFFER_LENGTH
55 #else
56 #define RS232_PRINTF_BUFFER_LENGTH 64
57 #endif
58 
59 #ifndef ADD_CARRAGE_RETURNS_TO_SERIAL_OUTPUT
60 #define ADD_CARRAGE_RETURNS_TO_SERIAL_OUTPUT 1
61 #endif
62 
63 typedef struct {
64  volatile uint8_t * udr;
65  volatile uint8_t * ubrrh;
66  volatile uint8_t * ubrrl;
67  volatile uint8_t * ucsra;
68  volatile uint8_t * ucsrb;
69  volatile uint8_t * ucsrc;
70  volatile uint8_t txwait;
71  int (* input_handler)(unsigned char);
72 } rs232_t;
73 
74 #if defined (__AVR_ATmega128__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega128RFA1__)
75 static rs232_t rs232_ports[2] = {
76  { // UART0
77  &UDR0,
78  &UBRR0H,
79  &UBRR0L,
80  &UCSR0A,
81  &UCSR0B,
82  &UCSR0C,
83  0,
84  NULL
85  },
86 
87  { // UART1
88  &UDR1,
89  &UBRR1H,
90  &UBRR1L,
91  &UCSR1A,
92  &UCSR1B,
93  &UCSR1C,
94  0,
95  NULL
96  }
97 };
98 #elif defined (__AVR_AT90USB1287__)
99 /* Has only UART1, map it to port 0 */
100 static rs232_t rs232_ports[1] = {
101  { // UART1
102  &UDR1,
103  &UBRR1H,
104  &UBRR1L,
105  &UCSR1B,
106  &UCSR1C,
107  0,
108  NULL
109  }
110 };
111 #elif defined (__AVR_ATmega8__) || defined (__AVR_ATmega8515__) \
112  || defined (__AVR_ATmega16__) || defined (__AVR_ATmega32__)
113 static rs232_t rs232_ports[1] = {
114  { // UART0
115  &UDR,
116  &UBRRH,
117  &UBRRL,
118  &UCSRB,
119  &UCSRC,
120  0,
121  NULL
122  }
123 };
124 #elif defined (__AVR_ATmega644__) || defined (__AVR_ATmega328P__)
125 static rs232_t rs232_ports[1] = {
126  { // UART0
127  &UDR0,
128  &UBRR0H,
129  &UBRR0L,
130  &UCSR0B,
131  &UCSR0C,
132  0,
133  NULL
134  }
135 };
136 #else
137 #error Please define the UART registers for your MCU!
138 #endif
139 
140 #if defined (__AVR_ATmega128__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega128RFA1__)
141 /*---------------------------------------------------------------------------*/
142 ISR(USART0_TX_vect)
143 {
144  rs232_ports[RS232_PORT_0].txwait = 0;
145 }
146 
147 /*---------------------------------------------------------------------------*/
148 ISR(USART0_RX_vect)
149 {
150  unsigned char c;
151 
152  c = *(rs232_ports[RS232_PORT_0].udr);
153 
154  if(rs232_ports[RS232_PORT_0].input_handler != NULL) {
155  rs232_ports[RS232_PORT_0].input_handler(c);
156  }
157 }
158 /*---------------------------------------------------------------------------*/
159 ISR(USART1_TX_vect)
160 {
161  rs232_ports[RS232_PORT_1].txwait = 0;
162 }
163 
164 /*---------------------------------------------------------------------------*/
165 ISR(USART1_RX_vect)
166 {
167  unsigned char c;
168 
169  c = *(rs232_ports[RS232_PORT_1].udr);
170 
171  if(rs232_ports[RS232_PORT_1].input_handler != NULL) {
172  rs232_ports[RS232_PORT_1].input_handler(c);
173  }
174 }
175 
176 #elif defined (__AVR_ATmega644__)
177 /*---------------------------------------------------------------------------*/
178 ISR(USART0_TX_vect)
179 {
180  rs232_ports[RS232_PORT_0].txwait = 0;
181 }
182  /*---------------------------------------------------------------------------*/
183 ISR(USART0_RX_vect)
184 {
185  unsigned char c;
186 
187  c = *(rs232_ports[RS232_PORT_0].udr);
188 
189  if(rs232_ports[RS232_PORT_0].input_handler != NULL) {
190  rs232_ports[RS232_PORT_0].input_handler(c);
191  }
192 }
193 #elif defined (__AVR_ATmega8__) || defined (__AVR_ATmega16__) || defined (__AVR_ATmega32__)
194 /*---------------------------------------------------------------------------*/
195 ISR(USART_TXC_vect)
196 {
197  rs232_ports[RS232_PORT_0].txwait = 0;
198 }
199 
200 /*---------------------------------------------------------------------------*/
201 ISR(USART_RXC_vect)
202 {
203  unsigned char c;
204 
205  c = *(rs232_ports[RS232_PORT_0].udr);
206 
207  if(rs232_ports[RS232_PORT_0].input_handler != NULL) {
208  rs232_ports[RS232_PORT_0].input_handler(c);
209  }
210 }
211 
212 #elif defined (__AVR_ATmega8515__) || defined (__AVR_ATmega328P__)
213 /*---------------------------------------------------------------------------*/
214 ISR(USART_TX_vect)
215 {
216  rs232_ports[RS232_PORT_0].txwait = 0;
217 }
218 
219 /*---------------------------------------------------------------------------*/
220 ISR(USART_RX_vect)
221 {
222  unsigned char c;
223 
224  c = *(rs232_ports[RS232_PORT_0].udr);
225 
226  if(rs232_ports[RS232_PORT_0].input_handler != NULL) {
227  rs232_ports[RS232_PORT_0].input_handler(c);
228  }
229 }
230 
231 #elif defined (__AVR_AT90USB1287__)
232 /*---------------------------------------------------------------------*/
233 ISR(USART1_TX_vect)
234 {
235  rs232_ports[RS232_PORT_0].txwait = 0;
236 }
237 
238 /*---------------------------------------------------------------------------*/
239 ISR(USART1_RX_vect)
240 {
241  unsigned char c;
242 
243  c = *(rs232_ports[RS232_PORT_0].udr);
244 
245  if(rs232_ports[RS232_PORT_0].input_handler != NULL) {
246  rs232_ports[RS232_PORT_0].input_handler(c);
247  }
248 }
249 #else
250 #error Please define the interrupt vectors for your MCU!
251 #endif
252 
253 /*---------------------------------------------------------------------------*/
254 void
255 rs232_init (uint8_t port, uint8_t bd, uint8_t ffmt)
256 {
257  *(rs232_ports[port].ubrrh) = (uint8_t)(bd>>8);
258  *(rs232_ports[port].ubrrl) = (uint8_t)bd;
259 
260  /*
261  * - Enable receiver and transmitter,
262  * - Enable interrupts for receiver and transmitter
263  */
264  *(rs232_ports[port].ucsrb) = USART_INTERRUPT_RX_COMPLETE | \
265  USART_RECEIVER_ENABLE | USART_TRANSMITTER_ENABLE;
266 
267  /*
268  * - mode (sync. / async)
269  * - Parity
270  * - Stop bits
271  * - charater size (9 bits are currently not supported)
272  * - clock polarity
273  */
274  *(rs232_ports[port].ucsrc) = USART_UCSRC_SEL | ffmt;
275 
276  rs232_ports[port].txwait = 0;
277 
278  rs232_ports[port].input_handler = NULL;
279 }
280 
281 void
282 rs232_print_p(uint8_t port, char *buf)
283 {
284  while(pgm_read_byte(buf)) {
285  rs232_send(port, pgm_read_byte(buf));
286  ++buf;
287  }
288 }
289 /*---------------------------------------------------------------------------*/
290 void
291 rs232_print(uint8_t port, char *buf)
292 {
293  while(*buf) {
294 #if ADD_CARRAGE_RETURNS_TO_SERIAL_OUTPUT
295  if(*buf=='\n') rs232_send(port, '\r');
296  if(*buf=='\r') buf++; else rs232_send(port, *buf++);
297 #else
298  rs232_send(port, *buf++);
299 #endif
300  }
301 }
302 /*---------------------------------------------------------------------------*/
303 void
304 rs232_printf(uint8_t port, const char *fmt, ...)
305 {
306  va_list ap;
307  static char buf[RS232_PRINTF_BUFFER_LENGTH];
308 
309  va_start (ap, fmt);
310  vsnprintf (buf, RS232_PRINTF_BUFFER_LENGTH, fmt, ap);
311  va_end(ap);
312 
313  rs232_print (port, buf);
314 }
315 /*---------------------------------------------------------------------------*/
316 void
317 rs232_send(uint8_t port, unsigned char c)
318 {
319  while (!(*(rs232_ports[port].ucsra) & (1 << UDRE1))) {
320  }
321  *(rs232_ports[port].udr) = c;
322 }
323 /*---------------------------------------------------------------------------*/
324 void
325 rs232_set_input(uint8_t port, int (*f)(unsigned char))
326 {
327  rs232_ports[port].input_handler = f;
328 }
329 /*---------------------------------------------------------------------------*/
330 void
331 slip_arch_writeb(unsigned char c)
332 {
333  rs232_send(SLIP_PORT, c);
334 }
335 /*---------------------------------------------------------------------------*/
336 int rs232_stdout_putchar(char c, FILE *stream);
337 static uint8_t stdout_rs232_port=RS232_PORT_0;
338 static FILE rs232_stdout = FDEV_SETUP_STREAM(rs232_stdout_putchar,
339  NULL,
340  _FDEV_SETUP_WRITE);
341 
342 int rs232_stdout_putchar(char c, FILE *stream)
343 {
344 #if ADD_CARRAGE_RETURNS_TO_SERIAL_OUTPUT
345  if(c=='\n') rs232_send(stdout_rs232_port, '\r');
346  if(c!='\r') rs232_send (stdout_rs232_port, c);
347 #else
348  rs232_send (stdout_rs232_port, c);
349 #endif
350  return 0;
351 }
352 /*---------------------------------------------------------------------------*/
353 void rs232_redirect_stdout (uint8_t port) {
354  stdout_rs232_port = port;
355  stdout = &rs232_stdout;
356 }