Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Put each HardwareSerial instance in its own .cpp file
By putting the ISRs and HardwareSerial instance for each instance in a separate compilation unit, the compile will only consider them for linking when the instance is actually used. The ISR is always referenced by the compiler runtime and the Serialx_available() function is always referenced by SerialEventRun(), but both references are weak and thus do not cause the compilation to be included in the link by themselves. The effect of this is that when multiple HardwareSerial ports are available, but not all are used, buffers are only allocated and ISRs are only included for the serial ports that are used. On the mega, this lowers memory usage from 653 bytes to just 182 when only using the first serial port. On boards with just a single port, there is no change, since the code and memory was already left out when no serial port was used at all. This fixes #1425 and fixes #1259.
- Loading branch information
1 parent
8e43c1a
commit 0e97bcb
Showing
5 changed files
with
229 additions
and
92 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |