AM263Px MCU+ SDK: Understanding the bootflow and bootloaders

| AM263Px MCU+ SDK 26.00.00 |

Understanding the bootflow and bootloaders

# Introduction

This section is aimed at explaining what a bootloader is, why is it needed and details regarding the bootloader and bootflow used in the MCU+SDK.

## What Is Bootloader?

Generally speaking, bootloader is a piece of software / firmware that runs as soon as you power on an SoC. A bootloader's main duty is to start the subsequent pieces of software, such an OS, a baremetal application or in some cases another bootloader. When it comes to embedded, the bootloader is usually closely tied with the underlying SoC architecture. The bootloader is usually stored in a protected, non-volatile on-chip memory. Typically the bootloader performs various hardware checks, initializes the processor and configures the SoC registers etc. Since the primary aim of the bootloader is to load the next piece of software, it needs to communicate to the external world to receive this firmware/application image. This can be over a number of protocols - USB, UART, SPI, I2C, External Flash, Internal Flash, SD Card, Ethernet, CAN etc. Bootloader is also a key component in embedded security. Hardware Root-of-Trust is usually passed onto the bootloader and is passed on down the line.

Note
  In devices supported by MCU+SDK, the first stage bootloader is burned into read-only memory of the device and is considered as device firmware / ROM. Mostly in MCU+SDK when we say "bootloader" we are referring to the secondary bootloader, or the SBL

## Multi-Stage Bootloader

As mentioned earlier, sometimes the bootloader would be loading another bootloader which can load another one and so on. This is usually the case in advanced SoCs, and there are various reasons for this. The first bootloader is usually kept on secure, read-only memory for security reasons and to have a known state always before application software starts. It makes sense then to keep this bootloader simple and let it do only the bare minimum configuration required. This secondary bootloader can be complex and configurable to suit the needs of the application. This can also be updated easily compared to the first stage bootloader. In fact for the devices in MCU+SDK, we have a two-stage bootloading - the first stage bootloader is called ROM Bootloader (RBL) and the second stage bootloader is called Secondary Bootloader (SBL).

## Multi-Core Bootloading

Multi-core bootloading is almost always a follow up when there is a multi-stage bootloading. In this case the first bootloader technically might not be even aware of the other cores, it will just boot the next stage bootloader and this second stage bootloader will take care of the complex bootloading on the different cores.

Loading a multi-core application is slightly more complicated than loading a single core application. There would be concerns regarding image preparation, shared memory access, and so on. Mostly there would be a particular format in which the individual core images are created, and then they may/may not be concatenated into a single image for SBL to load. Whatever format the application image is in, the SBL should be aware of it so that it can parse and load the image correctly.

# Bootloading in MCU+SDK

In the MCU+SDK, the bootflow takes place mainly in two steps after you power ON the device

- ROM boot, in which the ROM bootloader boots a secondary bootloader or an SBL
- SBL boot in which the secondary bootloader boots the application

## ROM Boot

The RBL or ROM Bootloader is stored in read-only memory and is almost considered as part of the SoC. The details regarding the RBL and ROM Boot is out of scope for this user guide. Please refer to the Technical Reference Manual of the device for more details. But basically the ROM expects an x509 signed binary image of the secondary bootloader to be provided for boot.

- As soon as the board is powered ON, the ROM bootloader or RBL starts running. The RBL is the primary bootloader.
- Depending on which boot mode is selected, the RBL will load the secondary bootloader or SBL from a boot media (OSPI flash, SD card or via UART).
- Rest of the booting is done by the SBL.
- The RBL expects the image it boots (SBL in our case) to always be signed as mentioned above. Refer Booting Tools for more information on signing scripts.

The x509 template for ROM looks something like this:

[ req ]
distinguished_name = req_distinguished_name
x509_extensions = v3_ca
prompt = no
dirstring_type = nobmp
[ req_distinguished_name ]
C = US
ST = SC
L = New York
O = Texas Instruments., Inc.
OU = SITARA MCU
CN = Albert
emailAddress = Albert@gt.ti.com
[ v3_ca ]
basicConstraints = CA:true
1.3.6.1.4.1.294.1.1=ASN1:SEQUENCE:boot_seq
1.3.6.1.4.1.294.1.2=ASN1:SEQUENCE:image_integrity
1.3.6.1.4.1.294.1.3=ASN1:SEQUENCE:swrv
[ boot_seq ]
certType = INTEGER:1
bootCore = INTEGER:16
bootCoreOpts = INTEGER:0
destAddr = FORMAT:HEX,OCT:70002000
imageSize = INTEGER:199488
[ image_integrity ]
shaType = OID:2.16.840.1.101.3.4.2.3
shaValue = FORMAT:HEX,OCT:1d1b24e6487709f007d87c8b2b593abf1853a82a99a54650de85f40ddc7b5ae4558a68e49ea3668732ea34ff4bcf76cc73e4e354a3b8128726843c71b05c4168
[ swrv ]
swrv = INTEGER:1

Depending on the device type, these are the validation requirements for ROM:

Validation for Device Types

- For ROM to accept any image to boot, there are some restrictions in the image preparation

### Preparing the SBL for boot

The SBL is like any other application, created using the same compiler and linker toolchain. It is an example implementation rather than a deliverable. It is customizable by users, but must adhere to the requirements by RBL which is a constant as mentioned above. However the steps to convert the application `.out` into a bootable image are different for SBL as listed below:

- Other special factors for SBL application are listed below
  - The linker command file for SBL has to place vectors at address `0x70002000` and this is the entry point for the SBL.
  - Nothing should be placed in ATCM or BTCM
  - Currently, the region 0x70002000 to 0x70040000 is used by the SBL code, data, stack, etc.
