As the world becomes increasingly driven by embedded systems, achieving safe, secure and reliable software has never been more important. Functional safety – part of the overall safety of a system or piece of equipment that depends on automatic protection – is firmly in the spotlight, across all kinds of markets, such as automotive, aerospace, medical devices and rail.
This puts pressure on engineers to ensure their software is safe, while continuing to innovate and maintain product performance, often against a back-drop of tight project timescales and budgets. Mega-trends such as artificial intelligence, augmented reality, blockchain and the internet of things (IoT) are driving increases in the complexity of both consumer and industrial software applications.
Most functional safety-related systems are implemented on custom-designed, embedded hardware platforms. For decades, C and C++ have been the programming languages of choice for such embedded systems. This is largely because they permit direct, deterministic control of hardware, and give flexibility to the developer. However, the use of these languages also introduces risk. Code which compiles and run can still have undefined or unspecified behaviour, or may not behave in the same way when compiled and run on different target hardware. This is clearly unacceptable in any safety-critical application such as a car braking system.
Alongside the proliferation of safety-related embedded systems, there has been a sea-change in software development culture. Across all markets, there is a move away from the traditional waterfall methodology towards Agile, Agile hybrids, DevOps and generally shorter, iterative development cycles of continuous integration, improvement, testing, delivery and deployment. This means that to remain competitive, standards compliance, safety and security should be baked into software development, from day one and across the entire lifecycle.
Standards are the starting point
Functional Safety standards, which promote consistent communication and shared understanding, enable organisations to work from a common baseline of best practice.
In some industries, such as rail or automotive, the correct implementation of functional safety is even a part of the approval process, which is required to place the system on the market.
Although it is sometimes considered a burden to work to the requirements of the standards, it is more often the case that they reduce costs and time to market because they implement best practice throughout the development.
Functional safety involves performing a hazard analysis on a system, and then implementing safety functions where needed, to reduce the risk of a hazard occurring to within a tolerable level. These safety functions may or may not be controlled by software. In cases where there is a software-controlled safety function, the standards set out the appropriate software development and verification activities that need to be undertaken in accordance with level of required risk reduction.
IEC 61508 covering electrical, electronic and programmable electronic safety-related systems, was first published more than 20 years ago, establishing a process was which could apply to any industry. Since then, almost all industries which have safety-critical software / hardware systems have created their own standards many of which are based on the IEC 61508, for example:
(ISO 25119)
Coding standards are key
Of course, the whole issue of how to write code that is guaranteed to be safe and secure is not always straightforward. This is where coding standards have a big role to play. They capture many person-years of expertise and give developers a set of rules to follow, which gives them confidence in the code they write. As a bonus, they also lead to more consistent, readable and thus understandable code that helps to reduce future maintenance effort.
Functional safety standards do not specify which coding standard to use – they just indicate that a suitable coding standard should be used and its use should be properly documented.
For example, ISO 26262 mandates the use of coding guidelines and specifies the topics that are recommended - or highly recommended - to be encompassed by those guidelines. Topics such as the use of a safe language subset, and the use of naming conventions are highly recommended.
MISRA C and MISRA C++ are two of the most well-known and widely used coding standards. MISRA C was first developed in 1998 for the automotive industry and has since been extended for use in any safety-critical system. MISRA C++ followed in 2008 since when they have become leading coding standards for critical software in all industry sectors.
Later, the AUTOSAR C++14 Coding Guidelines were developed to address the need for a safety-critical standard for modern C++. The MISRA consortium is planning to merge these rules into an updated version of its C++ standard in the near future.
The CERT coding standards have been developed by a community of experts with a focus on security, coordinated by the CERT division of the Software Institute at Carnegie Mellon University. With the growing awareness of the cybersecurity issues that can be introduced through poor coding practices, the use of CERT C and C++ for embedded applications is expected to increase
In practice, many organisations choose to fully or partially adopt multiple coding standards to meet their specific needs. Some organisations take a more flexible approach. For example, the NASA Jet Propulsion Laboratory developed a set of just ten rules that are intended to eliminate C coding practices that make it difficult to review or properly analyse with static analysis tools.
Regardless of whether they are obligatory or not, adoption of coding standards is gaining momentum in all areas of software development.
Best practice
There are some important issues to take into account when implementing coding standards, first of which is managing cultural change. There can be resistance to new processes and tools, so it is important to involve the development team in the selection process and adoption strategy. It is also essential for everyone to understand the business rationale behind the changes, for example: to ensure the safety of a product; meet a customer need; achieve external certification; and ultimately increase sales and ensure business success.
While it is possible to use manual code reviews to check code against a standard, an automated static code analysis tool is needed for any project of significant size. Much faster and more accurate than any human reviewer, a static analyser is capable of finding thousands of different types of potential defects at the earliest possible opportunity. Static code analysis integrates well with the ‘continuous improvement and test’ approach of DevOps.
A static analyser is able to scan an individual developer’s code changes before they are committed, as well as automatically scanning the code for the entire project as part of a continuous integration process. To help apply static analysis to a legacy codebase, some tools provide a baselining feature that gives visibility only to newly introduced issues, and other features that allow the team to easily prioritise reported issues.
The requirement to ensure the functional safety of software in embedded systems is only going to increase, so putting in place a strong foundation of coding standards, tools and processes will pay dividends both now and in the future.