Friday, October 30, 2009

Adventures in NAND Land

In a previous post, I talked about setting up an SD card to boot Ångström on the BeagleBoard. One thing that has been bugging me is that I need to hold the USER button on the BeagleBoard in order to boot to the SD card. If I don't do this, it boots partway, but stops before the kernel is loaded. What's going on here, and what can we do about it?

A great starting point if you have questions like this is the OMAP35x Technical Reference Manual. This sprawling document holds the answers to a lot of BeagleBoard questions. Of particular interest is Chapter 25, which details the intialization process. The basic steps of initialization are as follows:
  1. Preinitialization
  2. Power/clock/reset ramp sequence
  3. Boot ROM
  4. Bootloader
  5. OS/application
The USER button on the BeagleBoard controls the state of the SYS.BOOT[5] pin on the OMAP3530. The boot ROM uses this value to decide between one of two boot orders:
  • NAND, USB, UART3, MMC1, if the button is not pressed
  • USB, UART3, MMC1, NAND, if the button is pressed
Once the boot order is selected, the boot ROM goes through the devices in that order, looking for one that is bootable. Once it locates a bootable device, the boot ROM copies the bootloader from the device to on-chip memory and executes it.

To understand the bootloader, it's worth taking a closer look at the Linux boot process, which looks roughly like this:
  1. System startup
  2. Stage 1 bootloader
  3. Stage 2 bootloader
  4. Kernel
  5. Init
You can see there is some overlap with the initialization process above. Step 1 here combines the first three steps of the initialization process; steps 2 and 3 elaborate on step 4 above; and steps 4 and 5 here correspond with step 5 above.

The first-stage bootloader must be small enough to fit in the OMAP3530's on-chip memory. Remember, at this point the device has not initialized external memory, so it has only 64 kB of SRAM to work with. Our first-stage bootloader is called "X-Loader". A signed copy of X-Loader, called "MLO", is the first thing we copied onto the SD card when we set up Ångström. The first-stage bootloader initializes external memory, copies the secont-stage bootloader into memory, and executes it.

Our second-stage bootloader is called "U-Boot". Its job is to load the kernel and root filesystem. On our bootable SD card, "uImage" is the kernel image, and the second partition is our root filesystem.

Now that we understand the contents of the SD card a little better, we can return to the main question: How can we avoid having to hold the USER button on every boot?

My first thought was, if the boot ROM is looking in NAND first, why don't we just put the whole system there, instead of on the SD card? I had come across an article which describes how to do exactly that, so it seemed like a sensible enough starting point.

Ultimately, however, I had some difficulty installing MTD utils. I later discovered that a stable tarball could be found here, but the hiccup stalled me just long enough to wonder, is it even a good idea to put all of this in NAND?

Talking with other developers on the #beagle IRC channel, I realized that the main reason to put the system in NAND is to operate without an SD card attached. This may be useful in a production environment, but for development purposes, the general wisdom seems to be that keeping the bootloaders, kernel, and filesystem on the SD card increases flexibility.

So, why wasn't the SD card we prepared previously booting without the USER button depressed? On the BeagleBoard, the OMAP3530's NAND is partitioned as follows:
  • 0x00000000 to 0x00080000: X-Loader
  • 0x00080000 to 0x00260000: U-Boot
  • 0x00260000 to 0x00280000: U-Boot environment
  • 0x00280000 to 0x00680000: Kernel
  • 0x00680000 to 0x10000000: Filesystem
Without the USER button pressed, the boot ROM will always check NAND first, to see if it's bootable. To ensure that NAND would not be recognized as bootable, erase the contents of the first NAND partition as follows:
  1. Reset the BeagleBoard.
  2. When U-Boot comes up, hit a key to stop autoboot.
  3. At the prompt, enter "nand erase 0 80000".
This will erase the contents of the X-Loader partition. For good measure, you can also erase the contents of the U-Boot environment using "nand erase 260000 20000". The next time it loads, U-Boot will replace the environment settings with defaults.

Finally, it is necessary to update U-Boot's "bootargs" and "bootcmd" as noted on the BeagleBoardBeginners page. With an Ångström SD card in place and the first NAND partition erased, the BeagleBoard now boots from the SD card without the need to hold the USER button down.

Tuesday, October 27, 2009

Git Repository Added

We've been working on BRB with the aim of competing in SparkFun's Autonomous Vehicle Competition. Alas, it looks like we'll be on Baffin Island the day of the competition, so we'll be unable to participate. Nevertheless, we are going to forge ahead, and hopefully will be that much more prepared for the 2011 competition!

