Component Architectures for Microkernel-based Embedded Systems
The Component Architectures for Microkernel-based Embedded Systems (CAmkES) project aims to create a quick catalogue solution for embedded systems. Creating new component technology will increase the reliability of embedded systems and decrease the cost.
The project aims to reduce the complexity and cost of developing complex software for embedded systems such as handheld devices.
The traditional approach to creating software that runs on embedded systems is inflexible, expensive and requires highly-specialised programming skills. With a growing global demand on embedded systems to deliver more complex functionality, reliability and security, a new approach is required for software development for these devices.
CAmkES forms part of NICTA’s Embedded, Real-Time and Operating Systems (ERTOS) group, which focuses on reducing the cost and improving the reliability and trustworthiness of embedded systems software.
What has this research achieved?
This project has devised and developed a component-based framework for developing embedded operating system software.
In recent years, software developed for business, web-based and PC applications has achieved efficiency gains by taking a more modular approach to development. This allows significant re-use of software components, providing more flexibility and complexity in the resulting applications.
This project applies the same principles of reliable, re-usable software components to embedded systems, resulting in more powerful, flexible applications that are easier and less expensive to develop.
Who will benefit?
Creating rich software applications for embedded devices much more quickly and with less expense will create socio-economic benefits. Users of embedded systems devices will get more powerful applications for those devices more quickly.
What are the key features?
The CAmkES solution is built specifically for the L4 microkernel, an open source operating system for embedded systems, with growing support in the open source community. CAmkES will be released as open source, and therefore be exposed to a significant user community of developers and users.
A component architecture devised on top of microkernel operating systems directly addresses the low productivity in rapid development of complex and trusted embedded systems.
CAmkES specifically addresses the key issues of performance, overhead, and flexibility, by providing a component model where connections between components are first class entities. This means that connections (and therefore communication between components) are explicitly specified, and that the characteristics of the connections can be defined by the system designer in the same way as component functionality.
The initial work on creating the core component features of CAmkES was completed in 2006. Further work continued through 2007 to enhance those features and add new components. The technology has been licensed to NICTA spinout Open Kernel Labs for use in further development of the OKL4 embedded operating system.
The CAmkES framework for OKL4 has been released as open source. Please see our software site for more details.
Gernot Heiser, Kevin Elphinstone, Ihor Kuz, Gerwin Klein and Stefan M. Petters
Towards trustworthy computing systems: taking microkernels to the next level
ACM Operating Systems Review, 41(4), 3–11, (July, 2007) pdf
Ihor Kuz and Yan Liu
Extending the capabilities of component models for embedded systems
Proceedings of the Third International Conference on the Quality of Software-Architectures (QoSA), Boston, MA, USA, July, 2007 pdf
Ihor Kuz, Yan Liu, Ian Gorton and Gernot Heiser
CAmkES: a component model for secure microkernel-based embedded systems
Journal of Systems and Software Special Edition on Component-Based Software Engineering of Trustworthy Embedded Systems, 80(5), 687–699, (May, 2007) preprint
The category of embedded systems encompasses a broad range from very simple and heavily resource-constrained systems to complex distributed systems consisting of powerful and resource-rich processing nodes. The component architecture we developed has a minimum level of resource requirements, but can be used for all ranges of embedded systems that fulfil these requirements. This means that it will be usable for real-time embedded systems, networked and distributed embedded systems, power-constrained systems, sensor networks, secure systems and so on. We do not limit ourselves to any particular application domain.
Minimum targeted system: Hardware
Targeted systems must satisfy minimum requirements for the hardware they are implemented on. We require targeted systems to include:
- A 32-bit (or 64-bit) CPU
- A memory-protection unit (MPU)
- At least 200KB of primary memory (RAM and/or ROM).
It is important to note that in most cases the need for an MPU will be fulfilled by a memory-management unit (MMU). However, support for virtual address spaces is not a requirement, only memory protection is important. Also, while a number of features (in particular security-related features) of the component architecture require memory protection, it should be possible to make use of a subset of the component architecture on hardware without memory protection.
Second, the amount of memory necessary largely depends on the platform, application requirements and specific features of the component architecture used by the application. For example currently on ARM, the L4 microkernel requires 200KB of memory and the OS services provided by Iguana require at least 100KB. We expect this can be at least halved by tuning the kernel’s memory footprint and using better compilers. Furthermore, most of the memory will not need to be writable and could be provided as ROM containing the software images.
Typical resource constraints imposed by the available hardware (as well as the nature of the application) include limited primary memory, limited (or possibly no) secondary memory, limited power supply and limited processing power.
Minimum targeted system: Software
The system must run a minimal, high-performance microkernel. We have designed the system based on NICTA’s and Open Kernel Labs' L4 microkernel, however, a different kernel providing similar functionality could conceivably be used. In particular, the kernel must provide: pre-emptive multitasking, high-performance IPC (synchronous message passing), footprint optimisation, and memory protection.
The components and component architecture run at user level and are not part of the kernel. We require a minimal development environment to be available. This consists of a
(C language) cross-compiler suite (for example GCC) for the target platform. This minimal environment should also support debugging tools such as a debugger and profiler.
The purpose of our component architecture is to provide support for developing embedded systems on top of microkernels. The architecture provides a component model, standard interfaces and component definitions, standard component implementations, standard services, and support for various architectural patterns and styles suited for embedded systems.
Component-based development shifts the development emphasis from programming software to composing software systems. It brings with it obvious benefits for embedded systems such as reusability, maintainability and a reduction of software complexity which leads to improved productivity. However, applying component-based development in the embedded domain also introduces several new concepts and challenges:
- Must work in resource-constrained environments
- Must fulfil the real-time requirements of embedded systems
- Should provide flexibility for component design and implementation. For example, it should allow components to be parameterised and configured; it should allow various ways of connecting components; and it should allow components to make as few assumptions as possible about their environment.
- Should support a variety of computational models (or architectural styles), including event-based models and dataflow models.
The main features of the CAmkES architecture are:
- Modular. The core runtime only includes features that are really needed for any particular target applications. Other features can be added in the form of extensions. This modularity allows users to extend the runtime with special features on an as-needed basis depending on their specific applications.
- Simple. The core runtime is lightweight and only focuses on static components and their composition. This can minimise the overhead introduced by the component architecture.
- Deterministic. For static components, stub and glue code are inserted into the components at compile time. This allows the temporal behaviour of the resulting application to be analysed. Determinism is achievable for static components with static composition.
A layered component architecture
CAmkES is part of a layered architecture, as shown below:
- At the bottom is the hardware layer. This includes the CPU, memory, bus and any other devices.
- On top of the hardware layer is the real-time operating system layer. This consists of the L4 microkernel and Iguana server. Further support such as device drivers, file systems, and network stacks can be added at this layer as well. However, these services can also be implemented as CAmkES components and reside at a higher layer instead.
- The CAmkES core runtime forms the foundation of the component architecture, providing an execution environment and the basic services required to deploy CAmkES components. The core runtime supports static components and component compositions. This means that component instances are only created at initialisation or boot time and that connections between components are established at design time and cannot be created or modified dynamically at runtime. This allows us to minimise overhead for the most basic component-based applications, for example by inserting direct procedure calls into components, thus avoiding IPC and marshalling overheads.
- More advanced component features are provided by extensions that run on top of the core runtime in the extension layer. The extensions are themselves components that make use of the core runtime features. The extension layer is designed to address the various aspects of supporting dynamic components, including dynamic creation and destruction, dynamic binding and dynamic configuration. The reason for separating these features from the core runtime is to minimise overhead. For example, support for dynamic binding implies increased overhead with regards to code size and processing. By placing this support outside the core we can limit this overhead cost to those systems that actually make use of dynamic binding. The extension layer will have looser resource constraints than the core runtime layer.
- Frameworks further extend the functionality of the component architecture by providing components and services specifically geared to particular application domains. For example, a multimedia framework may specify specific interfaces for codecs as well as provide components that make use of codecs implementing these interfaces.
- Finally, user-defined components combine with the underlying layers to form complete applications.
- This layered architecture provides a good separation of concerns. For example, many of the services provided at the extension layer are orthogonal to each other and our architecture allows them to be implemented as such. Furthermore, because services and extensions introduce extra overhead, the layered architecture allows the CAmkES user to balance the trade-offs, such as overhead versus functionality, choosing to use only the features that they can afford.
Our layered architecture also provides an encapsulation of the dependency information, which makes it easy to create customised embedded applications without needing to know or understand the underlying OS architecture or feature dependency. For example, a developer can implement the function calls between component interfaces without knowing that the invocation relies on IPC.
As in general, non-embedded component-based software development, the development of CAmkES-based embedded systems has four stages: design, implementation deployment and runtime. These are shown below.
- Design. At design time the functionality of a component is defined through an interface definition language (IDL) and an architecture definition language (ADL). It could also be possible to define the non-functional requirements and properties of components, for example temporal requirements and properties. The tools used in this stage include an IDL and ADL compiler to generate skeleton code for components and their compositions.
- Implementation. At the implementation stage, the component functionality is implemented based on skeleton code generated during the first stage.
- Deployment. During deployment, CAmkES tools initialise the instance of a component. The configuration information of a component will be utilised for code generation. For example, the size of interface arrays will be used to generate a fixed sized array of interfaces. At the end of this stage, all the component, stub and glue code is compiled and linked into executable images.
- Runtime. The component code is loaded into the runtime environment for execution. Before this can happen a boot image file must be created using specific tools for this purpose. Once this image is booted, component instances are created and initialised and the component-based system is started.