![]() |
Linux is fast proving to be a popular operating system for embedded network devices. Just some of the many advantages are listed below. With all these advantages, there are many target platforms and this is continuing to grow. uClinux now supports the 68328 dragonball series, Coldfire, ARM7TDMI, ETRAX, I960. uClinux is the most popular form of embedded linux. uClinux (MicroController Linux) was first ported to the Dragonball 68k series processors in 1998 has since grown exponentially to include a wide range of targets. uClinux differs from it’s mainstream linux counterparts by having no support for memory management units (MMU). The other important part of uClinux is a small footprint, which is essential for microcontrollers with little resources and it's BFLT (Binary Flat) Executable Format.
The uClinux Kernel is where all the fuss is made. It is based on the 2.0.38 Linux kernel. Linux-2.0.38.tar.gz is the original kernel you would use on your desktop computer. A uClinux patch is applied to bring the kernel up to a level where it can be used on your microcontroller. This typically involves the device support and removing the reliance on the MMU. Download the tarballs and place them in /opt/uClinux. Unpack and patch the kernel. You will need to create the uClinux directory. cd /opt/uClinux tar –xzf linux-2.0.38.tar.gz gzip –d uClinux-2.0.38.1pre7.diff.gz cd linux patch -p1 < ../uClinux-2.0.38.1pre7.diff
Once this is done, you now have yourself the code base for the uClinux Kernel. However you will now need
to build a compiler which can cross compile the code to M68K. Later in the uC-libc building, it will try
to include files in linux/include/asm. "asm" is an symbolic link which points to a folder asm- This is therefore a good place to start by configuring the kernel which can be done without needing the m68k-coff compiler. make menuconfig The default configuration is for the uCSimm thus if you have other boards will need to configure it for your desired target. There is no need to build the kernel, in fact you can't build the kernel yet due to a lack of development tools. The make config will set up the asm links which are required laterfor the building of the standard c library, uC-libc. ToolchainsThere are two different tool chains for uCLinux. One is used for the compilation of the kernel and produces 32 bit M68K fixed position executables. The other is used for compilation of user-land binaries and produces 32 bit M68K position independent code (PIC). The kernel chain tool is nothing more than the standard run of the mill gcc version 2.7.2.3. The kernel diff makes one small modification to the /config/m68k/t-m68kbare file inserting TARGET_LIBGCC2_CFLAGS = -Dinhibit_libc to prevent it from requiring a libc library. The user-land chain tool is a different matter. It has some quite extensive changes. These changes lie with the requirement to have position independent binaries. No direct jumps are used, but instead these are replaced with relative branches. Global data is retrieved relative to the A5 register. Two options are given for building the tool chains. You can download uClinuxgcc-kit-160899.tar.gz which contains all the patches and a makefile which automatically builds the binutils and gcc for both the kernel and user environments. The other option is to patch and build the tools yourself and in the process learn what is happing along the way. We detail both methods here.
Download the following Extract uClinuxgcc-kit-160899.tar.gz. The buildtools can be built in any directory, independent of /opt/uClinux tar -xzf uClinuxgcc-kit-160899.tar.gz cd uclinuxgcc-kit-160899 Edit the Makefile (first line) changing the INSTALLDIR to a suitable destination - /opt/uClinux is recommended. Then make the m68k-coff and m68k-pic-coff tool chains by typing,
make This creates the executables in /opt/uClinux/bin which is not in the current path. Therefore we could either add /opt/uClinux/bin to the path, or link our newly created binaries to /usr/bin. cd /opt/uClinux/bin ln -f * /usr/bin Now that was easy, wasn’t it? Now that we have boosted your confidence, lets walk through what is happing by examining the manual version. Manually Building the Tool Chains - m68k-coff
We will start by building the M68K fixed position tools, m68k-coff. Download Extract the binutils src tarball to a suitable directory of your choice and enter its directory tar –xzf binutils-2.9.1.tar.gz cd binutil-2.9.1 Configure binutils for your target. We have started with m68k-coff first as it requires no patches. ./configure -–prefix=/opt/uClinux -–target=m68k-coff Then make the m68k-coff bin utilities. make make install This will create a directory /opt/uClinux/m68k-coff which will have 5 subdirectories including bin, include, libs, m68k-coff and man. This will contain headers which is needed when we create gcc. Change back to your directory where gcc-2.7.2.3.tar.gz is present Extract the gcc src tarball, patch it and then enter the gcc directory tar -xzf gcc-2.7.2.3.tar.gz gzip -d gcc-2.7.2.3.kernel.diff.gz cd gcc-2.7.2.3 patch -p1 < ../gcc-2.7.2.3.kernel.diff Configure gcc for your target. The prefix must be the same than the binutils, as gcc will expect to see the header files previously created by the binutils install. ./configure --prefix=/opt/uClinux --target=m68k-coff Then make the m68k-coff C Cross Compiler. The LANGUAGES=c instructs make only to build the C Compiler and not the C++ Compiler which will cause some unnecessary problems. make LANGUAGES=c make LANGUAGES=c install You should now have a m68k-pic-gcc compiler capable of building the kernel. The executables should be located in /opt/uClinux/m68k-coff/bin. To continue and build the pic-coff tools we must either delete the working directories or rename them. Renaming them is recommended as one of the reasons why you are building the source from scratch and not downloading an RPM is that you can later apply patches and bug fixes. Rename binutil-2.9.1 to binutil-2.9.1.kernel and gcc-2.7.2.3 to gcc-2.7.2.3.kernel Manually Building the Tool Chains - m68k-pic-coff (Position Independent Code)
Now we repeat the process for the m68k-pic-coff compiler. This time the binutils must be patched. tar -xzf binutils-2.9.1.tar.gz gzip -d binutils-2.9.1.pic.diff.gz cd binutils-2.9.1 patch –p1 < ../binutils-2.9.1.pic.diff and configure this time for the m68k-pic-coff toolchain. ./configure -–prefix=/opt/uClinux -–target=m68k-pic-coff Then make the m68k-coff bin utilities. make make install This now has us ready to start making the gcc compiler. Extract the src tarball, patch it and then enter the gcc directory. tar –xzf gcc-2.7.2.3.tar.gz gzip -d gcc-2.7.2.3.pic.diff.gz cd gcc-2.7.2.3 patch -p1 < ../gcc-2.7.2.3.pic.diff Configure gcc for your target. The prefix must be the same than the binutils, as gcc will expect to see those header files which binutils created. ./configure -–prefix=/opt/uClinux -–target=m68k-pic-coff Then make the m68k-coff C Cross Compiler. make LANGUAGES=c make LANGUAGES=c install As neither m68k-pic-coff or m68k-coff is in the current path, most make files will attempt to call gcc using m68k-pic-coff-gcc. We can either place these two directories in our path, or we can create hard links to them in /usr/bin. cd /opt/uClinux/bin ln -f * /usr/bin Hard links are created instead of soft links. If an attempt is made to create an softlink, gcc/evecvp will complain about "too many levels of symbolic links". The content of /opt/uClinux/bin is soft links which point to the bin directories of the individual compilers. At this stage we now have a C Compiler which makes position independent COFF binaries. What we don't have is any standard C or standard maths libraries thus gcc will complain. uClinux also relies on flat binaries and not coff binaries. Therefore we must add a coff to flat converter (coff2flt) which converts the coff images the compiler generates into flat binaries which we can then run on uClinux. coff2flt (COFF - Common Object File Format to Flat Binary Converter)
In order to seemlessly create flat binaries with one command, the linker (LD) is replaced with a script which first runs the linker that generates the .coff file, then runs coff2flt utility to generate the flat binary. Download the above file and extract it. tar –xzf coff2flt-0.5.tar.gz cd coff2flt-0.5 make This builds coff2flt. In the tarball is a script, ld. We must replace the pic-coff-ld with this script which in turns calls coff2flt to create a flat binary from our coff binary. However before we do this, edit the line in LD to set %prefix% to /opt/uClinux/m68k-pic-coff mv /opt/uClinux/m68k-pic-coff/bin/ld /opt/uClinux/m68k-pic-coff/bin/gld install -m 755 coff2flt /opt/uClinux/m68k-pic-coff/bin cp ld /opt/uClinux/m68k-pic-coff/bin chmod 755 /opt/uClinux/m68k-pic-coff/bin/ld Standard C Library
Two libraries are used when compiling user-land binaries. These are the standard C library and standard math library. These are static libraries which get linked at compilation time. The uC Standard C Library has always been plagued with bugs. In particular they have had bad memory leaks relating to their memory allocation functions. Some individuals have patches for the malloc functions which you can manually apply and build. The uC-libc is undergoing quite radical changes at the present moment. These experimental changes are available through the uClinux CVS repository. A stable library should be avalible soon which will supersede these early versions of uC-libc and provide a much more stable platform upon which to build your code. On a positive note, the maths library has had little problems. Extract the uC-libc tarball into /opt/uClinux. tar –xzf uC-libc-310899.tar.gz The uC-libc library has two symbolic links (include/linux and include/net) which should point to the headers of the uClinux Kernel. These links expect a linux directory to be present in the same tree the uC-libc directory is present in. If one doesn't exist due to a different install location, you may wish to create a link. The uC-libc library in its present form has no setjmp or longjmp functions which are later needed by sh. The easiest way to fix this, is to move uC-libc/machine/setjmp.S to uC-libc/sysdeps/ and include it (setjmp.o) to uC-libc/sysdeps/makefile.objs cd uC-libc make If you receive any errors about missing files typically in the asm, linux or net directories such as "/asm/types.h - No such file or directory," then check that you have configured your kernel (/include/asm links are in place) and that there is either the linux kernel source or a link to linux in the same directory that uC-libc is present in. This compiles the uC-libc library (libc.a) and leaves it in the uClibc directory. We now need to make this available to the m68k-pic-coff tools. Either a link can be made or the files copied. cp libc.a /opt/uClinux/m68k-pic-coff/lib/libc.a cp crt0.o /opt/uClinux/m68k-pic-coff/lib/crt0.o The include/header files also need to be available. The chaintool has already placed assert.h in /opt/uClinux/m68k-pic-coff/include therefore you may wish to rename the present directory. mv /opt/uClinux/m68k-pic-coff/include /opt/uClinux/m68k-pic-coff/include.old ln -sf include /opt/uClinux/m68k-pic-coff/includeStandard Maths Library
The standard maths library is far less problematic. Simply extract it into /opt/uClinux and make,
tar –xzf uC-libm-0.9.1.tar.gz cd uC-libm make then create links in the m68k-pic-coff/lib to point to the library and header files. These header files will actually find their way to the uC-libc/include directory by a symbolic link. ln -f libmf.a /opt/uClinux/m68k-pic-coff/lib/libmf.a ln -f libmf.a /opt/uClinux/m68k-pic-coff/lib/libm.a ln -f mathf.h /opt/uClinux/m68k-pic-coff/include/mathf.h ln -f mathf.h /opt/uClinux/m68k-pic-coff/include/math.hgenromfs - ROM FileSystem Generation Utility
Genromfs generates a ROM Filesystem. Extract, patch and build using tar -xzf genromfs-0.3.tar.gz gzip -d genromfs-0.3.diff.gz cd genromfs-0.3 patch -p1 <../genromfs-0.3.diff make make install "make install", will install genromfs in /usr/bin plus put its documentation in usr/man/man8 Genromfs can then be called on the command line to generate your own romfs. genromfs -v -V "ROM Disk" -f romdisk.img -d romdisk 2> romdisk.map The genromfs has some bugs relating to device nodes. If your romfs isn't correct, the kernel normally reports problems opening initial console (can't open the device node) and then panics. Often it is useful to mount your newly generated romfs to see if everything is correct. This can be done using mount –r –o loop –t romfs romdisk.img /mnt/romfsROM Disk FileSystem and Userland Binaries
The romdisk gziped tarball contains device nodes. As a result this file must be extracted as root into the /opt/uClinux directory. tar -xzf romdisk-0.9.1.tar.gz The romdisk forms the bases of your embedded systems filesystem. The genromfs utility will create a romfs.img from this tree, thus any changes or files you place in this tree will be present in the uClinux filesystem. The romdisk has the following directories (and file), bin dev etc htdocs lib proc ramfs.img sbin tmp usr var You will notice if you change into the bin directory that precompiled binaries are already present. Their source is installed next. tar -xzf uC-src-0.9.2.tar.gz cd src make If you experience problems building sh - undefined reference to 'setjmp' or 'longjmp' check that you have included setjmp.S in the uC-libc build. Running make will build all the sources listed in the SUBDIR define of the Makefile. Therefore if you add extra sources here you must include them in the Makefile. At the completion of the build process, the binaries will be in the src/bin directories. The deftemplate.sh script will copy the required binaries from /src to /romdisk/bin or sbin. cp deftemplate.sh /opt/uClinux/ One last file is needed. buildenv.sh will set up the build environment from a clean directory, copying the required sources and setting up a Makefile. Copy buildenv.sh to /opt/uClinux/bin and create a link in /usr/bin. cp buildenv.sh /opt/uClinux/bin/ ln /opt/uClinux/bin/buildenv.sh /usr/bin/buildenv and that is it. Now if you create an empty directory somewhere and type buildenv, a makefile will mysteriously appear. Then type make, to see the userland sources, romdisk etc copied over and built. PIC32 Patch - 32-bit PIC patch for m68k-pic-coff 2.7.2.3
With the current m68k-pic-coff compiler, a limitation exists which prevents building executables over 32k in size. This size comes about by using 16 bit signed offsets. Erwin Authried has released some patches for m68k-pic-coff-gcc to generate 32 bit offsets which removes this limitation. Code can be built normally with 16 bit offsets without specifying anything special. If your program exceeds 32k, then you can call the compiler with -fPIC which generates 32-bit offsets. Code compiled with the -fPIC switch is larger, thus it should only be used where needed. In addition to the compiler patch, a new C Startup file (crt0.S) is needed. This should be compiled and added to m68k-pic-coff/lib. The startup file contains no _cleanup() function thus this must be included elsewhere.
Debugging is an optional extra for the "smarter" uClinux programmers. It consists of two components, gdb-4.18 running on the host configured for m68k-coff and a gdbserver running on your uClinux platform. They talk together over the network (IP). While the gdb client should compile with little effort, the gdb-server requires not only patching but also support from the uClibc library, a debug uClibc library and support from the uClinux Kernel - but don't run away yet. gdbserver requires a trap in the uClinux Kernel to operate. The good news is that this has been included in the later kernels and thus in many cases needs no attention. The uClinux-2.0.38.1pre7 kernel detailed here already has this support. Download and extract gdb-4.18 tar -xzf gdb-4.18.tar.gz gzip -d gdb-4.18-gdbserver.diff.gz cd gdb-4.18 patch -p1 <../gdb-4.18-gdbserver.diff Now configure the gdb client running on the host to debug m68k-coff code and built it. ./configure --target=m68k-unknown-coff make To build gdbserver requires some extra functions not found in the default uC-Libc library. The source is present in the library but is not specified to be built by default. Change into the /uC-libc/sysdeps/m68k and edit ptrace.c so that the ptrace.h path is correct. Change #include <sys/ptrace.h> to #include <linux/ptrace.h>. Then add the source to be build by editing /uC-libc/sysdeps/makefile.objs and adding m68k/ptrace.o to the end of the OBJS list, so that it looks like waitpid.o \ write.o \ m68k/ptrace.o Then rebuild the uC-libc library and add the new libc.a to /m68k-pic-coff/lib. cd gdb-4.18/gdb/gdbserver ../../configure --target=m68k-linux-coff Then edit the Makefile, changing CC = gcc to CC = m68k-pic-coff-gcc make gdbserver coff2flt -s 32768 -o gdbserver gdbserver.coff Running make by itself will create a gdbserver flat binary, however it's default stack size is typically around 4k. As a result, gdbserver may crash or fail to connect. Therefore it is recommended you link with a stack size of 32k CVS – Concurrent Version SystemKeeping track of all the changes and providing diff files frequently can cause headaches. Some changes get included while others don’t. To ensure your development sources are always up to date Lineo has provided a CVS server. The CVS server allows changes to be made from multiple users, while keeping track of what the changes are and who made them. If something gets broken in the process it is simple to back track through the changes. The uClinux repository is available at http://cvs.uclinux.org. From there you can browse the source and check out what changes have been made and why. If you want to download the complete source then this can be done by logging into CVS using the CVS client on your development box. uClinux provides anonymous read-only access to their repository. To start, you must log in. Use the following command. echo anonymous > cvs –d:pserver:anonymous@cvs.uclinux.org:/var/cvs login This logs you into CVS using the username anonymous and password anonymous. cvs –z3 –d:pserver:anonymous@cvs.uclinux.org:/var/cvs co –P <dir> where <dir> is one of the present directories, uClibc The uClinux Userland C Library uClinux-2.0.x 2.0.38 uClinux Kernel uClinux-2.4.x 2.4.0 uClinux Kernel userland uClinux Userland Binaries The –z3 specifies the compression used. –z3 is maximum compression. The co stands for check out, while –P specifies pruning directories (i.e. remove empty directories). Then at a later date you can update your sources by using the following command in the relevant directory. cvs –z3 update –d –P |