Chip shortages are disrupting products that rely on electronic components, forcing companies to redesign their products and make urgent adjustments based on using available components.
Creating applications using standard components and approaches—keeping a flexible architecture and portability options in mind—can help companies create resilience and react faster to market disruptions.
If products are already built, however, and your supply chain is disrupted, you have to find new suppliers of chips and components and modify the firmware to accommodate the new microcontroller or microprocessor.
Enterprises with agile development processes in place can have an advantageous position in this environment. These companies continuously refine products, adjust features, and validate new designs, which helps in planning designs for portability.
Porting existing applications to alternative MCUs or building new firmware and validating new designs is a solution to combat the shortage of chips.
Firmware Porting (Software Porting)
Ideally, firmware must be designed to run on different MCUs and processor architectures with very few modifications.
It is possible to adjust existing firmware regardless of the MCU, microcontroller architecture, operating systems, and platforms. It especially makes sense to adjust the code if the costs are lower than creating a new code.
Benefits of Developing Portable Firmware
• Lower costs realized from reusing libraries and components
• Improved final products
• Develop less code and shorten development cycles
• Better documentation and fewer maintenance efforts
Firmware Porting Basics
Product managers try to build products on microcontrollers with defined generic interfaces and simplify the reuse of software, allow testing of new components, and combine software components from various vendors.
Developing portable code is a good strategy for businesses, particularly doing so in programming languages such as C or C++ in a standard accepted version that can use well-defined implementation mechanisms (constructs) to improve portability.
Code should be built in a modular fashion (loosely coupled) with few dependencies and cohesive elements that can execute specific functions (microservices architecture) to each peripheral.
Portable code should have a clean interface and detailed documentation that is easy to understand as well as a hardware abstraction layer included in the architecture.
Design of Embedded Software Architecture for Planning Portability
It is recommended that an architecture be developed in layers (decoupled), with boundaries between components, and low-level code separated from the application, which will allow us to reuse the components in developing other products. This process sets the location of the interfaces (API or HAL) with their functions and declarations for controlling software.
APIs define the interface of components’ capabilities and behaviors, ideally coded in a generic form, independent of their implementation, so they can be reused only by modifying the implementation part.
MCUs are designed with peripheral features that interact with the system and define its function, while the CPU’s architecture defines the type of code that can be used. Consider using the firmware libraries provided by the manufacturer, as these simplify the configuration and control of its components.
The overall system integration varies between manufacturers, with different implementations designed to optimize each system specific to its intended solution. As a result, many aspects can impact performance and how the code is built and ported.
• System bus and function integrations
• Memory structures and integrations
• Coordinate functions (clocks)
Hardware peripherals have registers that are set up differently among manufacturers, and they provide functions that work with their firmware libraries (using different register structures), or they may have specific or dedicated peripherals with unique functionality.
Firmware libraries are the codes created by the chip manufacturers that provide functionality for the application and help set the registers that control various system aspects. They are easy to set up through API calls, helping to reduce development time. But different or dedicated library functions may have issues and complicate firmware porting.
Microcontrollers integrate the CPU, memory, and peripherals uniquely and provide native features integrated with the coded application that are adjusted when doing the firmware porting process.
Hardware abstraction layers (HAL) provide definitions for accessing the elements of the CPU core, registers, and peripherals, helping with library portability. However, IoT Development teams still look at the relationship between the peripherals and their structure to function correctly. In addition, the different integrations of CPU, peripherals, memory, and different firmware library functions complicate the creation of standard abstraction layers and extensible custom features that work for different manufacturer products.
For example, microcontrollers based on Arm Cortex processors have defined generic interfaces that simplify reusing software and reduce the costs of migrating software between ARM-based Cortex processors. The Common Microcontroller Software Interface Standard (CMSIS) is a hardware abstraction layer for ARM-based processors that provides a standard for coding a microcontroller. But these standards only interact with the MCU’s core, leaving out the entire microcontroller, and may have functional limitations.
Firmware code controls the hardware with the CPU, peripherals, and closely integrated components. Also, different MCUs’ features, advanced functionality, unique peripherals, and code compatibility must be considered when doing firmware porting.
If an application runs on top of a Real-Time Operating System (RTOS), it is simpler to create an abstraction layer so it can be ported to another MCU that support the same RTOS and the same features, as the application is separate from the hardware. RTOS has standard APIs that define how to use the software. The FreeRTOS kernel has been ported to several microcontroller architectures.
Clients using specialized libraries provided by the MCU manufacturer often find it more difficult to port to other manufacturer’s chips, as they have proprietary information. In addition, even if chip suppliers use the same core, they might have developed firmware and peripherals for different use cases and, thus, may require rewriting library functions in the code (or adding layers to the software), making firmware porting a specialized job.
Building applications that rely heavily on specific MCU features and highly optimized software makes porting more complex.
IoT developers try to use the manufacturer’s existing HALs and APIs, as they understand their hardware, but must also evaluate if they are compatible with development tools to save on development time.
A firmware specialist at Krasamo can assess your IoT developers while exploring your porting software needs and HAL characteristics, as well as evaluate existing HALs, target microcontrollers, development time, and other details.
It is possible to develop and implement your own HALs to meet your use case requirements and control a microcontroller, avoiding lock-in with its toolchain by leveraging the know-how of experienced IoT engineers. Also, building API functions for common components to create generic and standard calls (interfaces) is a good strategy that should be aligned with each client’s product line evolution.
Considerations for Designing
• Compare APIs and HALs, modules, components, libraries, and frameworks (platforms) and review their characteristics.
• Review RTOS and its APIs, characteristics, and standard API interfaces.
• Develop APIs to improve and support multiple MCUs to increase reusability and speed up development.
• Understand memory regions and mapping techniques in your programming language.
• Discuss design methods of component integration with the application (inputs/outputs, effects, conditions, etc.).
• Compare microcontrollers’ data sheets.
• Understand how to implement device drivers and discuss the reusability of design patterns across platforms.
• Talk about programming languages and embedded programming techniques.
• Implement and test HALs on several MCUs.
• Test peripherals.
• Revise application frameworks from chip manufacturers.
• Discuss bootloader frameworks (firmware update capabilities).
• Discuss best practices for building portable firmware.