aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cores/arduino/HardwareSerial.cpp145
-rw-r--r--cores/arduino/HardwareSerial.h6
2 files changed, 50 insertions, 101 deletions
diff --git a/cores/arduino/HardwareSerial.cpp b/cores/arduino/HardwareSerial.cpp
index 59e0f1a..6bbef7a 100644
--- a/cores/arduino/HardwareSerial.cpp
+++ b/cores/arduino/HardwareSerial.cpp
@@ -84,20 +84,6 @@
#error "Not all bit positions for UART3 are the same as for UART0"
#endif
-inline void store_char(unsigned char c, HardwareSerial *s)
-{
- int i = (unsigned int)(s->_rx_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 != s->_rx_buffer_tail) {
- s->_rx_buffer[s->_rx_buffer_head] = c;
- s->_rx_buffer_head = i;
- }
-}
-
#if !defined(USART0_RX_vect) && defined(USART1_RX_vect)
// do nothing - on the 32u4 the first USART is USART1
#else
@@ -116,23 +102,7 @@ inline void store_char(unsigned char c, HardwareSerial *s)
ISR(USART_RXC_vect) // ATmega8
#endif
{
- #if defined(UDR0)
- if (bit_is_clear(UCSR0A, UPE0)) {
- unsigned char c = UDR0;
- store_char(c, &Serial);
- } else {
- unsigned char c = UDR0;
- };
- #elif defined(UDR)
- if (bit_is_clear(UCSRA, PE)) {
- unsigned char c = UDR;
- store_char(c, &Serial);
- } else {
- unsigned char c = UDR;
- };
- #else
- #error UDR not defined
- #endif
+ Serial._rx_complete_irq();
}
#endif
#endif
@@ -143,12 +113,7 @@ inline void store_char(unsigned char c, HardwareSerial *s)
#define serialEvent1_implemented
ISR(USART1_RX_vect)
{
- if (bit_is_clear(UCSR1A, UPE1)) {
- unsigned char c = UDR1;
- store_char(c, &Serial1);
- } else {
- unsigned char c = UDR1;
- };
+ Serial1._rx_complete_irq();
}
#endif
@@ -158,12 +123,7 @@ inline void store_char(unsigned char c, HardwareSerial *s)
#define serialEvent2_implemented
ISR(USART2_RX_vect)
{
- if (bit_is_clear(UCSR2A, UPE2)) {
- unsigned char c = UDR2;
- store_char(c, &Serial2);
- } else {
- unsigned char c = UDR2;
- };
+ Serial2._rx_complete_irq();
}
#endif
@@ -173,12 +133,7 @@ inline void store_char(unsigned char c, HardwareSerial *s)
#define serialEvent3_implemented
ISR(USART3_RX_vect)
{
- if (bit_is_clear(UCSR3A, UPE3)) {
- unsigned char c = UDR3;
- store_char(c, &Serial3);
- } else {
- unsigned char c = UDR3;
- };
+ Serial3._rx_complete_irq();
}
#endif
@@ -215,27 +170,7 @@ ISR(USART0_UDRE_vect)
ISR(USART_UDRE_vect)
#endif
{
- if (Serial._tx_buffer_head == Serial._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 = Serial._tx_buffer[Serial._tx_buffer_tail];
- Serial._tx_buffer_tail = (Serial._tx_buffer_tail + 1) % SERIAL_BUFFER_SIZE;
-
- #if defined(UDR0)
- UDR0 = c;
- #elif defined(UDR)
- UDR = c;
- #else
- #error UDR not defined
- #endif
- }
+ Serial._tx_udr_empty_irq();
}
#endif
#endif
@@ -243,53 +178,63 @@ ISR(USART_UDRE_vect)
#ifdef USART1_UDRE_vect
ISR(USART1_UDRE_vect)
{
- if (Serial1._tx_buffer_head == Serial1._tx_buffer_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 = Serial1._tx_buffer[Serial1._tx_buffer_tail];
- Serial1._tx_buffer_tail = (Serial1._tx_buffer_tail + 1) % SERIAL_BUFFER_SIZE;
-
- UDR1 = c;
- }
+ Serial1._tx_udr_empty_irq();
}
#endif
#ifdef USART2_UDRE_vect
ISR(USART2_UDRE_vect)
{
- if (Serial2._tx_buffer_head == Serial2._tx_buffer_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 = Serial2._tx_buffer[Serial2._tx_buffer_tail];
- Serial2._tx_buffer_tail = (Serial2._tx_buffer_tail + 1) % SERIAL_BUFFER_SIZE;
-
- UDR2 = c;
- }
+ Serial2._tx_udr_empty_irq();
}
#endif
#ifdef USART3_UDRE_vect
ISR(USART3_UDRE_vect)
{
- if (Serial3._tx_buffer_head == Serial3._tx_buffer_tail) {
- // Buffer empty, so disable interrupts
- cbi(UCSR3B, UDRIE3);
+ Serial3._tx_udr_empty_irq();
+}
+#endif
+
+
+// Actual interrupt handlers //////////////////////////////////////////////////////////////
+
+void HardwareSerial::_rx_complete_irq(void)
+{
+ if (bit_is_clear(*_ucsra, UPE0)) {
+ // No Parity error, read byte and store it in the buffer if there is
+ // room
+ unsigned char c = *_udr;
+ int i = (unsigned int)(_rx_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[_rx_buffer_head] = c;
+ _rx_buffer_head = i;
+ }
+ } else {
+ // Parity error, read byte but discard it
+ unsigned char c = *_udr;
+ };
+}
+
+void HardwareSerial::_tx_udr_empty_irq(void)
+{
+ if (_tx_buffer_head == _tx_buffer_tail) {
+ // Buffer empty, so disable interrupts
+ cbi(*_ucsrb, UDRIE0);
}
else {
// There is more data in the output buffer. Send the next byte
- unsigned char c = Serial3._tx_buffer[Serial3._tx_buffer_tail];
- Serial3._tx_buffer_tail = (Serial3._tx_buffer_tail + 1) % SERIAL_BUFFER_SIZE;
-
- UDR3 = c;
+ unsigned char c = _tx_buffer[_tx_buffer_tail];
+ _tx_buffer_tail = (_tx_buffer_tail + 1) % SERIAL_BUFFER_SIZE;
+
+ *_udr = c;
}
}
-#endif
// Constructors ////////////////////////////////////////////////////////////////
diff --git a/cores/arduino/HardwareSerial.h b/cores/arduino/HardwareSerial.h
index 5513226..cf3f6bd 100644
--- a/cores/arduino/HardwareSerial.h
+++ b/cores/arduino/HardwareSerial.h
@@ -74,7 +74,6 @@ class HardwareSerial : public Stream
volatile uint8_t *_udr;
bool transmitting;
- public:
volatile uint8_t _rx_buffer_head;
volatile uint8_t _rx_buffer_tail;
volatile uint8_t _tx_buffer_head;
@@ -86,6 +85,7 @@ class HardwareSerial : public Stream
unsigned char _rx_buffer[SERIAL_BUFFER_SIZE];
unsigned char _tx_buffer[SERIAL_BUFFER_SIZE];
+ public:
HardwareSerial(
volatile uint8_t *ubrrh, volatile uint8_t *ubrrl,
volatile uint8_t *ucsra, volatile uint8_t *ucsrb,
@@ -104,6 +104,10 @@ class HardwareSerial : public Stream
inline size_t write(int n) { return write((uint8_t)n); }
using Print::write; // pull in write(str) and write(buf, size) from Print
operator bool() { return true; }
+
+ // Interrupt handlers - Not intended to be called externally
+ void _rx_complete_irq(void);
+ void _tx_udr_empty_irq(void);
};
#if defined(UBRRH) || defined(UBRR0H)