I have set up a repository at GitHub, where we plan to keep up-to-date copies of all our schematics, board layouts, and so on. The repository currently contains CadSoft Eagle files for the interface board and the inertial sensor board.

Saturday, October 17, 2009

Introducing the BeagleBoard

Our first step in building BRB will be to put together a navigation system comprised of an IMU, a GPS, and a Kalman filter. Once BRB knows where it is, we will look into moving from place to place.

On the GPS side of things, we will be using a Topcon TG-3 100 Hz GPS which was generously donated by Topcon for another project. We hope this will give us plenty of data to work with.

For the "brains" of the vehicle, we ordered a BeagleBoard from Digi-Key. The BeagleBoard packs a pretty impressive set of features:
  • 600 MHz TI OMAP 3530 processor
  • 128 MB RAM
  • 256 MB NAND flash
  • Expansion port with I2C, SPI, UART
  • SD/MMC card slot
  • Audio, video, USB, and so on
This is arguably overkill for our project, but we wanted to be absolutely certain that we would not run short on horsepower.

One hitch in working with the BeagleBoard is that it uses 1.8 V logic levels, while our peripherals use 3.3 V. This can be overcome with a level translator IC. We've decided to put this IC, as well as a few other interface components, on a separate board. This keeps our design as modular as possible, so that if we want to change one part, we won't need to rebuild everything.

We have broken everything down into four boards, for the time being:
  • The BeagleBoard
  • The IMU board
  • The GPS receiver
  • An interface board
We sent the interface board off to BatchPCB at the same time as the IMU board, so we hope to have both back in the next couple of weeks. The interface board contains a mating connector for the BeagleBoard's expansion header, an ADG3304 level translator IC, a CAT6219 3.3 V regulator, and connectors for the IMU and GPS. The schematic is below:



In the meantime, I have been working on getting the BeagleBoard up and running. The first step is to get the Ångström Linux distribution installed. The BeagleBoard ships without cables or connectors, so the first thing to do is build a serial interface cable. These can be purchased, but they are easy enough to build.

It is possible to get Linux installed on the BeagleBoard using Windows, but support for this method is limited. I highly recommend working with Ubuntu. Much of the community support for BeagleBoard assumes you are using Linux, so things get a lot easier if you are.

Using Ubuntu, BeagleBoardBeginners is an excellent tutorial that will walk you through as far as booting Ångström from an SD card.

While running Ångström on the BeagleBoard is a fun milestone, you may wonder, how do I do anything with it? I found a few particularly illuminating links, which I would like to gather here.

The Beaglebot project includes loads of information on circuits and software needed to run a few servos and motors using a BeagleBoard. A quick browse through the source code will give you an idea of how things work. Basically, everything on the BeagleBoard is exposed as a device, and can be manipulated from the Linux shell, or using common C functions.

I spent some time looking for a program akin to "Hello World", and found a couple of helpful links:
  • A Make article showing how to blink an LED using GPIO.
  • A Google Groups post which takes this even further, showing you how to use GPIO, onboard LEDs, and buttons.
Finally, we are eventually going to need to run a bunch of these commands from within a C program. So how do you compile a C program for the BeagleBoard? You can do this from Ubuntu using Sourcery G++. To find the latest release, follow the "Download" link, then choose "GNU/Linux". Once you've installed Sourcery G++, look for the Getting Started Guide, which includes a small tutorial program.

Next, I want to write a small program to get the GPS running and log its output. We can then do some basic tests to quantify its accuracy.

Friday, October 9, 2009

The Inertial Measurement Unit

The inertial measurment unit (IMU) board for BRB is finally off to BatchPCB. The IMU will interface to a BeagleBoard, which will do the heavy lifting, by TWI.

The IMU is controlled by an ATMega168, and includes a 3-axis LIS3LV02DQ accelerometer, 3-axis gyro consisting of a single-axis LY510ALH and dual-axis LPR510AL, and a 3-axis compass consisting of a single-axis HMC1051ZL and 2-axis HMC1052L. All this for less than (or about) $100.

Schematics are below, starting with the microcontroller and accelerometer (which interfaces with the microcontroller via SPI):


then the compass (with attendant amplifiers and a MOSFET pair for setting and resetting the sensor):


and finally the gyros, for which the full scale will be selectable on the fly as either 400 degrees per second or 100 degrees per second: