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
  • EFM8BB3 (all)
  • EFM8LB1 (all)
  • 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
    RSEG    ?BL_JUMP
    LJMP    boot_start

 

 

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

                RSEG    ?C_C51STARTUP

#include "efm8_device.h"

#define BL_SIGNATURE 0xA5

BootloaderCheck:
  ; Read and 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
  jz GotoApplication

   ; 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
   jz GotoBootVector

GotoApplication:
   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.

 

To summarize:

  • 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

  • 8-bit MCUs
  • Knowledge Base Articles

  • BrianL wrote: 
    BootloaderCheck:
      ; Read and test R7 to see if we've already entered the bootloader
      ; since the last reset. If so, we should skip to the application
      clr A
      mov A, #BL_SIGNATURE
    

    There is no need to clear A first if you're going to fill it with something else immediately anyway.

    0

  • vanmierlo wrote:
    There is no need to clear A first if you're going to fill it with something else immediately anyway.

    Good catch! I'll clear it out.

    0