Why would you want to use uClinux? There could be many reasons to consider the uClinux for your embedded OS. Some of them could be as following:
Lightweight
You
can make a complete linux 2.6 preemptible kernel image including
console and some basic device drivers and ROMFS under 300KB!
(zImage) and the applications in flat-binary format are
approximately 30~50% lighter than typical conventional linux ELF
binaries, thanks to lighter standard C and C++ libraries.
XIP
With
much smaller RAM, you can execute your kernel and even the
applications by XIP(eXecution In Place). It could help you to boot
up faster, although the access time for the flash or rom for boot
image should be fast enough and/or enough cache size. (There could
be a trade-off between those values if we want to find the optimal
balance.)
Cheaper
It
is known that the MMU core size in typical ARM SoC wafer is about
30%. In typical network or embedded systems more than a half of
applications do not need the MMU. Many of RTOS do not use MMU in
default, even if target CPU has one.
Full
Linux API
You can use the full Linux APIs on your uClinux
platform with few exceptions. You can use the pThread in uClibc and
the standard system calls. There are plenty of applications which
are ported to uClinux in the userland in uClinux distribution
package.
Easier
to adapt
One of the interesting natures of uClinux is the
possibility of user application accessing the whole system,
including registers in devices. With a bit of wrapper, we can make
the firmware code run on uClinux as a plain application! Of course,
you can add some device driver and call the linux system calls and
use many open Ips in mixed with the old firmware code. If you're
planning to migrate your firmware codes to Linux, but you're not
familiar with Linux system programming, uClinux could be a good
starting point. ;-)
Full
Linux 2.6 kernel features
Although, it is lighter, it
supports almost full features of conventional linux 2.6 kernel,
including preemptible kernel feature and so many file-systems,
device drivers. Porting of device drivers for conventional Linux is
handy. Almost all codes should be compiled without change, except
memory mapping from virtual address to physical.
If you decided to set up an uClinux development environment, this is the list that you have to grab on your linux host:
uClinux
distribution
The easiest way to get started with uClinux is
to play with a copy of uClinux-dist from the uClinux.org site
at:
http://www.uclinux.org/pub/uClinux/dist/
Note
that the kernel version in the distribution may not be the latest.
You'll be able to gather the latest patch set and the vanilla Linux
kernel from the kernel.org to make a latest copy of uClinux
kernel.
At this time (20040427), the latest distribution is
“http://www.uclinux.org/pub/uClinux/dist/uClinux-dist-20040408.tar.gz”.
If you have some strange trouble with compilation, even after
following this guide, simply use this distribution for your testing,
and update later. :-)
the
Kernel and patch
You could find the latest uClinux/ARM kernel
patch at:
http://opensrc.sec.samsung.com/
At
the download section, you'll find the link of latest
“linux-2.6.x-hscx.patch.gz”
and the original kernel package
like:
http://opensrc.sec.samsung.com/download/linux-2.6.5-hsc2.patch.gz
and
http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.5.tar.bz2
ARM-ELF
toolchain
Since the Linux 2.6 kernel code uses some of the
new features from newer binutils, you need a newer ARM-ELF toolchain
for kernel compilation than the one of uclinux.org. You could find
the latest toolchain at the same place with the kernel and patch
download section above, and the direct url at current time is
:
http://opensrc.sec.samsung.com/download/arm-elf-tools-20040427.sh
Hardware
Platform or an ARMulator
Of course, you need a platform to
run the kernel on. Please refer the notice section which platform is
supported. Even if you can not find the one that you have, or if you
don't have any hardware platform, you can run a complete kernel on
your Linux PC! : the ARMulator.
The ARMulator is a GDB based
emulator which emulates full Atmel AT91x, arm7tdmi EB01. The url of
ARMulator home is
:
http://www.uclinux.org/pub/uClinux/utilities/armulator/
You
can download directly at this
urls:
http://www.uclinux.org/pub/uClinux/utilities/armulator/gdb-5.0.tar.bz2
(the original gdb-5.0
archive)
http://www.uclinux.org/pub/uClinux/utilities/armulator/gdb-5.0-uclinux-armulator-20021127.patch.gz
(Patches against gdb-5.0)
And
another patch if you want to run the kernel with ramdisk on the
ARMulator
:
http://opensrc.sec.samsung.com/download/gdb-5.0-uclinux-armulator-ramdisk-20040412.patch.gz
That's
all for your first compilation.
Okay, here we go step by
step.
(This guide is assuming that the downloaded files are
located at ~/incoming and the ARMulator is used for platform to run
on.)
Install the toolchain
su to log in as the root then execute the arm-elf-tools-20040427.sh like:
[root@hyoklinux /]# /bin/sh ~/incoming/arm-elf-tools-20040427.sh
You should see the list of files that is installed. The toolchain binaries for execution are installed to /usr/local/bin. So you need the directory to be included in your search path, usually it is default for common Linux distribution like Redhat.
Untar the uClinux distribution
On
a directory which has enough free available space(about 2GB?), untar
the uclinux distribution :
[root@hyoklinux
/]# tar -zxvf ~/incoming/uClinux-dist-20040408.tar.gz
Let's look around what we have on the uClinux-dist directory:
[root@hyoklinux /]# cd uClinux-dist/
[root@hyoklinux uClinux-dist]# ls -al
total 104drwxr-xr-x 15 1000 users 4096 Apr 8 09:27 .drwxr-xr-x 28 root root 4096 Apr 27 20:32 ..-rw-r--r-- 1 1000 users 18007 Apr 8 09:13 COPYINGdrwxr-xr-x 3 1000 users 4096 Apr 8 09:13 Documentation-rw-r--r-- 1 1000 users 9305 Apr 8 09:13 Makefile-rw-r--r-- 1 1000 users 4934 Apr 8 09:13 README-rw-r--r-- 1 1000 users 1743 Apr 8 09:13 SOURCEdrwxr-xr-x 2 1000 users 4096 Apr 15 15:19 bindrwxr-xr-x 3 1000 users 4096 Apr 8 09:27 config <-- the configuration files for userland and etc.drwxr-xr-x 11 1000 users 4096 Apr 8 09:27 freeswan <-- IPsec implementationdrwxr-xr-x 68 1000 users 4096 Apr 8 09:23 glibc <-- Yes, the GNU C library.drwxr-xr-x 18 1000 users 4096 Apr 8 09:28 lib <-- many libraries ported to uClinux include uC-libc.drwxr-xr-x 15 1000 users 4096 Apr 8 09:27 linux-2.0.x <-- uClinux 2.0.x kerneldrwxr-xr-x 16 1000 users 4096 Apr 8 09:27 linux-2.4.x <-- uClinux 2.4.x kerneldrwxr-xr-x 18 1000 users 4096 Apr 8 09:27 linux-2.6.x <-- uClinux 2.6.x kerneldrwxr-xr-x 3 1000 users 4096 Apr 8 09:26 tools <-- utilities for romfs install and etc.drwxr-xr-x 17 1000 users 4096 Apr 8 09:27 uClibc <-- the uClibc, from uclibc.org. Differ to uC-libc.drwxr-xr-x 174 1000 users 4096 Apr 8 09:27 user <-- the “userland”. The applications that is ported.drwxr-xr-x 44 1000 users 4096 Apr 8 09:27 vendors <-- the configuration files for each vendor/models.
Make a new linux-2.6.x kernel from the scratch
The kernel version of linux-2.6.x directory in the 20040408 distribution is “linux-2.6.2-uc0”. We need another kernel with newer kernel version for uClinux/ARM 2.6, here.
[root@hyoklinux uClinux-dist]# tar -jxvf ~/incoming/linux-2.6.5.tar.bz2
Now we got the whole linux-2.6.5 codes, and need to patch the kernel.
[root@hyoklinux uClinux-dist]# gzip -dc ~/incoming/linux-2.6.5-hsc2.patch.gz | patch -p0
You
should see the codes patched in directories that contain “armnommu”
string. You can use the directory name “linux-2.6.5” for
your uClinux 2.6 kernel directory without further modification.
However, I recommend using the kernel directory name to “linux-2.6.x”
because it is more convenient.
So you don't need the linux-2.6.x
directory which is included in the uClinux-dist. :
[root@hyoklinux uClinux-dist]# rm -rf linux-2.6.x/
And we rename the newer patched kernel directory to “linux-2.6.x”.
[root@hyoklinux uClinux-dist]# mv linux-2.6.5 linux-2.6.x
Confirm the configuration files
The current uClinux distribution does not contain the proper configuration files for uClinux/ARM 2.6. We need a simple fix-up. The default configuration for ARMulator is at vendors/GDB/ARMulator. We can fix-up the configuration files like this :
[root@hyoklinux uClinux-dist]# cp linux-2.6.x/arch/armnommu/configs/GDB_ARMulator_defconfig vendors/GDB/ARMulator/config.linux-2.6.x
Since we'll use a ramdisk for the rootfs, we need to fix the “rc” in the configuration directory to use ramdisk device number 1.
Edit the vendors/GDB/ARMulator/rc to just like :
[root@hyoklinux uClinux-dist]# vim vendors/GDB/ARMulator/rc
hostname GDB-ARMulator/bin/expand /etc/ramfs.img /dev/ram1mount -t proc proc /procmount -t ext2 /dev/ram1 /varmkdir /var/tmpmkdir /var/logmkdir /var/runmkdir /var/lockmkdir /var/emptycat /etc/motd
Distribution Configuration
We need to configure compilation options for kernel and user applications.
[root@hyoklinux uClinux-dist]# make menuconfig
At
the first Main Menu, Select the “Vendor/Product
Selection”.
And Select “GDB”
for the “Vendor”, and “ARMulator”
for the “GDB Products” like :
--- Select the Vendor you wish to target(GDB) Vendor--- Select the Product you wish to target(ARMulator) GDB Products
You can go back to main menu with 'esc' key or “Exit” button.
At
the Main Menu, Select the “Kernel/Library/Defaults
Selection”.
And Select “linux-2.6.x”
for the “Kernel Version”, and “uClibc”
for the “Libc version”.
And toggle the whole below
menus :
(linux-2.6.x) Kernel Version(uClibc) Libc Version[*] Default all settings (lose changes) (NEW)[*] Customize Kernel Settings (NEW)[*] Customize Vendor/User Settings (NEW)[*] Update Default Vendor Settings (NEW)
You can go back to main menu with 'esc' key or “Exit” button.
With the first “default all settings”, the configuration files in the vendors directory is loaded. And with the second “Customize kernel settings”, we can edit the kernel configuration. The third “Customize Vendor/User settings” is for configuration of applications and libraries configuration for making the romfs.img which will be the rootfs of the kernel. With the final “Update Default Vendor settings”, your changes on the kernel and user application configuration will be saved on the vendors/product directory.
You can go back to main menu with 'esc' key or “Exit” button, and do it again for save dialog. And save it!
Kernel Configuration
If you followed the steps in “confirm the configuration files” above, your kernel should have been configured.
However, we need to change the initial ramdisk size. Because the romfs.img size with the default applications are about 771KB. In “General setup” menu, there is “Default kernel command string”. Change this to:
root=/dev/ram0 initrd=0x01300000,800K keepinitrd
You can go back to main menu with 'esc' key or “Exit” button, and do again for save dialog. And save it!
Application/library Configuration
On this menu, we don't need fix anything for now.
Look around the configurations and simply “exit” and save.
Make
We are ready to make the whole bunch. Simply type:
[root@hyoklinux uClinux-dist]# make
For linux-2.4.x, you should do “make dep” before “make”. But with linux-2.6.x, you don't need to.
It will compile the whole kernel and uclibc, user applications, and make the romfs.img.
The results
You should get the files in the image directory like:
[root@hyoklinux uClinux-dist]# ls -al images
total 3036drwxr-xr-x 2 root root 4096 Apr 27 22:13 .drwxr-xr-x 17 1000 users 4096 Apr 27 22:13 ..-rw-r--r-- 1 root root 1540272 Apr 27 22:13 image.bin-rwxr-xr-x 1 root root 45912 Apr 27 22:13 linux.data-rwxr-xr-x 1 root root 704856 Apr 27 22:13 linux.text-rw-r--r-- 1 root root 789504 Apr 27 22:13 romfs.img
[root@hyoklinux uClinux-dist]# ls -al linux-2.6.x/linux
-rwxr-xr-x
2 root root 15499433 Apr 27 22:11 linux-2.6.x/linux
If you see all the files, you've the whole kernel and rootfs image.
Let's play with it with ARMulator!
ARMulator installation
We need another directory to compile the GDB/ARMulator. However, this time, I'll install it in the uClinux-dist directory for temporary usage.
[root@hyoklinux uClinux-dist]# tar -jxvf ~/incoming/gdb-5.0.tar.bz2
And patch it!
[root@hyoklinux uClinux-dist]# gzip -dc ~/incoming/gdb-5.0-uclinux-armulator-20021127.patch.gz | patch -p0
And another one.
[root@hyoklinux uClinux-dist]# gzip -dc ~/incoming/gdb-5.0-uclinux-armulator-ramdisk-20040412.patch.gz | patch -p0
Okay, the codes are ready for compilation. Let's make it.
[root@hyoklinux
uClinux-dist]# cd gdb-5.0/
[root@hyoklinux gdb-5.0]# ./configure
–target=arm-elf
[root@hyoklinux gdb-5.0]#
make
[root@hyoklinux gdb-5.0]# make install
(be the root before this)
Running the ARMulator
Before run the ARMulator, we need a symbolic link to the rootfs image, “romfs.img”.
[root@hyoklinux
gdb-5.0]# cd ..
[root@hyoklinux uClinux-dist]# ln -s
images/romfs.img boot.rom
And if we make this initial script for GDB, it's convenient.
[root@hyoklinux
uClinux-dist]# cat > .gdbinit
target sim
load
^D
That's all for our first kernel running. Let's do it!
[root@hyoklinux uClinux-dist]# arm-elf-gdb linux-2.6.x/linux
GNU gdb 5.0Copyright 2000 Free Software Foundation, Inc.GDB is free software, covered by the GNU General Public License, and you arewelcome to change it and/or distribute copies of it under certain conditions.Type "show copying" to see the conditions.There is absolutely no warranty for GDB. Type "show warranty" for details.This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-elf"...Loaded ROM boot.rom to 0x01300000Loaded ROM boot.rom to 0x01400000Loaded ROM boot.rom to 0x04000000Loaded ROM boot.rom to 0x01300000Loaded ROM boot.rom to 0x01400000Loaded ROM boot.rom to 0x04000000Connected to the simulator.Loading section .init, size 0xb000 vma 0x1000000Loading section .text, size 0xa0b98 vma 0x100b000Loading section __ex_table, size 0x5b8 vma 0x10abba0Loading section .data, size 0x8ef8 vma 0x10ae000Start address 0x1000000Transfer rate: 5931584 bits in <1 sec.(gdb) runStarting program: /uClinux-dist/linux-2.6.x/linuxLinux version 2.6.5-hsc1 (root@hyoklinux) (gcc version 2.95.3 20010315 (release)(ColdFire patches - 20010318 from http://fiddes.net/coldfire/)(uClinux XIP and shared lib patches from http://www.snapgear.com/)) #9 Mon May 3 11:00:29 KST 2004CPU: Atmel-AT91M40xxx [14000040] revision 0 (ARMvundefined/unknown)Machine: ATMEL EB01On node 0 totalpages: 1024DMA zone: 0 pages, LIFO batch:1Normal zone: 1024 pages, LIFO batch:1HighMem zone: 0 pages, LIFO batch:1Built 1 zonelistsKernel command line: root=/dev/ram0 initrd=0x01300000,800K keepinitrdPID hash table entries: 32 (order 5: 256 bytes)Memory: 4MB = 4MB totalMemory: 2448KB available (642K code, 92K data, 44K init)Calibrating delay loop... 15.87 BogoMIPSDentry cache hash table entries: 1024 (order: 0, 4096 bytes)Inode-cache hash table entries: 1024 (order: 0, 4096 bytes)Mount-cache hash table entries: 512 (order: 0, 4096 bytes)checking if image is initramfs...it isn't (ungzip failed); looks like an initrdPOSIX conformance testing by UNIFIXLinux NoNET1.0 for Linux 2.6Atmel USART driver version 0.99ttyS0 at 0xfffd0000 (irq = 2) is a builtin Atmel APB USARTttyS1 at 0xfffcc000 (irq = 3) is a builtin Atmel APB USARTRAMDISK driver initialized: 16 RAM disks of 4096K size 1024 blocksizeloop: loaded (max 8 devices)RAMDISK: romfs filesystem found at block 0RAMDISK: Loading 771 blocks [1 disk] into ram disk... done.VFS: Mounted root (romfs filesystem) readonly.Freeing init memory: 44KShell invoked to run file: /etc/rcCommand: hostname GDB-ARMulatorCommand: /bin/expand /etc/ramfs.img /dev/ram1Command: mount -t proc proc /procCommand: mount -t ext2 /dev/ram1 /varCommand: mkdir /var/tmpCommand: mkdir /var/logCommand: mkdir /var/runCommand: mkdir /var/lockCommand: mkdir /var/emptyCommand: cat /etc/motdWelcome to____ _ _/ __| ||_|_ _| | | | _ ____ _ _ _ _| | | | | | || | _ \| | | |\ \/ /| |_| | |__| || | | | | |_| |/ \| ___\____|_||_|_| |_|\____|\_/\_/| ||_|GDB/ARMulator support by <davidm@snapgear.com>For further information check:http://www.uclinux.org/Execution Finished, ExitingSash command shell (version 1.1.1)/> psPID PORT STAT SIZE SHARED %CPU COMMAND1 S 163K 0K 48.0 /sbin/init2 S 0K 0K 0.0 ksoftirqd/03 S 0K 0K 1.0 events/04 S 0K 0K 0.0 kblockd/05 S 0K 0K 0.0 pdflush6 S 0K 0K 0.0 pdflush7 S 0K 0K 0.0 kswapd08 S 0K 0K 0.0 aio/011 S0 R 165K 0K 0.0 /bin/sh/> cd bin/bin> ls -aldrwxr-xr-x 1 0 0 32 Jan 1 00:00 .drwxr-xr-x 1 0 0 32 Jan 1 00:00 ..-rwxr-xr-x 1 0 0 105980 Jan 1 00:00 boa-rwxr-xr-x 1 0 0 91104 Jan 1 00:00 dhcpcd-rwxr-xr-x 1 0 0 29624 Jan 1 00:00 expand-rwxr-xr-x 1 0 0 40504 Jan 1 00:00 gdbserver-rwxr-xr-x 1 0 0 73748 Jan 1 00:00 ifconfig-rwxr-xr-x 1 0 0 41144 Jan 1 00:00 inetd-rwxr-xr-x 1 0 0 31176 Jan 1 00:00 init-rwxr-xr-x 1 0 0 56380 Jan 1 00:00 login-rwxr-xr-x 1 0 0 64656 Jan 1 00:00 ping-rwxr-xr-x 1 0 0 34280 Jan 1 00:00 reboot-rwxr-xr-x 1 0 0 73860 Jan 1 00:00 route-rwxr-xr-x 1 0 0 79852 Jan 1 00:00 sh-rwxr-xr-x 1 0 0 51216 Jan 1 00:00 telnetd/bin> cat /proc/meminfoMemTotal: 2516 kBMemFree: 560 kBBuffers: 900 kBCached: 188 kBSwapCached: 0 kBActive: 984 kBInactive: 44 kBHighTotal: 0 kBHighFree: 0 kBLowTotal: 2516 kBLowFree: 560 kBSwapTotal: 0 kBSwapFree: 0 kBDirty: 0 kBWriteback: 0 kBMapped: 0 kBSlab: 752 kBCommitted_AS: 0 kBPageTables: 0 kBVmallocTotal: 4194303 kBVmallocUsed: 0 kBVmallocChunk: 4194303 kB/bin>