uart.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. // TODO: Teensy support(ATMega32u4/AT90USB128)
  2. // Fixed for Arduino Duemilanove ATmega168p by Jun Wako
  3. /* UART Example for Teensy USB Development Board
  4. * http://www.pjrc.com/teensy/
  5. * Copyright (c) 2009 PJRC.COM, LLC
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. * THE SOFTWARE.
  24. */
  25. // Version 1.0: Initial Release
  26. // Version 1.1: Add support for Teensy 2.0, minor optimizations
  27. #include <avr/io.h>
  28. #include <avr/interrupt.h>
  29. #include "uart.h"
  30. #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__)
  31. # define UDRn UDR0
  32. # define UBRRnL UBRR0L
  33. # define UCSRnA UCSR0A
  34. # define UCSRnB UCSR0B
  35. # define UCSRnC UCSR0C
  36. # define U2Xn U2X0
  37. # define RXENn RXEN0
  38. # define TXENn TXEN0
  39. # define RXCIEn RXCIE0
  40. # define UCSZn1 UCSZ01
  41. # define UCSZn0 UCSZ00
  42. # define UDRIEn UDRIE0
  43. # define USARTn_UDRE_vect USART_UDRE_vect
  44. # define USARTn_RX_vect USART_RX_vect
  45. #elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega32U2__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)
  46. # define UDRn UDR1
  47. # define UBRRnL UBRR1L
  48. # define UCSRnA UCSR1A
  49. # define UCSRnB UCSR1B
  50. # define UCSRnC UCSR1C
  51. # define U2Xn U2X1
  52. # define RXENn RXEN1
  53. # define TXENn TXEN1
  54. # define RXCIEn RXCIE1
  55. # define UCSZn1 UCSZ11
  56. # define UCSZn0 UCSZ10
  57. # define UDRIEn UDRIE1
  58. # define USARTn_UDRE_vect USART1_UDRE_vect
  59. # define USARTn_RX_vect USART1_RX_vect
  60. #elif defined(__AVR_ATmega32A__)
  61. # define UDRn UDR
  62. # define UBRRnL UBRRL
  63. # define UCSRnA UCSRA
  64. # define UCSRnB UCSRB
  65. # define UCSRnC UCSRC
  66. # define U2Xn U2X
  67. # define RXENn RXEN
  68. # define TXENn TXEN
  69. # define RXCIEn RXCIE
  70. # define UCSZn1 UCSZ1
  71. # define UCSZn0 UCSZ0
  72. # define UDRIEn UDRIE
  73. # define USARTn_UDRE_vect USART_UDRE_vect
  74. # define USARTn_RX_vect USART_RX_vect
  75. #endif
  76. // These buffers may be any size from 2 to 256 bytes.
  77. #define RX_BUFFER_SIZE 64
  78. #define TX_BUFFER_SIZE 256
  79. static volatile uint8_t tx_buffer[TX_BUFFER_SIZE];
  80. static volatile uint8_t tx_buffer_head;
  81. static volatile uint8_t tx_buffer_tail;
  82. static volatile uint8_t rx_buffer[RX_BUFFER_SIZE];
  83. static volatile uint8_t rx_buffer_head;
  84. static volatile uint8_t rx_buffer_tail;
  85. // Initialize the UART
  86. void uart_init(uint32_t baud) {
  87. cli();
  88. UBRRnL = (F_CPU / 4 / baud - 1) / 2;
  89. UCSRnA = (1 << U2Xn);
  90. UCSRnB = (1 << RXENn) | (1 << TXENn) | (1 << RXCIEn);
  91. UCSRnC = (1 << UCSZn1) | (1 << UCSZn0);
  92. tx_buffer_head = tx_buffer_tail = 0;
  93. rx_buffer_head = rx_buffer_tail = 0;
  94. sei();
  95. }
  96. // Transmit a byte
  97. void uart_putchar(uint8_t c) {
  98. uint8_t i;
  99. i = tx_buffer_head + 1;
  100. if (i >= TX_BUFFER_SIZE) i = 0;
  101. // return immediately to avoid deadlock when interrupt is disabled(called from ISR)
  102. if (tx_buffer_tail == i && (SREG & (1 << SREG_I)) == 0) return;
  103. while (tx_buffer_tail == i)
  104. ; // wait until space in buffer
  105. // cli();
  106. tx_buffer[i] = c;
  107. tx_buffer_head = i;
  108. UCSRnB = (1 << RXENn) | (1 << TXENn) | (1 << RXCIEn) | (1 << UDRIEn);
  109. // sei();
  110. }
  111. // Receive a byte
  112. uint8_t uart_getchar(void) {
  113. uint8_t c, i;
  114. while (rx_buffer_head == rx_buffer_tail)
  115. ; // wait for character
  116. i = rx_buffer_tail + 1;
  117. if (i >= RX_BUFFER_SIZE) i = 0;
  118. c = rx_buffer[i];
  119. rx_buffer_tail = i;
  120. return c;
  121. }
  122. // Return the number of bytes waiting in the receive buffer.
  123. // Call this before uart_getchar() to check if it will need
  124. // to wait for a byte to arrive.
  125. uint8_t uart_available(void) {
  126. uint8_t head, tail;
  127. head = rx_buffer_head;
  128. tail = rx_buffer_tail;
  129. if (head >= tail) return head - tail;
  130. return RX_BUFFER_SIZE + head - tail;
  131. }
  132. // Transmit Interrupt
  133. ISR(USARTn_UDRE_vect) {
  134. uint8_t i;
  135. if (tx_buffer_head == tx_buffer_tail) {
  136. // buffer is empty, disable transmit interrupt
  137. UCSRnB = (1 << RXENn) | (1 << TXENn) | (1 << RXCIEn);
  138. } else {
  139. i = tx_buffer_tail + 1;
  140. if (i >= TX_BUFFER_SIZE) i = 0;
  141. UDRn = tx_buffer[i];
  142. tx_buffer_tail = i;
  143. }
  144. }
  145. // Receive Interrupt
  146. ISR(USARTn_RX_vect) {
  147. uint8_t c, i;
  148. c = UDRn;
  149. i = rx_buffer_head + 1;
  150. if (i >= RX_BUFFER_SIZE) i = 0;
  151. if (i != rx_buffer_tail) {
  152. rx_buffer[i] = c;
  153. rx_buffer_head = i;
  154. }
  155. }