3
\$\begingroup\$

I'm confused about how to allocate boot loader memory space in the pic18 micro controller and spend sometime researching on it and landed up here .

I'll put my question :

I have a controller whose linker script looks like this and it defines the memory sections of the controller (which includes the SFR,GPR and other memory starting and ending locations).

My question is how does the boot loader should be placed in micro controllers, should they be kept on the starting of program memory? I'm having this doubt because one one example this guy advocates keeping the boot loader on program memory locations 0x000-0xfff

USB-HID bootloader link

Should all bootloaders replace the starting address of programming memory if we want to use boot loaders? Is there any thing we need to be careful while allocating space for bootloaders?

/

Original linker fileof pic18

/ File: 18f47j53_g.lkr
// Generic linker script for the PIC18F47J53 processor

#DEFINE _CODEEND _DEBUGCODESTART - 1
#DEFINE _CEND _CODEEND + _DEBUGCODELEN
#DEFINE _DATAEND _DEBUGDATASTART - 1
#DEFINE _DEND _DATAEND + _DEBUGDATALEN

LIBPATH .

#IFDEF _CRUNTIME
  #IFDEF _EXTENDEDMODE
    FILES c018i_e.o
    FILES clib_e.lib
    FILES p18f47j53_e.lib

  #ELSE
    FILES c018i.o
    FILES clib.lib
    FILES p18f47j53.lib
  #FI

#FI

#IFDEF _DEBUGCODESTART
  CODEPAGE   NAME=page       START=0x0               END=_CODEEND
  CODEPAGE   NAME=debug      START=_DEBUGCODESTART   END=_CEND        PROTECTED
#ELSE
  CODEPAGE   NAME=page       START=0x0               END=0x1FFF7
#FI

CODEPAGE   NAME=config     START=0x1FFF8           END=0x1FFFF        PROTECTED
CODEPAGE   NAME=devid      START=0x3FFFFE          END=0x3FFFFF       PROTECTED

#IFDEF _EXTENDEDMODE
  DATABANK   NAME=gpre       START=0x0               END=0x5F
#ELSE
  ACCESSBANK NAME=accessram  START=0x0               END=0x5F
#FI

DATABANK   NAME=gpr0       START=0x60              END=0xFF
DATABANK   NAME=gpr1       START=0x100             END=0x1FF
DATABANK   NAME=gpr2       START=0x200             END=0x2FF
DATABANK   NAME=gpr3       START=0x300             END=0x3FF
DATABANK   NAME=gpr4       START=0x400             END=0x4FF
DATABANK   NAME=gpr5       START=0x500             END=0x5FF
DATABANK   NAME=gpr6       START=0x600             END=0x6FF
DATABANK   NAME=gpr7       START=0x700             END=0x7FF
DATABANK   NAME=gpr8       START=0x800             END=0x8FF
DATABANK   NAME=gpr9       START=0x900             END=0x9FF
DATABANK   NAME=gpr10      START=0xA00             END=0xAFF
DATABANK   NAME=gpr11      START=0xB00             END=0xBFF

#IFDEF _DEBUGDATASTART
  DATABANK   NAME=gpr12      START=0xC00             END=_DATAEND
  DATABANK   NAME=dbgspr     START=_DEBUGDATASTART   END=_DEND           PROTECTED
#ELSE //no debug
  DATABANK   NAME=gpr12      START=0xC00             END=0xCFF
#FI

DATABANK   NAME=gpr13      START=0xD00             END=0xDFF
DATABANK   NAME=gpr14      START=0xE00             END=0xEAF
DATABANK   NAME=sfr14      START=0xEB0             END=0xEFF          PROTECTED
DATABANK   NAME=sfr15      START=0xF00             END=0xF5F          PROTECTED
ACCESSBANK NAME=accesssfr  START=0xF60             END=0xFFF          PROTECTED

#IFDEF _CRUNTIME
  SECTION    NAME=CONFIG     ROM=config
  #IFDEF _DEBUGDATASTART
    STACK SIZE=0x100 RAM=gpr11
  #ELSE
    STACK SIZE=0x100 RAM=gpr12
  #FI
