Skip to content

HardwareSerial improvements #1711

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions hardware/arduino/avr/cores/arduino/Arduino.h
Original file line number Diff line number Diff line change
@@ -87,6 +87,10 @@ void yield(void);
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))

// avr-libc defines _NOP() since 1.6.2
#ifndef _NOP
#define _NOP() do { __asm__ volatile ("nop"); } while (0)
#endif

typedef unsigned int word;

@@ -195,6 +199,10 @@ extern const uint8_t PROGMEM digital_pin_to_timer_PGM[];
#include "WCharacter.h"
#include "WString.h"
#include "HardwareSerial.h"
#include "USBAPI.h"
#if defined(HAVE_HWSERIAL0) && defined(HAVE_CDCSERIAL)
#error "Targets with both UART0 and CDC serial not supported"
#endif

uint16_t makeWord(uint16_t w);
uint16_t makeWord(byte h, byte l);
522 changes: 204 additions & 318 deletions hardware/arduino/avr/cores/arduino/HardwareSerial.cpp

Large diffs are not rendered by default.

24 changes: 12 additions & 12 deletions hardware/arduino/avr/cores/arduino/HardwareSerial.h
Original file line number Diff line number Diff line change
@@ -46,14 +46,9 @@ class HardwareSerial : public Stream
volatile uint8_t *_ucsrb;
volatile uint8_t *_ucsrc;
volatile uint8_t *_udr;
uint8_t _rxen;
uint8_t _txen;
uint8_t _rxcie;
uint8_t _udrie;
uint8_t _u2x;
bool transmitting;
// Has any byte been written to the UART since begin()
bool _written;

public:
volatile uint8_t _rx_buffer_head;
volatile uint8_t _rx_buffer_tail;
volatile uint8_t _tx_buffer_head;
@@ -65,11 +60,11 @@ 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,
volatile uint8_t *ucsrc, volatile uint8_t *udr,
uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udrie, uint8_t u2x);
volatile uint8_t *ucsrc, volatile uint8_t *udr);
void begin(unsigned long);
void begin(unsigned long, uint8_t);
void end();
@@ -84,6 +79,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();

// Interrupt handlers - Not intended to be called externally
void _rx_complete_irq(void);
void _tx_udr_empty_irq(void);
};

// Define config for Serial.begin(baud, config);
@@ -114,18 +113,19 @@ class HardwareSerial : public Stream

#if defined(UBRRH) || defined(UBRR0H)
extern HardwareSerial Serial;
#elif defined(USBCON)
#include "USBAPI.h"
// extern HardwareSerial Serial_;
#define HAVE_HWSERIAL0
#endif
#if defined(UBRR1H)
extern HardwareSerial Serial1;
#define HAVE_HWSERIAL1
#endif
#if defined(UBRR2H)
extern HardwareSerial Serial2;
#define HAVE_HWSERIAL2
#endif
#if defined(UBRR3H)
extern HardwareSerial Serial3;
#define HAVE_HWSERIAL3
#endif

extern void serialEventRun(void) __attribute__((weak));
54 changes: 54 additions & 0 deletions hardware/arduino/avr/cores/arduino/HardwareSerial0.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include "Arduino.h"
#include "HardwareSerial.h"

// Each HardwareSerial is defined in its own file, sine the linker pulls
// in the entire file when any element inside is used. --gc-sections can
// additionally cause unused symbols to be dropped, but ISRs have the
// "used" attribute so are never dropped and they keep the
// HardwareSerial instance in as well. Putting each instance in its own
// file prevents the linker from pulling in any unused instances in the
// first place.

#if defined(HAVE_HWSERIAL0)

#if defined(USART_RX_vect)
ISR(USART_RX_vect)
#elif defined(USART0_RX_vect)
ISR(USART0_RX_vect)
#elif defined(USART_RXC_vect)
ISR(USART_RXC_vect) // ATmega8
#else
#error "Don't know what the Data Received vector is called for the first UART"
#endif
{
Serial._rx_complete_irq();
}

#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)
#else
#error "Don't know what the Data Register Empty vector is called for the first UART"
#endif
{
Serial._tx_udr_empty_irq();
}

#if defined(UBRRH) && defined(UBRRL)
HardwareSerial Serial(&UBRRH, &UBRRL, &UCSRA, &UCSRB, &UCSRC, &UDR);
#else
HardwareSerial Serial(&UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UCSR0C, &UDR0);
#endif

// Function that can be weakly referenced by serialEventRun to prevent
// pulling in this file if it's not otherwise used.
bool Serial0_available() {
return Serial.available();
}

#endif // HAVE_HWSERIAL0
54 changes: 54 additions & 0 deletions hardware/arduino/avr/cores/arduino/HardwareSerial1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include "Arduino.h"
#include "HardwareSerial.h"

// Each HardwareSerial is defined in its own file, sine the linker pulls
// in the entire file when any element inside is used. --gc-sections can
// additionally cause unused symbols to be dropped, but ISRs have the
// "used" attribute so are never dropped and they keep the
// HardwareSerial instance in as well. Putting each instance in its own
// file prevents the linker from pulling in any unused instances in the
// first place.

#if defined(HAVE_HWSERIAL1)

