Contiki 2.6

rs232.c

00001 /*
00002  * Copyright (c) 2005, Swedish Institute of Computer Science
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the Institute nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  *
00029  * This file is part of the Contiki operating system.
00030  *
00031  */
00032 
00033 #include <stdio.h>
00034 #include <avr/io.h>
00035 #include <avr/interrupt.h>
00036 #include <avr/pgmspace.h>
00037 
00038 #include "contiki-conf.h"
00039 #include "contiki.h"
00040 
00041 #include "dev/slip.h"
00042 #include "dev/rs232.h"
00043 
00044 /*ATmega32 and smaller have UBRRH/UCSRC at the same I/O address.
00045  *USART_UCSRC_SEL (bit7) selects writing to UBRHH(0) or UCSRC(1).
00046  *It is OR'd in below so if not defined we can just set it to zero.
00047  */
00048 #ifndef USART_UCSRC_SEL
00049 #define USART_UCSRC_SEL 0x00
00050 #endif
00051 
00052 /* Currently only the STK500 platform uses a static RAM buffer for printfs.
00053  * Others print a character at a time using the gcc string pointer.
00054  * gcc may not strip the unused buffer, even though it is statically
00055  * allocated in an unused routine.
00056  */
00057 #ifdef RS232_CONF_PRINTF_BUFFER_LENGTH
00058 #define RS232_PRINTF_BUFFER_LENGTH RS232_CONF_PRINTF_BUFFER_LENGTH
00059 #else
00060 #if CONTIKI_TARGET_STK500
00061 #define RS232_PRINTF_BUFFER_LENGTH 64
00062 #endif
00063 #endif
00064 
00065 /* TX interrupts would allow non-blocking output up to the size of some RAM buffer.
00066  * Since a RAM buffer is not implemented tx interrupts are superfluous and unwanted
00067  * because they block debug prints from within interrupt routines
00068  */
00069 #ifdef RS232_CONF_TX_INTERRUPTS
00070 #define RS232_TX_INTERRUPTS RS232_CONF_TX_INTERRUPTS
00071 #else
00072 #define RS232_TX_INTERRUPTS 0
00073 #endif
00074 
00075 /* Insert a carriage return after a line feed. This is the default. */
00076 #ifndef ADD_CARRIAGE_RETURN_AFTER_NEWLINE
00077 #define ADD_CARRIAGE_RETURN_AFTER_NEWLINE 1
00078 #endif
00079 
00080 /* Reducing NUMPORTS from the default will harmlessly disable usage of those ports */
00081 /* Two ports take 400 bytes flash and 4 bytes RAM. */
00082 #ifdef RS232_CONF_NUMPORTS
00083 #define NUMPORTS RS232_CONF_NUMPORTS
00084 #endif
00085 
00086 #if defined (__AVR_ATmega128__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega128RFA1__)
00087 #ifndef NUMPORTS
00088 #define NUMPORTS 2
00089 #elif NUMPORTS > 2
00090 #error Only two serial ports are defined for this processor!
00091 #endif
00092 
00093 #if NUMPORTS > 0
00094 #define D_UDR0   UDR0
00095 #define D_UDRE0M (1 << UDRE0)
00096 #define D_UBRR0H UBRR0H
00097 #define D_UBRR0L UBRR0L
00098 #define D_UCSR0A UCSR0A
00099 #define D_UCSR0B UCSR0B
00100 #define D_UCSR0C UCSR0C
00101 #define D_USART0_RX_vect USART0_RX_vect
00102 #define D_USART0_TX_vect USART0_TX_vect
00103 
00104 #if NUMPORTS > 1
00105 #define D_UDR1   UDR1
00106 #define D_UDRE1M (1 << UDRE1)
00107 #define D_UBRR1H UBRR1H
00108 #define D_UBRR1L UBRR1L
00109 #define D_UCSR1A UCSR1A
00110 #define D_UCSR1B UCSR1B
00111 #define D_UCSR1C UCSR1C
00112 #define D_USART1_RX_vect USART1_RX_vect
00113 #define D_USART1_TX_vect USART1_TX_vect
00114 #endif
00115 
00116 #endif
00117 
00118 #elif defined (__AVR_AT90USB1287__)
00119 /* Has only UART1, map it to port 0 */
00120 #ifndef NUMPORTS
00121 #define NUMPORTS 1
00122 #elif NUMPORTS > 1
00123 #error Only one serial port is defined for this processor!
00124 #endif
00125 
00126 #if NUMPORTS > 0
00127 #define D_UDR0   UDR1
00128 #define D_UDRE0M (1 << UDRE1)
00129 #define D_UBRR0H UBRR1H
00130 #define D_UBRR0L UBRR1L
00131 #define D_UCSR0A UCSR1A
00132 #define D_UCSR0B UCSR1B
00133 #define D_UCSR0C UCSR1C
00134 #define D_USART0_RX_vect USART1_RX_vect
00135 #define D_USART0_TX_vect USART1_TX_vect
00136 #endif
00137 
00138 #elif defined (__AVR_ATmega8515__)
00139 #ifndef NUMPORTS
00140 #define NUMPORTS 1
00141 #elif NUMPORTS > 1
00142 #error Only one serial port is defined for this processor!
00143 #endif
00144 
00145 #if NUMPORTS > 0
00146 #define D_UDR0   UDR
00147 #define D_UDRE0M (1 << UDRE)
00148 #define D_UBRR0H UBRRH
00149 #define D_UBRR0L UBRRL
00150 #define D_UCSR0A UCSRA
00151 #define D_UCSR0B UCSRB
00152 #define D_UCSR0C UCSRC
00153 #define D_USART0_RX_vect USART_RX_vect
00154 #define D_USART0_TX_vect USART_TX_vect
00155 #endif
00156 
00157 #elif defined (__AVR_ATmega328P__)
00158 #ifndef NUMPORTS
00159 #define NUMPORTS 1
00160 #elif NUMPORTS > 1
00161 #error Only one serial port is defined for this processor!
00162 #endif
00163 
00164 #if NUMPORTS > 0
00165 #define D_UDR0   UDR0
00166 #define D_UDRE0M (1 << UDRE0)
00167 #define D_UBRR0H UBRR0H
00168 #define D_UBRR0L UBRR0L
00169 #define D_UCSR0A UCSR0A
00170 #define D_UCSR0B UCSR0B
00171 #define D_UCSR0C UCSR0C
00172 #define D_USART0_RX_vect USART_RX_vect
00173 #define D_USART0_TX_vect USART_TX_vect
00174 #endif
00175 
00176 #elif defined (__AVR_ATmega8__) || defined (__AVR_ATmega16__) || defined (__AVR_ATmega32__)
00177 #ifndef NUMPORTS
00178 #define NUMPORTS 1
00179 #elif NUMPORTS > 1
00180 #error Only one serial port is defined for this processor!
00181 #endif
00182 
00183 #if NUMPORTS > 0
00184 #define D_UDR0   UDR
00185 #define D_UDRE0M (1 << UDRE)
00186 #define D_UBRR0H UBRRH
00187 #define D_UBRR0L UBRRL
00188 #define D_UCSR0A UCSRA
00189 #define D_UCSR0B UCSRB
00190 #define D_UCSR0C UCSRC
00191 #define D_USART0_RX_vect USART_RXC_vect
00192 #define D_USART0_TX_vect USART_TXC_vect
00193 #endif
00194 
00195 #elif defined (__AVR_ATmega644__)
00196 #ifndef NUMPORTS
00197 #define NUMPORTS 1
00198 #elif NUMPORTS > 1
00199 #error Only one serial port is defined for this processor!
00200 #endif
00201 
00202 #if NUMPORTS > 0
00203 #define D_UDR0   UDR0
00204 #define D_UDRE0M (1 << UDRE0)
00205 #define D_UBRR0H UBRR0H
00206 #define D_UBRR0L UBRR0L
00207 #define D_UCSR0A UCSR0A
00208 #define D_UCSR0B UCSR0B
00209 #define D_UCSR0C UCSR0C
00210 #define D_USART0_RX_vect USART0_RX_vect
00211 #define D_USART0_TX_vect USART0_TX_vect
00212 #endif
00213 
00214 #else
00215 #error Please define the UART registers for your MCU!
00216 #endif
00217 
00218 #if NUMPORTS > 0
00219 int (* input_handler_0)(unsigned char);
00220 ISR(D_USART0_RX_vect)
00221 {
00222   unsigned char c;
00223   c = D_UDR0;
00224   if (input_handler_0 != NULL) input_handler_0(c);
00225 }
00226 #if RS232_TX_INTERRUPTS
00227 volatile uint8_t txwait_0;
00228 ISR(D_USART0_TX_vect)
00229 {
00230   txwait_0 = 0;
00231 }
00232 #endif
00233 
00234 #if NUMPORTS > 1
00235 int (* input_handler_1)(unsigned char);
00236 ISR(D_USART1_RX_vect)
00237 {
00238   unsigned char c;
00239   c = D_UDR1;
00240   if (input_handler_1 != NULL) input_handler_1(c);
00241 }
00242 #if RS232_TX_INTERRUPTS
00243 volatile uint8_t txwait_1;
00244 ISR(USART1_TX_vect)
00245 {
00246   txwait_1 = 0;
00247 }
00248 #endif
00249 
00250 #if NUMPORTS > 2
00251 int (* input_handler_2)(unsigned char);
00252 ISR(D_USART2_RX_vect)
00253 {
00254   unsigned char c;
00255   c = D_UDR2;
00256   if (input_handler_2 != NULL) input_handler_2(c);
00257 }
00258 #if RS232_TX_INTERRUPTS
00259 volatile uint8_t txwait_2;
00260 ISR(USART2_TX_vect)
00261 {
00262   txwait_2= 0;
00263 }
00264 #endif
00265 #endif
00266 
00267 #endif
00268 #endif
00269 /*---------------------------------------------------------------------------*/
00270 void
00271 rs232_init (uint8_t port, uint8_t bd, uint8_t ffmt)
00272 {
00273 #if NUMPORTS > 0
00274  if (port == 0) {
00275    D_UBRR0H = (uint8_t)(bd>>8);
00276    D_UBRR0L = (uint8_t)bd;
00277 #if RS232_TX_INTERRUPTS
00278    txwait_0 = 0;
00279    D_UCSR0B =  USART_INTERRUPT_RX_COMPLETE | USART_INTERRUPT_TX_COMPLETE | \
00280                USART_RECEIVER_ENABLE | USART_TRANSMITTER_ENABLE;
00281 #else
00282    D_UCSR0B =  USART_INTERRUPT_RX_COMPLETE | \
00283                USART_RECEIVER_ENABLE | USART_TRANSMITTER_ENABLE;
00284 #endif
00285    D_UCSR0C = USART_UCSRC_SEL | ffmt;
00286    input_handler_0 = NULL;
00287 
00288 #if NUMPORTS > 1
00289  } else if (port == 1) {
00290    D_UBRR1H = (uint8_t)(bd>>8);
00291    D_UBRR1L = (uint8_t)bd;
00292 #if RS232_TX_INTERRUPTS
00293    txwait_1 = 0;
00294    D_UCSR1B =  USART_INTERRUPT_RX_COMPLETE | USART_INTERRUPT_TX_COMPLETE | \
00295                USART_RECEIVER_ENABLE | USART_TRANSMITTER_ENABLE;
00296 #else
00297    D_UCSR1B =  USART_INTERRUPT_RX_COMPLETE | \
00298                USART_RECEIVER_ENABLE | USART_TRANSMITTER_ENABLE;
00299 #endif
00300    D_UCSR1C = USART_UCSRC_SEL | ffmt;
00301    input_handler_1 = NULL;
00302 
00303 #if NUMPORTS > 2
00304  } else if (port == 2) {
00305    D_UBRR2H = (uint8_t)(bd>>8);
00306    D_UBRR2L = (uint8_t)bd;
00307 #if RS232_TX_INTERRUPTS
00308    txwait_2 = 0;
00309    D_UCSR2B =  USART_INTERRUPT_RX_COMPLETE | USART_INTERRUPT_TX_COMPLETE | \
00310                USART_RECEIVER_ENABLE | USART_TRANSMITTER_ENABLE;
00311 #else
00312    D_UCSR2B =  USART_INTERRUPT_RX_COMPLETE | \
00313                USART_RECEIVER_ENABLE | USART_TRANSMITTER_ENABLE;
00314 #endif
00315    D_UCSR2C = USART_UCSRC_SEL | ffmt;
00316    input_handler_2 = NULL;
00317 #endif
00318 #endif
00319  }
00320 #endif /* NUMPORTS > 0 */
00321 }
00322 
00323 /*---------------------------------------------------------------------------*/
00324 void 
00325 rs232_send(uint8_t port, unsigned char c)
00326 {
00327 #if RS232_TX_INTERRUPTS
00328   /* Output character and block until it is transmitted */
00329 #if NUMPORTS > 0
00330   if (port == 0 ) {
00331     txwait_0 = 1;
00332     D_UDR0 = c;
00333     while (txwait_0);
00334 #if NUMPORTS > 1
00335   } else if (port == 1) {
00336     txwait_1 = 1;
00337     D_UDR1 = c;
00338     while (txwait_1);
00339 #if NUMPORTS > 2
00340   } else if (port == 2) {
00341     txwait_2 = 1;
00342     D_UDR2 = c;
00343     while (txwait_2);
00344 #endif
00345 #endif
00346   }
00347 #endif
00348 #else /* RS232_TX_INTERRUPTS */
00349   /* Block until tx ready and output character */
00350 #if NUMPORTS > 0
00351   if (port == 0 ) {
00352     while (!(D_UCSR0A & D_UDRE0M));
00353     D_UDR0 = c;
00354 #if NUMPORTS > 1
00355   } else if (port == 1) {
00356     while (!(D_UCSR1A & D_UDRE1M));
00357     D_UDR1 = c;
00358 #if NUMPORTS > 2
00359   } else if (port == 2) {
00360     while (!(D_UCSR2A & D_UDRE2M));
00361     D_UDR2 = c;
00362 #endif
00363 #endif
00364   }
00365 #endif
00366 #endif /* RS232_TX_INTERRUPTS */
00367 }
00368 /*---------------------------------------------------------------------------*/
00369 void
00370 rs232_set_input(uint8_t port, int (*f)(unsigned char))
00371 {
00372 #if NUMPORTS > 0
00373   if (port == 0) {
00374     input_handler_0 = f;
00375 #if NUMPORTS > 1
00376   } else if (port == 1) {
00377     input_handler_1 = f;
00378 #if NUMPORTS > 2
00379   } else if (port == 2) {
00380     input_handler_2 = f;
00381 #endif
00382 #endif
00383   }
00384 #endif
00385 }
00386 
00387 /*---------------------------------------------------------------------------*/
00388 void
00389 rs232_print(uint8_t port, char *buf)
00390 {
00391   while(*buf) {
00392 #if ADD_CARRIAGE_RETURN_AFTER_NEWLINE
00393     if(*buf=='\n') rs232_send(port, '\r');
00394         if(*buf=='\r') buf++; else rs232_send(port, *buf++);
00395 #else
00396     rs232_send(port, *buf++);
00397 #endif
00398   }
00399 }
00400 
00401 #if RS232_PRINTF_BUFFER_LENGTH
00402 /*---------------------------------------------------------------------------*/
00403 void
00404 rs232_printf(uint8_t port, const char *fmt, ...)
00405 {
00406   va_list ap;
00407   static char buf[RS232_PRINTF_BUFFER_LENGTH];
00408 
00409   va_start (ap, fmt);
00410   vsnprintf (buf, RS232_PRINTF_BUFFER_LENGTH, fmt, ap);
00411   va_end(ap);
00412 
00413   rs232_print (port, buf);
00414 }
00415 #endif
00416 /*---------------------------------------------------------------------------*/
00417 void
00418 slip_arch_writeb(unsigned char c)
00419 {
00420   rs232_send(SLIP_PORT, c);
00421 }
00422 /*---------------------------------------------------------------------------*/
00423 int rs232_stdout_putchar(char c, FILE *stream);
00424 static uint8_t stdout_rs232_port=RS232_PORT_0;
00425 static FILE rs232_stdout = FDEV_SETUP_STREAM(rs232_stdout_putchar,
00426                                              NULL,
00427                                              _FDEV_SETUP_WRITE);
00428 
00429 int rs232_stdout_putchar(char c, FILE *stream)
00430 {
00431 #if ADD_CARRIAGE_RETURN_AFTER_NEWLINE
00432   if(c=='\n') rs232_send(stdout_rs232_port, '\r');
00433   if(c!='\r') rs232_send (stdout_rs232_port, c);
00434 #else
00435   rs232_send (stdout_rs232_port, c);
00436 #endif
00437   return 0;
00438 }
00439 /*---------------------------------------------------------------------------*/
00440 void rs232_redirect_stdout (uint8_t port) {
00441   stdout_rs232_port = port;
00442   stdout = &rs232_stdout;
00443 }