Monday, October 15, 2012

on demand and configurable Arduino HardwareSerial

At some point you want to tune a hardware serial interface. Typically to increase the receive buffer size because the sender sends fast and you need some time to do other stuff then just receive data.

Sometimes you don't use the serial interfaces at all, or only use it for sending short debug messages.

In all those cases you're potentially wasting quite a bit of RAM as Arduino always instantiates all available serial interfaces with the fixed buffer size of typically 64 bytes.

I thought it a fun little coding challenge to adapt the Arduino HardwareSerial code to use C++ template parameters. Those parameters can then be used to instantiate the HardwareSerial only when you need it and only with buffer sizes you want.

It turned out quite simple, and the following basic example Arduino sketch illustrates the principle:

 1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil -*- */
 3 /* (c) 2012 Joost Yervante Damad <> */
 4 /* License: GPL3+ */
 6 static HardwareSerial<HARDWARE_SERIAL, 0, 16> MySerial;
 8 void setup()
 9 {
10   MySerial.begin(31250);
11 }
13 static uint8_t c = 0;
14 void loop()
15 {
16   delay(50);
17   ++c;
18   MySerial.write((char)c);
19 }

In line 6 I instantiate the HardwareSerial instance. It has 3 template parameters:

  1. HARDWARE_SERIAL: this indicates we want the first hardware serial of the microcontroller. This is used to differentiate the underlying ports, etc at compile time. On an Arduino Mega you could also use HARDWARE_SERIAL1, HARDWARE_SERIAL2 or HARDWARE_SERIAL3.
  2. 0: This is the receive buffer size. In this case it is 0 meaning we don't want to receive anything and won't waste any bytes on a buffer. As an added bonus the interrupts for receiving will not be enabled.
  3. 16: This is the transmit buffer size. The test program is only sending single bytes, so we could even use 1 here!
I like how it turned but I fear it is a bit too complex to be part of the official Arduino tree.

The code can be found in github at:


Matthijs Kooijman said...

One thing to keep in mind with an approach like this is that each instantation of your HardwareSerial class (with different template parameters) creates a new class, duplicating _all_ code. You'd expect the compiler to be smart about this, but in some cases in my TStreaming library I found that the compiler didn't even manage to remove the duplicate code when some methos didn't even use any of the template parameters at all, so don't get your hopes up...

Unknown said...

Yup. It was only a proof of concept.