Wednesday, August 27, 2008

Choosing Hardware for Diminuto

Diminuto is my attempt to put together a platform on which to teach real-time software design, systems programming, embedded software development and assembly language programming, all using real commercial hardware and open source software. Sure, it may be a stupid idea. But damn it, it's my stupid idea.

When I first started thinking about this, I scribbled down some basic goals.

The cost of entry has to be reasonable.

A university had to be able to put together a teaching laboratory with several stations at a reasonable cost. And although a university CS, CEG or EE department was the customer I had in mind, the cost shouldn't rule out the occasional individual from trying their hand at learning this stuff. This ruled out a lot of otherwise interesting evaluation boards and development kits that cost thousands of dollars or required specialized equipment to program. It also required the use of open source tools to keep the cost of the tool chain down. Using open source also admitted the possibility of modifying existing code, like the kernel or device drivers, as part of a class assignment.

(Disclaimer: if you are a professional embedded developer, or if you manage such, I would be remiss if I didn't tell you that paying for commercial tools for embedded development is, IMHO, well worth it. I've used tools like IAR Embedded Workbench and MontaVista DevRocket to extremely good effect, and would not hesitate to use them again. While embedded development is completely doable with open source tools, you will be trading time for money, and an essential element of happiness is knowing what your time is worth. If you are a university with a big endowment, you are certainly encouraged to use these tools also. Your students will no doubt encounter them in the real world of embedded product development.)

The hardware had to be commercially available.

No special developments or custom boards, nor processors that were far off the mainstream, nor stuff that was hard to find. Partly this was a cost issue, but also I wanted it to be likely that students using this platform would encounter something very similar in the work place.

The instruction set of the processor had to be amenable to learning assembly language programming.

The advent of reduced instruction set computer (RISC) architectures made this challenging. The PDP-11 had the simplest instruction set of any processor I've ever examined, but many current RISC machines make even the old IBM 370 instruction set seem simple in comparison. The platform had to have an instruction set that was rich enough to not be too painful to use and to illustrate all the necessary concepts, yet simple enough to be taught in sufficient depth in perhaps a ten week college course.

The processor had to be widely used in actual devices, especially consumer hand-held devices.

I wanted students to use processor architectures that they would be likely to encounter in the real world. I wanted them to look at their PDA, cell phone, MP3 player, or other hand-held, and be able say to themselves "I'm writing code that could run on this device".

The platform had to be sufficient to run Linux, but had to be resource constrained enough that developing for it wasn't like developing for a Pentium-based Linux desktop.

I've used a lot of real-time operating systems (RTOS) during my years in embedded development: roll-your-own, pSOS, VxWorks, PSX/C-Executive, and RTX are the ones that come immediately to mind. But Linux is becoming more and more common in embedded devices, as the devices become more powerful, and tools become available that allow Linux to run in a smaller memory footprint. I had already gotten Linux running on several embedded platforms, ranging from one that booted from ROM and ran only single-user with a RAM disk, to one that booted and ran multi-user from a persistent disk-like file system.

Still, embedded systems have resource constraints that make developing for them unlike developing for your typical white box PC. In fact, the resource constraints often get tighter and tighter, because companies continue to shoehorn microcontrollers into smaller and cheaper devices. The ability to run Linux on a resource constrained platform was the best of both worlds: familiar, relatively inexpensive, and challenging.

Realistically, this meant a 32-bit processor with a memory management unit (MMU).

The platform had to be capable of running a lighter weight real-time operating system without undue pain.

It couldn't just run Linux, because Linux isn't always the answer, particularly for hard-real-time or highly memory constrained applications. There had to be at least the possibility of running some other open source or at least inexpensive RTOS without a huge amount of pain writing a board support package to initialize the processor, the MMU, etc. The fact that the platform could run Linux meant that much of this code could be cribbed from the Linux boot code for the platform and used in other, perhaps standalone, applications.

The platform had to have a rich set of contemporary, useful devices, including Ethernet and removable storage media.

Students had to have access to devices both for accessing and running the system and for programming as part of their class assignments. Removable media would allow them to take their projects with them when they left their station in the laboratory.

For cost reasons, this almost certainly required a system-on-a-chip (SoC), in which I/O controllers are embedded in the processor chip itself. This has become common in real-life embedded development, with ARM-based and PowerPC-based processors having integrated controllers for technologies like serial, Ethernet, and even USB. It is also a good example of specialized multi-core architecture.

The platform must include a boot-loader in ROM.

I didn't care so much what the boot-loader was, although something mainstream like U-Boot, widely used in the embedded community, was very desirable. The boot-loader was necessary so that each station didn't require an exotic (read: expensive) tool, like as a JTAG hardware debugger, to load software. The ability to boot from removable media or the network was very highly desirable. Having a boot-loader whose source code was open source also meant that code to initialize the processor could be cribbed from this and used elsewhere.

