AM261x MCU+ SDK: Booting Tools

| AM261x MCU+ SDK 26.00.00 |

Booting Tools

Note
  To see the exact sequence of steps in which applications and secondary bootloader (SBL) are converted from compiler generated .out files to boot images, see the makefile `makefile_ccs_bootimage_gen` that is included in every example and secondary bootloader (SBL) CCS project.
  If you are using makefile based build, then see the file named `makefile` in the example folder.

# Introduction

This section describes the various tools that are used to create boot images for all the SDK applications

# Important files and folders

Folder/Files | Description
--- | ---
${SDK_INSTALL_PATH}/tools/boot/
sbl_prebuilt/ | Pre-built secondary bootloader (SBL) images and flash configuration files for different supported EVMs, see also Flashing Tools
signing/ | Security signing scripts need to create boot images that can be booted by ROM bootloader (RBL)
uart_bootloader.py | Python script used to send the SBL and application binaries over UART using XMODEM protocol in UART boot mode
uart_uniflash.py | Python script used to flash SBL and applications to EVM flash using UART. See Flashing Tools for more details.
genimage.py | Python script used to generate multicore elf image from individual core elf images.

Note
  RPRC tools (Out2RPRC and Multi-core Image Gen) has been deprecated from SDK 11.00 release onwards. MCELF would be the default application format.

# MCELF Image Gen

- This tool takes individual core ELF files as input and combines their segments to create a single ELF file.
- Shown below is the file format for an mcelf image file and its metacontent as seen by `readelf`

MCELF Image File Format

- Segment data from each input ELF file is extracted and appended together to form a single list of segments.
- The program header table fields are then re-calculated and the header table is regenerated using information from this new segment list.
- Once that is done, from the updated program header, the ELF header is regenerated.
- The first segment is the note segment. It can be customized to store information according to your application. By default the note segment contains vendor information, segment to core mapping and entry points.
- The segment sizes can be manipulated using appropriate arguments.

Argument | Description
--- | ---
`--core-img` | Path to individual binaries of each core. It is a mandatory argument. Input is given in this format: `--core-img=0:<core0_binary.out> --core-img=1:<core1_binary.out>`
`--output` | The output file name. It is a mandatory argument. `--output=<file_name>.mcelf`
`--merge-segments` | Enable merging segments based on a tolerance limit. Default value is false.
`--tolerance-limit` | The maximum difference (in bytes) between the end address of previous segment and start address of current segment for merging the segments. Default value is zero.
`--ignore-context` | Enable merging of segments that are of different cores. Default value is false.
`--xip` | XIP section's start and end address seperated by a colon. It creates a new file `<filename>.mcelf_xip`. It is a mandatory argument. In case of no XIP regions, use `--xip=None` (XIP is disabled even though file exists). Argument format when XIP region exists: `--xip=0x60100000:0x60200000`
`--max-segment-size` | Maximum allowed size of a loadable segment. This feature can only be used with merge_segments disabled. Default value is 8192 bytes.
`--xlat` | SOC specific Address Translation. (Under development, reserved for future use)
`--sso` | Path to SSO binary file. Default value is None.
`--otfaConfigFile` | Path to JSON file containing the OTFA config. Disabled by default with value None.

- The input for arguments 3-8 are defined in {MCU_SDK_PATH}/devconfig/devconfig.mak file.
- Given below are the structs used in the bootloader library to parse a 32 bit MCELF binary

#define E_IDENT 16
/* ELF HEADER */
typedef struct Bootloader_ELFH32_s
{
uint8_t e_ident[E_IDENT];
uint16_t e_type;
uint16_t e_machine;
uint32_t e_version;
uint32_t e_entry;
uint32_t e_phoff;
uint32_t e_shoff;
uint32_t e_flags;
uint16_t e_ehsize;
uint16_t e_phentsize;
uint16_t e_phnum;
uint16_t e_shentsize;
uint16_t e_shnum;
uint16_t e_shstrndx;
} Bootloader_ELFH32;
/* PROGRAM HEADER */
typedef struct Bootloader_ELFPH32_s
{
uint32_t type;
uint32_t offset;
uint32_t vaddr;
uint32_t paddr;
uint32_t filesz;
uint32_t memsz;
uint32_t flags;
uint32_t align;
} Bootloader_ELFPH32;
/* NOTE SEGMENT */
typedef struct Bootloader_ELFNote_s
{
uint32_t namesz;
uint32_t descsz;
uint32_t type;
} Bootloader_ELFNote;

- Use the following command to invoke this script to generate a basic `.mcelf` image from input `.out` files without any segment manipulations

$ cd tools/boot/multicore-elf
$ pip install -r requirements.txt
$ {PYTHON} genimage.py --core-img={CORE_0_ID}:{core0_app.out} --core-img={CORE_1_ID}:{core1_app.out} --core-img={CORE_2_ID}:{core2_app.out} --core-img={CORE_3_ID}:{core3_app.out} --output={application.mcelf}

- The various core ID to be used are as below.

