This “Product How-To” article focuses how to use a certain product in an embedded system and is written by a company representative.
As microprocessors get increasingly more powerful, so does appetite for additional software functionalities. Size of embedded systems software increase every year and new types of problems is caused as a result.
The software industry agree that the largest problems while developing software is no longer how to write the individual code lines; today's problems are more related to managing ever increasing code complexity, increasing development costs and delays, geographically separated project teams, and too low quality in many software products.
Still, it is surprising to see that almost all integrated development environments for development of embedded systems software focus on the same tasks as 20 years ago, mostly the traditional chain of editing, compiling and debugging only.
With better development tools, covering a wider field of problems facing software developers in their everyday work, development times can be reduced and software quality can be improved.
Admittedly, tools have been improved over the past 20 years, but it is still primarily the traditional steps of editing, compiling and debugging that are handled. Editors are of course better today; developers expect features like expand/collapse of code blocks, spell checking of text in C/C++ comments, functions for visualization and navigation of the code structure, etc.
Today, embedded compilers handle C++ as well as C, and code size is improved even if that is less important in the new powerful 32-bit devices. The difference in size between compilers from different vendors is marginal on most cases, and the free GNU compiler is in many cases even better than some commercial compilers. Debuggers are better too, but it is still functions for execution of code and inspection of variable values that are in focus.
By looking at tool support in a wider perspective, development teams can start to address the problems that really cost money, delay projects, and cause companies to deliver software products of low quality.
Modern C/C++ tools ought to extend the traditional features (editing, compiling and debugging) with new features covering support for design and documentation, team collaboration, traceability in code changes and better tools for improving software quality.
One way of improving the work methodology is to better describe what should be developed before coding starts. This can be done with UML, a standardized graphical language for visualization of software using a number of different types of diagrams. Examples of diagram types are class diagrams, activity diagrams, sequence diagrams, state-chart diagrams, etc.
Atollic TrueSTUDIO is an example of a C/C++ tool that integrates graphical UML editors right into the C/C++ environment (see figure 1), to give developers better possibilities for requirements capture, and to model the static structure as well as dynamic behavior of the application.
Fig 1: Graphical modeling integrated in a C/C++ tool from Atollic.
UML tools for embedded systems have traditionally been very expensive and often required a change of work methodology at the entire development department. A much cheaper and softer way info graphical UML modeling is to choose a C/C++ environment with UML-editors built-in right from the start.
Manage the code
Most seasoned development engineers have experienced changed requirements, the code needs to be extended and modified, experienced developers leave the project and after some time, no one knows how the code works or why. Furthermore, no one remembers when a certain change was made, or what the code looked like before.
A good solution that all companies ought to use is a version control system, essentially a database containing all files in the project, including all older versions of them from the project start. A good version control system shall not only store all earlier versions of a file, but also the complete directory structure.
A version control system gives full traceability, and it is easy to work out which program line was added by whom, when and why. It is also easy to revert to earlier versions, and to create parallel code bases that can later be merged again. Releases can be labeled so it is easy to restore the source code for a specific earlier release.
Fig 2: Accessing a version control system from inside a C/C++ environment.
A version control system is a must if several engineers work simultaneously in the project, especially if they are located in different geographical locations. With a version control system, several developers can work in the same source code file simultaneously, and “check-in” their changes independently from each other. Other developers can synchronize their local work copies with the latest changes from the server at select times. All developers thus have access to the latest changes in a file, independently of who made the change.
Version control systems are often classified as team collaboration tools, and it is true that they are very useful in projects with several developers. But a version control system is equally useful in smaller projects with only one single developer, as it gives full traceability and it becomes easy to find earlier versions of the code and to track changes over time.
Many popular version control systems are available on the market, both commercial and open-source. One of the most popular ones has been the now aging CVS, which largely has been replaced by the newer Subversion (SVN). Subversion is open-source and thus free of charge, is successfully used by many companies world-wide, and is deployed on a team server or on a single developer's computer.
A modern C/C++ IDE ought to have deep integration to popular version control systems. Figure 2 for example show the integrated support for subversion in Atollic TrueSTUDIO.
Manage feature requests and bug reports
In the same manner as it is important to keep track of code changes over time, development teams ought to keep track on all feature requests and bug reports as well. These issues are typically stored in a centralized issue management system (often called a bug database) on the server. Several bug database systems are available free of charge, such as Bugzilla and Trac.
A modern C/C++ development tool ought to be able to connect to a bug database server, and provide integrated features for listing, searching and editing of bug reports and feature requests right from inside the C/C++ environment.
Fig 3: Integration of the bug database into the C/C++ environment simplify daily work.
Some tools go even further and integrate both code editing and debugging towards the bug database system. Atollic TrueSTUDIO for example, remembers which files were opened the last time work was done to a specific bug report, and if the bug report is activated (maybe weeks) later, the editor will automatically open the same C/C++ files that were opened the last time work was done on that bug.
Other features integrated into the Atollic TrueSTUDIO product is possibilities to document the state of the debugger using screenshots, which can be attached to a bug report. The screenshots from the debugger can be cropped and annotated with arrows and text, right from inside the tool. The next time someone open the bug report, the screenshot from the debug session is available as additional information related to the bug report.Finding errors using a debugger is often necessary, but to fix a bug, it must first be detected. It is far cheaper to find the bug before the test phase is started, not to mention before the product is delivered to customers.
Companies who develop software for safety critical systems (such as the aerospace industry) have become good at finding software errors even before the product goes into the test phase. This is achieved using a stringent requirements definition and code reviews where developers study each other's code and thus identify potential problems.
Code reviews are by many considered to be one of the cheapest and best ways to improve software quality, but surprisingly enough there has been virtually no tool support for this until now in the embedded industry.
Fig 4: TrueSTUDIO integrates code review features in the C/C++ environment.
Modern C/C++ development environments ought to integrate code review functions, in the way that has already been done in Atollic TrueSTUDIO (see figure 4). Using this tool, a project manager or a team member can easily create a code review session by defining what files in the project shall take part, and what team members shall become reviewers.
Reviewers can then study the source code files in the editor using their own computer, and add code review comments to various source code lines using a couple of mouse-clicks in the editor. Review comments are classified by the reviewer (such as logic error, portability problem, maintainability, etc) as well as priority (such as critical, major, minor etc).
In the second phase of the review, all reviewers sit down and discuss all the different review comments together, and optionally assign them to different team members for fixing.
Using this simple methodology, software quality can be improved. Reviewers can study the code in their own time, and all team members taking part in the code review meeting improve their coding skills by learning from the colleagues and their mistakes. Now that functions for code reviews are getting integrated into professional C/C++ environments, there is no longer any excuse not to use this methodology, at least for the most critical parts of the application.
What has been tested?
Code coverage analysis is commonly used to study what parts of the code have been tested. There are many different types of code coverage analysis, from very simple analysis up to very stringent types.Code coverage analysis is often classified formally. The more advanced types of code coverage analysis (such as MC/DC described below) are often used for development of safety critical software.
As an example, RTCA DO-178B (a standard for development of flight safety critical software) requires MC/DC testing of software on “Level-A criticality”, the most critical part of airborne software, where a software error can lead to a catastrophic situation with loss or aircraft or human lives.
Many projects also outside the aerospace industry would benefit from better control of what has been tested. In particular this is valid for companies with high production volumes, or products that are difficult to upgrade in the field. The same goes for products where the supplier want to keep its good reputation and where bad-will can be costly for the company.
For these reasons, code coverage analysis ought to be used to verify whether the software has been tested well enough before delivery to customers. Examples of different types of code coverage analysis are:
– Function coverage. Which of all C/C++ functions have been called during execution?
– Function call coverage. Which of all alternative calls to a specific C/C++ function have been executed?
– Statement coverage (classification: C0-level). What code lines have been executed? This measurement does not say everything about why or under which circumstances a line has been executed.
– Decision/branch coverage (classification: C1-level). Has both the TRUE and FALSE part in all if-statements (or more generally, all alternative execution paths in decision/branches) been executed?
– Modified condition/decision coverage (classification: MC/DC-level). This is a very advanced type of code coverage. To fulfill MC/DC coverage for a code section, the below requirements must be fulfilled at least once during the test execution:
1. Each decision tries every possible outcome
2. Each condition in a decision takes on every possibly outcome
3. Each entry and exit point is invoked
4. Each condition in a decision is shown to independently affect the outcome of the decisions
Code coverage analysis on MC/DC-level is of course very complicated without sufficient tool support. There are however tools that do this automatically, such as Atollic TrueSTUDIO depicted in figure 5. This tool instrument the application, run it in the target system, and present the MC/DC analysis results right in the C/C++ environment on the PC.
Fig 5: Code coverage analysis in target using a tool from Atollic.
The fact that the code coverage analysis is run in the target system is important; if it is done in a simulated environment on a PC, interaction with the target system (users push buttons, other systems send communication packages etc) cannot be done properly. Timing and code execution paths might become different, thus deprecating the value of the analysis.
The software industry has been progressing rapidly over the last years, and developers of Windows software have very powerful tools at their disposal. At the same time, tools for development of embedded software are still more or less on the same level as years ago, and only offer features for editing, compiling and debugging for the most part.
It is time to give embedded system developers proper tools, in the form of highly integrated products that cover a much wider set of problems. Such tools are already available, and will give development projects better possibilities to delivery well designed software with improved quality.
Magnus Unemyr is Vice President of Sales & Marketing at Atollic AB in Sweden.