- After building, the SBL application `.out` file is first converted to a binary format `.bin` using the TI ARM CLANG `objcopy` tool.
  - This copies the loadable sections from the .out into a binary image stripping all symbol and section information.
  - If there are two loadable sections in the image which are not contiguous then `objcopy` fills the gaps with `0x00`.
  - It is highly recommended to keep all loadable sections together within a SBL application.
- This `.bin` file is then signed using the Signing Scripts to create the final `.tiimage` bootable image.
  - The `.tiimage` file extension is kept to separate the SBL boot image from a normal application image
- Refer SBL Signing for details on signing SBL image.

## Booting MCELF application

- In this case, SBL looks for the multicore elf image (refer Booting Tools for more on multicore elf image) of the application binary at a specified location in a boot media.
- If the mcelf file is found, it is parsed into multiple loadable segments. These are then loaded into individual CPUs.
- The Note segment of the MCELF image will have information regarding the core on which each segment that application binary needs to be loaded
- The SBL uses this information to initialize each core, loads the segments to specified addresses, and then releases the core from reset. Now the core will start running.

SBL Boot for MCELF

- To understand the steps to use XIP, see Enabling XIP or eXecute In Place

Now, as mentioned above, to boot an application with SBL it has to be specially prepared. Refer here Building an Application to see how an application is prepared to be bootable.

### Booting the application

After a SBL and application image is flashed, shown below is the high level boot flow, after the SOC is powered on.

HIGH LEVEL BOOTFLOW

# Secure Boot

In secure device variants, there are slight differences in the bootflow. For details on secure boot, please refer Enabling Secure Boot

# PBIST For 200MHz and 400MHz R5F Core Variants

pBIST (parallel Built-In Self-Test) can be performed for both 200MHz and 400MHz part numbers by including the instance of `mcu_bist` in the sys-config for the bootloader examples. By default it's enabled only for bootloader `sbl-sd`. For 400 MHz part numbers ROM performs pBIST on R5FSS0 Memories and L2 Memory - Bank-0 and Bank-1. But due to ROM limitation this test is not done by ROM for 200 MHz part numbers. The `mcu_bist` instance can be added or removed on the basis of use-case. pBIST is perfromed only on L2 memory - three banks (Bank-1,Bank-2,Bank3 (not on Bank-0)) and R5FSS1 TCM Memories. Please refer below for more information.

Note
  Important Information:
  - pBIST is a destructive test and cannot be run on active memories.
  - Perform pBIST on specific sections of RAM and Subsystem 1 TCM, excluding active areas.
  - SBL code must resides in the 0th bank of L2 memory to perform pBIST on the other three banks, as `mcu_bist` instance will run pBIST on L2 memory - Bank 1, Bank 2, Bank 3. The `mcu_bist` instance can be added for `sbl_qspi` as it resides in Bank-0. If SBL resides in banks other than Bank-0, the pBIST setup must be updated with the specific memories.

Step | Description
--- | ---
1 | SBL Startup Ensure SBL is installed correctly on the target device Power on or reset the device to initiate SBL startup
2 | Efuse Bit Detection During SBL startup, efuse bits will be checked If 200 MHz variant is detected, proceed to Step 3 Otherwise, skip to the next startup process
3 | pBIST Execution Initiating pBIST if 200 MHz variant is detected pBIST performed on specific sections of RAM and Subsystem 1 TCM memories, excluding active areas i.e., Subsystem 0 TCM memories SBL code resides in the 1st bank of L2 memory (Bank-0); So pBIST is performed on the other three banks of L2 memories.

In software workaround, pBIST is perfromed only on L2 memory - three banks (Bank-1,Bank-2,Bank3 (and not on Bank-0)) and R5FSS1 TCM Memories.
User can perfrom pBIST on the remaining L2 Memory bank-0 and R5FSS0 TCM memories on their own by following the steps given below: The following table provides an overview of the steps to perform pBIST on RFSS0 TCM and L2 Memory Bank-0:

Step | Description
--- | ---
1 | Use the SDL example of pBIST that utilizes the SDL pBIST library.
2 | Set up the test environment to specify L2 bank-0 and R5FSS0 TCM memories.
3 | Update the SBL to be loaded on other memory banks (excluding bank 0).
4 | The SBL will load the application on the RFSS1 core, which will run pBIST on the remaining L2 bank-0 and R5FSS0 TCM memories.
5 | Once pBIST is completed, the device will be reset to proceed with normal booting.

By following these steps, you can perform pBIST on the specified L2 memory bank-0 and R5FSS0 TCM memories, ensuring proper self-testing, and allowing the device to boot normally afterwards.

• The pBIST can be run for both 200 MHz and 400 MHz part variants. To run the pBIST user can include `mcu_bist` instance for the specific bootloader in the syscfg.
• By default it's enabled only for bootloader `sbl-null`.
• The software workaround described in this user guide for L2 Memory Bank-0 and R5FSS0 TCM memories is specifically designed to address the ROM errata affecting 200 MHz R5F core variants.
• The pBIST procedure performed during the SBL startup helps mitigate the limitations imposed by the ROM.
• It is important to ensure that the SBL and associated software are correctly installed and configured on the target device for the workaround to function effectively.

To know more about pBIST and overall SDL support for pBIST, please take a look at PBIST

# Additional References

See also these additional pages for more details and examples about the boot flow,

- To understand different secondary bootloader (SBL) examples see,
  - SBL NULL
  - SBL UART Flash Writer
  - SBL OSPI
  - SBL UART
  - SBL CAN
- To understand the flashing steps, see Flashing Tools
- To understand the boot image creation tools, see Booting Tools