OS Hacking and more.

5.04.2011

Revival: Starting from Embedded Systems

I haven't posted anything in quite a while, but as I wait for stuff to compile here, I think sharing a few observations might not be a bad idea.

I'm currently going through the process of compiling TinyOS and the appropriate ARM toolchain for a Cortex-M0 board I got my hands on. Specifically, I've got an NXP board with an LPC1114, and if you were wondering, it was free. To give a little perspective here, the LPC1114 is an MCU with 32K of flash and 8K of ram...essentially the same resource class as an MSP430 or Atmega328. The difference here is that this is ARM, so we get 60Mhz and 32bit instruction set. This doesn't help with resource constraints, but it should allow for some performance niceties.

Out of the box, the NXP kit has some basic libraries and an IDE integrated with GCC+proprietary flashing tools. The example code provides some single-task I/O examples, written in C. Pretty basic, but really these are things I'd be far happier to do on an Atmega328 with a lazy-man Arduino boot loader. I guess this is what they expect applications to look like; nice prototyping or something.

Thing is, this hardware is suited to much more sophisticated applications: it supports I/O at faster rates than the Atmega could dream of, while providing enough clock cycles and operation efficiency to do more than one task at once. The thing screams "multi-tasked OS" at me. The step up here is of the kind needed to support efficient, concurrent handling of multiple sensors and coordination of outputs (ala mechanical devices--if you don't already see the robotic tendencies here...)

The other neat thing we should be able to do on Cortex devices of this class is support some greater levels of abstraction. If we're going to be building multicomponent systems, the benefits of thinking at a high-level about those components are pretty clear. This should be a language/framework feature, one we have no excuse to avoid.

Ok, so I'm looking to build a parallelized, modular system on this cortex. I can think of a hundred ways to do this--throw linux at it and run, slap a JVM on the metal, zoom around in a comfy RTOS. Only one problem...Memory footprint. 32K won't fit any sort of JVM, definitely not linux, and even most respectable RTOSes need more space. Not a happy situation.

Well, out of the box, the folks NXP have given me an example of a FreeRTOS implementation on the lpc1114, so thats something. Pretty straightforward to build and deploy in their tools (which run on linux and windows, but not on my mac--nbd) and the debugger works as it ought to. All well and good here, I can spawn tasks from C function pointers, and they get scheduled. I/O runs. Unfortunately this isn't moving me toward a parallelized system on two fronts. First, this mode of operation is conducive to spawning a bunch of tasks related to the same component of a project, but not separate systems. This seems like a trivial distinction from a code perspective, but its actually a pretty serious abstraction barrier. If I have to mix subsystem code, abstraction suffers, period. Speaking of abstractions, this code is no more high-level than the C that drives the Blinky demo. I'm still calling out to and polling GPIO pins for control of a device.

Ugh.

A step in a different direction, then, is to play with the model used in wireless sensor networks--the TinyOS platform and its associated nesC language. Ironically, this was designed to run on the Atmegas and MSPs that the LPC is trying to displace, but porting TinyOS to the Cortex should give some neat advantages.
The biggest thing is that on the slower 8 and 16bit MCUs, even with TinyOS, Motes would be serving a single purpose or monitoring a single system in the physical world. There wasn't really room to be switching around--the most switching you'd do would be between radio operations and sensing. In the Cortex world, we should be able to manage a handful of different real world systems without introducing serious I/O or processing latency.

So why try TinyOS?

TinyOS's model for application design is pretty neat: it revolves around locally-scoped modules, and wires that link interfaces between them together. With these wires, modules send each other events, and a great amount of logic is executed asynchronously/on demand. The system is conducive to reactivity, which is essentially what all robots and sensors do in the physical world. By using modules that operate on their own, TinyOS establishes a neat sort of *implicit* parallelism--whereby its explicitly declared what operations are done in series and parallel, but the development paradigm is toward modules acting in parallel streams. To be clear: you can have modules for different sensors, for example, and they'll notify controller logic independently of each other--in parallel. This also parallelizes the handling logic for real-world events, accommodating them better. It's neat. Or a starting point for something better at least ;)

So I'm trying to setup everything to make TinyOS work on this little LPC. I'm starting with the work from this project which should setup the toolchain nicely. I'll build using the tinyOS system and then use the NXP flasher to move binaries around. For reference I'm working out of an Ubuntu 11.04 VM, 64bit, fresh from today.

HowTo Notes/Progress:

Sorry to say it, but TinyOS-Cortex is crappily documented. Cortex-M3 ports of tinyOS have been made and rolled into the main tinyos 2.x stream, leaving m0 a bastard little brother. Alas.

From my fresh vm, I installed the flasher for the NXP (part of their lpcxpresso kit, whatever, irrelevant). Then I pull the scripts from google code to setup the tinyos-cortex stuff. There are a few of dependencies that aren't stated as part of this-- I needed to add the 32bit support libraries (ia32-libs), java (sun-java6-jdk), autoconf/automake, a symlink for the 32 bit c++ stdlib (“ln -s /usr/lib32/libstdc++.so.6 /usr/lib32/libstdc++.so”)
^^ simple things you may already have. Just make sure they're there.
Given these things, I pulled the scripts into my /opt directory as specified here
I made a build directory within the tinyos-cortex directory as directed. As fix before running the script though, there is a change to be made. The fetch() function is slightly broken: in main.subr, wget should have a [capital] -O flag rather than a lower case -o. Subtle.
Then I run the tinyos toolchain script, followed by the cortex toolchain script. You have to watch really really carefully to see if stuff breaks, because its non obvious/doesnt fail the exit() call. It takes a while too.
After that, you have to add the binaries to your path:

export PATH=/opt/tinyos/bin/:/opt/cortex/bin/:$PATH

and get some symlinks in place

ln -s /opt/tinyos/build/tinyos-2.x /opt/tinyos/tinyos-2.x

Once that's in place we should be able to start building stuff. So here's the first problem: we don't actually have a cortex M0 target. I'm hacking around and using the m3 target, with the knowledge that the m0 compiler is getting invoked (i hope?)...otherwise i might need to define a new set of rules here...

1 comment:

Rick Drolet said...

Curious if you have had any luck w/tinyos?