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
In the meantime the research project in the department
finished. It is available for download
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.
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
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:
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.
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.
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
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.
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
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 22.214.171.124-at91rm9200 (carsten@quines)
(gcc version 3.4.2) #17 Tue Jul 4 11:51:10 CEST 2006
CPU: ARM920Tid(wb)  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
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)
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 126.96.36.199-at91rm9200 #17 Tue Jul 4 11:51:10 CEST 2006 armv4tl unknown