Vous êtes sur la page 1sur 3

by Shawn Prestridge, IAR Systems

by Shawn Prestridge, IAR Systems Constructing a bootloader Please note that this article describes how to

Constructing a bootloader

Please note that this article describes how to create a bootloader for an ARM target, using IAR Embedded Workbench for ARM. The steps involved may differ for other targets.

As software becomes more and more complex, the potential for defects to exist in shipped code increases exponentially. It is therefore becoming quite common for design specifications to call for the ability to dynamically update a device’s firmware in the field. This is done commonly via a bootloader. In this article, we will discuss some of the issues involved with developing a bootloader and show you how to set one up with IAR Embedded Workbench.

The pragmatics of designing a bootloader are somewhat difficult to discuss because there can be so many different requirements placed on it, e.g. the mechanism for getting the new application into the MCU; for some, it will be through the USB peripheral of the MCU, for others, it might be through the Ethernet peripheral and TCP/IP and still others might choose to do it through the venerable RS232 port. Because a bootloader is a very common thing to do, it is highly advisable that you check with your silicon provider’s Field Applications Engineer to see if they have already created a sample bootloader project for your MCU which can greatly simplify your construction of a bootloader to fit your needs.

In the IAR Embedded Workbench hierarchy for project management, the workspace is the top-level entity and is what opens when you start the tool suite. Workspaces can have multiple projects contained within them; for this article, I have attached a workspace with two projects—a main application project as well as a bootloader project.

Within the workspace, we can control in what order the projects are built. For our purposes, we want the application to be built first and then the bootloader; this is because we will place the application image in the bootloader when the bootloader is built. This can be done using the “Batch build” facility available from the IAR Embedded Workbench IDE by clicking Project-BatchBuild. You can edit the batch to add projects to the build as well as rearrange them in the order that you would like for them to be built.

There are compelling reasons to NOT place your bootloader and application in the same project. First, IAR Embedded Workbench will generate a massive binary (especially if the bootloader and application start addresses are far apart). If there are peripheral addresses between the end of the bootcode and the start of the application code, you may experience flashloader failures when they try to write blank bytes to those addresses, thus necessitating a rewrite of the flashloader. Even if this isn’t the case, a bootloader will most likely have a statically allocated array for code reception that will waste space when the application is running. By having them as two separate applications, the linker can more efficiently allocate memory. Yet another compelling reason is that you cannot independently revise your bootloader or application—if they are in the same project, touching one automatically means touching the other and can therefore lengthen the test-and-fix cycle for your project.

As previously stated, we want to allocate space for the bootloader and then place the application in the unused space. For this example, the idea is to set up the linker so that all of the code for the main application project is placed above a certain address (0x2000 in this case) and all of the bootloader code is placed below that address. Once this is done, it is possible to produce a binary image of the main application project; the advantage of doing so is that you can import the binary image of the main application into the bootloader project which will allow you to download the bootloader and main application all at once with the debugger. To summarize, we do the following:

Page 2


1. Create a project for the main application.

2. Set up the linker to place all the code (and constant data) between the start of the space reserved for the application and the end of memory.

3. Set the output converter (Project-Options-OutputConverter-Output) to create a binary file. The binary file is simply the content of the memory, i.e. there is no formatting or address information of any kind.


1. Create a project for the bootloader.

2. Set up the linker to place all of the code and constant data between 0 and the end of the space reserved for the bootloader (0x1FFF in this case).

3. Set up the linker to import the binary file created in part 1 above; this is done from Project- Options-Linker-Input. The linker will treat the binary image as though it were a constant array and simply copy its contents to the address specified in the linker configuration file. The linker must be given a symbol name for this image as well as in which section to place this image and the number of bytes to on which to align the image. The linker must also be told to keep this symbol in case the symbol is not referred to in the bootloader—any symbol not specifically referred to by an application will normally be removed. In the attached example, I have chosen to make the symbol name “application”, the section name “.app” and the alignment 4 bytes.

4. Set up the linker to place the section “.app” at the desired location. To accomplish this, I have defined two memory regions called BOOTROM_region and APPROM_region in the attached flash_bootloader.icf. The binary image is placed in APPROM_region and everything else

goes in BOOTROM_region.

Debugging To download the main application without erasing the bootloader, you must configure the flashloader. The flashloader is a small piece of code downloaded through the JTAG into RAM and is what takes the application code from the JTAG and programs your code into the flash of your device (or perhaps into an external flash part on your board). We must modify the flashloader to program only a certain range so that we don’t overwrite the previously written bootloader (or vice–versa). By looking in the application’s Project-Options-Debugger-Download, you will see that the “Use flashloader(s)” and “Override default .board file” options are checked. To change the range over which the flashloader operates, click the “Edit” button, then select the flashloader and click “Edit” once more. In the flashloader configuration dialog box, you will see the memory range box for the flashloader—set this range to exclude the part you do not wish to erase.

In general, debugging a bootloader can be a bit tricky since you will only have source-level access to either the bootloader or the application at debug-time. It may be useful to implement a well-crafted delay loop in the startup of the application to allow you time to halt source-level debugging of the bootloader and begin source-level debugging of the application. In your application, choose Project- Options-Debugger-Download and click the box for “Attach to program”—notice that this deselects the “Use flash loader(s)” box. “Attach to program” allows you to non-intrusively attach to a running board without halting or resetting it. Once you have selected “Attach to program”, click OK and then click “Debug without downloading” to attach to the board. You can now press the Halt button in the debug toolbar to see where you are in the delay loop, set breakpoints or whatever you need to do to debug the application. To summarize the debugging:

1. Insert a delay loop of 10–15 seconds in the startup routine of the application.

2. Modify Project-Options-Debugger-Download in the application project settings to “Attach to program”.

3. Batch build in the order of the application first, then the bootloader.

4. Download/debug the bootloader (which also downloads a binary image of the application).

5. Debug your bootloader—when it hands off execution to the application, exit the debugger to allow the delay loop to execute.

Page 3

6. Switch to the application project and click “Debug without downloading” to attach to the board.

7. Halt the board to see where you are in the delay loop and/or set breakpoints.

8. Debug your application!

Creating a bootloader can be somewhat tricky, but with these tips and tricks you should be well on your way to creating a successful dynamic software update mechanism.