Computing stuff tied to the physical world

A tale of stand-alone builds

In AVR, Software on Jun 10, 2009 at 00:01

The JeeBot Duo runs off a Baby Orangutan controller by Pololu, which isn’t entirely compatible with the Arduino IDE. Well, it can be made to work with it but in this case it looks like just using avr-gcc and avrdude directly from a Makefile would be just as simple.

Boy, was I wrong.

I’ve spent nearly two days trying to understand why this thing wasn’t working. Or rather, it was. Sometimes. But with resets all the time, and the watchdog being tripped even though I never enabled it.

One problem is that the BOC has no other signaling on board than a single LED. So first thing was to set up serial communication. Well, that worked. But then it didn’t. And then things got really totally erratic…

The problem turned out to be in the highlighted portion of this Makefile:

Picture 2.png

Without the $(CFLAGS) on the linker line, everything   s o r t   o f   works.

Until you start using RAM for data, such as statics/externals and strings. Or C++ classes inside the Pololu libraries for example.

Then the system goes berzerk. Because the linker wrongly assumes that RAM starts at 0x0060. So strings and data variables end up being written into the extended I/O area. Want to know what’s at address 0x0060? The watchdog control register.

Anyway. It took me many hours of complete despair to figure this one out. Salvation came from “avr-objdump -h”, which clearly showed that the “.data” segment was in the wrong place compared to an Arduino sketch. With many thanks to Ben @ Pololu for nudging me towards the solution and for patiently responding to my emails, some of which must have been pretty weird…

I think that what baffled me most of all was the fact that the simplest bits of code worked just fine. You can get a lot of little tests going without ever using strings or allocating static variables. And the failures being random resets (from the watchdog) kept me looking for hardware problems – silly me.

At one point, I had figured out the incorrect starting RAM address and added this linker option: “-Wl,-Tdata,0x800100”. Unsure why it had to be specified but it got past the most erratic behavior.

But then interrupts wouldn’t work. Disassembly (with “avr-objdump -D”) showed that the generated code was using an incorrect set of vectors. And then it dawned on me: the $(CFLAGS) includes “-mmcu=atmega328p” which the linker needs to put things in the right place and to use the right vectors.

Doh. Totally obvious in hindsight.

Now I can finally generate and upload code without having to go through the Arduino IDE.