CORE | CORE ID
--- | ---
r5fss0-0 | 0
r5fss0-1 | 1
r5fss1-0 | 2
r5fss1-1 | 3

# UART Bootloader Python Script

- This script is used in UART boot mode for sending the SBL and application binaries to the EVM via UART using XMODEM protocol
- Make sure that python3 and its dependent modules are installed in the host machine as mentioned in Python3
- Booting via UART is slow, but is useful if application loading via CCS or OSPI boot is not an option
- Make sure the UART port used for terminal is identified as mentioned in Setup UART Terminal
- Make sure you have the EVM power cable and UART cable connected as shown in Cable Connections
- To boot applications using this script, POWER OFF the EVM
- Switch to UART BOOT MODE.
- POWER ON the EVM
- To confirm that the board is in UART boot mode, open the UART terminal and confirm that you see the character 'C' getting printed on the console every 2-3 seconds.
- Now close the terminal. This is important as the script won't be able to function properly if the UART terminal is open.
- Open a command prompt and run the below command to send the SBL and application binary to the EVM if SOC_AM64X || SOC_AM243X
  cd ${SDK_INSTALL_PATH}/tools/boot
  python uart_bootloader.py -p COM<x> --bootloader=sbl_prebuilt/{board}/sbl_uart.release.tiimage --file=< path to multicore application binary > --soc=am64x_am243x
- When you execute this, the script first sends the uart bootloader, and then the multicore application
- After the multicore application file is successfully parsed, the uart bootloader sends an acknowledgment to the script and waits for 5 seconds before running the application binary
- Upon receiving the ack, the script will exit successfully
- Connect to the UART terminal within 5 seconds to see logs from the application
- Below are the logs of the script after all the files have been sent if (SOC_AM263X || SOC_AM263PX || SOC_AM261X)
  Sending the UART bootloader sbl_prebuilt/{board}/sbl_uart.release.tiimage ...
  Sent bootloader sbl_prebuilt/{board}/sbl_uart.release.tiimage of size 243975 bytes in 23.94s.
  Sending the application ../../examples/drivers/udma/udma_memcpy_polling/{board}/r5fss0-0_nortos/ti-arm-clang/udma_memcpy_polling.release.mcelf ...
  Sent application ../../examples/drivers/udma/udma_memcpy_polling/{board}/r5fss0-0_nortos/ti-arm-clang/udma_memcpy_polling.release.mcelf of size 99580 bytes in 11.74s.
  [STATUS] Application load SUCCESS !!!
  Connect to UART in 2 seconds to see logs from UART !!!

# USB Bootloader Python Script

