Piziheng Embedded: NXP i.MX RT1xxx series MCU startup those things (6)-Bootable image format and loading (elftosb/.bd)

Piziheng Embedded: NXP i.MX RT1xxx series MCU startup those things (6)-Bootable image format and loading (elftosb/.bd)


Hello, everyone, I am the ruffian, a serious ruffian who engages in technology. Today Pi Ziheng will introduce to you the Bootable image format and loading process of NXP i.MX RT1xxx series MCU .

Start the third article Serial Downloader mode (sdphost, mfgtool) in the i.MXRT1xxx series of the Ziheng used an image file named ivt_flashloader.bin when introducing the use of sdphost to boot Flashloader. In fact, this image file is a part of Bootable image. Kind of, although Pi Ziheng briefly analyzed the composition of ivt_flashloader, but the introduction is not exhaustive. Today, Pi Ziheng will systematically explain i.MXRT Bootable image for everyone.

1. What is Bootable image?

If you are an experienced embedded developer, you must have an understanding of the image format. The Applications we usually develop are for MCUs with internal FLASH, such as Kinetis, LPC, STM32 and other MCUs, which are integrated internally. A piece of Parallel NOR FLASH, and the FLASH address is mapped in the ARM 4GB system address (usually starting from 0x0 address), the FLASH stored directly is the original Application binary (.bin) generated after our compilation and linking, without any extra data composition. Maybe you would say that there are other image formats such as .hex, .srec, yes, but these image formats with address information are for programmers or downloaders. These image formats are actually downloaded after being parsed by the programmer or downloader. The data that enters the FLASH inside the MCU is still the original Application binary. After this kind of MCU is powered on, the CPU can directly obtain the Application code from the internal FLASH and execute it in situ (XIP), so for this kind of MCU, the Bootable image is the Application binary (.bin) stored in the internal FLASH.
However, the above experience encountered problems when developing i.MXRT, i.MXRT has no internal FLASH, and an external FLASH memory is needed to store the image. As we all know, FLASH is divided into NOR and NAND in structure. i.MXRT supports both FLASH at the same time. NOR FLASH can realize XIP, NAND FLASH cannot XIP. In order to be compatible with all FLASH, it is necessary to design the i.MXRT bootable image format. Take the non-XIP situation as a benchmark. Since it is a non-XIP execution, it means that when i.MXRT is powered on, the image will be copied from the external FLASH to the internal SRAM for execution. When copying, it is inevitable to know two important data: image link starting address (determining image Which address is copied to the SRAM), the total length of the image (deciding how long the image data should be copied from the external FLASH into the SRAM), in fact, in addition to the two most basic data, there are other more advanced data (configuration, security, etc.) Features), therefore, the i.MXRT Bootable image stored in the external FLASH must contain additional information in addition to the Application binary data. These additional information data and the Application binary form the i.MXRT Bootable image. As for how this additional information is organized in Bootable image, Pi Ziheng will continue to talk about it later.

2. Bootable image link space

The link space of an image is divided into two types, one is the link space of the read-only segment (readonly code, data), and the other is the link space of the read-write segment (readwrite data, STACK). These two types of link space require storage The media characteristics are different.
Di Ziheng explained one by one: I mentioned that i.MXRT supports both external NOR and NAND FLASH. Among them, NAND FLASH cannot XIP, so the image read-only segment stored in NAND FLASH must be linked in SRAM. There are three kinds of SRAM inside i.MXRT, namely ITCM, DTCM, OCRAM, can all these three kinds of SRAM be linked at will? The answer is not! Because during Boot, BootROM also needs to occupy SRAM, which is used to store the read-write segment of BootROM, so SRAM occupied by BootROM cannot be used to link the read-only segment of the image. If the link is forced, it will cause BootROM to copy the read-only segment of the image. Destroy its own read-write segment, resulting in unpredictable behavior. The following figure is the memory map of RT1050 BootROM. From the figure, it can be seen that BootROM occupies OCRAM starting at 0x20200000, and it seems that the entire block of OCRAM is occupied, so it is not recommended to use OCRAM to link the image read-only segment.
Black Technology: If a friend expresses dissatisfaction, the OCRAM of RT1060/RT1050/RT1020 is 1MB/512KB/256KB, BootROM read-write segment cannot be so large, yes, Pi Ziheng tells you, in fact, the BootROM data segment only needs 32KB (0x20200000- 0x20207FFF). In addition, 4KB is required to load the initial non-XIP image (0x20208000-0x20208FFF), so for the image stored in non-XIP FLASH you can link the image read-only segment from the space after 0x20209000, and for the image stored in XIP FLASH You can link the read and write sections of the image from the space after 0x20208000. This secret is usually not told by Pi Ziheng.

The precautions for linking the read-only segment of the image stored in NAND FLASH are mentioned above. For NOR FLASH that can be XIP, in addition to linking the read-only segment to SRAM like NAND, it can also be linked to i.MXRT and allocated to external memory. In the XIP mapping space, the following table shows the starting address of the mapping of Serial NOR (QSPI) and Parallel NOR (SEMC). It should be noted that the maximum XIP space supported by Serial NOR is 504MB, but the maximum XIP supported by Parallel NOR The space is only 16MB, don't ask how Pi Ziheng knows, Pi Ziheng knows everything.

As for the read and write section of the image, there is no need to distinguish between Non-XIP/XIP FLASH during linking. They can only be placed in SRAM, and there is no need to consider the use of BootROM on SRAM (because it is not used in a time domain), as long as Be careful not to conflict with the read-only section of the image itself.
Black Technology: Some friends have noticed SDRAM. Yes, i.MXRT also supports SDRAM. SDRAM is read and written through the SEMC interface. So if SDRAM is connected externally and enabled, you can also put the image read-only section/read-write section into it. SDRAM, regarding the use of SDRAM, Pi Ziheng will introduce it in a later article.

3. the seven major components of Bootable image

Bootable image is composed of some additional information data and Application binary. Those additional information data are divided into 6 categories according to functions, but not all of these 6 types of information data are necessary, and 4 of them are optional. Therefore, a Bootable image consists of 7 parts at most and 3 parts at least. The following Pi Ziheng introduces the seven major parts of Bootable image in the order of storage location in FLASH from low to high:

3.1 Offset 0x0000: FDCB (Flash Device Configuration Block)

The first component is called FDCB, which is an optional component, currently only used for Serial/Parallel NOR FLASH. FDCB is stored from the start address of FLASH, which is also the first part of Bootable image. The maximum size of FDCB is 4KB, and it does not have a unified structure that has nothing to do with FLASH. The specific structure depends on the interface type (Serial/Parallel) that starts FLASH. It is generally used to store the specific characteristic parameters of the currently connected FLASH. BootROM will power up. Use the general and reliable FLASH interface controller configuration (that is, the default parameter configuration in BootROM, which is generally a relatively low-speed configuration) to access the external FLASH and obtain the FDCB, and then reconfigure the FLASH interface controller according to the parameters stored in the FDCB to further access FLASH. The following structure is the FDCB prototype of Serial NOR. Di Ziheng will not introduce this structure here. I will leave it to the follow-up introduction of Serial NOR and then introduce it in detail.

