全部博文(75)
分类: LINUX
2008-08-07 09:19:44
This document provides a summary of the steps when porting Linux to a new ARM platform or a new processor. In this page we assume that the reader has a knowledge of C and assembly programming and is familiar with ARM and operating systems concepts such as interrupt handling, system calls and memory management.
Some useful information can be found in the kernel documentation section on how to configure the kernel itself. It is probably best to familiarize with Linux on x86 before if you are not familiar with embedded platforms. In addition to Linux kernel source documentation, some notes maintained by community members are available on booting and setting up Linux for ARM platforms, you can consult the following kernel document and Vincent Sander's documentation for additional information.
Development for embedded platforms is usually done using cross-development tools. In the case of Linux, the host platform is often a Linux host computer connected to the target board using Ethernet, serial and/or ICE/JTAG.
The GNU compiler is required to build the Linux kernel. There is more information on downloading and installing GNU tools is available on . Other compilers compliant with the new for the ARM Architecture can also be used to compile user-space applications and some libraries.
Download the latest stable release of the Linux kernel sources from and install the source in your local directory. Working from the latest kernel source base is preferred as older versions will not be supported by the community. Later kernel versions usually contain recent bug fixes and enhancements. Older kernels such as 2.4 kernels are no more actively supported.
Support code for a new board consist in processor support, board specific code including where devices are mapped etc. and device drivers. Source code for device drivers is based in the drivers/ directory and net/ directories. Board specific code should be placed into the arch/arm/ directory.
The following sections will use as an example and assume that the processor support code already exist. The board intialisation and definition files are located in the arch/arm/mach-versatile directory. ARM Versatile board comes in two different form factors, a compact version () and a expandable version (). This directory contains the following files:
The MACHINE_START() macro defined at the end of versatile_pb.c contains the base definition for this platform, using initialisation functions defined in other platform files in this directory.
Header files are located in a similar directory: include/asm-arm/. In the case of versatile files are located in include/asm-arm/arch-versatile/.
Create a Kconfig file for the board in arch/arm/mach-versatile/ to link this board to the overall build system so that it can be selected when running make *config. Refer to Documentation/kbuild/kconfig-language.txt for a description of the syntax.
A Makefile entry need to exist to enable the systen to recurse into the platform sub-directories. Use Makefiles from existing boards as starting points and modify as appropriate.
Platform ID
Finally, add your machine group and type ID. A unique identifier can be obtained by registering your machine at http://www.arm.linux.org.uk/developer/machines/. You could initially assign a local ID in arch/arm/tools/mach-types while developing your BSP locally and then register it to get an official ID. You must be careful when changing kernel version as new machine are regularly added and make sure this doesn't conflict with the ID you have chosen.
This ID is used very early in the boot process to determine the platform type and pull in the correct initialisation functions. It is used by the boot loader and stored in banked registers (i.e. r1) before the bootloader hands over to the kernel.
New device driver should be added in the appropriate directories, net/ for network drivers or drivers/ for others. Makefiles and Kconfig files also need to be edited (or created) so they are linked to the rest of the system. The following provide a good guide on how to develop new device drivers with Linux.
If the board contains controllers or devices for which Linux already has support for, we only need to include these in Kconfig files and pass the correct parameters to these drivers when initialisation is done.
Ensure that the cross-toolchain program names are correct and accessible from your execution path (i.e. your PATH environment variable).
To configure the kernel you can use some of the following command:
These commands assume that you have a cross-compiler accessible on your execution path.
For other options you can either use the default or select 'No'. The resulting configuration file is stored as .config in the top level directory.
We can now type make dep and make to build a kernel image. If successful, the resulting image is placed in the arch/arm/boot directory. You can either build a compressed image (zImage) or a raw binary image (Image). The ELF file containing debug information (if selected in the Makefile) is called vmlinux and is at the top-level directory. When loading a kernel image onto the board using a debugger, you should use either zImage or Image files. The vmlinux image can be loaded to perform symbolic debugging.
Early signs of a working Linux kernel come from the output of printk(), which is routed directly to the first console. Having configured a serial console, we should be able to see some kernel messages on the serial port if it has been setup correctly. Note that often the bootmonitor from the board or the boot loader initialises the serial device, however the kernel should not necessarily rely on this.
The setup of the serial console happens much later during the kernel initialisation process. Chances are your new kernel probably dies even before that which is where early printk are useful. printk() allows you to print text as early as the first line of C code. The early initialisation steps are listed in init/main.c:start_kernel(). From this you can see that the console_init() call is done later on after we already had calls to printk().
Early printk() is very useful, however the serial driver should be working to enable further debug. For Versatile platforms, the serial driver is in drivers/serial/amba-pl011.c.
KGDB enables developers to debug the kernel while running and set breakpoints or do single stepping at source code level. If available, you can use two serial ports on the target, one used for KGDB communication and the other to print messages. You should use a crossover-cable (or null-modem) to connect it to your development host. Doing everything using one serial port is also possible.
You should select the Remote GDB kernel debugging which is listed under Kernel hacking when you configure the kernel and then do a 'make clean' and recompile the kernel to make sure that debugging symbols are compiled into the generated Linux image.
Run the new kernel image. At this stage the kernel will be waiting for a gdb client connection. If there is a cross-over serial cable connected between the serial port on the target and the host, you can then set the appropriate baud rate and start the gdb on your host:
At the gdb prompt, type: target remote /dev/ttyS0
If successful, you should be talking to the kernel through KGDB.
When porting the kernel to a new board it often hangs in the calibration step. This is normal if the interrupt code is not yet implemented in which case jiffies are never updated. Before adding support code for interrupt handling you need to identify interrupt controllers, all interrupt sources and how they are routed.
The following steps are involved to handle interrupts:
A descriptor structure (see irqdesc structure in include/asm-arm/mach/irq.h) is associated with each registered IRQ source. This structure contains pointers to functions declared by device drivers to handle individual interrupts.
Linux relies on a system timer to advance the tick count, jiffies. Without this, Linux won't run and will stop in calibrate_delay() during the startup process as jiffies will never be incremented. Access to a real-time clock (RTC) device is also required to obtain the calendar date and time when the kernel boots up.
ARM Versatile board includes primecell SP804 which provide facilities for periodic timers. One of the timers is used to generate system ticks. This is done at the end of arch/arm/mach-versatile/core.c with the definition and initialisation of the versatile_timer structure.
TBD.
-- - 26 Oct 2006
TBD.