AN945 Bootloader on non-bootloader enabled devices
06/163/2017 | 05:53 PM
For the release of Silicon Labs' EFM8 product line, a factory bootloader was created. However, this bootloader only works natively on devices that are 'bootloader enabled'. These 'bootloader enabled' devices are:
EFM8BB1 rev A, date code > 1601
EFM8BB2 rev C, date code > 1601
EFM8UB1 rev C, date code > 1601
EFM8UB2 rev B
EFM8SB1 rev A, date code > 1544
EFM8SB2 rev B
The AN945 bootloader will also be compatible on any future EFM8 devices (including newer revisions of the above devices).
Bootloader enabled devices have the ability to check to see if they should jump to the bootloader or the application after a reset, before code starts running. Other Silicon Labs 8-bit devices, or older EFM8 devices, don't have this capability. However, you can change this by mimicking this function in the bootloader and application firmware.
Firstly, the bootloader image should contain a jump to the bootloader at the reset vector 0x0000. You can do this by adding the following code to the boot_startup.asm file in the bootloader project:
?BL_JUMP SEGMENT CODE AT 0
So, if there is no application, this will jump automatically to the bootloader.
Now, you need to modify your application code to mimic the bootloader capable parts' additional functionality. I've done this in the SILABS_STARTUP.A51 file of an application, since this is where you can insert code that effectively runs before your application. In here, we'll simply need to check to see if the bootloader exists. If it does, we'll jump there first and it will perform the other checks to see if we should go to the application.
However, in this case, we'll also need to determine whether we just came from the bootloader, since we technically are the application. Without this, we would get stuck in a loop - jumping from the application to the bootloader, back to the application, back to the bootloader, etc. I used R7 to store a particular value to say that we've just come from the bootloader. Here is the modified SILAB_STARTUP.A51 file:
CSEG AT 0?C_STARTUP: LJMP BootloaderCheck
#include"efm8_device.h"#define BL_SIGNATURE 0xA5BootloaderCheck:;Readand test R7 to see if we've already entered the bootloader
; since the last reset. If so, we should skip to the application
mov A, #BL_SIGNATURE
xrl A, R7
; Read and test the boot vector enable byte (byte before Lock Byte)
; The signature is present if A is 0 (leave result in A)
mov DPTR, #(BL_FLASH0_LIMIT - 2)
movc A, @A+DPTR
xrl A, #BL_SIGNATURE
; Restore the DPTR
mov DPTR, #0000h
; If the signature is present, jump to the boot vector
clr A ; Restore A
mov R7, #0x00 ; Restore R7
jmp STARTUP1 ; Jump to reset vector (use this to save a byte)
GotoBootVector: ; A = 0, no need to restore
mov R7, #BL_SIGNATURE ; Write 0xA5 to R7 to indicate we've bootloaded
ljmp BL_START_ADDRESS ;Jump to boot vector
The full SILABS_STARTUP.A51 file is zipped and attached to this forum post.
Rebuild the bootloader that contains a jump at address 0x0000 that jumps to the bootloader start address
Replace the SILABS_STARTUP.A51 file in your application with the one attached to this post