typedef struct _ flexspi_nor_config { flexspi_mem_config_t memConfig; //!< Common memory configuration info via FlexSPI uint32_t pageSize; //!< Page size of Serial NOR uint32_t sectorSize; //!< Sector size of Serial NOR uint8_t ipcmdSerialClkFreq; //!< Clock frequency for IP command uint8_t isUniformBlockSize; //!< Sector/Block size is the same uint8_t reserved0[ 2 ]; //!< Reserved for future use uint8_t serialNorType; //!< Serial NOR Flash type: 0/1/2/3 uint8_t needExitNoCmdMode; //!< Need to exit NoCmd mode before other IP command uint8_t halfClkForNonReadCmd; //!< Half the Serial Clock for non-read command: true/false uint8_t needRestoreNoCmdMode; //!< Need to Restore NoCmd mode after IP commmand execution uint32_t blockSize; //!< Block size uint32_t reserve2[ 11 ]; //!< Reserved for future use } flexspi_nor_config_t ; copy code

3.2 Offset 0x0400/0x1000: IVT (Image Vector Table)

The second component is called IVT, which is a necessary component and the core data in the 6 types of information data. IVT is a unified FLASH-independent structure. Its prototype is shown in the following structure. From the structure definition, we get It is known that the location information of Application, DCD, BD, and CSF is recorded in the IVT, which is essential for BootROM to load and start. The IVT size is fixed to 32 bytes, and its offset position in Bootable image is also fixed (for XIP FLASH, the offset is 0x1000, for Non-XIP FLASH, the offset is 0x400). Some friends may wonder why the IVT offset address is fixed? In fact, the answer is very simple, because BootROM must first obtain the IVT to further find other information data, and the location information of the IVT itself is not marked elsewhere, so it can only be recorded with a constant in the BootROM.

# define HAB_TAG_IVT0 0xd1 /**< Image Vector Table V0 */ /** @ref hab_header structure */ typedef struct hab_hdr { uint8_t tag; /**< Tag field */ uint8_t len[ 2 ]; /**< Length field in bytes (big-endian) */ uint8_t par; /* *< Parameters field */ } hab_hdr_t ; /** @ref ivt structure */ struct hab_ivt_v0 { /** @ref hdr with tag #HAB_TAG_IVT0, length and HAB version fields */hab_hdr_t hdr; /** Absolute address of the first instruction to execute from the image */ uint32_t entry; /** Reserved in this version of HAB: should be NULL. */ uint32_t reserved1; /** Absolute address of the image DCD: may be NULL. */ uint32_t dcd; /** Absolute address of the Boot Data: may be NULL, but not interpreted any further by HAB */ uint32_t boot_data; /** Absolute address of the IVT.*/ uint32_t self; /** Absolute address of the image CSF.*/ uint32_t csf; /** Reserved in this version of HAB: should be zero. */ uint32_t reserved2; }; Copy code

3.3 Offset 0x0420/0x1020: BD (Boot Data)

The third component is called BD, which is a necessary component and is the core data second only to IVT. BD is also a unified FLASH-independent structure. Its prototype is shown in the following structure. BD records the start of Bootable image Start address and total length. The BD size is fixed at 16 bytes. Although the BD information is recorded in the IVT, its offset position in the Bootable image is not arbitrary, and the BD is next to the IVT.

/** @ref boot_data structure */ typedef struct boot_data { uint32_t start; /* Start address of the image */ uint32_t size; /* Size of the image */ uint32_t plugin; /* Plugin flag */ uint32_t placeholder; /* placehoder to make even 0x10 size */ } BOOT_DATA_T; Copy code

3.4 DCD (Device Configuration Data)

The fourth component is called DCD, which is an optional component and is currently mainly used for the configuration of the SDRAM interface controller (SEMC). Since the internal SRAM size of i.MXRT is usually sufficient and the access speed is also very fast, SDRAM does not necessarily have to be enabled. Bootable image often does not include DCD, so Pi Ziheng will not expand here first. I will introduce it again. The following is an example of DCD used by the hello_world project (flexspi_nor) in the SDK_2.3.1_EVKB-IMXRT1050 package:

# define DCD_TAG_HEADER (0xD2) const uint8_t dcd_data[] = { /*0000*/ DCD_TAG_HEADER, 0x04 , 0x30 , 0x41 , 0xCC , 0x03 , 0xAC , 0x04 , 0x40 , 0x0F , 0xC0 , 0x68 , 0xFF , 0xFF , 0xFF , 0xFF , /* 0010 */ 0x40 , 0x0F , 0xC0 , 0x6C , 0xFF , 0xFF , 0xFF , 0xFF, 0x40 , 0x0F , 0xC0 , 0x70 , 0xFF , 0xFF , 0xFF , 0xFF , ... /*0420*/ 0x00 , 0x00 , 0x00 , 0x01 , 0xCC , 0x00 , 0x0C , 0x04 , 0x40 , 0x2F , 0x00 , 0x4C , 0x50 , 0x21 , 0x0A , 0x09 , }; Copy code

3.5 Offset 0x2000: Application Binary

The fifth component is the Application binary you are most familiar with. It is of course a necessary component. Its offset position in Bootable image is fixed (0x2000). I won't repeat it here about Application itself. Only one special mention is that the Application read-only segment of i.MXRT (mainly refers to the ARM interrupt vector table) cannot be linked from any address. There is a small restriction, which must be offset from the selected memory address space by 0x2000 Then start linking (if ITCM is selected, it must be linked after 0x00002000; if DTCM is selected, it must be linked after 0x20002000...), because at least 8KB of space must be reserved for IVT, BD, DCD and other data. This restriction is It is determined by BootROM itself, so you must pay attention to it.

3.6 CSF (Command Sequence File)

The sixth component is called CSF, which is a feature component, which is mainly used for authentication-related features of safe boot, which will be further introduced in Safe Boot.

3.7 KeyBlob

The seventh component is called KeyBlob, which is a feature component, which is mainly used for encryption-related features of secure boot, which will be further introduced in Secure Boot.

The above picture is the layout of Bootable image including IVT, BD, DCD, Application, and CSF. This picture illustrates the role of IVT well.

4. three categories of Bootable image

As mentioned earlier, Bootable image has up to 7 major components, some are necessary, some are optional, and some are features. In practical applications, it is mainly the combination of essential + features that form the following three commonly used categories:

  • Unsigned Image: This is the simplest image type, composed of IVT+BD+Application, mainly used in the product development phase.
  • Signed Image: This is a more complex image type, composed of IVT+BD+Application+CSF, and is generally used in the product release stage.
  • Encrypted Image: This is the most complex image type, composed of IVT+BD+Application+CSF+KeyBlob, and is mainly used in products with higher security requirements.

5. use elftosb to generate Bootable image

NXP officially provides a tool for generating Bootable images, called elftosb. This tool is located in the/Flashloader_i.MXRT1050_GA\Flashloader_RT1050_1.1\Tools\elftosb directory. This tool can be used to generate all types of Bootable images. Commands The format is fixed as follows:

elftosb.exe -f imx -V -c config_application.bd -o ivt_application.bin application.out

Among them, ivt_application.bin is the final Bootable image. The two input files required for the command are application.out and config_application.bd. Application.out is the ELF file generated by your Application project compilation link, and config_application.bd is the user configuration. File, this .bd file mainly instructs the elftosb tool how to add IVT, BD and other information data on the basis of Application binary to form a Bootable image, so writing a .bd file is a key step. The bd file has a special syntax format, but/Flashloader_i. There are many bd file examples in the MXRT1050_GA\Flashloader_RT1050_1.1\Tools\bd_file\imx10xx directory, we only need to modify a certain bd file.

If you have followed Piziheng's blog post, you should know that Piziheng has measured RT1052's coremark performance. The coremark project has been uploaded to Piziheng s github.com/JayHeng/cor... and the project path is in/cortex-m_app\apps/coremark_imxrt1052\bsp\build\coremark.eww, compile this project to get coremark_a000.out and coremark_a000.bin files, the read-only segment of the coremark program is linked to the ITCM address (0x0000a000), let s try to use elftosb to convert the coremark program into a bootable image , Bd file can refer to imx-itcm-unsigned.bd, open this reference bd file:

options { flags = 0x00; # Note: This is an example address, it can be any non-zero address in ITCM region startAddress = 0x8000; ivtOffset = 0x400; initialLoadSize = 0x2000; # Note: This is required if the default entrypoint is not the Reset_Handler # Please set the entryPointAddress to Reset_Handler address //entryPointAddress = 0x60002411; } sources { elfFile = extern(0); } section (0) { } Copy code

ivtOffset and initialLoadSize do not need to be changed, they represent the offset address of IVT and Application in Bootable image respectively, startAddress is BOOT_DATA_T.start, this can be modified, keep in mind the following formula:

startAddress + initialLoadSize = the start link address of the Application read-only segment

coremark_a000.out is linked at address 0xa000, 0x8000 + 0x2000 = 0xa000, so startAddress does not need to be changed here, the only thing that needs to be confirmed is entryPointAddress, for insurance purposes, set entryPointAddress as the reset interrupt address of Application, that is, entryPointAddress = 0x0000ecd1. After the bd file is modified, save it as config_coremark_a000.bd, let us try to execute the following command:

elftosb.exe -f imx -V -c config_coremark_a000.bd -o ivt_coremark_a000.bin coremark_a000.out copy the code

Open coremark_a000.bin and ivt_coremark_a000.bin respectively, you can see that ivt_coremark_a000.bin has more data of the first 8KB than coremark_a000.bin. The first 8KB contains valid IVT (offset 0x400) and BD (offset 0x420).

6. Bootable image loading process

Knowing the composition of Bootable image, Pi Ziheng will briefly introduce to you how i.MXRT BootROM loads Bootable image from external memory into SRAM memory. Taking non-XIP image loading as an example (the image link is in ITCM), the following figure shows the four stages of i.MXRT loading image:

  • The first stage is before loading, at this time the Bootable image is completely stored in the external Flash, and there is no image data in the SRAM;
  • The second stage is the initial loading. BootROM first reads the first 4KB data of Bootable image from the external Flash into the SRAM temporary buffer area (OCRAM: 0x20208000-0x20208FFF). We know that the 4KB data contains IVT and BD. BootROM reads from IVT and BD. Get the target address (BOOT_DATA_T.start) and total length (BOOT_DATA_T.size) of the Bootable image in it, and then you can start further loading;
  • The third stage is internal transfer. Since BootROM has read 4KB from the external Flash into the SRAM temporary buffer area, in order to avoid repeated reading, BootROM will first copy the 4KB data to the target address of the Bootable image (ITCM);
  • The fourth stage is that the loading is completed, and BootROM will then read the remaining Bootable image (BOOT_DATA_T.size-4KB) from the external Flash and save it to the target area (ITCM) to complete the loading.

So far, the Bootable image format and loading process of NXP i.MX RT1xxx series MCUs have been introduced, where is the applause~~~

Welcome to subscribe

The article will also be published to my blog Home Park , CSDN home , micro-channel public number on the platform.

Search " Piziheng Embedded " on WeChat or scan the QR code below, and you can view it on your phone for the first time.