lucky
Microchip staff
   
Reged: Oct 06 2003
Posts: 1204
Loc: Brisbane, Australia
|
|
Bootloaders
With flash memory becoming more readily available in micro-controllers, the possibility of software updates in applications can now more easily be realized.
Firstly, for those of you who are not familiar with bootloaders; a bootloader is a utility which reads a program from a communication channel, writes it to program/data memory and executes it. It therefore allows the possibility for programs to be updated or changed at a later date without requiring special programming hardware. Often products refer to this feature as "flash upgradeable".
In this tutorial I will describe the implementation of a bootloader for a Microchip PIC processor (16F877A), however, the same procedure could be applied to many other types of processors (8051, ARM, MSP430, etc.).
The first thing to do when developing a bootloader is to decide exactly how it is going to work and under what situations. Below is a list of things that should be considered:- Is the bootloader interacting with a user or another processor(s)?
- How will the updated program be presented to the bootloader? Will it simply be a HEX file, or will it come in another form.
- Will a special program and/or protocol be required to transmit the updated program to the bootloader?
- How much program memory is going to be available for the bootloader and where in memory will it be located?
- Will the bootloader have to take care of any relocation requirements such as redirecting interrupts, etc...
For this particular example, we have decided the bootloader should have the following features:
- Since PIC's don't really have that much program memory, we need to make the bootloader as small as possible so as to maximize the available space for downloaded programs.
- For this example, the bootloader will interact with the user to do its updating. We would like to make it so that the user doesn't require any special downloading program. They should be able to use a regular terminal program such as Windows HyperTerminal.
- Because we won't be using a special downloading program, it will mean that HEX files will be sent directly to the bootloader and so it will have to interpret this directly.
- It would also be nice if programs which are intended to be downloaded to the bootloader, didn't require special changes to the code or complicated linker options in order to be compatible.
Before any coding starts, we should first think about how things are going to be positioned in program memory. Since the bootloader needs control after reset, it will mean that it will need to use the reset vector. Since we want to make it easy to build bootloader compatible programs, it is best if the bootloader is positioned entirely at the start of memory, or, all at the end of memory. On mid-range PIC's, the regular interrupt vector is located at address 0x4. If the bootloader was going to be positioned entirely at the start of memory, it would then have to redirect the interrupt vector to the downloaded program. Since this would add complexity to the code and latency to the vector, we have decided to position the bootloader at the end of memory. We will still need the reset vector, however, so this will mean shifting the downloaded program's reset vector elsewhere. Below is a diagram showing the memory map of a program with and with-out the bootloader installed.
As shown in Figure A, typically the reset vector contains instructions to jump into the main program. Because the bootloader needs the reset vector, we therefore must move the downloaded program's reset vector elsewhere. Figure B shows how the reset vector now points to the bootloader code and the downloaded program's reset vector will be positioned to an address just before the bootloader.
How it works:
- On reset the bootloader will take control and prompt the user to send a hex file. It will wait here (with count down) for a configurable number of seconds.
- If no hex file is sent, the bootloader will assume that no update is required and it will jump to the redirected reset vector which in turn will run the previously downloaded program. If no program has ever been downloaded, the redirected reset vector will simply contain a jump to the beginning of the bootloader and the whole process will start again.
- If a HEX file is sent to the bootloader within the count down period, it will start interpreting the data and writing it to program memory. The bootloader will look for addresses less than 0x4 (reset vector) and will instead write this elsewhere. It will also ignore addresses conflicting with those used by the bootloader, thus protecting itself from being overwritten.
Compiling the bootloader: Since the bootloader will live at the end of program memory, we can make use of the -A compiler option to shift it to the desired location. Some assembler code with an absolute psect will put the reset vector at address 0x0. Compiling downloaded programs: Since the bootloader will live at the end of program memory, we will have to make sure the downloaded program won't use those addresses. To do this we can use the compiler's -RESROM option which allows us to reserve those memory addresses. Because the bootloader takes care of redirecting the reset vector, nothing extra has to be done.
Attached is commented source code for the bootloader and a sample program to download to it. Also included are MPLAB projects which can be used to build these programs and a text file which describes in more detail how to compile the bootloader and downloadable programs. This bootloader is suitable for the following processors: 16F870, 16F871, 16F873, 16F873A, 16F874, 16F874A, 16F876, 16F876A, 16F877, 16F877A.
Update 23 March 2007 This and previous versions (and a PIC18 version) of the bootloader are available in the source share forum.
|
Daniel
Reged: Nov 28 2003
Posts: 167
|
|
Bootloader at the end or at the start of the memory? I don't agree with your choice. Chips like the PIC16F87x/A can make the first page of their program memory (0-FF) write protected. Putting the bootloader in this area, ensures that it will never get accidentally erased, either during programming or during normal operation. This is why I wrote my own bootloader; all the examples I could find (yours or Microchip) where located at the end of the memory. The resulting code is as transparent to the user as it would be with the loader at the end of memory. True, the interrupt latency is increased by 4 cycles (2 jumps). Bye, Daniel
|
lucky
Microchip staff
   
