OS Porting - Our Approach
Porting an Operating System to a given ARM hardware platform generally involves three stages: the boot loader (if required), the OS kernel itself and the drivers. Of these the drivers generally involve the most effort, particularly those that must be writen from scratch from the datasheets.
Some Operating Systems require a boot loader to prepare the system for the OS kernel.
Typical boot loader tasks include setting up SDRAM memory, memory test, initialising a serial port or screen and displaying some system information, checking and loading the kernel and setting up parameters, then starting up the kernel.
Since we specialise in ARM technology, we have built up a substantial body of boot code for various ARM processors and can readily apply the to the booting needs of different hardware platforms. This can substantially speed up this part of the port.
Tools used generally include a suitable IDE including compilers and debuggers, and an ICE unit. In most cases we make use of ARM's RealView Developer Suite and RealView ICE.
Where self test code is required, the boot loader is a good place to put it. This functionality can be activated either automatically, or by a button pressed on start-up, or perhaps by detecting the presence of some test hardware on power-up. Self test code can check access to various peripherals (possibly performing loop-back tests if available), reading and writing to SDRAM and flash memory and power management functions. With the user's assistance it is possible to check many more functions such as LCD screen, network and any attached input such as touchscreen and buttons.
In many cases the boot loader functionality is built into the start-up code of the Operating System. In this case, this code must be ported as part of the OS rather than as part of the boot loader.
OPERATING SYSTEM KERNEL
Bringing up an OS kernel starts with the start-up code. This generally sets up the processor (e.g. cache and MMU) and memory and gets the system ready to execute tasks. At this level an OS will normally require access to timers, possibly a UART, interrupt handling and a memory map (which describes where each block of physical memory is located).
Once this is done, the kernel should come up. Testing will determine what problems remain. It should be possible to build and run kernel test programs where available. If the kernel includes a clock, it should be tested to make sure that it keeps reasonable time.
Sometimes an obscure problem will cause the kernel to crash before it starting running properly. In this case, the more information available on the kernel the better. Many Operating Systems come with full source code which can enormously speed up this process. Where source code is not provided, a complex guessing game and many support emails to the manufacturer may be necessary.
Interrupt performance can be tested - interrupt latency is the time taken between raising a hardware line, and the interrupt routine starting to run. Interrupt performance is often a critical feature of the system, so it is important to extract the best possible performance out of this part of the OS. Of course, some Operating Systems are inherently better than others.
Drivers are the pieces of software which control hardware and make it accessible to the rest of the system and applications software in particular. Often driver code is already available, particularly for the larger and better supported Operating Systems such as Linux. In this case the code merely needs porting to the platform, which involves changing addresses, register access routines and plumping in the interrupts.
Where the OS does not have a driver for the particular hardware device already, the manufacturer may have a starting point available. If not, we must resort to the datasheets and such example code as we can find. In this case it often makes sense to develop the driver code in a 'neutral' environment, with the ARM tools. The basic functions of the hardware can be tested and made to work. Once the code is correct it can be poured into a driver structure in the OS, and brought up from there. Since many OSes have limited support for debugging device drivers, this can often save time.
Hardware tools are important for driver development. A good oscilloscope or logic analyser can save hours or days of guesswork. Prototype hardware is often designed with these in mind, bringing out test points or whole 40-pin headers where signals can be tested and watched.
Once a driver is complete it must be tested. This may involve connecting another piece of hardware to the board to enable a sort of loopback testing. Or it may involve using the driver 'in anger' to see if it breaks under heavy load - heavy load is likely to show up interrupt faults or race conditions.
There really is no substitute for experience. Where an engineer has experience with ethernet, for example, he will be able to bring up the next ethernet chip much more quickly. The same sorts of problems often crop up on different OS ports, so building up experience with this is a key goal.
Bluewater's staff engineers have a wealth of experience in many types of OS bring-ups. With the tools available to our engineers, they are able to perform OS bring-ups extremely quickly and efficiently.