Dynamic Serial port selection and use without instantiating all Serialx objects I have an arduino project that reads a config file from SD and then receives data on a serial port that is specifed in the config file.

I therefore need to instantiate the Serial (Serial0), Serial1,..2,3, etc based on dynamic data. 

I am using a mega2560 with 4x HardwareSerial. Serial (also Serial0) is the USB. Serial 1, 2, 3 are on specific hardware pins. 

I started with code something like:

uint8_t InitPort(uint8_t port) {
    switch (port) {
        case 0:
            if(Serial.begin(9600) return 1;
            break;
        case 1:
            if(Serial1.begin(9600) return 1;
            break;

        ... etc...

        default:
            return 0;
}


However, this instantiates all Serialx objects (using 157 bytes of data/bss each). 

I've since written a class wrapper that takes a referece to the desired serial object as an initialising paramter, but this just pushes the problem up-stack to the calling code. 

Is there a way that a Serial object can be instanitated dynamically with a port number passed in, to only end up with one instance connected to the desired port?
You can create an instance of HardwareSerial referencing a hardware
port that depends on a function parameter, as in



void initPort(uint8_t port) {
    switch (port) {
        case 0: {
            HardwareSerial serial(&amp;UBRR0H, &amp;UBRR0L,
                     &amp;UCSR0A, &amp;UCSR0B, &amp;UCSR0C, &amp;UDR0);
            serial.begin(9600);
            break;
        }
        case 1:
            // etc...
    }
}


However, since only a local variable can be created in this manner, it
is not of much use. Ideally, you would want to have a global variable
for the serial port, and initialize it in initPort(), as

HardwareSerial serial;

void initPort(uint8_t port) {
    switch (port) {
        case 0:
            // Invoke fictional init() method.
            serial.init(&amp;UBRR0H, &amp;UBRR0L,
                     &amp;UCSR0A, &amp;UCSR0B, &amp;UCSR0C, &amp;UDR0);
            break;
        case 1:
            // etc...
    }
    serial.begin(9600);
}


Alas, this is not possible, as the HardwareSerial class has no default
constructor. This means that binding the object to the hardware port can
only be done when it is constructed.

Short of modifying the Arduino core (adding a default constructor and an
init() method), the only option I can see is to have the global
variable be a pointer. Then, in initPort() the object is
instantiated while initializing the pointer. I tried this approach in
the example program below. There was a slight technical difficulty
though: since the object files from the core defining Serial,
Serail1, etc. will hopefully not be linked to the program, the
interrupt service routines defined therein must be also defined in the
sketch itself. And since an ISR cannot be bound to an interrupt at run
time, the ISRs have to be defined for all the ports, even though only
one ends up being actually used.

Here is my test program:

#include &lt;HardwareSerial_private.h&gt;

HardwareSerial *serial;

ISR(USART0_RX_vect) { serial-&gt;_rx_complete_irq(); }
ISR(USART1_RX_vect, ISR_ALIASOF(USART0_RX_vect));
ISR(USART2_RX_vect, ISR_ALIASOF(USART0_RX_vect));
ISR(USART3_RX_vect, ISR_ALIASOF(USART0_RX_vect));
ISR(USART0_UDRE_vect) { serial-&gt;_tx_udr_empty_irq(); }
ISR(USART1_UDRE_vect, ISR_ALIASOF(USART0_UDRE_vect));
ISR(USART2_UDRE_vect, ISR_ALIASOF(USART0_UDRE_vect));
ISR(USART3_UDRE_vect, ISR_ALIASOF(USART0_UDRE_vect));

void initPort(uint8_t port)
{
    switch (port) {
        case 0:
            serial = new HardwareSerial(&amp;UBRR0H, &amp;UBRR0L,
                         &amp;UCSR0A, &amp;UCSR0B, &amp;UCSR0C, &amp;UDR0);
            break;
        case 1:
            serial = new HardwareSerial(&amp;UBRR1H, &amp;UBRR1L,
                         &amp;UCSR1A, &amp;UCSR1B, &amp;UCSR1C, &amp;UDR1);
            break;
        case 2:
            serial = new HardwareSerial(&amp;UBRR2H, &amp;UBRR2L,
                         &amp;UCSR2A, &amp;UCSR2B, &amp;UCSR2C, &amp;UDR2);
            break;
        case 3:
            serial = new HardwareSerial(&amp;UBRR3H, &amp;UBRR3L,
                         &amp;UCSR3A, &amp;UCSR3B, &amp;UCSR3C, &amp;UDR3);
            break;
    }
    serial-&gt;begin(9600);
}

void setup() {
    initPort(0);
    serial-&gt;println("Hello, World!");
}

void loop(){}


It should be noted that the ISRs do not take that mush flash space.
There are actually only two of them, even though each is referenced four
times in the interrupt vector table.