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.


  1. I was able to achieve a similar boot process by setting some environment variables in NAND:

    After copying the boot image to the first FAT partition on the SD card, and the rest of the OS to an ext3 partition (I used Ubuntu, but I think this will work with Angstrom) I halted the boot process and entered:

    setenv bootcmd 'mmc init; fatload mmc 0:1 0x80300000 uImage; bootm 0x80300000'

    setenv bootargs 'console=ttyS2,115200n8 console=tty0 root=/dev/mmcblk0p2 rootwait rootfstype=ext3 ro omapfb.mode=dvi:1280x720MR-16@60'



  2. Thanks! Great post on your blog. I've bookmarked it for future reference.