- This script is used in DFU boot mode for sending the SBL and application binaries to the EVM via USB DFU.
- Make sure that dfu-util tool is installed properly and the DFU enumeration is verified.
- The source code for DFU Utils tool is available in GitHub (https://github.com/TexasInstruments/dfu-util) and Prebuilt binary is packaged in SDK.
- Make sure that python3 and its dependent modules are installed in the host machine as mentioned in Python3
- Change the boot mode to DFU boot mode EVM Setup
- POWER cycle the EVM
- Open a command prompt and run the below command to send the SBL and application binary to the EVM

cd ${SDK_INSTALL_PATH}/tools/boot
python usb_bootloader.py --bootloader=sbl_prebuilt/{board}/sbl_dfu.release.hs_fs.tiimage --file=< path to multicore mcelf application binary --use-sdk-utility

- This –use-sdk-utility option selects the custom DFU util from the SDK to perform DFU operations.
- When you execute this, the script first sends the SBL USB bootloader, and then the multicore appimage
- Connect to the UART terminal to see the booting information
- Below are the logs of the script after all the files have been sent

INFO: Bootloader_loadSelfCpu:207: CPU r5f0-0 is initialized to 800000000 Hz !!!
INFO: Bootloader_loadSelfCpu:207: CPU r5f0-1 is initialized to 800000000 Hz !!!
[BOOTLOADER_PROFILE] Boot Media : USB DFU
[BOOTLOADER_PROFILE] Boot Image Size : 114 KB
[BOOTLOADER_PROFILE] Cores present :
m4f0-0
r5f1-0
r5f1-1
r5f0-0
r5f0-1
[BOOTLOADER PROFILE] CPU load : 200191us
[BOOTLOADER_PROFILE] SBL Total Time Taken : 200192us
Image loading done, switching to application ...
INFO: Bootloader_runCpu:155: CPU m4f0-0 is initialized to 400000000 Hz !!!
INFO: Bootloader_runCpu:155: CPU r5f1-0 is initialized to 800000000 Hz !!!
INFO: Bootloader_runCpu:155: CPU r5f1-1 is initialized to 800000000 Hz !!!
INFO: Bootloader_runSelfCpu:217: All done, reseting self ...
[IPC NOTIFY ECHO] Message exchange started by main core !!!
[m4f0-0] 0.030020s : [IPC NOTIFY ECHO] Remote Core waiting for messages from main core ... !!!
[r5f0-1] 0.002099s : [IPC NOTIFY ECHO] Remote Core waiting for messages from main core ... !!!
[r5f0-1] 2.338054s : [IPC NOTIFY ECHO] Remote core has echoed all messages !!!
[r5f1-0] 0.022147s : [IPC NOTIFY ECHO] Remote Core waiting for messages from main core ... !!!
[r5f1-0] 2.358900s : [IPC NOTIFY ECHO] Remote core has echoed all messages !!!
[r5f1-1] 0.015147s : [IPC NOTIFY ECHO] Remote Core waiting for messages from main core ... !!!
[r5f1-1] 2.351658s : [IPC NOTIFY ECHO] Remote core has echoed all messages !!!
[IPC NOTIFY ECHO] All echoed messages received by main core from 4 remote cores !!!
[IPC NOTIFY ECHO] Messages sent to each core = 1000000
[IPC NOTIFY ECHO] Number of remote cores = 4
All tests have passed!!
[m4f0-0] 3.568946s : [IPC NOTIFY ECHO] Remote core has echoed all messages !!!

- Refer SBL DFU

# SoC ID parser Python Script

- Boot ROM reports SoC ID on UART console of the device when UART boot mode is selected. It reports on both GP and HS devices and it provides insights into device configuration which would be helpful for debugs.
- uart_boot_socid.py is a python3 based parser to convert the hexadecimal numbers reported by ROM to human readable text, below are the steps involved to use this parser. This will be helpful in debugging the device boot issue. This will also help to see important information about device like device type, prime/non-prime, key count, key revision, MPK hash etc.
- Make sure python3 is installed as mentioned in Python3
- Steps to use the parser:
  - Copy the soc id reported in UART console
  - pass the copied id to the script either as a plain string or saving it into a file
  - execute the script
    $python uart_boot_socid.py -d am64x --string=<copied soc id>
    or
    $python uart_boot_socid.py -d am64x --file=soc_id.txt
- Example Output:
  -----------------------
  SoC ID Header Info:
  -----------------------
  NumBlocks : 2
  -----------------------
  SoC ID Public ROM Info:
  -----------------------
  SubBlockId : 1
  SubBlockSize : 26
  DeviceName : am64x
  DeviceType : HSSE
  DMSC ROM Version : [0, 2, 0, 0]
  R5 ROM Version : [0, 2, 0, 0]
  -----------------------
  SoC ID Secure ROM Info:
  -----------------------
  Sec SubBlockId : 2
  Sec SubBlockSize : 166
  Sec Prime : 0
  Sec Key Revision : 1
  Sec Key Count : 1
  Sec TI MPK Hash : b018658ad99dc903c8c9bfb27b12751099920a042ad1dfea7b7ba57369f15546de285edde6a7b39a8bdc40a27b237f8fb1e57f245e80b929c1e28b024aa2ecc6
  Sec Cust MPK Hash : 1f6002b07cd9b0b7c47d9ca8d1aae57b8e8784a12f636b2b760d7d98a18f189760dfd0f23e2b0cb10ec7edc7c6edac3d9bdfefe0eddc3fff7fe9ad875195527d
  Sec Unique ID : 01f22176afca3a82692ce53b2738b8c982f7538602871e0bdb7dc2f7668d04b2

# CAN Bootloader Python Script

- This script is used in QSPI boot mode for sending the mcelf binaries to the EVM via CAN, after flashing the SBL CAN. Refer Basic steps to flash files for flashing.
- Make sure that python3 and its dependent modules are installed in the host machine as mentioned in Python3
- Make sure the UART port used for terminal is identified as mentioned in Setup UART Terminal
- Make sure you have the EVM power cable and CAN cable connected as shown in SBL CAN
- To boot applications using this script, POWER OFF the EVM
- Switch to OSPI BOOT MODE
- POWER ON the EVM
- Open a command prompt and run the below command to send the application binary to the EVM
  cd ${SDK_INSTALL_PATH}/tools/boot
  python can_bootloader.py --file=< path to multicore mcelf application binary >
- When you execute this, the script first sends the multicore mcelf to the EVM
- After the multicore mcelf is successfully parsed, the CAN bootloader sends an acknowledgment to the script
- Upon receiving the ack, the script will exit successfully
- Connect to the UART terminal to see logs from the application
- Below are the logs of the script after all the files have been sent
  Sending the application ../../examples/drivers/udma/udma_memcpy_polling/{board}/r5fss0-0_nortos/ti-arm-clang/udma_memcpy_polling.release.mcelf ...
  Sent application ../../examples/drivers/udma/udma_memcpy_polling/{board}/r5fss0-0_nortos/ti-arm-clang/udma_memcpy_polling.release.mcelf of size 99580 bytes in 11.74s.
  [STATUS] BOOTLOADER_CAN_STATUS_LOAD_SUCCESS!!!
  Connect to UART to see logs from UART !!!

flags
uint8_t flags
Definition: hsmclient_msg.h:2