在上一篇文章 Boot 配置(ISP Pin, OTP) 里痞子衡為大家介紹了 i.MXRTxxx Boot 的行為配置,其中第 1.2 節(jié)里講了 Boot 有三類行為模式:Serial ISP、Serial Boot、Device Boot,后兩種都是跟 App 啟動執(zhí)行相關(guān)的行為模式,而 Serial ISP 模式則是相對獨立的 Flash 下載功能,有了 Serial ISP,便可省去專用 Flash 編程器,今天痞子衡就來詳細聊一聊 Serial ISP 模式。
在前面我們已經(jīng)講過 Serial ISP 模式是一種串行編程模式,在這種模式下,BootROM 通過指定的 UART/SPI/I2C/USB-HID 口來接收來自 Host(恩智浦提供了上位機工具 blhost.exe 或者 MCUBootUtility)的 Application 數(shù)據(jù),并將數(shù)據(jù)下載進 i.MXRTxxx 支持的所有外部非易失性存儲器中,為后續(xù)從外部存儲器啟動做準(zhǔn)備。
一、進入 Serial ISP 模式
i.MXRTxxx 上電永遠是從 ROM 啟動去執(zhí)行 BootROM 程序,最頂層的 Boot 行為模式由 OTP memory 里的 PRIMARY_BOOT_SRC[3:0]位和芯片外部 ISP[2:0]管腳狀態(tài)共同決定。假設(shè)我們正處于研發(fā)階段,PRIMARY_BOOT_SRC[3:0]并未燒寫,那想進入 Serial ISP 模式最直接的方式便是將 ISP[2:0]輸入狀態(tài)撥成 3'b110,在設(shè)計 i.MXRTxxx 的硬件板時 ISP[2:0] pins 應(yīng)設(shè)計成可通過撥碼開關(guān)選擇輸入電平,下圖是 RT600-EVK 板(Rev.E)的參考設(shè)計:
撥碼開關(guān) SW5 應(yīng)撥向 SW_DIP-6 的 6,即設(shè)置 ISP[2:0]=3'b110,此時便直接進入了 Serial ISP 模式。
二、blhost 的使用
進入了 Serial ISP 模式,此時便可以用恩智浦提供的 host 工具與 BootROM 進行命令交互,host 工具在 MCUBootUtility 包 里。下載好 MCUBootUtility 包之后,在 MCUBootUtilityToolsblhost2_3win 下可以找到用于與 BootROM 通信的 blhost.exe。
2.1 支持的通信外設(shè) pinout
BootROM 支持四種通信外設(shè),分別是 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-MCUBootUtilitytoolsblhost2_3win> .blhost.exe
usage: D:NXP-MCUBootUtilitytoolsblhost2_3winblhost.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.
當(dāng)使用串口轉(zhuǎn) USB 模塊連接 i.MXRTxxx 的 Flexcomm UART0 或者使用 USB Cable 連接上 USB1 口后可以看到 PC 設(shè)備管理器會識別出相關(guān)設(shè)備:
讓我們嘗試一下使用 blhost 與 BootROM 通信,先試一下 USB 通信:
PS D:NXP-MCUBootUtilitytoolsblhost2_3win> .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 通信,似乎通信失敗了。需要注意的是,當(dāng)使用 USB 通信過一次之后,BootROM 已經(jīng)激活 USB 外設(shè),不會再去檢測其他外設(shè)(包括 UART),如果想使用 UART 通信,需要將板子 reset 一次,使 BootROM 重回外設(shè)檢測狀態(tài)。
PS D:NXP-MCUBootUtilitytoolsblhost2_3win> .blhost.exe -p COM25 -- get-property 1
Error: Initial ping failure: No response received for ping command.
三、下載更新 Application 示例
因為 BootROM 支持啟動的外部存儲器很多,所以 Serial ISP 模式下進行 Application 更新操作要指定具體的外部存儲器類型。在上一節(jié) blhost 的命令幫助里,我們可以看到 Memory ID 里已經(jīng)給各種外部儲存器分配了 ID 號,在使用 blhost 命令時使用不同的 ID 號即可操作相應(yīng)外部存儲器。
其實 BootROM 里已經(jīng)把外部存儲器的下載更新 Application 操作封裝得很簡單也很統(tǒng)一,我們其實只需要 3 步操作即可完成 Application 的下載。以備份啟動的 1bit SPI NOR 為例(即 Flexcomm SPI NOR Memory,Memory ID=0x110):
// 在 SRAM 里臨時存儲 1bit SPI NOR 配置數(shù)據(jù)
blhost -p COMx -- fill-memory 0x1C000 0x4 0xC0300000 // Flexcomm SPI3, NOR Flash
// 使用 1bit SPI NOR 配置數(shù)據(jù)去配置 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 類型數(shù)據(jù)的 Application 鏡像,關(guān)于上述命令的具體意義痞子衡會在后續(xù) Serial(1-bit SPI) NOR 恢復(fù)啟動的文章里詳盡解釋,這里只是給大家一個初步體驗。