When do you need one? Just about always

I like to keep "bootloader" for the ROM and use "loader" for the code I write.

I have worked on a number of loaders for the automotive and aviation industry using CAN, LIN, RS232, ethernet, on a wide range of embedded DSPs and controllers.

I just completed extending a vendor supplied loader for the SAMv71 to use a serial driver. The Atmel AT16743 app note has a nice discussion of generic loader concepts before it gets into SAMv71 specifics.

This app note makes a distinction between privacy, integrity, and authentication which are all important to keep in mind. Privacy is encrypting the firmware and/or the communications. Integrity means using a CRC or hash to verify the update. Authentication is verifying the identity of the sender and receiver of the firmware. It also covers the decision on whether to jump into the app or loader and several ways to make the decision.

In my experience it's always good idea to have the ability to update the loader itself. The loaders I have worked on were setup to run entirely from ram. The complete loader upload is saved in ram until the entire update has been validated. At that point, the loader flash is erased and written. This reduces the window of time when the device could lose power and become a "brick". With aviation, automotive and marine, products using loaders we have never bricked a unit in the field. The loader doesn't need to be updated very often if the design is kept simple and it is well tested.

I make provisions keeping not just a loader and an application in flash but for multiple components (parameters, models, production calibration values, and at least one reserved space). Each component uses the same structure with it's own version and fingerprint and each is delivered in it's own binary file. (usually a .hex) The GUI and the loader understand this structure and can updates any or all of these components with no additional overhead. The loader only requires the application to be valid to make the jump. It's the applications responsibility to validate the other components.

In the early days, we used a hardware pin to instruct the loader to stay in the loader. We sometimes put a jumper or switch across a pin in the serial port db9. Lately, we have been relying on a "jump signature" shared memory location between the application and the loader to decide when to stay in the loader. With this approach, there is some risk of locking up the application that you won't be able to set the "jump signature". A locked up application will still reboot on the watchdog and you can have the loader check communication before jumping to the application.

I highly recommend having the capability of reading the version AND the fingerprint(CRC/SHA hash) of every component (bootloader, application, parameters, models, etc...) that reside in flash. Not knowing the exact software resident in flash is a recipe for confusion. My first two questions when debugging a controller are is it plugged in and what versions are on it.

One of the other posts mentions the loader initializing memory, gpio, etc. We have the loader test and initialize what it needs but the application is responsible for initializing everything it uses. It doesn't need to retest memory checked by the loader but it does need to initialize everything it uses. The application can not rely on power up values nor the state the loader may have set up. This is useful when you use a debugger which may not go through the loader and it keeps the loader requirements untangled from the application.

Development Stories

I was involved in one project where the loader worked fine until just prior to a production deadline. The loader was tested early in the project when the application was relatively small. During development the developers needed to use a jumper to disable the watchdog to use the debugger. The size of the application grew from one sector to five. During the final tests, the watchdog jumpers came off and the watchdog would occasionally reset during the application sector erase. At this point many of the controllers had passed the hardware quality tests and were sealed up. Being about to update the loader to refresh the watch dog during the sector erase saved a lot of expense. It also taught me to always fill and test the application at maximum size.

Keep in mind the field conditions and always test the bootloader under worst case conditions. I have worked on shipboard CAN interfaces with extremely long cables and aviation systems mounted near strong motor interference. Being able to slow down the baud rate can make a difference when conditions get bad or the customer has a slow laptop. But slower isn't always better. Bit rate accuracy is critical. I fixed one project that had been using 115.2K serial communications and then switched main crystals in the DSP. The new crystal didn't divide down exactly to 115.2K and boot loader communications weren't 100% reliable. Most the time it would work, but you didn't know it failed until the entire application was downloaded. We suffered for quite a while before finding the cause and changing the baud to 128K which had no frequency error. The communications were more reliable at 1024K than at 115.2K because of the clock divide accuracy error. Make sure your communication setup is as accurate as possible. Clocks should divide exactly to the baud rate you want to use.

The ability to update the loader saved me on a Marine application. The controller used the internal oscillator and the original loader did not perform temperature compensation. It "worked" until you added long communication cables and temperature extremes when the loader started dropping bits.

And if you are dealing with CAN it isn't just picking a 500K bit rate. If another company or group is writing the loader UI you need to know what sample point they expect and choose the appropriate sample method and jump width sync to keep the loader functional over a wide range of termination, cabling, and environment conditions. It's not trivial to pick all the CAN quanta to get the UI PC and embedded device at optimal settings. But before your loader goes out into the field you need to assure the bit rate accuracy and all parameters give you as much margin as possible for clocks that change with temperature and cable capacitance. It may look funny to have a long coil of cable that could run the full length of a ship under your desk but using representative cables is important to CAN and communications in general so get your development setup as close as possible to the field install.

I would also stress keeping the loader requirements simple and reducing User interface opportunities for errors. The Atmel GUI with AT16743 loader reads the name of the .bin file and has the user enter the starting address. What were they thinking? The starting address exists in the .hex file. Why would you give the user the opportunity to make a mistake? Why would you add another UI item that needs to be tested?

An advanced bootload subject is what to do with when you have multiple devices on a bus or multiple buses. Multiple devices on the same bus are the norm for CAN. What happens to the other devices during updates, do they keep talking? A further complication is that some devices may be on multiple CAN buses but the UI for update may only have access to a subset. With careful planning, you can update everything on your network via a single bus. You may also wish to simultaneously update multiple devices. This may not seem important until you have dozens of devices on the bus and minutes per update with expensive systems and labor the costs add up.

Last but not least, think about manufacturing. You need to get the loader into the controller at least once. In the old days, we would provide programmed EPROMs. Today most systems have flash internal to a SMD micro. As an engineer you will probably flash the loader via an emulator. But what are they going to use on the factory floor the first time? Most microcontrollers come with a basic bootloader in ROM that can boot from serial, CAN, etc. Make sure your hardware guys make these pins easily available during manufacturing builds. The ROM bootloader may require manipulating certain pins. Make sure these pins are available during manufacturing. Don't expect a lot of quality or support for the ROM bootloaders. Expect garbage and you won't be disappointed. This is probably the biggest reason not to depend on the ROM bootloader from the silicon vendor. Make sure you test the provided bootloader utilities, because they probably won't be improved. I have been on multiple projects where ancient PCs running XP were kept around for years because they were the only machine that could talk to the ROM bootloader.