Why I'm ditching the Arduino software platform

I'm getting set up for my next project and decided to update my development environment. I've finally decided to entirely ditch the Arduino software environment and just use the boards. I stopped using the Arduino IDE some time ago, but now I'm going whole hog and ditching the Arduino library as well. Why? Well, it's simple:

Significant parts of it are pile of junk.



OK, let's look at the new write() function that does interrupt-driven output:

size_t HardwareSerial::write(uint8_t c)
  int i = (_tx_buffer->head + 1) % SERIAL_BUFFER_SIZE;

  // wait for the interrupt handler to empty it a bit
  // ???: return 0 here instead?
  while (i == _tx_buffer->tail)

  _tx_buffer->buffer[_tx_buffer->head] = c;
  _tx_buffer->head = i;

  sbi(*_ucsrb, _udrie);
  return 1;

Is there a problem? Let's look at the definition of _tx_buffer:

struct ring_buffer
  unsigned char buffer[SERIAL_BUFFER_SIZE];
  volatile unsigned int head;
  volatile unsigned int tail;

Oh dear. head and tail are declared as int, i.e. 16 bits, 2 bytes. They are accessed by both the write routine and the interrupt service routine that actually transmits the data yet there's no locking in the write routine so the accesses aren't atomic. Why is that an issue? Well, the avr-libc documentation makes it clear:



"So what?" you say, "That's only one chunk of code that's a bit naff." Unfortunately it's not an isolated instance. Let's move on now to look at one of the newer features that has been added to the Arduino platform, the re-implemented String class. Ok, let's build a minimal program that uses it:

#include "WString.h"
int main(void) {
    String bloat = "hello world";
    return 0;

And let's build it:



   text    data     bss     dec     hex filename
  10194      20       5   10219    27eb build/test.elf

Can that really be right? 10K for a one-line program? Unfortunately it is. Any mention of String pulls in the entirety of the class, as well as all the other avr-libc routines it references. So on a Duemilanove that only has 32k to start with, a third of the available memory is gone before you start. At the time the class was being rewritten I expressed my opinion that it was probably a bad idea and that the Arduino developers really needed to target the platform they actually had and not the one they wished they had. And that's not the end of the issues with the String class - on a constrained-memory platform such as the AVR, providing a class like String that relies on malloc, creates lots of temporaries, fragments the (tiny) heap and has no real ability to deal with out-of-memory conditions is a recipe for problems, problems that will manifest themselves as random, mysterious and un-diagnosable run-time errors. And sure enough, a quick google shows that's exactly what tends to happen - just about the worst possible outcome for a platform that's targeted at neophytes.

That's just two examples - there are others as well, such as the well-known performance problems with pin access, which may be up to 50x slower that direct pin access. In fact the only two remaining parts of the Arduino libraries that I still use are the millisecond clock and the serial IO, and they are easy enough to replace, so that's what I'm doing.

While I applaud the aims of the Arduino project, the realities of the restricted hardware platform have to be taken into consideration. In addition, one of the aims of the project is to:


Categories : Tech, AVR

Scala snippet of the day

The following is useful for benchmarking code from inside the REPL:

def timed(op: => Unit) = {
  val start = System.nanoTime
  (System.nanoTime - start) / 1e9

Then you can use it like this:

scala> timed { Thread.sleep(5000) }
res0: Double = 5.010083526


scala> def fn = Thread.sleep(5000)
fn: Unit

scala> timed(fn)
res0: Double = 5.010088248


Tags : ,
Categories : Web, Tech