Designing Safe & Secure Embedded Systems Best Practices
April 21, 2021
Software development projects for embedded systems are faced with a variety of challenges.
Time limitations put developers under pressure to complete project requirements within strict and, in many cases, inadequate timelines. Further, expectations for reliability, accuracy, and performance of embedded software are greater than that for real-time computing. We also need to consider constraints of the actual target hardware that the embedded software runs on. Software compliance and certification requirements are commonly imposed by industries to address safety and security.
Process standards offer processes, verification methods, and best practices to ensure with a sufficient level of confidence that the software is secure, safe and of quality. These include:
ISO 26262 (automotive)
IEC 62304 (medical)
IEC 61508 (industrial)
EN 50128 (rail)
Software verification and validation is a crucial component to adhering to process standards. It's a process that involves different software testing techniques that can be rigorous, expensive, and time consuming.
Employing one or two software testing techniques won't cut it. Using a variety of automated approaches during the development life cycle will save you time and money. It will also help create a reliability reputation, which is priceless.
Automated Testing Methods for Embedded Software Development
Automation is essential for testing embedded software because manual approaches are error prone and time consuming. Let's discuss important automated testing methods that will help your team.
Static Code Analysis
To start, I highly recommend to always employ static code analysis as the first testing method. A wonderful advantage to performing static analysis is that you can introduce and use it at any stage of a project. Static code analysis is effective even if a project is incomplete and partially coded because code execution is not required.
The biggest challenge with introducing static analysis is that a large amount of code can produce a large number of warnings. When integrating static analysis into a project it's advised to focus on the following:
Getting the team productive as soon as possible.
Minimizing the opportunity for the team to get overwhelmed by all the static analysis warnings.
This is not to diminish the importance of these warnings. However, most developers don’t have the luxury of fixing existing or legacy code. Not immediately, at least.
Because there are various coding compliance standards (MISRA C:2012, AUTOSAR C++14, SEI CERT, CWE, and so on) start with a goal in mind. If security is the key goal, it makes sense to enable all security-related rules, disable less important rules, and enable one of the built-in secure coding standards, like CERT C/C++.
Dynamic Analysis Methods or Runtime Error Detection
As previously mentioned, one testing method is not enough. It’s not possible to identify all bugs or defects through static analysis only. Dynamic analysis methods or runtime error detection are a testing practice to employ as well.
This testing should be linked to requirements. It examines the running code, exposing architectural and behavioral flaws, other weaknesses and/or security vulnerabilities, including memory leaks and more.
Teams can apply this type of testing at various levels of software abstraction. Starting with testing each individual unit or function, then integrating additional software parts. Eventually software testing the system as a whole or black box. This is commonly represented in the well-known V-model software life cycle.
Structural Code Coverage
Within dynamic analysis methods are the overlaying of other techniques that can be applied, like structural code coverage.
In a nutshell, structural coverage is the identification of code that has been executed and logged for the purpose of determining if the system has been adequately tested. If you can determine the code that has been exercised through test case execution, then the uncovered or unexecuted code exposes the need for additional tests.
If your compliance requirement is to obtain 100% code coverage, you will need to perform coverage by way of unit testing and manual testing at minimum. Though we could continue down the path of revealing other testing methods like regression, performance, stress, API, UI, acceptance, and more, lets dive into modern deployments for testing of embedded systems.
Continuous Integration and Continuous delivery
A topic that's increasingly gaining popularity during the past several years, is continuous integration and continuous delivery (CI/CD). CI/CD is the software development practice of nightly integration (combining smaller build units into apps, libraries, or components) with the intention of building testable software for continuous delivery and early detection of build/integration issues and errors.
CI/CD in embedded software development is often constrained in ways application development isn't. Besides the physical and computational constraints of the target hardware platform, there are compliance constraints. The marketplace for embedded software has unique requirements for safety and security with extremely long life cycles. Products can remain in the market for decades.
Today, some organizations incorporate static analysis into their CI/CD modern development workflow. Adaptation has generally been around Git-based development environments with a dynamic approach to branching and merging, where developers can specify a parent/reference branch to compare against their current development branch and automatically compare and compute the delta for analysis.
So, instead of running the analysis on the entire project, which may take considerable time, even hours, it can be run on a minimal set of files. This reduces the duration of the evaluation session and focusing. Coding violations can then be addressed and remedied for a clean, safe, and secure build.
Containerized Development Environments
Another type of modernization comes from containerized development environments. Containerized deployments of development tools are becoming the bread and butter of embedded development teams.
Even though containers were initially developed to solve problems with the deployment of microservices and web-based applications, they recently gained popularity among embedded teams. Especially with big teams that use containers to manage complex toolchains.
When it comes to managing complex development environments, especially in the safety-critical space, teams usually struggle with the following challenges, which are easy to solve with containers:
Synchronizing upgrades for the entire team to the latest version of a tool like a compiler, build toolchain, and so on.
Dynamically reacting to a new security patch for the library or software development kit (SDK), and the like.
Assuring consistency of the toolchain for all team members and the automated infrastructure (CI/CD).
Ability to version the development environment and restoring it to service the older version of the product that was certified with the specific toolchain.
Onboarding and setting up new developers.
In the example below, you have Parasoft C/C++test accessing the containerized compiler (GNU GCC) and the runtime environments. There are two separate Docker containers, one for the compiler and build tools and another for the execution environment (for example, stripped version of embedded Linux).
In this example, Parasoft C/C++test standard can be used as a command line-based tool, which is suitable for in-container deployments. It can be packaged with the compiler and build system into one container image and used for CI/CD and deployed to developers’ desktops for the local command line scans. The image below shows the high-level overview of this setup.
The following example can be done by automation or each team member can pull a consistent development environment where containerization offers the following:
Development environment versioning
Centralized management and deployment
Immediate reaction to security vulnerabilities
Lower onboarding cost
Discover How Industry Leaders Are Delivering Safe & Secure Software
If you want to streamline your team workflow, cut costs, and improve time to market, then learning about the challenges, solutions, and modern approaches in development of embedded safety- and security-critical systems is important to you.
Hear from industry leaders and learn from real life experiences at the Embedded Testing and Compliance Summit on Thursday, May 6, from 8 a.m. to 10:30 a.m. PT.
You'll have the opportunity to join the conversation and ask questions! Here's a preview of what they'll share:
A medical device technology company successfully adopted a unit testing solution and gained value right from the start.
An avionics developer and manufacturer achieved code compliance and streamlined productivity.
An automotive data platform provider delivered the first safe, secure, and scalable platform for fully autonomous vehicles.
A software tool chain development company for embedded systems accelerated the CI/CD pipeline with build tools for Linux for Arm.