From 218eb5e80706b53c691da133461830c895e0c8ff Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Tue, 1 Mar 2011 20:00:16 -0500 Subject: Moving wiring.h contents into Arduino.h. --- cores/arduino/HardwareSerial.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cores/arduino/HardwareSerial.cpp') diff --git a/cores/arduino/HardwareSerial.cpp b/cores/arduino/HardwareSerial.cpp index 4397efb..7cea350 100644 --- a/cores/arduino/HardwareSerial.cpp +++ b/cores/arduino/HardwareSerial.cpp @@ -24,7 +24,7 @@ #include #include #include -#include "wiring.h" +#include "Arduino.h" #include "wiring_private.h" // this next line disables the entire HardwareSerial.cpp, -- cgit v1.2.3-18-g5258 From d8d233ad3e4513cb5378dca459c251e0a127e129 Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Sat, 5 Mar 2011 14:17:26 -0500 Subject: Implemented serial transmit buffering. Now Serial.write() places characters in the transmit buffer, and the data register empty interrupt reads and transmit them. Based loosely on the implementation here: ftp://wookey.org.uk/arduino. http://code.google.com/p/arduino/issues/detail?id=262 --- cores/arduino/HardwareSerial.cpp | 160 ++++++++++++++++++++++++++++++++------- 1 file changed, 134 insertions(+), 26 deletions(-) (limited to 'cores/arduino/HardwareSerial.cpp') diff --git a/cores/arduino/HardwareSerial.cpp b/cores/arduino/HardwareSerial.cpp index 7cea350..1cd8cc5 100644 --- a/cores/arduino/HardwareSerial.cpp +++ b/cores/arduino/HardwareSerial.cpp @@ -34,46 +34,50 @@ #include "HardwareSerial.h" // Define constants and variables for buffering incoming serial data. We're -// using a ring buffer (I think), in which rx_buffer_head is the index of the -// location to which to write the next incoming character and rx_buffer_tail -// is the index of the location from which to read. +// using a ring buffer (I think), in which head is the index of the location +// to which to write the next incoming character and tail is the index of the +// location from which to read. #if (RAMEND < 1000) - #define RX_BUFFER_SIZE 32 + #define SERIAL_BUFFER_SIZE 16 #else - #define RX_BUFFER_SIZE 128 + #define SERIAL_BUFFER_SIZE 64 #endif struct ring_buffer { - unsigned char buffer[RX_BUFFER_SIZE]; - int head; - int tail; + unsigned char buffer[SERIAL_BUFFER_SIZE]; + volatile int head; + volatile int tail; }; #if defined(UBRRH) || defined(UBRR0H) ring_buffer rx_buffer = { { 0 }, 0, 0 }; + ring_buffer tx_buffer = { { 0 }, 0, 0 }; #endif #if defined(UBRR1H) ring_buffer rx_buffer1 = { { 0 }, 0, 0 }; + ring_buffer tx_buffer1 = { { 0 }, 0, 0 }; #endif #if defined(UBRR2H) ring_buffer rx_buffer2 = { { 0 }, 0, 0 }; + ring_buffer tx_buffer2 = { { 0 }, 0, 0 }; #endif #if defined(UBRR3H) ring_buffer rx_buffer3 = { { 0 }, 0, 0 }; + ring_buffer tx_buffer3 = { { 0 }, 0, 0 }; #endif -inline void store_char(unsigned char c, ring_buffer *rx_buffer) +inline void store_char(unsigned char c, ring_buffer *buffer) { - int i = (unsigned int)(rx_buffer->head + 1) % RX_BUFFER_SIZE; + int i = (unsigned int)(buffer->head + 1) % SERIAL_BUFFER_SIZE; // if we should be storing the received character into the location // just before the tail (meaning that the head would advance to the // current location of the tail), we're about to overflow the buffer // and so we don't write the character or advance the head. - if (i != rx_buffer->tail) { - rx_buffer->buffer[rx_buffer->head] = c; - rx_buffer->head = i; + if (i != buffer->tail) { + buffer->buffer[buffer->head] = c; + buffer->head = i; } } @@ -167,16 +171,105 @@ inline void store_char(unsigned char c, ring_buffer *rx_buffer) #endif +#if !defined(UART0_UDRE_vect) && !defined(UART_UDRE_vect) && !defined(USART0_UDRE_vect) && !defined(USART_UDRE_vect) + #error Don't know what the Data Register Empty vector is called for the first UART +#else +#if defined(UART0_UDRE_vect) +ISR(UART0_UDRE_vect) +#elif defined(UART_UDRE_vect) +ISR(UART_UDRE_vect) +#elif defined(USART0_UDRE_vect) +ISR(USART0_UDRE_vect) +#elif defined(USART_UDRE_vect) +ISR(USART_UDRE_vect) +#endif +{ + if (tx_buffer.head == tx_buffer.tail) { + // Buffer empty, so disable interrupts +#if defined(UCSR0B) + cbi(UCSR0B, UDRIE0); +#else + cbi(UCSRB, UDRIE); +#endif + } + else { + // There is more data in the output buffer. Send the next byte + unsigned char c = tx_buffer.buffer[tx_buffer.tail]; + tx_buffer.tail = (tx_buffer.tail + 1) % SERIAL_BUFFER_SIZE; + + #if defined(UDR0) + UDR0 = c; + #elif defined(UDR) + UDR = c; + #else + #error UDR not defined + #endif + } +} +#endif + +#ifdef USART1_UDRE_vect +ISR(USART1_UDRE_vect) +{ + if (tx_buffer1.head == tx_buffer1.tail) { + // Buffer empty, so disable interrupts + cbi(UCSR1B, UDRIE1); + } + else { + // There is more data in the output buffer. Send the next byte + unsigned char c = tx_buffer1.buffer[tx_buffer1.tail]; + tx_buffer1.tail = (tx_buffer1.tail + 1) % SERIAL_BUFFER_SIZE; + + UDR1 = c; + } +} +#endif + +#ifdef USART2_UDRE_vect +ISR(USART2_UDRE_vect) +{ + if (tx_buffer2.head == tx_buffer2.tail) { + // Buffer empty, so disable interrupts + cbi(UCSR2B, UDRIE2); + } + else { + // There is more data in the output buffer. Send the next byte + unsigned char c = tx_buffer2.buffer[tx_buffer2.tail]; + tx_buffer2.tail = (tx_buffer2.tail + 1) % SERIAL_BUFFER_SIZE; + + UDR2 = c; + } +} +#endif + +#ifdef USART3_UDRE_vect +ISR(USART3_UDRE_vect) +{ + if (tx_buffer3.head == tx_buffer3.tail) { + // Buffer empty, so disable interrupts + cbi(UCSR3B, UDRIE3); + } + else { + // There is more data in the output buffer. Send the next byte + unsigned char c = tx_buffer3.buffer[tx_buffer3.tail]; + tx_buffer3.tail = (tx_buffer3.tail + 1) % SERIAL_BUFFER_SIZE; + + UDR3 = c; + } +} +#endif + // Constructors //////////////////////////////////////////////////////////////// -HardwareSerial::HardwareSerial(ring_buffer *rx_buffer, +HardwareSerial::HardwareSerial(ring_buffer *rx_buffer, ring_buffer *tx_buffer, volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, volatile uint8_t *ucsra, volatile uint8_t *ucsrb, volatile uint8_t *udr, - uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x) + uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udrie, uint8_t u2x) { _rx_buffer = rx_buffer; + _tx_buffer = tx_buffer; _ubrrh = ubrrh; _ubrrl = ubrrl; _ucsra = ucsra; @@ -185,7 +278,7 @@ HardwareSerial::HardwareSerial(ring_buffer *rx_buffer, _rxen = rxen; _txen = txen; _rxcie = rxcie; - _udre = udre; + _udrie = udrie; _u2x = u2x; } @@ -220,18 +313,21 @@ void HardwareSerial::begin(long baud) sbi(*_ucsrb, _rxen); sbi(*_ucsrb, _txen); sbi(*_ucsrb, _rxcie); + cbi(*_ucsrb, _udrie); // XXX: what if there's already data in the tx buffer? } +// XXX: should we empty the rx and tx buffers here? void HardwareSerial::end() { cbi(*_ucsrb, _rxen); cbi(*_ucsrb, _txen); cbi(*_ucsrb, _rxcie); + cbi(*_ucsrb, _udrie); } int HardwareSerial::available(void) { - return (unsigned int)(RX_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % RX_BUFFER_SIZE; + return (unsigned int)(SERIAL_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % SERIAL_BUFFER_SIZE; } int HardwareSerial::peek(void) @@ -250,7 +346,7 @@ int HardwareSerial::read(void) return -1; } else { unsigned char c = _rx_buffer->buffer[_rx_buffer->tail]; - _rx_buffer->tail = (unsigned int)(_rx_buffer->tail + 1) % RX_BUFFER_SIZE; + _rx_buffer->tail = (unsigned int)(_rx_buffer->tail + 1) % SERIAL_BUFFER_SIZE; return c; } } @@ -271,18 +367,30 @@ void HardwareSerial::flush() void HardwareSerial::write(uint8_t c) { - while (!((*_ucsra) & (1 << _udre))) + bool empty = (_tx_buffer->head == _tx_buffer->tail); + int i = (_tx_buffer->head + 1) % SERIAL_BUFFER_SIZE; + + // If the output buffer is full, there's nothing for it other than to + // wait for the interrupt handler to empty it a bit + while (i == _tx_buffer->tail) ; - - *_udr = c; + + _tx_buffer->buffer[_tx_buffer->head] = c; + _tx_buffer->head = i; + + if (empty) { + // The buffer was empty, so enable interrupt on + // USART Data Register empty. The interrupt handler will take it from there + sbi(*_ucsrb, _udrie); + } } // Preinstantiate Objects ////////////////////////////////////////////////////// #if defined(UBRRH) && defined(UBRRL) - HardwareSerial Serial(&rx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRE, U2X); + HardwareSerial Serial(&rx_buffer, &tx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRIE, U2X); #elif defined(UBRR0H) && defined(UBRR0L) - HardwareSerial Serial(&rx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRE0, U2X0); + HardwareSerial Serial(&rx_buffer, &tx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRIE0, U2X0); #elif defined(USBCON) #warning no serial port defined (port 0) #else @@ -290,13 +398,13 @@ void HardwareSerial::write(uint8_t c) #endif #if defined(UBRR1H) - HardwareSerial Serial1(&rx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UDR1, RXEN1, TXEN1, RXCIE1, UDRE1, U2X1); + HardwareSerial Serial1(&rx_buffer1, &tx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UDR1, RXEN1, TXEN1, RXCIE1, UDRIE1, U2X1); #endif #if defined(UBRR2H) - HardwareSerial Serial2(&rx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UDR2, RXEN2, TXEN2, RXCIE2, UDRE2, U2X2); + HardwareSerial Serial2(&rx_buffer2, &tx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UDR2, RXEN2, TXEN2, RXCIE2, UDRIE2, U2X2); #endif #if defined(UBRR3H) - HardwareSerial Serial3(&rx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UDR3, RXEN3, TXEN3, RXCIE3, UDRE3, U2X3); + HardwareSerial Serial3(&rx_buffer3, &tx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UDR3, RXEN3, TXEN3, RXCIE3, UDRIE3, U2X3); #endif #endif // whole file -- cgit v1.2.3-18-g5258 From 01d82d82770de18628b0fc9f9be1c85c7abc294e Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Sun, 6 Mar 2011 11:47:18 -0500 Subject: Fixing race condition in Serial write (Brian Cook). --- cores/arduino/HardwareSerial.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'cores/arduino/HardwareSerial.cpp') diff --git a/cores/arduino/HardwareSerial.cpp b/cores/arduino/HardwareSerial.cpp index 1cd8cc5..6738675 100644 --- a/cores/arduino/HardwareSerial.cpp +++ b/cores/arduino/HardwareSerial.cpp @@ -367,7 +367,6 @@ void HardwareSerial::flush() void HardwareSerial::write(uint8_t c) { - bool empty = (_tx_buffer->head == _tx_buffer->tail); int i = (_tx_buffer->head + 1) % SERIAL_BUFFER_SIZE; // If the output buffer is full, there's nothing for it other than to @@ -378,11 +377,7 @@ void HardwareSerial::write(uint8_t c) _tx_buffer->buffer[_tx_buffer->head] = c; _tx_buffer->head = i; - if (empty) { - // The buffer was empty, so enable interrupt on - // USART Data Register empty. The interrupt handler will take it from there - sbi(*_ucsrb, _udrie); - } + sbi(*_ucsrb, _udrie); } // Preinstantiate Objects ////////////////////////////////////////////////////// -- cgit v1.2.3-18-g5258 From 0ba1f0ec5040b68d2b09266c461d1a22b64c7e1b Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Sun, 6 Mar 2011 12:20:42 -0500 Subject: Flushing outgoing and incoming data in Serial.end(). That is, waiting for outgoing data to transmit and dropping any received data. --- cores/arduino/HardwareSerial.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'cores/arduino/HardwareSerial.cpp') diff --git a/cores/arduino/HardwareSerial.cpp b/cores/arduino/HardwareSerial.cpp index 6738675..1154ae7 100644 --- a/cores/arduino/HardwareSerial.cpp +++ b/cores/arduino/HardwareSerial.cpp @@ -313,16 +313,22 @@ void HardwareSerial::begin(long baud) sbi(*_ucsrb, _rxen); sbi(*_ucsrb, _txen); sbi(*_ucsrb, _rxcie); - cbi(*_ucsrb, _udrie); // XXX: what if there's already data in the tx buffer? + cbi(*_ucsrb, _udrie); } -// XXX: should we empty the rx and tx buffers here? void HardwareSerial::end() { + // wait for transmission of outgoing data + while (_tx_buffer->head != _tx_buffer->tail) + ; + cbi(*_ucsrb, _rxen); cbi(*_ucsrb, _txen); cbi(*_ucsrb, _rxcie); cbi(*_ucsrb, _udrie); + + // clear any received data + _rx_buffer->head = _rx_buffer->tail; } int HardwareSerial::available(void) -- cgit v1.2.3-18-g5258 From c7c7302d9df5451e6b134d8228bee6c551ca2125 Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Sat, 7 May 2011 12:05:27 -0400 Subject: Changing Serial.flush() to write outgoing data, not drop incoming data. This brings it in line with most other uses of flush(), both in and out of Arduino. http://code.google.com/p/arduino/issues/detail?id=497 --- cores/arduino/HardwareSerial.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'cores/arduino/HardwareSerial.cpp') diff --git a/cores/arduino/HardwareSerial.cpp b/cores/arduino/HardwareSerial.cpp index 1154ae7..74a0641 100644 --- a/cores/arduino/HardwareSerial.cpp +++ b/cores/arduino/HardwareSerial.cpp @@ -359,16 +359,8 @@ int HardwareSerial::read(void) void HardwareSerial::flush() { - // don't reverse this or there may be problems if the RX interrupt - // occurs after reading the value of rx_buffer_head but before writing - // the value to rx_buffer_tail; the previous value of rx_buffer_head - // may be written to rx_buffer_tail, making it appear as if the buffer - // don't reverse this or there may be problems if the RX interrupt - // occurs after reading the value of rx_buffer_head but before writing - // the value to rx_buffer_tail; the previous value of rx_buffer_head - // may be written to rx_buffer_tail, making it appear as if the buffer - // were full, not empty. - _rx_buffer->head = _rx_buffer->tail; + while (_tx_buffer->head != _tx_buffer->tail) + ; } void HardwareSerial::write(uint8_t c) -- cgit v1.2.3-18-g5258 From 111c55581b9b5c401843f7ed6b3ce98ceae942bc Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Sat, 7 May 2011 12:47:43 -0400 Subject: Refactoring the UART0 / USART0 receive interrupt handler. --- cores/arduino/HardwareSerial.cpp | 51 +++++++++------------------------------- 1 file changed, 11 insertions(+), 40 deletions(-) (limited to 'cores/arduino/HardwareSerial.cpp') diff --git a/cores/arduino/HardwareSerial.cpp b/cores/arduino/HardwareSerial.cpp index 74a0641..91c79d3 100644 --- a/cores/arduino/HardwareSerial.cpp +++ b/cores/arduino/HardwareSerial.cpp @@ -81,61 +81,32 @@ inline void store_char(unsigned char c, ring_buffer *buffer) } } +#if !defined(USART_RX_vect) && !defined(SIG_USART0_RECV) && \ + !defined(SIG_UART0_RECV) && !defined(USART0_RX_vect) && \ + !defined(SIG_UART_RECV) + #error Don't know what the Data Received vector is called for the first UART +#else #if defined(USART_RX_vect) SIGNAL(USART_RX_vect) - { - #if defined(UDR0) - unsigned char c = UDR0; - #elif defined(UDR) - unsigned char c = UDR; // atmega8535 - #else - #error UDR not defined - #endif - store_char(c, &rx_buffer); - } -#elif defined(SIG_USART0_RECV) && defined(UDR0) +#elif defined(SIG_USART0_RECV) SIGNAL(SIG_USART0_RECV) - { - unsigned char c = UDR0; - store_char(c, &rx_buffer); - } -#elif defined(SIG_UART0_RECV) && defined(UDR0) +#elif defined(SIG_UART0_RECV) SIGNAL(SIG_UART0_RECV) - { - unsigned char c = UDR0; - store_char(c, &rx_buffer); - } -//#elif defined(SIG_USART_RECV) #elif defined(USART0_RX_vect) - // fixed by Mark Sproul this is on the 644/644p - //SIGNAL(SIG_USART_RECV) SIGNAL(USART0_RX_vect) +#elif defined(SIG_UART_RECV) + SIGNAL(SIG_UART_RECV) +#endif { #if defined(UDR0) unsigned char c = UDR0; #elif defined(UDR) - unsigned char c = UDR; // atmega8, atmega32 + unsigned char c = UDR; #else #error UDR not defined #endif store_char(c, &rx_buffer); } -#elif defined(SIG_UART_RECV) - // this is for atmega8 - SIGNAL(SIG_UART_RECV) - { - #if defined(UDR0) - unsigned char c = UDR0; // atmega645 - #elif defined(UDR) - unsigned char c = UDR; // atmega8 - #endif - store_char(c, &rx_buffer); - } -#elif defined(USBCON) - #warning No interrupt handler for usart 0 - #warning Serial(0) is on USB interface -#else - #error No interrupt handler for usart 0 #endif //#if defined(SIG_USART1_RECV) -- cgit v1.2.3-18-g5258 From ac5defcea611319084ca7334b347c061a95e00ac Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Sat, 7 May 2011 13:04:13 -0400 Subject: Adding serialEvent(), serialEvent1(), etc. Called from within the serial receive interrupt. These are implemented as an empty weak function in the core that be overridden by the user's sketch. http://code.google.com/p/arduino/issues/detail?id=263 --- cores/arduino/HardwareSerial.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'cores/arduino/HardwareSerial.cpp') diff --git a/cores/arduino/HardwareSerial.cpp b/cores/arduino/HardwareSerial.cpp index 91c79d3..9f5ed50 100644 --- a/cores/arduino/HardwareSerial.cpp +++ b/cores/arduino/HardwareSerial.cpp @@ -86,6 +86,8 @@ inline void store_char(unsigned char c, ring_buffer *buffer) !defined(SIG_UART_RECV) #error Don't know what the Data Received vector is called for the first UART #else + void serialEvent() __attribute__((weak)); + void serialEvent() {} #if defined(USART_RX_vect) SIGNAL(USART_RX_vect) #elif defined(SIG_USART0_RECV) @@ -106,36 +108,44 @@ inline void store_char(unsigned char c, ring_buffer *buffer) #error UDR not defined #endif store_char(c, &rx_buffer); + serialEvent(); } #endif -//#if defined(SIG_USART1_RECV) #if defined(USART1_RX_vect) - //SIGNAL(SIG_USART1_RECV) + void serialEvent1() __attribute__((weak)); + void serialEvent1() {} SIGNAL(USART1_RX_vect) { unsigned char c = UDR1; store_char(c, &rx_buffer1); + serialEvent1(); } #elif defined(SIG_USART1_RECV) #error SIG_USART1_RECV #endif #if defined(USART2_RX_vect) && defined(UDR2) + void serialEvent2() __attribute__((weak)); + void serialEvent2() {} SIGNAL(USART2_RX_vect) { unsigned char c = UDR2; store_char(c, &rx_buffer2); + serialEvent2(); } #elif defined(SIG_USART2_RECV) #error SIG_USART2_RECV #endif #if defined(USART3_RX_vect) && defined(UDR3) + void serialEvent3() __attribute__((weak)); + void serialEvent3() {} SIGNAL(USART3_RX_vect) { unsigned char c = UDR3; store_char(c, &rx_buffer3); + serialEvent3(); } #elif defined(SIG_USART3_RECV) #error SIG_USART3_RECV -- cgit v1.2.3-18-g5258 From 90c487402cefadb6a2aab907ab07075cbb759e34 Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Thu, 12 May 2011 16:58:56 -0400 Subject: Small optimization in HardwareSerial. begin(long) -> begin(unsigned long) Conflicts: hardware/arduino/cores/arduino/HardwareSerial.h --- cores/arduino/HardwareSerial.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cores/arduino/HardwareSerial.cpp') diff --git a/cores/arduino/HardwareSerial.cpp b/cores/arduino/HardwareSerial.cpp index 9f5ed50..d6d7b60 100644 --- a/cores/arduino/HardwareSerial.cpp +++ b/cores/arduino/HardwareSerial.cpp @@ -265,7 +265,7 @@ HardwareSerial::HardwareSerial(ring_buffer *rx_buffer, ring_buffer *tx_buffer, // Public Methods ////////////////////////////////////////////////////////////// -void HardwareSerial::begin(long baud) +void HardwareSerial::begin(unsigned long baud) { uint16_t baud_setting; bool use_u2x = true; -- cgit v1.2.3-18-g5258 From 664e9af2cd359b6e301c43cbfd21a80f390df5f4 Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Sat, 14 May 2011 12:25:39 -0400 Subject: Fixing 300 baud communication for serial. Because UBBR is only 12 bits, we were overflowing it at 300 baud because of the use of the U2X bit. Now we turn off U2X if it would yield a UBBR value that would overflow. Note that this breaks 300 baud communication with the computer on the Uno and Mega 2560 because the 8U2 USB-serial firmware has this same bug (and previously they cancelled each other out). Since, however, it seems more likely that people will need to use 300 baud to communicate with other (legacy) hardware than with the computer, I'm making this change. Issue for 8U2 firmware bug: http://code.google.com/p/arduino/issues/detail?id=542 http://code.google.com/p/arduino/issues/detail?id=522 --- cores/arduino/HardwareSerial.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'cores/arduino/HardwareSerial.cpp') diff --git a/cores/arduino/HardwareSerial.cpp b/cores/arduino/HardwareSerial.cpp index d6d7b60..db6b149 100644 --- a/cores/arduino/HardwareSerial.cpp +++ b/cores/arduino/HardwareSerial.cpp @@ -278,6 +278,8 @@ void HardwareSerial::begin(unsigned long baud) use_u2x = false; } #endif + +try_again: if (use_u2x) { *_ucsra = 1 << _u2x; @@ -286,6 +288,12 @@ void HardwareSerial::begin(unsigned long baud) *_ucsra = 0; baud_setting = (F_CPU / 8 / baud - 1) / 2; } + + if ((baud_setting > 4095) && use_u2x) + { + use_u2x = false; + goto try_again; + } // assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register) *_ubrrh = baud_setting >> 8; -- cgit v1.2.3-18-g5258