#FI
\$\endgroup\$
3
\$\begingroup\$

I have always put my PIC 18 bootloaders at the end of program memory. The reason you can't put them at the beginning is that this is where the interrupt vectors also are. Assuming your app uses interrupts, since most do, you don't want the bootloader owning that section of memory.

Build the bootloader as a separate project that has a known fixed starting address near the end of memory. I use a include file to define the things that both the main app and the bootloader need to agree on, like the start address of the bootloader and where the bootloader needs to jump to run the main app. These need to be fixed addresses since different versions of the bootloader and main app need to be able to work together.

Execution does have to go to the bootloader on reset. That means a GOTO instruction at location 0 to the bootloader's known fixed starting address. Since location 0 is in the main app image, this is something the main app code has to provide.

With this kind of project, the main app usually contains a uploader. During its normal operation, it communicates with whatever can provide a new app image. This new app image is stored to a external EEPROM or roughly the second half of program memory. All the complicated code for doing the communication with the host and getting the new app image is contained in the main app.

The bootloader is then a small piece of code at the end of memory that runs from reset. It compares the main app and uploaded image versions and runs checksums on them. Under the right conditions it copies the new app image into the main app area and then runs it. Of course it never runs a main app that has a bad checksum.

There is one small vulnerability with this. To update the main app image, the bootloader has to erase and then overwrite the first erase block of program memory. Unfortunately, that is where the reset vector is. If a power failure or glitch occurs in the few milliseconds when the GOTO at the reset vector isn't there, then the PIC is toast and can only be recovered with a external programmer. Fortunately, that is a very small window of vulnerability, with the odds of it actually happening very very small. Note that a glitch during erasing/writing any of the other erase pages is recoverable. As long as the GOTO at the reset vector is there, the bootloader will be re-run, the main app checksum will fail, and it will attempt to re-write the main app from the stored app image.

\$\endgroup\$
5
  • 1
    \$\begingroup\$ I am completely unfamiliar with the PIC series, so this may not be helpfull. I implemented a bootloader for a SiM3 series (Silicon Labs ARM) microcontroller. They provide a register to relocate the interrupt vector block. This allowed me to put the bootloader in low memory, with its own vectors at 0x0000. Just before transferring control to the loaded program, I relocated the vector block to the base of the loaded code, where its own vectors were located. This eliminates the overwrite windows plus allows the bootloader to use interrupts. \$\endgroup\$
    – DoxyLover
    Jan 30 '15 at 18:34
  • \$\begingroup\$ @Doxy: The PIC 18 has fixed interrupt vectors, and 8 and 18h. \$\endgroup\$ Jan 30 '15 at 19:52
  • \$\begingroup\$ @OlinLathrop Thank you very much for the broad explanation and your valuable time olin. \$\endgroup\$
    – Rookie91
    Jan 31 '15 at 5:11
  • \$\begingroup\$ @OlinLathrop So i should edit the linker script so that the boot loader occupies the near bottom of program memory space and i trust that would be the best practice. Correct me if i got it wrong.Thanks again sir. \$\endgroup\$
    – Rookie91
    Jan 31 '15 at 6:31
  • \$\begingroup\$ @Rook: Yes, you'd have make modified linker scripts. The main app and the bootloader would be built separately, each with its own modified linker script. \$\endgroup\$ Jan 31 '15 at 14:32
0
\$\begingroup\$

Bootloaders by definition need to be called before the regular firmware so they can choose either to run, or immediately pass control on to the main firmware.

On most devices this means the bootloader is written at the start address (0x0000) and the main firmware image is offset by some fixed amount - as an example, the main firmware might be on the next page of flash so that the bootloader is not in danger of erasing itself when updating the firmware, and there is enough space that the bootloader code could grow a little without having to re-compile the main firmware to move its start address.

\$\endgroup\$
1
  • \$\begingroup\$ The PIC 18 program memory isn't divided into pages. \$\endgroup\$ Jan 30 '15 at 14:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.