At Roedan we specialise in embedded software and I was asked the other day why have you specialised? Surely software is software, right?
So I thought I would elaborate a bit…..
Well the obvious difference is the target environment, this is usually heavily resource constrained compared with a server or a desktop PC. Embedded systems can also be operating in difficult environments with limited or patchy communications to the outside world. They may also be part of a wider system where interoperability and reliability are essential. Sometimes these devices are controlling critical infrastructure or dangerous equipment where safety critical operation is necessary.
These differences affect the whole development process from the synthesis of requirements right through to testing. For an embedded system it is vital to capture the system requirements, context and initial system design first, irrespective of the development methodology. This will enable the optimum distribution of functionality across all parts of the system.
When capturing requirements for an embedded system, either we get asked for lots and lots of disparate features or for very few. For an embedded system we need to find a middle ground, not too many system functions, as the more you have, the more patches and upgrades you have to manage, and not too few so that the device becomes an inflexible part of a system that offers little value in the future.
In a non-embedded system the hardware will usually be known up front with standard hardware features, adding requirements that lead to very specific behaviour are therefore acceptable, conversely in an embedded system this may lead to over-engineering the hardware and the embedded software. We try to leave constraining design decisions as late as possible in the process.
It is also vitally important in the requirements capture process that all the safety requirements are fully specified, these may not constrain the design but they are intrinsic to the system and its context and will influence the development process and the technologies and design patterns used. The identified embedded functionality can then form part of the trade-off between the cost of the hardware and software development and its value.
Initial System Design
Initially it is advantageous to create a non-deployed abstract system design, this will allow you to capture all the required behaviour of the system and its interactions with its context without specifying the hardware or software. Once the design is complete, it will naturally fall into sections that can be deployed in hardware, FPGA, embedded software or pushed up to a server. There will be some parts of the design that could be implemented in various ways and depending upon factors including: your chosen extension points, risk, experience or availability of third party items you will make key design decisions.
The initial abstract design can then be synthesised into a concrete design, in the non-embedded world this step is usually not required. From the requirements the concrete design can be created directly using the chosen methodology.
If you are using an Agile, Waterfall or Iterative development process the project steps after the system design has been deployed will differ, but for an embedded system we need to keep a constant reminder that we are working with a resource constrained device. This will help us to keep designs simple and implementation straight forward.
Determinism, Responsiveness and Timeliness
Most embedded systems are designed to perform a specific task and will interact with external equipment via sensors and actuators or communications paths. This leads to the requirement for a high degree of determinism in the system, we expect that given the same set of inputs the output will always be the same. We also expect the delay from input to output to be very similar each time and not too long. These expectations will govern the design and implementation.
Choices in operating system and design deployment will highly impact these attributes. In a non-embedded application determinism can be achieved but responsiveness and timeliness will change widely between invocations. This is due to having non-real time operating systems with multiple applications and services running, it may also depend upon the hardware this is not as tightly controlled as in an embedded system.
Some embedded systems are safety critical, this means that it if the device fails there is a risk to persons or equipment. To ensure that a device is suitable for use in a safety critical environment many techniques and processes are required depending of the probability or failure and severity.
Safety is a system issue and usually cannot be bolted on afterwards, hazards and risks should be defined before the system requirements are finished.
We need to guard against systematic faults and random faults. There should be no single point of failure, redundancy where required and a separation of safety channels from non-safety channels. Continuous checking the validity of input data and the output data along with continuous self-testing and self-monitoring are essential design components.
Any device in a safety critical environment needs a lot of testing, usually the testing effort can be as large or larger that the development effort.
Embedded systems usually spend there life out in the field, maybe integrated into a larger piece of equipment and physical access may be limited. We usually design in a fall-back mode of operation to allow remote recovery if possible but it is vitally important that the device is as reliable as possible.
A system manager tying in with the self-monitoring functionality is usually employed. This will allow a hierarchical recovery mechanism to be created. Restarting failed sub-systems, rebooting the device or operating in a reduced capacity may be applicable actions but as a last resort failing in a safe state must always be achievable.
There are many factors that affect the technology choices on a project. The requirements and design, the operating environment (noise immunity, temperature range etc.) the power consumption, cost of hardware, availability of tools and the development team’s experience. It is sometimes a seriously undervalued and rushed part of a project. There are so many choices and interactions between those choices and the best subset of all the options is hard to visualise. A Rapid prototyping phase is usually useful to test the possibilities and measure their effectiveness. In a non-embedded world these choices are usually trivial and known up front, or even chosen for you.
Device Drivers, BSP and RTOS
A lot of the embedded software on a device is made up of device driver code, to implement this we need to be able to wade through hardware data sheets and poke the right registers at the right time. The drivers will also integrate with the chosen Real Time Operating System which in turn needs porting to the hardware platform. All this requires specific skills that non-embedded developers don’t need.
Developing at this level also needs a deep insight into the inner workings of the chosen OS and hardware, debugging at the hardware level is usually commonplace and knowing how to use things like oscilloscopes and logic analysers (and knowing which end of a soldering iron to hold!) are things that you don’t normally need to get involved in when developing for the desktop or enterprise.
To sum up I think that embedded software is the superset of software engineering, not only do we need to provide a well-engineered application, we need to specify and implement the middleware, drivers and BSP for that application to execute. It requires the wider system knowledge and extra skills to be able to distil a set of requirements into a successful product by negotiating the more treacherous path.