When developing on an embedded device, it is typical that actual software is built on a host PC, and then tested on the embedded system. However this requires that the software be downloaded from the Host PC to the embedded device for every test - which can be quite time consuming. On smaller devices, a programming dongle is typically used to push the entire code base onto the device via a debugger (such as a JTAG device). However when using larger embedded devices this is generally not practical, as the entire suite of software may be many tens, or hundreds, of megabytes in size.
When developing for a Linux-based embedded platform, where ethernet networking is available, there is a very quick method of development called 'NFS Root'. This uses the standard Unix NFS system to export the Linux root filesystem to the device, allowing it to be easily shared between your host PC, and the embedded device. Using this same protocol it is also possible to download the Linux kernel on boot up from a server, making kernel upgardes/testing equally easy.
Using a network attached root filesystem also allows multiple devices to share a common code base, limiting the possibility that changes are not propagated from one development area to another.
Contents |
NFS Server
To set up an NFS server, first install the server software. If using a modern Linux distribution, this will typically be in a package called 'nfs-kernel-server'. For example, on Ubuntu this can be installed via:
user@machine:~$ sudo apt-get install nfs-kernel-server
Once installed, the NFS server is configured via the /etc/exports file. Ensure it has a line similar to the following:
/export 192.168.2.0/255.255.255.0(rw,sync,no_subtree_check,no_root_squash)
This allows the /export directory to be mounted by anything on the 192.168.2.X network. The options after that allow read/write access, and also allow remote machines to access this as the 'root' user. This is a requirement when a remote system is going to use the export for its root filesystem. Once this file is correct, the server will need to be restarted to apply the latest config.
user@machine:~$ sudo /etc/init.d/nfs-kernel-server restart
Network access
When mounting an NFS share, the NFS server will typically do a reverse DNS look-up on the client. Unfortunately, if you do not have a full DNS server set-up on your network, this can result in a DNS timeout, which in turn will cause the NFS mount to fail. To avoid this problem, the simplest solution is to ensure that there is an entry in the /etc/hosts file for each of your client devices. This entry should look like this:
192.168.2.200 snapper
This associates the 192.168.2.200 IP address with the 'snapper' name, and will prevent DNS resolution timeouts.
Installing the filesystem
Once the NFS server is correctly set up, a root filesystem must be unpacked into the exported directory for the client systems to use. For the Bluewater Snapper modules, our minimal root filesystem is available here. Once downloaded, this file should be unpacked into /export.
andre@tutira:~$ cd /export
andre@tutira:~$ wget http://www.bluewatersys.com/public/linux/root.tar.gz
--15:34:25-- http://www.bluewatersys.com/public/linux/root.tar.gz
=> `root.tar.gz'
Resolving www.bluewatersys.com... 69.89.21.90
Connecting to www.bluewatersys.com|69.89.21.90|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2,331,793 (2.2M) [application/x-gzip]
100%[====================================>] 2,331,793 56.31K/s ETA 00:00
15:35:01 (63.87 KB/s) - `root.tar.gz' saved [2331793/2331793]
andre@tutira:~$ cd /export
andre@tutira:/export$ sudo tar xfz ~/root.tar.gz
[sudo] password for andre:
andre@tutira:/export$ ls
busybox-root/
andre@tutira:/export$ ls -l busybox-root/
total 48
drwxrwsr-x 2 andre public 4096 Oct 20 19:54 bin/
drwxrwsr-x 3 andre public 4096 Oct 20 19:54 boot/
drwxrwsr-x 6 andre public 4096 Oct 20 19:54 dev/
drwxrwsr-x 3 andre public 4096 Oct 20 19:54 etc/
drwxrwsr-x 2 andre public 4096 Oct 20 19:54 home/
drwxrwsr-x 2 andre public 4096 Oct 20 19:54 lib/
lrwxrwxrwx 1 andre public 11 Oct 21 15:35 linuxrc -> bin/busybox*
drwxrwsr-x 2 andre public 4096 Oct 20 19:54 mnt/
drwxrwsr-x 2 andre public 4096 Oct 20 19:54 proc/
drwxrwsr-x 2 andre public 4096 Oct 20 19:54 sbin/
drwxrwsr-x 2 andre public 4096 Oct 20 19:54 sys/
lrwxrwxrwx 1 andre public 8 Oct 21 15:35 tmp -> /var/tmp/
drwxrwsr-x 6 andre public 4096 Oct 20 19:54 usr/
drwxrwsr-x 4 andre public 4096 Oct 20 19:54 var/
andre@tutira:/export$ sudo mv busybox-root/ root
Once this is done, a fully bootable root filesystem is available under /export/root.
Installing a Linux Kernel
Generally when using network booting it is desirable to also boot the kernel from the network as well. This means that the state of the local storage on the module is not important, meaning it can be freely re-written for test purposes, without interfering with the running of the system.
See the Linux Kernel page for more details on modifying the Linux kernel.
Once an appropriate uImage file is available, place this into /export/root along with the root filesystem.
andre@tutira:/export/root$ cp ~/snapper/linux-2.6.20/arch/arm/boot/uImage .
Note: Although the Linux Kernel & filesystem areas are not touched during network booting, Bootloader areas are still vital to booting the unit, and should not be modified
Linux boot command-line changes
To instruct the Linux kernel to use the NFS server for its root filesystem, some changes must be made to the Linux kernel command line.
All Bluewater snapper modules come with a set of scripts in the U-Boot environment to cover various boot methods. For NFS booting there are two available options:
- nfs_boot - this will load a kernel from an NFS server, and then boot using an NFS mounted root filesystem. The IP address is statically configured using the 'ipaddr', 'gateway', 'serverip' environment variables.
- dhcp_boot - this will load a kernel from a TFTP server, and then boot using an NFS mounted root filesystem. The IP address will be determined via a DHCP request.
Note: By default, the Snapper modules look for a kernel called uImage-model-serial, ie: uImage-9260-103. The uImage file created previously may need to be renamed as appropriate.
The following examples assume you have a working network with the appropriate servers running (DHCP, TFTP, NFS).
To use either of these boot options, use the U-Boot 'run' command:
Snapper> run dhcp_boot
BOOTP broadcast 1
DHCP client bound to address 192.168.2.182
TFTP from server 192.168.2.2; our IP address is 192.168.2.182
Filename '/tftpboot/snapper/uImage-cl15-59'.
Load address: 0xc0000000
Loading: 1787kB: ############################################################
############################################################
########
done
Bytes transferred = 1830200 (1bed38 hex)
## Booting image at c0000000 ...
Image Name: Linux-2.6.20-snapper 23:15:45 20
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 1830136 Bytes = 1.7 MB
Load Address: c0008000
Entry Point: c0008000
Verifying Checksum ... OK
OK
Starting kernel ...
Uncompressing Linux................................................................
......................................................... done, booting the kernel.
If the pre-installed scripts have been lost the following commands can be used to boot the unit of the network.
NFS Boot:
Snapper> setenv ipaddr 192.168.2.200 Snapper> setenv serverip 192.168.2.25 Snapper> setenv gateway 192.168.2.254 Snapper> setenv netmask 255.255.255.0 Snapper> nfs 0x23f00000 $serverip:/export/root/uImage Snapper> setenv bootargs 'console=ttyS0,115200 ip=$ipaddr:$serverip:$gateway:$netmask:snapper:eth0:off nfsroot=/export/root,v3,rsize=1024,wsize=1024' Snapper> bootm
DHCP Boot:
Snapper> setenv bootaddr 0x23000000 Snapper> setenv bootfile /tftp_path_to_uImage/uImage Snapper> bootp Snapper> setenv bootargs 'console=ttyS0,115200 ip=any nfsroot=/export/root,v3,rsize=1024,wsize=1024' Snapper> bootm



