pingswept.org
now with web 1.0 again

November 20, 2010

Building a custom AT91 bootloader with AT91Bootstrap

Rascal development is continuing at a furious pace. Rascal 0.4, which has a cheaper, more awesome memory arrangement than previous versions, arrived from the assembler recently. I've been working on rebuilding the bootloaders properly so they work with the new memory. To do this I've had to understand some of the details of Atmel's bootloader, AT91Bootstrap. For the benefit of the internet, and for my own benefit once I pass into the shadowlands beyond the bounds of my short-term memory (next week), I thought I should record the details here.

(For those readers whose eyes are beginning to glaze over, have no fear. You don't need to know this stuff to use the Rascal. Go back to your web browsing.)

Rascal memory setup

Let's start with a little background about the Rascal's memory setup.

The Rascal has four pools of memory on board. Two of them, a tiny chunk of RAM in the processor and two 32 MB external RAM chips, lose their contents when the board is unplugged. The other two are nonvolatile, i.e. they remember their contents even when powered down. One of the two nonvolatile memory elements is a microSD card. It can hold several GB of data, which is enough for an operating system and a lot of datalogging. The other is a small, simple chip called a serial flash, only 4 MB in size. (In 2010, fancy cameras take pictures that won't fit in 4 MB, so I think "small" is fair.) The serial flash holds all the code other than the filesystem that the Rascal needs to start operating-- bootloaders and the Linux kernel. This is the code that you don't want to mess with unless you know what you're doing.

The first code that gets read out of the serial flash is called AT91Bootstrap. It loads a general-purpose bootloader called U-boot, which loads, decompresses, and runs the Linux kernel. I could make it so that AT91Bootstrap loaded Linux directly, but U-boot makes things a little easier for programmers like me by letting us load new kernels through the Ethernet port, or move code around from one part of memory to another.

For reasons that I don't get, Atmel has released two different branches of AT91Bootstrap. One is the version that you find if you google "AT91Bootstrap" and click on the first link. However, for several of their more powerful processors, Atmel provides versions of AT91Bootstrap that have more code for talking to different peripherals. These expanded versions are contained within what Atmel calls the "Software Package" for each chip. For the Rascal's AT91SAM9G20, I'm building AT91Bootstrap from the revision C software package. Within that zip file, there is a smaller file called at91bootstrap-at91sam9g20-ek-gnu.zip that contains AT91Bootstrap.

The documentation provided by Atmel is a little weak, containing aspiring sentences like, "By default, this array contains only one line whose all data is C precompilator defines." ("Precompilator" is almost a word in French; I think a lot of the work for the AT91 chips happens at the Atmel office just west of Versailles, France (you can just make out the Atmel logo on the sign).)

To build the bootloader, I used the 2010q1 release of the CodeSourcery arm-none-eabi toolchain. The "none" means that the binary is being built for use without an operating system; the "eabi" means that the executable will use the standard compilation conventions for ARM processors.

The build command

Atmel provides a peculiar build script in the software package-- even though the package is specific to the AT91SAM9G20, it builds binaries for a long list of Atmel processors. The script is aptly named make_all.

To build the bootloader for the Rascal, you can customize this script, but I found it easier to just copy out the command used to build the Rascal code and forget the rest.

The structure of the build command is: make [lots of flags to the compiler] clean all, which basically means "clean out the old binaries and make new ones with these options."

Some of the flags are mandatory; some are optional. The details are below.

Mandatory

Mandatory, but not necessarily on the command line

These flags are only given on the command line if there is only one module to load. If there is more than one module to load, you need to modify the array tabDesc in boot.h.

Optional

Optional but not very interesting

Here's the command that I've been using for the Rascal.

language-bash make CHIP=at91sam9g20 BOARD=at91sam9g20-ek ORIGIN=serialflash DESTINATION=sdram BIN\_SIZE=0x30000 FROM\_ADDR=0x10000 DEST\_ADDR=0x23F00000 TRACE\_LEVEL=5 clean all

If you don't provide a name for the output file as BOOTNAME, one will be constructed for you from the options you've supplied. In the case of the Rascal, the auto-generated binary name will be boot-at91sam9g20-ek-serialflash2sdram.elf or .bin.

The last step

Once you've compiled the program, you load it onto the processor via a JTAG pod. There are a few ways of doing this. If you just want to test the code, you can use the executable in ELF format, which can be loaded with GDB. If the code works, you'll want to copy the raw binary (not the ELF file) to the serial flash with Atmel's "boot assistant," SAM-BA.

Unfortunately, there is a catch. To make the AT91SAM9G20 acknowledge the binary as valid, it requires valid ARM interrupt vectors in the first seven 32-bit words of the binary. The compiler takes care of this for you, but there is one exception: the sixth vector. The sixth vector must contain the size of the binary in hex. (There might be a way to get the compiler to do this for you, but I don't know of one.) Thus, you have to edit the binary size with a hex editor to make the processor recognize it as a valid boot program.

November 01, 2010

Rascal 0.4 with Arduinos and shields

I just received the next revision of the Rascal (0.4); the boards should be assembled by next week.

Like the previous versions, the new Rascal can mate with most Arduino shields. I haven't tested them all, and they're not all supported in software yet, but mechanically, they fit together. Unlike the older boards, the new Rascal can also talk to an Arduino, which itself can connect to a shield of its own.

The idea here is to let the Arduino and the Rascal each play to their strengths. The Arduino is cheap and easy to program, but not powerful enough to run a full operating system. It's great for reading sensors and controlling motors, but lousy for serving web pages or running a filesystem. The Rascal, on the other hand, can do all of that more advanced stuff. Unfortunately, this makes the Rascal bad for tasks where instantaneous responses are needed, like controlling a motor. For example, a Rascal would do a lousy job of running a CNC machine-- the machine would jitter every time someone requested a page from the webserver.

The combination of the two is powerful-- the Rascal acts as the interface to the outside world, the datalogger, the supervisor of the Arduino. The Arduino runs in a tight loop, receiving instructions from the Rascal over a serial port, and then driving the motors with precision. There's some overlap, of course. The Arduino, with the right shield, can serve simple webpages or store data to an SD card. Similarly, the Rascal can toggle digital outputs and read sensors as well.

That's the concept for how the devices work together. The mechanical interaction is shown below. The Arduino plugs in underneath the Rascal. Shields can attach in two places-- in the left position, they connect to the Rascal; in the right, they connect to the Arduino.

October 21, 2010

Finding the Rascal

One unusual function of the Rascal blog is to document publicly the plans I have for the Rascal as a defense against patents.

Why don't I patent these ideas myself? The average time for a patent to issue is 6 years; the cost is somewhere around $10,000. These ideas aren't the core of the Rascal-- they're components of a larger design.

In the mechanical realm, it's realistic to think that someone could devise a clever way of joining two cylindrical shafts (like the Trantorque, US patent 4202644, 1980) and become the exclusive supplier of "keyless bushings" to the shaft couplers of the world. In the realm of software, it is not reasonable to think that someone might become the exclusive supplier of a certain sorting algorithm. There's the additional wrinkle that algorithms can't be patented directly; you have to patent a device that performs the algorithm. On top of all that, if I wanted to take software patents seriously, I'd need to read a lot of them, which means that any subsequent infringements would incur triple damages.

I'm trying to build a movement, not a secret club, so I'm going to do what all the programmers I know do, which is ignore the broken system and hope it changes before it affects me. (There are probably programmers at large companies that behave differently, but I don't know them.) I talked with a gentleman a few months ago who is one of the directors at the MIT Technology Licensing Office; I was heartened by his assertion that MIT doesn't license software patents, it generally doesn't pursue patents unless they suspect that they're licensable, and they don't renew patents that haven't been licensed in the first couple of years after issuing.

But enough about patents-- the real point of this post is to explain what I'm planning to detect Rascals on a network.

When you buy a small computer with an Ethernet port, like a Gumstix or some other embedded Linux board, you have to figure out how to find it on your network. You plug the device into your network with an Ethernet cable and power it up. Most of these devices send out what's called a "DHCP request." (DHCP stands for Dynamic Host Configuration Protocol.) The request goes out to all of the computers on the local network. One of the computers, usually some server in the basement, is in charge of handing out IP addresses to new arrivals. It sends back a packet that contains the IP address that your computer should use.

The unfortunate part is that you can't see internet traffic with the naked eye, so even though your device now has an address, you don't know what it is. There are a few solutions. You can use a program like nmap to scan the network to see what computers exist, and then try them one by one. If you have a computer that comes with a Zeroconf implementation installed, i.e. a computer not running Windows, you might be able to use that to detect the new device. You could install and use Apple's Zeroconf implementation for Windows. You could also connect your new device to a hub that repeats all incoming traffic on all ports and use a packet sniffer like Wireshark to listen for the IP assignment response from the DHCP server.

These are all painful techniques for normal people.

My intent is to make the Rascal reveal its identity more easily. What follows is the plan I'm thinking of using, but it's still in pre-natal condition. Better ideas are welcome. When you plug in a Rascal, it gets an IP address like any other device. After it receives an address, it starts sending packets periodically to a server running at ip.rascalmicro.com (doesn't exist yet). The packet contains the serial number and ip address of the Rascal. Upon receiving the packet, the server adds the IP address to a database, which you can search for on the Rascal Micro website using the serial number as the key. This links you to a page that tells you the IP address.

From there, you connect directly to your Rascal. If you want, you can add a static IP address for your Rascal, so you don't have to go through this again. (You can also configure your DHCP server to always give your Rascal the same IP address, but that means mucking around with your DHCP server. The DHCP server can identify the Rascal, or any computer, by its unique Ethernet MAC address.)

October 18, 2010

Adding a microSD card to the Rascal

I've decided that it's time to get rid of the NAND flash chip on the Rascal. The new idea is that the Rascal will have a microSD card slot on it. The bootloaders and the Linux kernel will continue to reside on the serial flash, but the filesystem, which previously lived on the NAND flash, will instead live on the microSD card. This means that we can start to develop different filesystems preconfigured for different applications. If you want to switch from one configuration to another, you just swap out the microSD card and reboot.

SD cards are just NAND flash chips packaged with a memory controller. They have several advantages: the memory controller takes care of correcting errors common to NAND flash and can probably do some caching of recent data. Also, SD cards are something like 10x cheaper per byte than NAND flash (because I can't buy NAND flash in quantities of 10 million). Furthermore, there are lots of sources of standard cards; I don't have to worry about sourcing a single chip. There's also the modularity of the system-- being able to swap out the filesystem by mechanical means is just beautiful.

The disadvantage is that at a basic level, microSD cards use a 4-bit bus, while the NAND flash on the Rascal uses an 8-bit bus. Even if the clocking limit on the two buses were identical, a microSD card has to be half as fast as NAND flash, and in reality, you probably can't clock a card as fast because of the connector in the circuit. The AT91SAM9G20 MCI controller, which is what talks to the card, peaks at 25 MHz, while the NAND flash can in theory handle 50 MHz. But I suspect all of these metrics are swamped by considerations like how your data is stored. I've seen a decent embedded Linux system that took 2 seconds to serve a 20 kB web page off of an SD card, but that could could be caused by all sorts of different things-- maybe each byte was stored in a different block of memory, or something like that.

Once a filesystem is loaded onto an SD card, it behaves transparently to the rest of the world, but writing a new filesystem to a card can be a dangerous process, as I learned a few years ago. I was trying to write a filesystem image to the microSD card pictured above using the Linux command "dd," which is used to copy bytes from one place to another. It's a dangerous command.

I think I typed something like:

language-bash dd if=/sd-card-image.bin of=/dev/sda1

I thought that I was copying the 256 MB filesystem image to the SD card at /dev/sdb1, but I accidentally hit sda1 rather than sdb1. Unfortunately, this copied the image over the first 256 MB of my hard drive, which I believe includes valuable elements like the master boot record. At the time, I thought, "Ohhh, this could be bad," but my computer kept working, so I forgot about it.

A few weeks later, I tried to reboot my computer; it failed utterly. After lots of mucking around, but no remembering of my previous error, I ended up on the phone with Linux support at Dell. They had me run hardware diagnostics; the drive passed with no errors. Eventually, they sent me a replacement hard drive in the mail. A few hours after hanging up, I was thinking about trying a fresh install of Linux, which got me thinking about wiping the master boot record, which reminded me of the SD card incident.

In the end, I offered to return the drive to Dell, but they refused.

older postsnewer posts