This document is concerned with low level developments of RISC OS in order
to support future ARM based platforms. Loosely, this has been considered as
creating a hardware abstraction layer, or HAL. This term is a useful
shorthand, but with the following caveats. Firstly, the HAL work is only
envisaged to provide a modest level of low level abstraction (at least for
the next OS generation). Secondly, significant non-HAL work, at all levels,
is required to make a useful next generation RISC OS.
Note that most of the hardware dependence of the OS is already confined to
low level code (essentially, the kernel and device drivers). Here we assume
that the OS is only expected to run on an ARM processor, and with somewhat
restricted choices of I/O hardware (eg. friendly video pixel formats).
Up to now (version 4), RISC OS has evolved while closely coupled to an ARM
processor core and to an Acorn proprietary chip set (video, memory, I/O). It
has remained highly hardware specific. For the purposes of further
investment in RISC OS, three key areas of hardware dependence must be
addressed; 32-bit clean operation, support for new ARM cores, support for
various video, memory and I/O configurations. Without all of these, the OS
is essentially useless on forseeable future hardware.
All RISC OS code must run 32-bit clean on future releases. This is because
all ARM cores from ARM9 onwards (and also some ARM7 variants) have entirely
removed support for RISC OS’s native 26-bit modes. Note that 32-bit clean
code is not precluded from working on the older ARM cores (back to ARM 610).
With more care, 32/26-bit agnostic code can be written to work back to ARM
2. This may be of interest to module and application code, but note that the
OS kernel itself is only expected to work back to ARM 610, since an MMU is
Much of the work required is routine and has been done for the OS itself
(though long term weeding of consequent bugs is required). A 32-bit
compatible shared C library has been released in order to encourage
conversion of application code by third parties. This work is not part of
hardware abstraction and is not considered further in this document.
ARM core support (including caches and MMU) has historically been coded in a
tailored way for one or two specific variants. Since version 3.7 this has
meant just two variants; ARM 6/7 and StrongARM SA110. A more generic
approach is required for the next generation. This aims both to support
several cores in a more structured way, and to cover minor variants (eg.
cache size) with the same support code. The natural approach is to set up
run-time vectors to a set of ARM support routines.
Note that it is currently assumed that the ARM MMU architecture will not
change radically in future ARM cores. Hence, the kernel memory management
algorithms remain largely unchanged. This is believed to be a reasonable
assumption, since the last major memory management change was with Risc PC
and ARM 610 (when the on-chip MMU was introduced).
ARM core support is confined almost entirely to the kernel, and is therefore
not strictly part of the HAL. The HAL will only be concerned with any
external factors such as clock selection. Only HAL aspects are considered
further in this document.
A simple HAL is to be inserted underneath RISC OS. This will provide two
functions. Firstly, it will be responsible for initial system bootstrap,
much like a PC BIOS, and secondly it will provide simple APIs to allow
The HAL APIs are a thin veneer on top of the hardware. They are designed to
act as replacements for all the hardware knowledge and manipulation
performed by the RISC OS Kernel, together with some APIs that will allow
RISC OS driver modules to become more hardware independent. No attempt will
be made (at this stage) to perform such tasks as separating the video
drivers from the Kernel, for example.
One tricky design decision is the amount of abstraction to aim for. Too
little, and the system is not flexible enough; too much and HAL design is
needlessly complicated for simple hardware. The present design tries to err
on the side of too little abstraction. Extra, more abstract APIs can always
be added later. So, initially, for example, the serial device API will just
provide discovery, some capability flags and the base address of the UART
register set. This will be sufficient for the vast majority of devices. If
new hardware comes along later that isn’t UART compatible, a new API can be
defined. Simple hardware can continue to just report UART base addresses.
The bulk of device driver implementation remains in RISC OS modules – the
difference is that the HAL will allow many device drivers to avoid direct
access to hardware. For example, PS2Driver can now use HAL calls to send and
receive bytes through the PS/2 ports, and thus is no longer tied to IOMD’s
PS/2 hardware. Similarly, interrupt masking and unmasking, as performed by
any device vector claimant, is now a HAL call. Note that HAL calls are
normally performed via a Kernel SWI – alternatively the Kernel can return
the address of specific HAL routines. There is nothing to stop specific
drivers talking to hardware directly, as long as they accept that this will
tie them to specific devices.
This dividing line between the HAL and RISC OS driver modules is crucial. If
the HAL does everything, then we have achieved nothing – we have just as
much hardware dependent code – it’s just in a different place. It is
important to place the dividing line as close to the hardware as possible,
to make it easy to design a HAL and to prevent large amounts of code
duplication between HALs for different platforms.
The Kernel remains responsible for the ARM’s MMU and all other aspects of
the CPU core. The HAL requires no knowledge of details of ARM
implementations, and thus any HAL implementation should work on any
processor from the ARM610 onwards.