Embedded software developers have grown used to working at the lowest, nitty-gritty hardware level within a microcontroller based system. Twiddling and manipulating bits and bytes is what embedded software developers were born to do. The embedded software industry is changing and that change is requiring developers to start working at higher levels of abstraction which requires designing and creating APIs (application programming interfaces) that allow software to be reused. Let’s examine seven tips for developing great API’s.
1. Make it an Iterative Process
When designing an API or a HAL (hardware abstraction layer), don’t assume everything is going to go right the first time. There is no such thing as one API to rule them all and expecting to create such an API, especially on a single try, is a setup for failure. Instead, start with a draft API with the expectation that it will change slightly in future iterations. Usually over the course of three or four projects, the API will stabilize to the point where further changes are minor to non-existent.
2. Examine More than One Microcontroller Datasheet
If the plan is to create an API that can be used across multiple microcontroller vendors, developers must look at more than a single microcontroller datasheet. Developers should examine the same peripheral for multiple microcontrollers and make a list for all the common and uncommon features. The common features should be rolled up into the API since they are undoubtedly industry standard features while the uncommon features can be implemented in an API extension only if those features are required.
3. Use No More than 10 Interfaces Per Module
The human mind can only consistently remember approximately 10 to 12 pieces of information that belong together. Developers should aim to keep their API’s with no more than approximately 10 interfaces. Expanding well beyond this number will make it difficult to remember the calls and can also make the interface look complex and may even obfuscate understanding. Find ways to refactor interfaces by using control and configuration structures.
4. Test Pre-Conditions and Post-Conditions
A great API implementation will not assume that the calling function or application has done everything it is supposed in order for the function to work correctly. Developers should use assertions within the API to test that all pre-conditions are met and even to test post-conditions to ensure that the API has successfully performed its function. Don’t assume, as many developers do, that everything has been set up correctly and will execute properly. Design and implement the interface defensively.
5. Logical Naming Conventions
A great API will have logical naming conventions that allow developers to easily recognize and recall the API interfaces. Using cryptic letters at the front of API’s will often make developers scratch their heads and question what that symbol meant. Be explicit in the naming convention and follow best practice recommendations such as starting the naming convention from the general and working toward the specific.
6. Provide a Method for Extending the Interface
The goal is to create a great clean interface that is easy to understand and use but also contains the most common elements that developers need during their development. There are times when there may be uncommon features that developers will want to use in the microcontroller, such as a GPIO hardware debounce that every microcontroller may not have. In these cases, developers will want to make sure they have a mechanism built into their API’s that allow the interface to be extended. This can be done by allowing a pointer to a new interface structure or by creating register accesses into an API that allow low level manipulation and higher level interfaces to be created.
7. Build Interrupt Handling into the API
In order to make sure interrupts are handled properly, it is easier for the API developer to handle interrupts internal to the API so that interrupts are a black box to the API user. This means that there needs to be a mechanism used to assign functions to interrupt handlers in the higher-level application code. One way to do this is to add callback registration into the API so that interrupts can be assigned their executable code in the application code. This allows the API to ensure that interrupts are handled properly, but also allow developers to override those defaults with their own custom code.
Developing API’s and HAL’s are nearly a requirement now if developers want to decrease costs and time to market. Microcontrollers have reached a level of complexity, performance, and capability that are comparable to early x86 microprocessors. With such complexity in systems today, designing API’s to maximize code reuse is a must. These seven tips should help developers looking to reuse their own code more able to developer their own API’s and HAL’s.
To learn more about API and HAL design, listen to the Design News/Digi-Key Continuing Education Course “Designing API's and HAL's for Real-time Embedded Systems.”
Jacob Beningo is an embedded software consultant who currently works with clients in more than a dozen countries to dramatically transform their businesses by improving product quality, cost and time to market. He has published more than 200 articles on embedded software development techniques, is a sought-after speaker and technical trainer and holds three degrees which include a Masters of Engineering from the University of Michigan. Feel free to contact him at email@example.com, at his website www.beningo.com/, and sign-up for his monthly Embedded Bytes Newsletter.
Bootloader Design Techniques for Microcontrollers.
Remotely updating firmware is a critical for any embedded system and even more so for an IoT device. Bootloaders are often added along side application code to facilitate firmware updates but very few developers truly understand how to build one robustly. Join Jacob Beningo as he examines the fundamental challenges facing software engineers in performing updates in a secure and safe manner during his half-day tutorial, "Bootloader Design Techniques for Microcontrollers" at ESC Boston 2017 , May 3-4. Register today !