Welcome to a six-part series on “Making embedded processing development easy.” This is the third vignette created to introduce you to the fundamentals of embedded software design and considerations to aid with embedded processor design. This series is derived from the expertise of embedded processor software experts from Texas Instruments and is meant to provide an objective view of easing software design.
This week’s edition is brought to you by Steven Magee, software architect, embedded processing, Texas Instruments, while the earlier two parts were carried in the last two weeks respectively.
Q: I really would like to protect my software investment and re-use my code. What’s the best way to do this?
A: We completely understand this desire and it is a consistent priority of our customers across microcontroller, microprocessor, DSP and embedded processing product lines. Customers desire products to have very long life cycles so that end-systems can be deployed for many years with no changes. They also want a wide variety within our product lines – that is they want price, performance, functionality and flexibility with maximum software compatibility. Customers also require multi-generational compatibility and want to see future generations that are backwards-compatible on a very detailed level. Embedded processing companies, like TI, strive to address these needs. Most are now recognizing the value of helping to protect their customers’ software investments.Still, silicon-level compatibility, while necessary, is not sufficient to maximizing ROI over a long period of time. We find that there are important issues in software development itself that must be successfully addressed. To get started on this exploration, here are a few questions that can help you proceed:
1. Are you planning for software reuse?
A good first step in the reuse process is to decide whether or not to spend effort planning for reuse. If reuse is nplanned, then programmers just reuse applicable software they know is available or happen to discover is available. In this case, components are not developed with reuse specifically in mind, so the likelihood that the component will be reusable exactly “as is” becomes reduced.
Planning for reuse requires much more effort and commitment not only from the software developer, but also from management. Management must take a longer term view beyond the immediate project since the reuse payoff will only be realized after multiple projects have benefited from the components.
Creating reusable software in many cases requires a well-planned architecture which modularizes components and specifies certain rules the software must follow. Ideally, each individual component would be developed to ensure it provides a feature set that spans multiple use cases. Typically, new features will be required from the component. So, thought should be given to the component API and the component design such that it is easily extendable without drastic modification of both the component and the software using the component. When extending the component, providing backward compatibility will allow use of the component with the original API and also with the updated API.
2. Consider the scale of software reuse – is the reuse for a function, module, subsystem or higher level application?
The larger the software code base is, the more difficult it will be to reuse. Therefore, the software targeted for reuse should be modularized so the system integrator can pick and choose modules that meet the needs, modify others that partially meet the needs, and develop from scratch those that don’t.
To make software easy to reuse, the component should be well documented so potential users will understand what features are supported, how to call the component and what limitations may exist. Documentation and example code using the API provided by the component are important to the programmer trying to reuse the component. In many cases, the example code provides not only some of the best documentation on how to use the component but a great set of code to start with when creating the larger system. The internals of the component itself should be well documented, including a design document and comments in the code to help with understanding during debugging and potential modification for feature addition.
3. Is the software to be reused of good quality?
The quality of the component is also a factor in reuse. The component should be well tested so that few bugs will be encountered. If the component to be reused contains too many bugs, then the programmer trying to reuse the component may spend more time debugging it than if he wrote the component himself. Debugging of a reusable component is harder since the programmer may not be familiar with the code and has to spend time to understand the inner workings. Of course, reuse of a component across multiple projects can also help harden the component since more people will be testing against it and reporting bugs that can be fixed for everyone’s benefit.
4. Do you have a place to store and search existing software components?
To aid in the software reuse, repositories or databases should be created to store software components so that others will know what’s available. It’s preferable to appoint a database owner to ensure components are properly archived. The database owner can also help to make sure components are following reuse guidelines to help make the software the most reusable.
5. Are you planning to reuse large software modules/subsystems or utilize code through frameworks?
Reuse of larger software modules like subsystems or higher level applications involves a different set of factors to consider compared to smaller components. To reuse complete subsystems, the subsystem must be designed to work properly with many other parts of the system. To achieve this, layering is frequently adopted with well-defined APIs specified at each layer. These layers help abstract the subsystem from other parts of the system that might need to change in future products. The underlying layers can be modified without affecting the API or the subsystem calling the API. Some examples of layers that are used for portability across devices and end product applications are hardware abstraction layers and OS abstraction layers. Care must be taken when architecting the layers, otherwise the layers can lead to excessive overhead or complexity that makes debugging more difficult.
In some cases, reuse is fostered through the use of frameworks which allow components to be plugged together to create larger subsystems. Frameworks have specific rules that components must adhere to. All developers creating components for the framework must follow those rules so the components can then be plugged into the framework and work properly together. Multi-media is one area where frameworks are commonly adopted for audio and video processing. Multi-media frameworks such as G-Streamer, OpenMAX or DirectShow can be used to build pipelines of video and audio elements. Note that in many cases, a particular framework may be available and well suited for one operating system (OS) but may not be available or as well supported on another OS. Therefore, the system manufacturer may have to work with a variety of frameworks to create all the desired products.
6. Does your software involve components developed by other entities?
Reuse may also involve components developed by other entities to reduce development effort and improve time to market. These may be purchased components or open source components, but the cost of these options must be accounted for. The purchased components typically require up front cost but may also require yearly support fees or even royalties for each product shipped. Many believe that using open source code is without cost; however, there are various costs that programmers must consider. Sometimes costs are incurred because of the frequently changing nature of open source code for enhancements. For example, when using the Linux OS, migration of the product to a new Linux kernel may be required to pickup new features and bug fixes. Therefore, the project will require someone familiar with open source development to be able to keep up with the changes. Many open source components are targeted at desktop PCs and may require optimization to meet embedded system performance. Legal council may be needed to achieve compliance with open source licensing requirements.
Software development teams must be cautious when integrating open source software with their proprietary software. Unless the software system is properly partitioned and structured to meet requirements of open source licenses, any new code may be considered open source code. Because of this, the system manufacturer may be obliged to contribute the new code back to the open source community. By carefully partitioning the system’s software architecture, the risks of this happening can be reduced.
Some technology companies have taken steps to avoid open source licensing issues. Most software from TI, for example, comes with a ‘software manifest’ which fully explains and delineates the sources of the code and any third-party or open source licenses or obligations associated with it. Furthermore, these software manifests and the software itself are reviewed by the company’s Open Source Review Board to ensure the code is properly structured and architected for the protection of the system manufacturer.
In the end, the best, highest level of software re-use will be achieved when the system manufacturer’s software development teams have:
Management support;Time to architect, develop and test for reuse;A software component database.All programmers engaged in the reuse processDevelopers can then adequately mix and match previously developed code, adding or subtracting product features and functionality to quickly meet the requirements of a particular product offering.
Next week, we’ll discuss open source and when to utilize the open source community. Future topics include graphics and multimedia programming, as well as security.
Read other parts here:
About the author:
Steven Magee is a software architect in the embedded processing team at Texas Instruments. He has served in a variety of software systems engineering roles in TI’s video, audio, and emerging end equipment businesses. Magee received his bachelor’s in mechanical engineering from Louisiana Tech University and his master’s in electrical engineering from Louisiana State University.