在上一篇文章 Boot 配置(ISP Pin, OTP) 里痞子衡为大家介绍了 i.MXRTxxx Boot 的行为配置,其中第 1.2 节里讲了 Boot 有三类行为模式:Serial ISP、Serial Boot、Device Boot,后两种都是跟 App 启动执行相关的行为模式,而 Serial ISP 模式则是相对独立的 Flash 下载功能,有了 Serial ISP,便可省去专用 Flash 编程器,今天痞子衡就来详细聊一聊 Serial ISP 模式。
在前面我们已经讲过 Serial ISP 模式是一种串行编程模式,在这种模式下,BootROM 通过指定的 UART/SPI/I2C/USB-HID 口来接收来自 Host(恩智浦提供了上位机工具 blhost.exe 或者 MCUBootUtility)的 Application 数据,并将数据下载进 i.MXRTxxx 支持的所有外部非易失性存储器中,为后续从外部存储器启动做准备。
一、进入 Serial ISP 模式
i.MXRTxxx 上电永远是从 ROM 启动去执行 BootROM 程序,最顶层的 Boot 行为模式由 OTP memory 里的 PRIMARY_BOOT_SRC[3:0]位和芯片外部 ISP[2:0]管脚状态共同决定。假设我们正处于研发阶段,PRIMARY_BOOT_SRC[3:0]并未烧写,那想进入 Serial ISP 模式最直接的方式便是将 ISP[2:0]输入状态拨成 3'b110,在设计 i.MXRTxxx 的硬件板时 ISP[2:0] pins 应设计成可通过拨码开关选择输入电平,下图是 RT600-EVK 板(Rev.E)的参考设计:
拨码开关 SW5 应拨向 SW_DIP-6 的 6,即设置 ISP[2:0]=3'b110,此时便直接进入了 Serial ISP 模式。
二、blhost 的使用
进入了 Serial ISP 模式,此时便可以用恩智浦提供的 host 工具与 BootROM 进行命令交互,host 工具在 MCUBootUtility 包 里。下载好 MCUBootUtility 包之后,在 \MCUBootUtility\Tools\blhost2_3\win 下可以找到用于与 BootROM 通信的 blhost.exe。
2.1 支持的通信外设 pinout
BootROM 支持四种通信外设,分别是 UART/SPI/I2C/USB-HID(其中 UART 和 USB 比较常用),pinout 如下(Pinout 适用 RT600):
2.2 blhost 用法
blhost.exe 是命令行工具,使用 blhost 可以通过上述 UART/SPI/I2C/USB-HID 口与 BootROM 进行通信与命令交互。
在命令行下打开 blhost.exe,输入 -?命令可以看到 blhost 使用帮助,blhost 支持的命令很多:
PS D:\NXP-MCUBootUtility\tools\blhost2_3\win> .\blhost.exe
usage: D:\NXP-MCUBootUtility\tools\blhost2_3\win\blhost.exe
[-?|--help]
[-p|--port <name>[,<speed>]]
[-u|--usb [[[<vid>,]<pid>]]]
[-t|--timeout <ms>]
-- command <args...>
Options:
-?/--help Show this help
-p/--port <name>[,<speed>] Connect to target over UART. Specify COM port
and optionally baud rate
(default=57600)
If -ftbi, then port is BusPal port
--ftdi spi[,<speed>,<polarity>,<phase>,lsb|msb] |
i2c[,<address>,<speed>]
Use SPI or I2C for BusPal<-->Target link
All parameters between square brackets are
optional, but preceding parameters must be
present or marked with a comma.
(ex. -b spi,1000,0,1) (ex. --ftdi spi,1000,,lsb)
spi: speed(KHz),
polarity(0=active_high | 1=active_low),
phase(0=rising_edge | 1=falling_edge),
"lsb" | "msb"
(default=100,1,1,msb)
i2c: address(7-bit hex), speed(KHz)
(default=0x10,100)
-u/--usb [[[<vid>,]<pid>] | [<path>]]
Connect to target over USB HID device denoted by
vid/pid (default=0x15a2,0x0073) or device path
-t/--timeout <ms> Set packet timeout in milliseconds
(default=5000)
Memory ID:
Internal Memory Device internal memory space
0 Internal Memory
(Default selected memory)
16 (0x10) Execute-only region on internal flash
(Only used for flash-erase-all)
Mapped External Memory The memories that are remapped to internal space,
and must be accessed by internal addresses.
(IDs in this group are only used for flash-erase-all and
configure-memory, and ignored by write-memory, read-memory,
flash-erase-region and flash-image(use default 0))
1 QuadSPI Memory
9 FlexSPI NOR Memory
Unmapped External Memory Memories which cannot be remapped to internal space,
and only can be accessed by memories' addresses.
(Must be specified for all commands with <memoryId> argument)
272 (0x110) SPI NOR/EEPROM Memory
288 (0x120) uSDHC SD Memory
289 (0x121) uSDHC MMC Memory
** Note that not all memories are supported on all platforms.
Command:
reset Reset the chip
get-property <tag> [<memoryId> | <index>]
Return bootloader specific property.
<memoryId> and <index> are required by some properties.
<memoryId> = 0, <index> = 0, if not specified.
<memoryId> and <index> are ignored for the other properties.
If <index> is over the range supported by the device, bootloader
will treat as <index> = 0.
1 Bootloader version
2 Available peripherals
3 Start of program flash, <index> is required
4 Size of program flash, <index> is required
5 Size of flash sector, <index> is required
6 Blocks in flash array, <index> is required
7 Available commands
9 Last Error
10 Verify Writes flag
11 Max supported packet size
14 Start of RAM, <index> is required
15 Size of RAM, <index> is required
23 QuadSpi initialization status
24 Target version
25 External memory attrubutes, <memoryId> is required
27 Flash page size, <index> is required
28 Interrupt notifier pin
29 FFR key store update option
set-property <tag> <value>
10 Verify Writes flag
28 Interrupt notifier pin
<value>:
bit[31] for enablement, 0: disable, 1: enable
bit[7:0] for GPIO pin index
bit[15:8] for GPIO port index
29 FFR key store update option
<value>:
0 for Keyprovisioning
1 for write-memory
flash-erase-region <addr> <byte_count> [memory_id]
Erase a region of flash according to [memory_id].
flash-erase-all [memory_id] Erase all flash according to [memory_id],
excluding protected regions.
read-memory <addr> <byte_count> [<file>] [memory_id]
Read memory according to [memory_id] and write to file
or stdout if no file specified
write-memory <addr> [<file>[,byte_count]| {{<hex-data>}}] [memory_id]
Write memory according to [memory_id] from file
or string of hex values,
e.g. data.bin (writes entire file)
e.g. data.bin 8 (writes first 8 bytes from file)
e.g. "{{11 22 33 44}}" (w/quotes)
e.g. {{11223344}} (no spaces)
fill-memory <addr> <byte_count> <pattern> [word | short | byte]
Fill memory with pattern; size is
word (default), short or byte
receive-sb-file <file> Receive SB file
execute <addr> <arg> <stackpointer>
Execute at address with arg and stack pointer
call <addr> <arg> Call address with arg
configure-memory <memory_id> <internal_addr>
Apply configuration block at internal memory address
<internal_addr> to memory with ID <memory_id>
key-provisioning <operation> [arguments...]
<enroll>
Key provisioning enroll. No argument for this operation
<set_user_key> <type> <file>[,<size>]
Send the user key specified by <type> to bootloader. <file> is
the binary file containing user key plaintext. If <size> is not
specified, the entire <file> will be sent. Otherwise, only send
the first <size> bytes
<set_key> <type> <size>
Generate <size> bytes of the key specified by <type>
<write_key_nonvolatile> [memoryID]
Write the key to a nonvolatile memory
<read_key_nonvolatile> [memoryID]
Load the key from a nonvolatile memory to bootloader
<write_key_store> <file>[,<size>]
Send the key store to bootloader. <file> is the binary file
containing key store. If <size> is not specified, the entire
<file> will be sent. Otherwise, only send the first <size> bytes
<read_key_store> <file>
Read the key store from bootloader to host(PC). <file> is the
binary file to store the key store
flash-image <file> [erase] [memory_id]
Write a formated image <file> to memory with ID
<memory_id>. Supported file types: SRecord
(.srec and .s19) and HEX (.hex). Flash is erased
before writing if [erase]=erase. The erase unit
size depends on the target and the minimum erase
unit size is 1K.
list-memory List all on-chip Flash and RAM regions, and off-chip
memories, supported by current device.
Only the configured off-chip memory will be list.
efuse-program-once <addr> <data> [nolock/lock]
Program one word of OCOTP Field
<addr> is ADDR of OTP word, not the shadowed memory address.
<data> is hex digits without prefix '0x'
efuse-read-once <addr>
Read one word of OCOTP Field
<addr> is ADDR of OTP word, not the shadowed memory address.
generate-key-blob <dek_file> <blob_file>
Generate the Blob for given Dek Key
<dek_file> - input, a binary Dek Key (128 Bits) generated by CST tool.
<blob_file> - output, a generated blob (72 Bytes) in binary format.
** Note that not all commands/properties are supported on all platforms.
当使用串口转 USB 模块连接 i.MXRTxxx 的 Flexcomm UART0 或者使用 USB Cable 连接上 USB1 口后可以看到 PC 设备管理器会识别出相关设备:
让我们尝试一下使用 blhost 与 BootROM 通信,先试一下 USB 通信:
PS D:\NXP-MCUBootUtility\tools\blhost2_3\win> .\blhost.exe -u 0x1fc9,0x0020 -- get-property 1
Inject command 'get-property'
Response status = 0 (0x0) Success.
Response word 1 = 1258487808 (0x4b030000)
Current Version = K3.0.0
再接着试一下 UART 通信,似乎通信失败了。需要注意的是,当使用 USB 通信过一次之后,BootROM 已经激活 USB 外设,不会再去检测其他外设(包括 UART),如果想使用 UART 通信,需要将板子 reset 一次,使 BootROM 重回外设检测状态。
PS D:\NXP-MCUBootUtility\tools\blhost2_3\win> .\blhost.exe -p COM25 -- get-property 1
Error: Initial ping failure: No response received for ping command.
三、下载更新 Application 示例
因为 BootROM 支持启动的外部存储器很多,所以 Serial ISP 模式下进行 Application 更新操作要指定具体的外部存储器类型。在上一节 blhost 的命令帮助里,我们可以看到 Memory ID 里已经给各种外部储存器分配了 ID 号,在使用 blhost 命令时使用不同的 ID 号即可操作相应外部存储器。
其实 BootROM 里已经把外部存储器的下载更新 Application 操作封装得很简单也很统一,我们其实只需要 3 步操作即可完成 Application 的下载。以备份启动的 1bit SPI NOR 为例(即 Flexcomm SPI NOR Memory,Memory ID=0x110):
// 在 SRAM 里临时存储 1bit SPI NOR 配置数据
blhost -p COMx -- fill-memory 0x1C000 0x4 0xC0300000 // Flexcomm SPI3, NOR Flash
// 使用 1bit SPI NOR 配置数据去配置 Flexcomm SPI 接口
blhost -p COMx -- configure-memory 0x110 0x1C000
// 擦除 1bit SPI NOR 并将 image 下载进 1bit SPI NOR
blhost -p COMx -- flash-erase-region 0x0 0x20000 0x110
blhost -p COMx -- write-memory 0x1000 bt_image.bin 0x110
其中 bt_image.bin 是填充了 Image 类型数据的 Application 镜像,关于上述命令的具体意义痞子衡会在后续 Serial(1-bit SPI) NOR 恢复启动的文章里详尽解释,这里只是给大家一个初步体验。