The tool chain must provide C and C++ compilers and an assembler, and be expandable to include other languages.

C is the lingua franca of embedded development, and is an absolute requirement if you are going to go about hacking the Linux kernel. C++ is, in my personal experience, a lot more common in embedded application development than embedded development pundits would have you believe. If you have C and C++, chances are you are getting an assembler as part of the deal too, but in any case it's required if you are going to learn even a little bit about assembly language.

But I wanted students to be able to explore other options as well, like Java, or Digital Mars' D, or even scripting languages. A tool chain based on the GNU Compiler Collection (GCC) seemed like a pretty open-ended choice.

The platform must expose its devices physically and programmatically.

By this I mean I wanted the chips physically accessible, and didn't want the lower level device details hidden by a BIOS in ROM. I wanted the possibility of students getting experience using logic analyzers, oscilloscopes, or other diagnostic equipment, because that's part of the real-life embedded experience. Not having a ROM meant that existing Linux device drivers for the platform could be studied in all their glorious awful detail regarding the hardware interface and perhaps even modified as part of a class assignment.

The platform should be an unlikely theft target.

When I started contemplating this project, my first step was to Google around to see what others had done before me. (I also interviewed some of my embedded mentors from Bell Labs, Tam, Doug and Randy, quizzed my former colleagues from graduate school who were still in academia, Dale and David, and even pinged my former professors, most of whom had long since retired.)

I was particularly impressed with the work of Arnold Berger (University of Washington) and Dennis Brylow (Marquette University), both of whom tackled the problem of teaching embedded software development. (In fact, I will excuse you if you simply ignore everything else I have to say on this topic and go off and base a course around their work, so delighted I will be that you are doing anything at all.) Berger took a approach very similar to mine. Brylow did what I thought was pretty damn clever and used existing consumer devices like LinkSys routers that could be pried open and programmed and modified. Before embarking on this project, I also experimented with my own Nokia N800 hand-held to see if it could be used as platform.

But Berger did his work in 2000, so his choices for hardware were different from mine. Things change a lot in just a few years. And while consumer devices like the LinkSys and N800 were more cost effective, I didn't think they exposed the hardware sufficiently, and more importantly, I thought they would be attractive theft targets, having had some experience with that during my time in academia.

The platform should have a form factor that is typical of prototypes in the real world of embedded software development.

I just liked the idea of students laboring over a circuit board. It was nostalgic, particularly of the prototype phase of a project before the physical cabinet or chassis has been completed.

My next step was to choose some candidates for processors. I admit I had my own prejudices.

The Motorola (now Freescale Semiconductor) PowerPC was the original processor architecture of the IBM RS/6000, with which I've also had much experience during the supercomputing phase of my career. It was also the architecture of choice for almost every embedded telecommunications product I've ever worked on. I wasn't that crazy about its instruction set from a teaching point of view, having had to learn enough of it to debug the occasional ugly problem. Development kits were easy to come by, but a little more expensive than I was happy with. SoC implementations were common. I was very familiar with running Linux and other RTOSes on such processors, and was confident that the project was completely doable on the PowerPC.

The ARM series of processor architectures can be found in, I dunno, thousands of consumer devices. ARM doesn't actually produce hardware, they produce IP (intellectual property) processor cores that can be dropped into various logic devices. Which means everybody and his brother (247 licensees to be exact, including Freescale Semiconductor) makes processor chips that run the ARM instruction set. I've worked on a couple of projects that used ARM cores, one of which ran Linux. I probably own a dozen devices that contain ARM-based processors, several within arm's reach as I write this. The ARM instruction set is pretty nice, a little reminiscent of the PDP-11, particularly in its 16-bit Thumb mode. ARM-based development kits are widely available and reasonably priced, and SoC implementations are easy to come by.

The next step was crucial to making life easier for all of us: I downloaded the latest Linux 2.6 kernel, ran make menuconfig for ARCH=arm and ARCH=powerpc, and explored the kernel configuration menu for what development kits were already supported with board support packages by the kernel and its build environment. I limited my Google search for development kits to these choices.

No use in making life harder than it needs to be.

Eventually I settled on the Atmel AT91RM9200-EK evalutation kit. This board has an AT91RM9200 SoC based on the ARM9 core, has the U-Boot bootloader in flash, an MMU, 32 megabytes of RAM, 10/100 Base-T Ethernet, several serial ports, supports removable media in the form of both SD cards and USB drives, and has a JTAG debugging port.

In upcoming articles I'll describe the AT91RM9200-EK in detail, and discuss how to get Linux running on it.

No comments: