A 32 bit single board computer

Self made computer

My student research project was programming a bootloader and patching the Linux kernel and a root filesystem in a way that an Atmel AT91RM9200 based microcontroller board does not only boot without problems, but is also a nice environment for applications. The following text will give you a short introduction.

The Atmel AT91RM9200 microcontroller is based on the ARM9 CPU. This is a very powerful RISC CPU design that includes a MMU. This is a very good precondition for installing a unix like operating system as the MMU provides the virtualization and memory protection.

In the meantime the research project in the department OMI is finished. It is available for download now.


The following image of the board gives an impression of the boards population with electronic devices. It is a 4 layer board and electronic devices are mounted on top and bottom side.

[Top side]

The above image shows the top side. You can spot the important components (from left to right): CF socket with wireless LAN CF card, bus drivers, the AT91RM9200 microcontroller itself and on the rightmost side the power supply. In the front part of the image you'll see the USB and RS-232 connectors and the ethernet port. I did solder all the components for myself, including passive components and the PHY controller. The PHY controller is a Micrel KS8721, I added support for it in the Linux kernel.

The bottom side includes most of the passive circuitry and smaller active ciruits. Additionally 32 MiByte SDRAM and 8 MiByte are to be found there. I made an image of the bottom side, that I'll show here:

[Bottom side]

and software

the software is even more interesting. The software consists of two main parts:


The first part must be programmed in parts by myself. This part is the bootloader that initializes the hardware and configures the microcontroller. In prinziple there are already existing bootloaders for the ARM cpu, e.g. uBoot or BLOB. Unfortunatly these bootloaders only boot from a normal flash memory. My bootloader doesn't require preprogramming the onboard flash but can be downloaded directly via the RS-232 port using the boot-uploader of the AT91RM9200 microcontroller. The bootloader loads the Linuxkernel from compact flash into SDRAM main memory. Currently also an initrd is read from the compact flash card. Before loading the Linux kernel the to be used mac address of the ethernet port is read from nvram. The last 64 KiByte of the integrated flash memory are used as nvram. I made this quite similar as it is in the openwrt/linksys routers.

To make the handling with the compact flash cards easy the bootloader understands the partition table that is used by PC hardware. The Linux kernel is loaded from the first found, primary, bootable partition with type 0xda.

Linux Kernel

Of course, the Linux kernel is able to access compact flash cards directly using the IDE driver after booting.

As all data is known by reading data from the partition table used by the compact flash the kernel parameters are generated automatically by the bootloader. If a compact flash card containing the "right" data, Linux kernel zImage on bootable primary partition with type 0xda and valid root filesystem it is loaded and started immediatly. If one of the conditions is not met the prompt of the bootloader is shown and the start can be done later.

Starting a Linux kernel on an ARM based system is quite different to starting Linux on an IBM compatible PC. As there are many, many different ARM based platforms (Handheld PCs, Acorn Archimedes and additionally a lot of embedded systems) it is required to fill a special structure before starting the system. This structure holds information about memory size and position, physical position of an initrd in main memory and more. Many of the parameters could also be given via Linux command line options, but this way it is easier to handle for the user.

It's not only required to fill a structure (called ATAG list) but also necessary to supply the machine type when starting the Linux kernel. The machine type tells the Linux kernel which hardware is there. (The information is later on available in /proc/cpuinfo). It's important to compile the kernel with support for the machine type, otherwise the system wont boot, in the worst case without saying anything.

Root Filesystem

The initrd holds a complete minimum system that is based on the buildroot environment of the uClibc. With the help of the Open Source GNU tools gcc, binutils and the uClibc a toolchain is generated that is able to compile software for the root filesystem of the ARM based computer system.

After generating the toolchain itself, it's not only possible to compile the Linux kernel but also the software of the root file system. The base software used is busybox, a universal tool holding the most important Linux base tools in one single application.

Starting the system

These are the boot messages of my system:

Loading 0x000F96FC bytes kernel code.
Loading 0x002FB000 bytes of initrd
Uncompressing Linux...................................................... done, bo[...]
Linux version (carsten@quines) 
       (gcc version 3.4.2) #17 Tue Jul 4 11:51:10 CEST 2006
CPU: ARM920Tid(wb) [41129200] revision 0 (ARMv4T)
Machine: Atmel AT91RM9200 (OMI car control board)
Memory policy: ECC disabled, Data cache writeback
On node 0 totalpages: 8192
  DMA zone: 8192 pages, LIFO batch:1
Clocks: CPU 179 MHz, master 59 MHz, main 18.432 MHz
CPU0: D VIVT write-back cache
CPU0: I cache: 16384 bytes, associativity 64, 32 byte lines, 8 sets
CPU0: D cache: 16384 bytes, associativity 64, 32 byte lines, 8 sets
Built 1 zonelists
Kernel command line: console=ttyS0,115200 root=/dev/mtdblock2 
       rootfstype=jffs2 mtdparts=phys_mapped_flash:64K(boot),1536K(linux),6528K(root),64K(nvram)
AT91: 96 gpio irqs in 3 banks
PID hash table entries: 256 (order: 8, 1024 bytes)
Console: colour dummy device 80x30
Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)
Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)
Memory: 32MB = 32MB total
Memory: 29824KB available (1988K code, 521K data, 88K init)
Calibrating delay loop... 89.49 BogoMIPS (lpj=447488)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
NET: Registered protocol family 16
NET: Registered protocol family 2
IP route cache hash table entries: 256 (order: -2, 1024 bytes)
TCP established hash table entries: 1024 (order: 0, 4096 bytes)
TCP bind hash table entries: 512 (order: -1, 2048 bytes)
TCP: Hash tables configured (established 1024 bind 512)
TCP reno registered
NetWinder Floating Point Emulator V0.97 (extended precision)
audit: initializing netlink socket (disabled)
audit(0.450:1): initialized
JFFS2 version 2.2. (NAND) (C) 2001-2003 Red Hat, Inc.
Initializing Cryptographic API
io scheduler noop registered
io scheduler anticipatory registered (default)
io scheduler deadline registered
io scheduler cfq registered
AT91 SPI driver loaded
at91_usart.0: ttyS0 at MMIO 0xfefff200 (irq = 1) is a AT91_SERIAL
at91_usart.1: ttyS1 at MMIO 0xfffc4000 (irq = 7) is a AT91_SERIAL
at91_usart.2: ttyS2 at MMIO 0xfffc0000 (irq = 6) is a AT91_SERIAL
RAMDISK driver initialized: 16 RAM disks of 64000K size 1024 blocksize
loop: loaded (max 8 devices)
eth0: Link now 100-FullDuplex
eth0: AT91 ethernet at 0xfefbc000 int=24 100-FullDuplex (00:30:05:19:72:01)
eth0: Micrel KS8721 PHY
physmap flash device: 800000 at 10000000
phys_mapped_flash: Found 1 x16 devices at 0x0 in 16-bit bank
 Amd/Fujitsu Extended Query Table at 0x0040
number of CFI chips: 1
cfi_cmdset_0002: Disabling erase-suspend-program due to code brokenness.
4 cmdlinepart partitions found on MTD device phys_mapped_flash
Creating 4 MTD partitions on "phys_mapped_flash":
0x00000000-0x00010000 : "boot"
0x00010000-0x00190000 : "linux"
0x00190000-0x007f0000 : "root"
0x007f0000-0x00800000 : "nvram"
mice: PS/2 mouse device common for all mice
TCP bic registered
NET: Registered protocol family 1
NET: Registered protocol family 17
VFS: Mounted root (jffs2 filesystem) readonly.
[root@babbage /root]# uname -a
Linux babbage #17 Tue Jul 4 11:51:10 CEST 2006 armv4tl unknown

© Carsten Groß - last change 08.03.2008 10:38