Best Practices on Embedded Firmware Development: Typical Challenges and Solutions
September 26, 2022 15 min read
Chief Technology Officer, PhD in Physics and Mathematics
Firmware is an integral part of any embedded system. A device is more than a combination of components. Without instructions, the microcontrollers do not “know” how to manage the peripherals. But embedded firmware development is not an easy task. It involves not only coding but a lot of testing and debugging as well. Today, we are going to talk about the common challenges of embedded firmware programming and their solutions.
Any embedded system requires firmware. Embedded systems, such as smart watches, microwave ovens, or TV remote control, have different peripherals. Their work is managed by a controlling element – usually a microcontroller. To function properly, the microcontroller needs “instructions”. Embedded firmware is specialized software that controls the work of the microcontroller.
Firmware can also be installed on microprocessors and FPGA, but in this article, we will only discuss the challenges of firmware development for microcontrollers.
You may have also heard the term “embedded software”. It is software designed for a particular device – in contrast to typical application software that can run on any computer or smartphone as long as they have the necessary operating system on them. If we compare embedded firmware vs embedded software, we’ll see that software controls higher-level functions of the device. Low-level functions are controlled by firmware.
However, the difference between embedded hardware and software is not distinctive. A task traditionally controlled by hardware can be handled by software and vice versa.
Other examples of devices running embedded software include fitness trackers, washing machines, calculators, robots, certain toys, medical devices, and many more.
Embedded firmware development is an integral part of designing embedded systems. We offer various custom firmware development services. Our team is experienced with 8, 16, 32, and 64-bit microcontrollers from the most popular manufacturers: Atmel, Nordic Semiconductor, Texas Instruments, STMicroelectronics, Renesas, Silicon Labs, and others. We mostly work with the Arm Cortex-M processor core family but are skilled with other alternatives as well, including AVR, PIC, and MSP430 microcontrollers.If you require embedded development from scratch, we can take care of both hardware and firmware development. If you already have a device that requires embedded software design, we can do that as well. If your device needs a real-time response, we will create RTOS-based firmware. If it simply needs to run a set of tasks forever as long as power is on, we can develop non-OS based firmware. We can also test, debug, and optimize your existing firmware and help with migration to new hardware. Contact our team to discuss your case.
Types of Embedded Systems
Based on the performance of the microcontroller, embedded systems are divided into the following types:
- small-scale systems (use 8 or 16-bit microcontrollers);
- medium-scale systems (use 16 or 32-bit microcontrollers);
- complex systems (use 32 or 64-bit microcontrollers).
By performance and functions, embedded systems are divided into four types:
- Real-time embedded systems
They are designed to give output signals at particular time intervals. Hence, they can provide a real-time or almost real-time response, which is why they require real-time based firmware. Such systems are used in time-critical spheres: healthcare, military equipment, traffic control, etc.
- Stand-alone embedded systems
Such systems can work by themselves without a host system (a computer). They only receive input signals, process them, and provide outputs. A washing machine, a calculator, or an MP3 player are typical examples of stand-alone embedded systems.
- Networked systems
Such embedded systems are connected to a wired or wireless network. Through this connection, they communicate with an embedded server to access resources and provide output to the attached devices. An ATM machine is a networked embedded system.
- Mobile systems
These systems are used in small portable devices such as smartphones, tablets, digital cameras. This type overlaps with stand-alone embedded systems. Basically, these are portable stand-alone embedded systems. All these systems require embedded software to function properly. Integra Sources has worked with all these systems and knows how to cope with the typical challenges of embedded system software development.
Typical Challenges of Embedded Firmware Development
Firmware can be a threat vector for embedded systems. Programmers usually focus on protecting applications and operating systems. But the first code to be executed on a device is firmware. And if a hacker gets access to this code, the entire system can be compromised.
In 2011, Charlie Miller, a security researcher, discovered a vulnerability in MacBook batteries. He was able to take control of the firmware of the microcontrollers that manage the batteries. As a result, Miller could infect the computers through the firmware and even make the batteries overheat and catch fire.
Intellectual property protection is another security issue common for firmware programming. One of our projects illustrates typical protection measures programmers can use for security. When we developed the Bluetooth musical pedal for turning music sheets hands-free, we had to secure its firmware updates. Using encryption for Over-the-Air updates is a standard practice here.
In this project, we used nRF51822 with BLE 4.0 support and Cortex-M0 core as MCU. For encryption, the team used the nRF Util development tool capable of generating cryptographic keys and device firmware update (DFU) packages. The tool allows you to encrypt the package before sending it over the air to the device.
Another project in our portfolio included embedded firmware and software development for a battery management system. Security was an important matter for the customer. Our team provided two levels of protection.
As the first protection level, our team used encryption. The system has several PCBs with microcontrollers, and each of them requires regular firmware updates. To launch the process, someone receives an update image – usually via email. This is when the file can be stolen. To make sure its content cannot be copied, our team encrypts the image files with the AES-256 algorithm. When the device receives the file, it decrypts the content before installation.
As the second protection level, the team protects image files with digital signatures. When the hardware receives the update, it checks the signature to make sure it came from Integra Sources. If the signature is incorrect or there is no signature at all, the device will not install it.
This measure is often used to protect devices from potential hacking attacks. Even if the hacker manages to crack the encryption code, the system will still ignore the update file because there is no correct signature.
Read our previous article to learn about the ABCs of battery management system design.
Lack of Memory
Embedded development is limited in available resources, and that includes firmware as well. As mentioned above, some embedded systems can be very small: TV remote controls, web cameras, MP3 players. The size, in turn, imposes limitations on the battery capacity, available processing power, or memory size. Moreover, as devices become smaller, consumers demand more functions to be implemented. Our custom firmware development services will help you resolve this contradiction.
One particular problem arising from design limitations is the available memory size.
As a rule, engineers try to find a workaround at the design stage of embedded system development. Designers can approximately estimate what memory size the device will need and know components of what size can be used. Moreover, our team tries to pick microcontrollers or microprocessors with a certain memory or processing power margin. We can estimate these parameters based on the number and complexity of the functions we want to implement.
Nevertheless, these estimations can be inaccurate, or the requirements can change during the prototyping phase. As a result, developers may have to optimize the firmware to fit into the available memory size.
Our team was having this issue with a graphical calculator for which we developed hardware and firmware. The calculator’s firmware had an input interpreter that processes mathematical formulas. The device also used an embedded language. The latter basically used the same syntax for expression evaluation as the interpreter. In other words, two functions are performed by very similar pieces of code.
Therefore, the firmware team added the unique functions from the interpreter to the embedded language and deleted the interpreter. This allowed us to save about 100 KB on the microcontroller’s flash memory.
Another way to optimize the firmware in terms of memory size is to use proper data types. If you need to store numbers from 0 to 100, a 1-byte data type is enough. But if the firmware uses a 4-byte data type to store the same numbers, the use of memory is inefficient.
In the project mentioned above, we initially used the double data type (8 bytes). It is more precise than many other types. But the calculator didn’t require this level of accuracy, so the team decided to use float (4 bytes) instead. Although float isn’t as precise, it requires twice as little memory space as double.
Using lighter data types will work with both constants and variables. If you know for sure that a variable’s value will not exceed 100, there’s no need to use heavier data types.
When embedded firmware developers deal with portable devices, energy efficiency becomes another challenge. It’s important to understand what functions the device needs to perform and what components can meet these requirements before starting the development process. Contact our team so that we could give you a word of advice.
A microcontroller’s energy consumption is composed of two power consumers: the processor core and the peripherals. One can make the device more energy efficient by optimizing the work of these two elements.
The obvious way to reduce the energy consumption of a processor core is to reduce the number of instructions it processes. In this case, optimizing the code will help.
Another way to do it is to use the microcontroller’s sleep mode. As a rule, we don’t need the core to work all the time. So, when processing data is not required, we put it to sleep. The core remains in this mode until an outside event occurs – for example, a timer interruption.
The firmware of the graphical calculator we created consists of a single cycle. During each cycle, the core polls the buttons. It happens 30 times per second and takes just a few microseconds. If it doesn’t detect any keystrokes, the core remains asleep the rest of the time.
As a result, the microcontroller consumes about 5 mA in the poll mode. For comparison, in the busy wait mode, it would have consumed about 80 mA.
Firmware developers employ the same approach to peripherals – by turning them off when they are not required. Another project we worked on used battery power as well. Due to extensive data package exchange, the device outputs logs regularly through the UART. However, when the exchange is not happening, the device stands idle. To minimize the UART’s energy consumption, we programmed it to turn off when not required.
Naturally, this method works only for outputs. Since the processor core performs instructions based on the signals from inputs, it is generally not a good idea to turn them off. In this particular case, the UART was used only for signal output.
If you want to learn more about efficient energy management in larger systems, read our article on battery energy storage systems.
Our team used a similar approach with the people and assets tracking device we helped to create. It uses BLE 5.0 to send and receive data packages every 7.5 milliseconds. During the connection, the BLE’s power consumption is at maximum. One of our goals was to reduce it as much as possible without affecting the channel’s capacity.
With the firmware, we programmed the device to buffer the data packages. This allowed us to increase the connection intervals threefold. During the intervals, the BLE’s power consumption is at minimum. So, longer intervals let us reduce the device’s power consumption.
Debugging is an unavoidable part of embedded firmware and embedded software development services, especially when it comes to designing complex devices. To find errors in the code, programmers use debugging tools. They allow you to run the code step by step and detect the pieces where the program crashes. However, some devices don’t have a compatible debugging tool. Arduino is an example of such devices.
In this case, one has to monitor what’s happening with the program by printing the required values, code lines, or text in a console – for example, by outputting the data through the UART. These lines are put into the pieces of code that presumably contain the error.
If the value, code line, or text are printed, it means the code is executed as it should be. If the line is not printed or the value changes, it means something went wrong at the previous step. One can also command an LED to switch on and off if the console is not available.
As one has to detect errors manually so to speak, this process is very tiresome and time-consuming compared to when you can use a debugging tool. But sometimes, firmware developers have no choice.
The firmware development process ends with a debug configuration of the firmware. In addition to the code required for the microcontroller, it contains debugging information. It allows you to see the code in the debugging tool and move through it step by step to find errors.
However, before downloading the firmware into the device, the debugging information is removed for the purpose of optimization. This version of the firmware is called the release configuration. Of course, by this phase the code would be double-checked for errors, so no issues should be detected after the installation. Problems can arise when you have to update the firmware.
In this case, the device starts malfunctioning after the update, which means the code contains errors. And programmers can’t use a debugging tool anymore, they have to use the method described above.
Updates and Over-the-Air Updates
Whenever new bugs are discovered or the users ask for new features, developers have to update the firmware. And this can become another firmware design issue – especially Over-the-Air (OTA) updates.
Updating a simple device is quite simple. But complex systems and particularly IoT devices require a more resourceful approach. Programmers have to deal with a number of issues: lack of memory size, insufficient bandwidth, version management, and, of course, security.
A common problem here is interruptions. Simple devices that lack memory size have to rewrite the firmware as soon as they receive the data. If anything interrupts the process, the firmware will be corrupted: for example, if the power shuts off before the installation is complete.
In the worst case scenario, the device will brick, and nothing can fix it. If the device has a bootloader, the firmware can be reinstalled. Nevertheless, when you deal with OTA updates, interruptions can be frequent. The problem is commonly fixed with backup memory.
When our team worked on a smart home project, it was clear that the device will be updated over the air. Bricking or malfunctioning because of interruptions were not acceptable. Therefore, the team provided the system with backup memory.
In this case, the update file is downloaded to the backup memory first. It can be either a file system or a flash memory area. After that, the device runs a data integrity check to make sure no byte was lost or changed during transmission. Only after that, the update is installed. Thus, interruptions cannot have serious consequences.
Any embedded system requires firmware to perform its functions. Whether you deal with small devices or want to create a complex system, their functionality and performance depend heavily on their firmware. Moreover, the quality of embedded software defines the stability of the device.
Developers regularly face various design limitations when they work on firmware. The size of the device, its power source, price, and other factors define what microcontroller can be used. This, in turn, leads to other problems, namely lack of memory or energy efficiency issues.
Another typical challenge is related to firmware updates. Over-the-Air updates lack stability, which causes interruptions in data transmission and eventually data corruption. Trying to install such updates directly without loading them to backup memory first can brick the device. Security is another important problem to solve, as firmware can be a threat vector for embedded systems.
And finally, developers often spend a lot of time on debugging. To make this process faster, developers need experience and professional knowledge.This is why many companies outsource embedded firmware development to electronics design firms like Integra Sources. We have worked with microcontrollers from various manufacturers, such as Atmel, Nordic Semiconductor, Texas Instruments, STMicroelectronics, Renesas, Silicon Labs, and others. Our experience with 8, 16, 32, and 64-bit microcontrollers allows us to offer all kinds of embedded firmware development solutions of any complexity. Get in touch with our team to discuss what we can do for your project.
Share this article