Reged: Oct 06 2003
Posts: 1204
Loc: Brisbane, Australia
|
|
Quote:
Bootloader at the end or at the start of the memory? I don't agree with your choice. Chips like the PIC16F87x/A can make the first page of their program memory (0-FF) write protected. Putting the bootloader in this area, ensures that it will never get accidentally erased, either during programming or during normal operation.
Thanks for the feedback.
Yes - this is true. Actually the previous version of our bootloader was located at the start of memory but we moved it to the end because of the problems it was causing with interrupts. The problems we had were:
A user program is running some code which happens to be located towards the end of memory. An interrupt occurs and it vectors to address 0x4. The problem occurs because we now have to jump to the redirected vectors. A simple goto isn't enough because PCLATH is still pointing to the end of memory. So for this to work we would have to save and change PCLATH. But if you save PCLATH, it means you are going to use the W and STATUS registers which will also need to be saved. Now even if you save all of those things, you'll need to restore them which means you have to somehow put this inside the user's interrupt code. It's not impossible because our previous version worked this way. It just meant there were quite a few instructions before getting to the actual interrupt and it also meant the user program had to have some code inserted. Perhaps you had a different/better way of solving this problem?
I know a lot of people have written their own bootloaders. If anyone has a better or alternative implementation which you don't mind sharing - feel free to post it here.
-------------------- Matt Luckman
Microchip Technology Inc.
|
AndrewH
Reged: Oct 16 2003
Posts: 12
|
|
Can this version of the bootloader be built using PICC Lite, or do its restrictions on code size, available options etc prevent this? When I attempt I get a curt "BUILD FAILED" error message.
|
lucky
Microchip staff
   
Reged: Oct 06 2003
Posts: 1204
Loc: Brisbane, Australia
|
|
Quote:
Can this version of the bootloader be built using PICC Lite, or do its restrictions on code size, available options etc prevent this? When I attempt I get a curt "BUILD FAILED" error message.
It would be possible to use the bootloader with on a 16F877[A] with PICC-Lite, however, PICC-Lite only supports 2K of program memory. So that would mean if you wanted to build the bootloader, you would have to use the -A option set to 0x700 (assuming you're not using ICD).
A better option would be to use the pre-built HEX file I've included for the 16F877[A] which puts the bootloader at address 0x1F00. PICC-Lite will still limit your user program to 2K, but at least the bootloader is not consuming any of that space.
-------------------- Matt Luckman
Microchip Technology Inc.
|
fmaimon
Reged: Jun 03 2004
Posts: 5
|
|
Is this bootloader still compatible with PIC downloader 1.08?
|
lucky
Microchip staff
   
Reged: Oct 06 2003
Posts: 1204
Loc: Brisbane, Australia
|
|
Quote:
Is this bootloader still compatible with PIC downloader 1.08?
No. One of the hassels of the older version was that you needed a special downloading program. This version of the bootloader doesn't need that - just send a hex file to it.
-------------------- Matt Luckman
Microchip Technology Inc.
|
AndrewH
Reged: Oct 16 2003
Posts: 12
|
|
Quote:
A better option would be to use the pre-built HEX file I've included for the 16F877[A] which puts the bootloader at address 0x1F00. PICC-Lite will still limit your user program to 2K, but at least the bootloader is not consuming any of that space.
Presumably then PICL does not just limit you to 2K of code space, but it has to be the FIRST 2K of code space? i.e. the program must be wholly contained within 0-0x7FF?
|
lucky
Microchip staff
   
Reged: Oct 06 2003
Posts: 1204
Loc: Brisbane, Australia
|
|
Quote:
Presumably then PICL does not just limit you to 2K of code space, but it has to be the FIRST 2K of code space? i.e. the program must be wholly contained within 0-0x7FF?
Yes - it must be the first 2K.
-------------------- Matt Luckman
Microchip Technology Inc.
|
dfnr2
Reged: Jul 27 2004
Posts: 11
|
|
This seems to be a nice little bootloader--simple, clear, and extensible. I have a couple of questions.
1) With reference to the above discussion, why can't a bootloader be in the first page, but above the interrupt vector, with the reset vector still jumping to the bootloader?
2) Are there any likely difficulties in compiling the bootloader to high memory as a function other than main, and redirecting the reset vector to it, but also calling it from the main program under the appropriate circumstance?
For example, I would like to incorporate a bootloader which would wait for a download if either a dongle is inserted or the program ROM has a bad checksum (bungled upgrade). Otherwise transfer control to the main program. The program itself would have an "upgrade" feature which invokes the bootloader.
Is there any special consideration, or the code be adapted straight up?
|