Getting started

Right now, you have to manually find and download all the needed dependancies. A script will hopefully be written someday to automate downloading and patching all the files.

Use the Atmel SAM9N12 linux4sam page for a general overview of the build process.


A few years later this board was brought up again with the intention of using the most recent versions of mainline linux and new tools to help streamline the process. This can be read here How to set up the board using the old way via this readme has been kept because it shows how to set everything up by hand and therefore still presents useful information.

Dataflash (like SPI NOR flash) is attached to the SPI bus from the chip to the SPI bus pads while also using it's own board. DRAM is also underclocked to 100 Mhz instead of 133 Mhz via the main system bus downclock, causing the processor to run at 300 Mhz instead of 400 Mhz. AT91 Bootstrap and U-Boot are located on dataflash at 0x00 and 0x8400 respectively, with U-Boot pulling the kernel from a flash drive connected via USB OTG as well. The kernel then pulls the rootfs off the flash drive in a dedicated ext2 rootfs as rw (read write). GCC has been cross compiled to this board and compiles programs correctly, so this board was used for completion of the project.

Boot process

  • NVM bootloader: Primary bootloader which searches for executable code via Arm exception vectors on NAND and Dataflash and elsewhere except USB.
  • AT91bootstrap: Secondary bootloader which setups up DRAM and puts the next executable code (again, via ARM exception vectors) into DRAM.
  • U-Boot: Third bootloader for loading the linux kernel off USB and into memory while passing proper kernel boot arguments.
  • Linux Kernel: Indended application, runs the rootfs off USB (not copied into memory).


The NVM bootloader exists in ROM on the SAM9N12 and is the first thing executed upon powerup. This searches in for possible bootable storage mediums such as NAND, Dataflash, SPI, and others except USB, as well as sets up the serial port. If nothing was found then it starts up SAM-BA, which lets the SAM-BA client on a desktop to issue commands to the SAM9N12 over USB, this is used for writing both AT91 bootstrap and U-Boot to onboard dataflash.

Next up is the AT91 bootloader which does pretty much the same as the NVM bootloader but also sets up DRAM. Keep in mind that even if DRAM seems to work via SAM-BA, it does NOT mean that it will work also via the at91 bootloader, memory timings were needed to be modified (relaxed) and clock lowered by 33 Mhz to get DRAM working. This sits in Dataflash at 0x00 which in this case is a 8 megabit chip. Some memory testing routines were added to this. Keep in mind that the endianess of this is NOT the same as most x86 systems, nibble swapping is done in the memory testing routines when printing.

U-Boot sits in dataflash at 0x8400 and sets up USB host, reads the DOS partition table for the first partition (FAT) loads uiamge.bin which is the kernel into memory at 0x00, and lastly passes control to the kernel as well as passing boot arguments which are added via compile time. MDT-tools can be used for passing storage mediums information to the kernel but I didn't use it since it just sucks. Enviroment variables such as boot media can be supplied via a text file on USB but it seems we can't initialize USB before reading this file.

The linux kernel does it's magic setting up cache and the MMU and all that jazz, and then loads the root filesystem from USB partition 2 as an ext2 filesystem but ext4 could be used if enabled in the kernel during compilation. The kernel then looks for /bin/init which baisically tells busybox to call /etc/inittab that tells the system what to do upon a restart/shutdown/ctrl-alt-del/respawn/sysinit. Sysinit tells to check /etc/init.d/rcS which handles telling the kernel to fill /proc and /sys. A small 5 megabyte ramfs is also made at this step as per rcS, afterwards the ash shell is started which is a very small alternative to bash while lacking some tools.

Root filesystem.

Busybox is a very awesome tool which lets you combine tools like ls, cat, mount, ln, etc into one executable for memory savings and simplicity. Busybox during make install makes an _install dir that holds the rootfs containing symbolic links to the single busybox executable, allowing calling these tools normally. The single executable can also just be copied into /bin without any symbolic links (assuming static compilation) with the tools called by doing busybox tool. Busybox can also handle an inittab for you, but it assumes that there are serial ports which aren't there, which spams the serial port every 250 milliseconds saying it didn't find them. Supplying an inittab without those serial port declerations fixes this.

A small 5 megabyte ram file system is made via rcS but it isn't needed and is a remenant of when I used to mount the rootfs as read only. You can write to it using dd and whatnot to do rough memory tests or writing quickly changing data without wearing down flash.

GCC is included in the rootfs at /usr/home/arm-none-linux-gnueabi/ which has been cross compiled to run on this board, as well as a hello world source file at /usr/home/hello-world/. Compiling the hello world takes a solid 5 or so seconds, a lot more if any sort of optimizations are enabled.

Libraries are also included in /lib which are required by busybox if busybox isn't statically compiled. GCC has it's own copy of these libraries in /usr/home/arm-none-linux-gnueabi/arm-none-linux-gnueabi/rootfs/ which are used during static compilation by GCC as well as for the dynamic linker. Since gcc was not statically compiled, it also uses the libraries in /lib. The libraries to put in /lib should be copied from the gcc cross-compiler's rootfs/lib/ folder.


Crosstools-NG was indespensable for handling all toolchain issues. While ARM do offer their version of GCC on Launchpad which includes pending additions to mainline GCC, it is preferrable to make a custom cross-compiler to select what standard c library to use. Crosstools-NG can properly compile a cross compiler as well as handling the chicken and egg problem with the c library and compiler, but it takes a solid 30 minutes to make a cross-compiler. Then, using a Canadian Build (cross-native isn't currently supported), a cross-native compiler is compiled with the target tuple being the previously compiled cross-compiler, which takes roughly 45 minutes. In total, compiling a cross compiler and then a cross-native compiler using a normal build and then canadian build respectivly, takes roughly an hour and fifteen minutes.

Resources blob from OneTab

results matching ""

    No results matching ""