#if defined(USART_RX_vect)
ISR(USART_RX_vect)
#elif defined(USART1_RX_vect)
ISR(USART1_RX_vect)
#elif defined(USART_RXC_vect)
ISR(USART_RXC_vect) // ATmega8
#else
#error "Don't know what the Data Received vector is called for the first UART"
#endif
{
Serial1._rx_complete_irq();
}

#if defined(UART1_UDRE_vect)
ISR(UART1_UDRE_vect)
#elif defined(UART_UDRE_vect)
ISR(UART_UDRE_vect)
#elif defined(USART1_UDRE_vect)
ISR(USART1_UDRE_vect)
#elif defined(USART_UDRE_vect)
ISR(USART_UDRE_vect)
#else
#error "Don't know what the Data Register Empty vector is called for the first UART"
#endif
{
Serial1._tx_udr_empty_irq();
}

#if defined(UBRRH) && defined(UBRRL)
HardwareSerial Serial1(&UBRRH, &UBRRL, &UCSRA, &UCSRB, &UCSRC, &UDR);
#else
HardwareSerial Serial1(&UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UCSR1C, &UDR1);
#endif

// Function that can be weakly referenced by serialEventRun to prevent
// pulling in this file if it's not otherwise used.
bool Serial1_available() {
return Serial1.available();
}

#endif // HAVE_HWSERIAL1
54 changes: 54 additions & 0 deletions hardware/arduino/avr/cores/arduino/HardwareSerial2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include "Arduino.h"
#include "HardwareSerial.h"

// Each HardwareSerial is defined in its own file, sine the linker pulls
// in the entire file when any element inside is used. --gc-sections can
// additionally cause unused symbols to be dropped, but ISRs have the
// "used" attribute so are never dropped and they keep the
// HardwareSerial instance in as well. Putting each instance in its own
// file prevents the linker from pulling in any unused instances in the
// first place.

#if defined(HAVE_HWSERIAL2)

#if defined(USART_RX_vect)
ISR(USART_RX_vect)
#elif defined(USART2_RX_vect)
ISR(USART2_RX_vect)
#elif defined(USART_RXC_vect)
ISR(USART_RXC_vect) // ATmega8
#else
#error "Don't know what the Data Received vector is called for the first UART"
#endif
{
Serial2._rx_complete_irq();
}

#if defined(UART2_UDRE_vect)
ISR(UART2_UDRE_vect)
#elif defined(UART_UDRE_vect)
ISR(UART_UDRE_vect)
#elif defined(USART2_UDRE_vect)
ISR(USART2_UDRE_vect)
#elif defined(USART_UDRE_vect)
ISR(USART_UDRE_vect)
#else
#error "Don't know what the Data Register Empty vector is called for the first UART"
#endif
{
Serial2._tx_udr_empty_irq();
}

#if defined(UBRRH) && defined(UBRRL)
HardwareSerial Serial2(&UBRRH, &UBRRL, &UCSRA, &UCSRB, &UCSRC, &UDR);
#else
HardwareSerial Serial2(&UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UCSR2C, &UDR2);
#endif

// Function that can be weakly referenced by serialEventRun to prevent
// pulling in this file if it's not otherwise used.
bool Serial2_available() {
return Serial2.available();
}

#endif // HAVE_HWSERIAL2
54 changes: 54 additions & 0 deletions hardware/arduino/avr/cores/arduino/HardwareSerial3.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include "Arduino.h"
#include "HardwareSerial.h"

// Each HardwareSerial is defined in its own file, sine the linker pulls
// in the entire file when any element inside is used. --gc-sections can
// additionally cause unused symbols to be dropped, but ISRs have the
// "used" attribute so are never dropped and they keep the
// HardwareSerial instance in as well. Putting each instance in its own
// file prevents the linker from pulling in any unused instances in the
// first place.

#if defined(HAVE_HWSERIAL3)

#if defined(USART_RX_vect)
ISR(USART_RX_vect)
#elif defined(USART3_RX_vect)
ISR(USART3_RX_vect)
#elif defined(USART_RXC_vect)
ISR(USART_RXC_vect) // ATmega8
#else
#error "Don't know what the Data Received vector is called for the first UART"
#endif
{
Serial3._rx_complete_irq();
}

#if defined(UART3_UDRE_vect)
ISR(UART3_UDRE_vect)
#elif defined(UART_UDRE_vect)
ISR(UART_UDRE_vect)
#elif defined(USART3_UDRE_vect)
ISR(USART3_UDRE_vect)
#elif defined(USART_UDRE_vect)
ISR(USART_UDRE_vect)
#else
#error "Don't know what the Data Register Empty vector is called for the first UART"
#endif
{
Serial3._tx_udr_empty_irq();
}

#if defined(UBRRH) && defined(UBRRL)
HardwareSerial Serial3(&UBRRH, &UBRRL, &UCSRA, &UCSRB, &UCSRC, &UDR);
#else
HardwareSerial Serial3(&UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UCSR3C, &UDR3);
#endif

// Function that can be weakly referenced by serialEventRun to prevent
// pulling in this file if it's not otherwise used.
bool Serial3_available() {
return Serial3.available();
}

#endif // HAVE_HWSERIAL3
2 changes: 2 additions & 0 deletions hardware/arduino/avr/cores/arduino/USBAPI.h
Original file line number Diff line number Diff line change
@@ -55,6 +55,8 @@ class Serial_ : public Stream
};
extern Serial_ Serial;

#define HAVE_CDCSERIAL

//================================================================================
//================================================================================
// Mouse