There are few projects where embedded firmware developers have more time than they need for a project. In fact, embedded firmware development is more like a gas: they take up all the available space. Often times this means that test and quality review are under pressure at the end of a project, which increases risk. So while project managers wring their hands over meeting schedule deadlines, embedded designers and test engineers are also at odds for development time versus quality of test coverage.
But what if everyone could have what they wanted? What if hardware builds could continue to progress without being code complete? What if firmware test could continue even during production builds, and what if the whole team knew that if worst came to worst they could always do a field upgrade to make critical changes? Everyone might actually be able to sleep at night. I've got good news: this is possible with the use of an embedded bootloader.
First, let’s get our lexicons in sync. A bootloadable is code that will be loaded into memory and become the main application code running on the microprocessor during normal operation. It resides on the microprocessor forever, either in ROM (Read Only Memory) programmed in the factory or in a reserved portion of on-board Flash memory. The bootloadable can be updated via a “bootloader”. It is this on-board bootloader (Figure 1 ) that makes it possible for a product's firmware to be updated in the field.
A bootloader resides in protected program memory on a given microcontroller. It is usually the first software to run after power up or reset and is highly processor- and board-specific. The bootloader could be considered a “dumb” piece of code in that it doesn’t understand what application needs to be performed or even what the device function is. Rather, it is specially designed to understand communication from the outside world via any number of communication protocols (UART, I2C, SPI, CAN, Ethernet) and to understand the memory map of the microcontroller. When the bootloader does its job, it communicates with the outside world, or host, reads the data file sent by the host, and updates the Microprocessor in which it resides to run the new application code provided.
Depending on the embedded system, bootloaders can begin their operation upon receiving a boot signal from a human (i.e., manual reset) or a peripheral device (i.e., the system host). This bootloader signal will first validate whether the bootloader itself is valid, determine whether the current device application is valid or not, communicate with the host to load the new application being presented, and then execute the application Flash rewrite as directed.
Most modern microcontrollers have the ability to reprogram their own Flash. A typical bootloader can accomplish this in microseconds. With larger memory sizes, however, this time increases quickly and can sometimes take several seconds for an update. Once bootloaded, the bootloader must validate the bootloadable image and turn over control to the bootloadable code. Pointers to interrupt vectors must also be set. Typically, a bootloader will perform a soft reset to allow the application to take over. Figure 2 shows an example bootloader logic flow.
Because the bootloader is programmed into a device at manufacturing and is not the primary application necessary for device operation, it can be considered “overhead” code. The project manager and embedded designer, however, must decide if the risk protection afforded by a bootloader is worth the code space it consumes.
As a result of this code space use, many designers try to keep the memory footprint of the bootloader as small as possible. This maximizes the available memory for application code. As a minimum, bootloaders must supply the following: a communication channel, a method to erase and reprogram Flash memory, and a method to validate and execute newly programmed application code.
Additionally, a bootloader should be able to detect, report, and handle errors that occur during the bootload operation, such as power failure, loss of communication, and Flash write error. Flash error protection is usually done by storing a checksum or Cyclic Redundancy Code (CRC) for the application.
When the bootload operation is started, these bits are cleared. If the new application is downloaded and installed successfully, the checksum is updated. If, however, an error occurs during download (such as loss of communication or power failure), the bootloader detects invalid check bits and does not begin application operation. Instead, it communicates with the host and waits for a valid retry of the bootload operation.
Another key consideration is to prevent code from overwriting the bootloader area itself. If a bootloader attempts to, or accidently does, overwrite itself and an error event occurs, the bootloader can be left inoperable. The next time the processor boots, the bootloader most likely will be corrupt. The effects of this could be wide ranging. It is possible that the bootloader would not be able to open the communication channel to the host or that the system might not turn over control to the last valid bootloadable image.
Either way, the result will require a reprogram of the entire system.Reprogramming typically requires a qualified technician with developmenttools in hand to plug into the board. This tends to defeat the appealof the bootloader. Proper control over device memory locations iscritical when developing a bootloader. Special care must be taken toensure memory locations are managed and changes to application size donot improperly erase or rewrite bootloader memory. To prevent potentialrewrite problems, some microcontrollers even put the bootloader in ahard-coded bootload read-only memory (ROM) that is separate from Flash,as shown in Figure 3 .
Figure 3 shows four memory spaceexamples. The left-most graphic is a normal non-bootloader applicationprogram. The typical tool chain will place the application code ataddress 0 and the entire Flash memory array is eligible to be used forapplication code space. If this type of system is put into the field as areleased product, it cannot be remotely modified. Upon reset theapplication code begins to execute. Any bugs or defects in theapplication code are permanent.
In the left center is an exampleof a bootloader with bootloadable image in ROM. This configurationallows for the full Flash space to be used for the application becausethe bootloader resides in separate ROM memory. This option protects thebootloader from being mistakenly overwritten, but if the bootloaderneeds to be updated, it will not be impossible. ROM is written once andcannot be reprogrammed or fixed if a defect is discovered.
Inthe right-center graphic, the bootloader is shown located at address 0and executes first out of reset. Once the bootloader has determined thatthe bootloadable image is valid and there are no commands from the hostto re-image the part, the bootloader will turn over control to thebootloadable application. You can see how the bootloadable image startsjust after the bootloader image ends. This maximizes the quantity ofmemory available for use by the bootloadable image. The last image showstwo sections of memory used for two different bootload events.
Inthis case, the bootloader may decide which application will be rununder different bootup operations as directed by the host. This approachconsumes double the Flash space as it requires holding two completeapplication programs, but it is quite an efficient design methodology ifengineers desire to have single device operate differently underdifferent host-directed conditions.
Themost obvious benefit of a bootloader is the ability to fix errors inthe field. Products can also benefit from feature updates. For example,customers have been known to launch products that are designed withbasic functionality to get to market faster only to later release abootloadable update to change OS drivers, product features, update powermanagement options, etc.
Bootloaders allow design teams to getto market with a future roadmap of hardware updates. For example, somecompanies use a radio link for communications to provide remotemonitoring of equipment. These companies have found it morecost-effective to deploy updates to equipment over the radio linkcompared to having a technician visit a remote site to update firmware.
Considerthe case of fleet management in the trucking industry. Taking a vehicleout of service for something as minor as a code update or enhancementis expensive. Just the shop time for code upgrades can run into thehundreds of dollars. Remote bootloading can provide tremendous value forfielded products.
So what makes a bootloader a good bootloader?While there are many answers to this question, one of the principlerequirements is ease of use. Making a bootloader that allows designersto easily choose and connect to a serial communication port is critical.Additionally, providing a convenient method to get into the bootloaderor to bypass the bootloader and directly access the application areimportant as well.
Once created, the bootloadable image becomesdependent on the bootloader. Having to determine where the bootloaderimage ends and the application can begin is also tedious and prone toerror. A good bootloader should handle these issues automatically andwill also give the designer the flexibility to use multiple applicationimages. These dual bootloadable systems are sometimes referred to asmulti-application bootloaders. This type of bootloader will load the newimage to a separate area in memory. Once validated, the bootloader willeither copy that image over the existing application or just switchover to that image for execution.
Consider the way this isaccomplished in the bootloader used in the PSoC3 and PSoC5LP families ofproducts. As shown in Figure 4, the communication component is selectedvia a dropdown menu. A time to “Wait for command” to enter thebootloader (2s in this example) can be configured to a settime. Allowing the designer to select from checksum types is alsoconvenient.
Onthe bootloadable side, it is nice to have numerical revisionidentification. This allows the firmware to automatically determine if anew bootloadable image is out of date. The image in Figure 4 shows howdesigners have the flexibility to specify the application version andID. In addition, designers have the ability to manually move theapplication image to a desired memory address.
Finally, one ofthe key issues noted above is the risk of memory overwrite. The toolchain in the bootloader used in the PSoC3 and PSoC5LP families ofproducts automatically locates the end of the bootloader and thebeginning of application address to remove this risk. Since the entirepoint of using a bootloader is to strategically eliminate risk, this is agreat feature to employ.
So, if all or your projects are ontime, all of your code is perfect, and all your firmware engineers arecode-complete before hardware must be built, then you really have no usefor a bootloader. If you are like the rest of the world, there aresubstantial benefits for implementing a bootloader in any embeddedsystem your organization develops.
Bootloaders allow a productto be updated after launch for any number of reasons ranging fromcatastrophic bug fixes to planned product feature upgrades. The keyissues while bootloading, however, concern the flexibility and ease ofthe bootloader itself as well as the code space and configuration usedfor the bootloader. But in the end, a well designed bootloader justmight save your product, just might save your team, and just might saveyour sanity.
David Durlin is a Principle Field Applications Engineer at Cypress. He has been in this position for 6 years. Prior to Cypress David was a FAE for Future Electronics. The first six years out of University David gained experience in design of instrumentation and lighting in heavy equipment. David also designed microcontrollers at Zilog.
David’s hobbies when not at work are making beer, designing and programming home automation projects.
David received his undergraduate degree in Electrical Engineering from University of Idaho.
Now living in Washington and can be contacted via email at email@example.com.
Trevor Davis is a Cypress veteran who has worked within several different product groups at Cypress. He has most recently led the World Wide Business Development organization for Cypress’s TrueTouch products and is now the Regional Sales Manager for the Rocky Mountain region in the USA. Before TrueTouch, Trevor served in several different Product Marketing and Business Development leadership roles for Cypress Programmable System on Chip (PSOC), USB products, Network Search Engines, CPLDs, and Software products.
Trevor received his undergraduate degree from the United States Air Force Academy and also holds his Masters in Business Administration. Trevor has worked in high technology positions for the military, nonprofit, and commercial sectors. Trevor lives in Seattle, WA and can be reached at firstname.lastname@example.org