Internet of Things (IoT) sensor-based applications are expanding, and so too is the size and complexity of the microcontroller firmware in the IoT endpoint. This firmware must become more efficient to speed execution, which is one reason flash firmware updates in the field are a necessity. However, securely updating firmware in the field usually requires halting execution of firmware while the update is in progress. Depending on the architecture, the size of the update, and network speed, this can be accomplished in as quickly as a minute or as long as an hour. For critical applications this delay can be unacceptable.
This article explains the considerations for updating interrupt-driven firmware in the field and the need to keep executing application firmware while the update is in process. It then introduces the PIC32MZ2048EFH144T-I/PH microcontroller from Microchip Technology and shows how it can be used to execute firmware while simultaneously receiving updated firmware over a network.
The importance of firmware updates
Firmware is updated for four main reasons: to correct bugs in the code, to add or improve features, to make adjustments to system security, and to make firmware more efficient. Code efficiency is measured by the number of clock cycles it takes to perform a specific task or thread. The fewer clock cycles to perform a task, the more efficient the code, which speeds execution and usually (not always) reduces code size. This is especially true for IoT sensor-based endpoints as these applications are interrupt-driven and so must quickly switch context whenever a sensor or peripheral generates an interrupt.
Two factors affecting the efficiency of interrupt-driven IoT applications are the efficiency of the architecture, and the efficiency of the code. While it is impractical to change the architecture of a microcontroller in the field, it is practical and normal to update the microcontroller firmware to improve efficiency.
Sensor-based firmware is almost always interrupt-driven. Intelligent sensors connected to a microcontroller serial port can generate an interrupt to the microcontroller to halt normal execution so the firmware can vector to an interrupt service routine for that particular sensor. This is more efficient than sensors that need to be periodically polled to determine if the sensor reading has new data to transmit. The advantage of an interrupt-driven sensor strategy is that the microcontroller only spends clock cycles on reading the sensor when there is useful data to receive. Polling wastes clock cycles when firmware has to access the sensor to read data that is discarded because the sensor reading has not updated.
With multiple sensors and tasks comes multiple subroutines and interrupt routines to manage them, increasing code size. Complex code requires some form of real-time operating system (RTOS) to manage all these separate tasks. The RTOS can be a simple firmware application written by the software engineer or an off-the-shelf product. The RTOS manages the different firmware tasks to make sure each individual task starts and finishes within the time necessary for the application to operate properly. If many tasks need to be managed by the RTOS, it is beneficial for the application for tasks to finish in as few clock cycles as possible. This prevents different tasks from delaying each other.
When an interrupt is received, the time it takes to complete the interrupt service routine is mostly a combination of three factors:
- The clock cycles required to recognize the interrupt and begin to vector to the interrupt service routine. If the task is lower priority than the task that is running, this will be delayed until the present task is complete. This is application dependent.
- The clock cycles required to save the context of the present CPU state and vector to the interrupt service routine. This is architecture dependent and outside of the control of the software engineer.
- The clock cycles required to execute the interrupt service routine. This depends upon both the complexity and the efficiency of the code written by the software engineer.
The more efficient the firmware, the less likely a conflict will occur between tasks that need to finish within a certain period.
Flash firmware update memory requirements
Systems that need to be reliably updated in the field require twice the estimated flash program memory needed for the application. This is because the flash memory must be large enough to contain both the existing flash firmware and the updated firmware. However, it is common for small systems running only from internal flash program memory to halt code execution while the firmware update is being received over the network. This can be unacceptable for mission-critical applications and is contrary to the target of efficient firmware—i.e., code that is stopped is running at zero percent efficiency!
Executing firmware while updating flash
A high performance microcontroller that can execute firmware while updating the on-chip flash memory is the Microchip Technology PIC32MZ2048EFH144T-I/PH microcontroller (Figure 1). The PIC32MZ2048EFH144T-I/PH is based on the MIPS32 M-Class core architecture with a floating point unit (FPU) that targets complex interrupt-driven IoT endpoints. It has 2 megabytes (Mbytes) of program memory flash and 512 kilobytes (Kbytes) of SRAM. It also has 160 Kbytes of boot flash. The PIC32MZ2048EFH144T-I/PH core can run as fast as 252 megahertz (MHz) over a -40°C to +85°C temperature range, and at 180 MHz over -40°C to +125°C. Operating voltage is a low 2.1 volts to 3.6 volts.
It has nine 32-bit capture/compare timers to support complex firmware as well as measuring external signals.
Figure 1: The 252 MHz Microchip Technology PIC32MZ2048EFH144T-I/PH is based on the MIPS32 M-Class architecture and has a wide range of serial ports for interfacing to external sensors. (Image source: Microchip Technology)
External serial ports include nine UARTs and five I2C ports. There are six SPI ports that also support the audio I2S interface. A 12-bit analog-to-digital converter (ADC) with 48 inputs can measure voltages from precision analog sensors. With these many serial ports and ADC inputs, the PIC32MZ2048EFH144T-I/PH can interface with many external sensors, making it appropriate for complex sensor-based IoT endpoints. Two CAN 2.0b ports allow the microcontroller to network with industrial and automotive networks that use the common CAN protocol.
An Ethernet port supports 10/100Base-T networking. A USB 2.0 Hi-Speed controller supports an external interface for additional peripherals or debugging, and also supports USB On-The-Go (OTG).
Each of these peripherals can generate one or more interrupts. With so many sensors and interrupt sources, maintaining code efficiency becomes a necessity.
To improve efficiency the MIPS32 M-Class CPU core has 32 32-bit general purpose registers (GPRs). This improves efficiency by reducing accesses to external memory. Besides the usual bit set and clear instructions, the M-Class also supports single-cycle bit invert instructions. This improves RTOS efficiency by increasing the efficiency of semaphore handling. The core also has a five-stage instruction pipeline that improves efficiency by minimizing memory access conflicts, resulting in more single-cycle instructions.
The MIPS32 M-Class also has seven GPR shadow register sets. This significantly improves interrupt performance and context switching by eliminating the many clock cycles required to save the GPRs on the stack. With seven shadow register sets, the core can nest interrupts and context switches seven deep before having to spend clock cycles saving the GPRs on the stack.
The PIC32MZ2048EFH144T-I/PH has two 1 Mbyte banks of program flash memory (PFM), designated PFM Bank 1 and PFM Bank 2. Each PFM has its own dedicated boot flash memory (BFM) designated BFM Bank 1 and BFM Bank 2. The BFM does not need to be updated during a PFM update. Having these two separate banks of memory has multiple advantages. For example, the microcontroller supports dual booting, so on power-up it can be configured to boot from either flash memory bank. This allows the microcontroller to support two different device configurations.
The two banks of flash also provide the added advantage of allowing firmware execution from one flash bank while updating the firmware in the other flash bank. Microchip refers to this as Live-Update, also referred to as run-time self-programming (RTSP). When RTSP is initiated in an active IoT endpoint executing firmware out of PFM Bank 1, firmware is received over the network in blocks. The recommended method for managing firmware updates over a network is to store the block of new firmware in SRAM. After receiving a complete block, the firmware executing out of PFM Bank 1 can initiate a programming sequence of the SRAM data into PFM Bank 2. While this firmware is being programmed, firmware execution out of PFM Bank 1 can continue.
When the block programming is completed, firmware can request the next block of code over the network and the sequence repeats. This continues until the block of code in PFM Bank 2 is completed. Once the programming is complete, firmware can configure the PIC32MZ2048EFH144T-I/PH on the next reset to boot from BFM Bank 2 and execute the new firmware in PFM Bank 2 by clearing the SWAP bit in the NVMCON configuration register (Figure 2). If the PIC32MZ2048EFH144T-I/PH firmware must be updated again while SWAP=0, firmware can execute out of PFM Bank 2 while simultaneously updating PFM Bank 1.
Figure 2: The PIC32MZ2048EFH144T-I/PH microcontroller has two independent banks of PFM. If SWAP=1, firmware can run out of PFM Bank 1 while PFM Bank 2 is being updated. Clearing SWAP=0 allows the microcontroller to boot out of PFM Bank 2. (Image source: Microchip Technology)
The status of the SWAP bit can be changed from either the BFM or the PFM depending upon the needs of the firmware.
Developing dual-boot firmware
For development with the PIC32MZ2048EFH144T-I/PH microcontroller, Microchip Technology provides the DM320007 PIC32MZ starter kit (Figure 3). This board supports multiple serial ports using dedicated connectors as well as header connectors. A USB Host port is used for debugging while a USB OTG port can be used for the application. A USB-to-UART/I2C connector, when connected to a PC USB port, creates a virtual COM port on a connected host PC. This allows the host PC to communicate to the I2C port on the PIC32MZ.
Figure 3: The Microchip Technology DM320007 compact starter kit supports the development and testing of USB and Ethernet applications with the PIC32MZ2048EFH144T-I/PH microcontroller. It includes connectors for USB OTG, USB Host, 10/100 Ethernet, and UART/I2C. (Image source: Microchip Technology)
A 40-pin expansion header connector allows access to additional I2C, SPI, and UART ports as well as general purpose I/O (GPIO) pins on the PIC32MZ EF. There are three pushbuttons and three LEDs that can be configured by firmware.
IoT sensor endpoints in critical systems are demanding higher memory requirements due to increased code complexity. The more complex the code, the more it is necessary to improve firmware efficiency in order to improve the response times of context switching in the firmware. By selecting a microcontroller that can efficiently run interrupt-driven code that can simultaneously retrieve and update firmware, developers can improve the reliability of critical IoT applications without sacrificing performance.