2.1 Modes of Operation
The bootloader communicates with the personal computer host application through a predefined communication protocol, for additional information refer to UART Bootloader Protocol).
The bootloader framework works in these two modes:
- Basic mode (Single-bank bootloader)
- Fail-safe Update mode (Dual-bank bootloader)
Basic Mode (single-bank bootloader)
The basic mode bootloader resides at the starting location of the Flash memory. It performs Flash erase, program, or verify operations on the binary sent from the host. Once the firmware upgrade and verification are completed, it jumps to the starting address of the application.
For a detailed explanation on the basic mode bootloader, refer to the documents specified in the References section.
Fail-Safe Update Mode (Dual-Bank Bootloader)
One of the challenges with a basic mode bootloader is the failure of the booting process. The booting process could fail during the firmware upgrade stage. The bootloader may not be able to complete the ongoing firmware upgrade due to several reasons, for example, interface disconnect, power cut, and so on. When the firmware upgrade process is aborted in between, the embedded device goes into an unstable state and may not work as expected.
A fail-safe bootloader overcomes the limitation of the basic bootloader. A fail-safe bootloader is designed on the premise that even if there is a firmware upgrade failure during the booting process, the system is still have a stable application image to run.
A fail-safe update is supported on devices which have the dual-bank Flash memory. Typically, memory in a microcontroller is organized in one or more banks. While most of the microcontrollers have single bank memory, there are some high-end microcontrollers that have dual bank. The dual-bank Flash memory enables the user to program one bank without affecting the application code of the other bank.
The boot failure situation is addressed by a dual-bank bootloader (Fail-safe update mode). With a dual-bank bootloader, whenever the device is running in one memory bank, the user can upgrade the firmware with the new features into the other bank and swap the firmware once the upgrade completes. If the upgrade process fails, the working copy of the firmware which is running in the first memory bank will help the device to work normally.
In a dual-bank bootloader the memory is distinguished into two banks. Each bank holds the bootloader code residing at the beginning location of the respective bank, and the firmware (application code) follows as shown in the following figure.
When booting from one bank, another bank is used as an upgrade buffer to accept the new firmware. After the new firmware is received and verified, the boot banks are switched. Therefore, there can be two workable firmware versions in the memory. The bootloader can perform a Flash operation in either of the banks based on the address sent by the host application. It performs a bank swap and resets the system to run the application programmed in the opposite bank after the verification is completed.
The following figure shows the memory layout of dual-bank bootloader:
The SAM E54 Flash memory is configured to two banks: Bank A and Bank B. At the start of both the banks, the bootloader is situated and then followed by an application image as shown in the figure above.
By default, Bank A is mapped to the address 0x00000000 and Bank B is mapped to the address 0x00080000. The bank mapped to the address 0x00000000 is referred to as the active bank (by default Bank A), whereas the other bank mapped to the address 0x00080000 is referred to as the inactive bank.
The bootloader in an active bank can receive the following upgrade requests:
- Upgrade the active bank application image at address 0x00002000
- Upgrade the inactive bank application image at address 0x00082000
- Upgrade the inactive bank merged image (bootloader + application) at address 0x00080000
Upgrade Active Bank Application Image
The bootloader receives the application image from the host. Once the bootloader performs a successful upgrade, it notifies the host application. The host then sends a reset command to run the upgraded application, and examples are given below:
- This request to the bootloader is usually made when the device is loaded with the bootloader at the factory but not the application. This application upgrade request is made on the field when the user chooses this option for the first application image upgrade request to the device.
- This option could be used to upgrade certain metadata into the Flash memory. The metadata being added or upgraded is just a small part of the application image and therefore it does not require an upgrade to the whole memory region of the application to update the metadata.
Upgrade Inactive Bank Application or Merged Image
The bootloader, which is running from the active bank, receives the application or merged image from the host. Once the bootloader performs the successful upgrade, it notifies the host application. The host then sends the bank swap and system reset (BKSWRST) command. The BKSWRST performs the following actions:
- Swaps the memory banks to make the inactive bank active, and the active bank as inactive. BANK A is made inactive, while BANK B is made active.
- Issues a reset command to run the upgraded application
The information of which bank is mapped to the Flash address 0x00000000 is self-contained in special fuse bits in the Flash memory. These fuse bits can be erased or programmed individually. When the bootloader receives the BKSWRST command from the host, it sets the BKSWRST bit in the Flash (NVM) control register. When the BKSWRST is set, the Flash (NVM) controller swaps the banks and sets the Fuse bit (STATUS.AFIRST) based on the last status of the Fuse bit (STATUS.AFIRST) as given below:
- STATUS.AFIRST = 0; Start address of the Bank B is mapped to 0x00000000
- STATUS.AFIRST = 1; Start address of the Bank A is mapped to 0x00000000
On reset, the Flash (NVM) controller checks the status of the fuse bit (STATUS.AFIRST) and jumps to the active memory bank to run the code.