在前面提過 Flashloader 程序主要是用來將你的 Application 下載進 i.MXRTyyyy 支持的所有外部非易失性存儲器中,為后續(xù)從外部存儲器啟動做準(zhǔn)備。BootROM 只有啟動 Application 功能,沒有下載更新 Application 功能,而 Flashloader 最核心的就是下載更新 Application 功能,所以 Flashloader 是 BootROM 的完美補充。你可能會疑問,為什么不把 Flashloader 的下載更新 Application 的功能也放進 BootROM 里?痞子衡個人覺得應(yīng)該是芯片成本問題,ROM 的空間是 96KB(RT102x/RT105x)/128KB(RT106x),如果把 Flashloader 功能也放進 BootROM 里,勢必要擴大 ROM 空間,從而導(dǎo)致芯片成本上升,做成二級 Flashloader 既不占 ROM 空間,也方便 Flashloader 程序自身的維護升級(目前 RT1050 的 Flashloader 版本是 1.1,你看,這不顯然升級過嘛)。
一、進入 Flashloader 程序
1.1 官方程序包
恩智浦提供了 Flashloader 程序包,你首先需要下載這個 Flashloader 包,F(xiàn)lashloader 所有相關(guān)資源全在包里面。注:每個 i.MXRTyyyy 子系列均有一個以子系列名字命名的 Flashloader 包,即 Flashloader 程序并不是通用的(偷偷告訴你,其實 RT105x 與 RT106x 是通用的),此處以 RT1050 系列為例:
Flashloader 程序是 Flashloader_i.MXRT1050_GAFlashloader_RT1050_1.1Flashloaderflashloader.elf
Flashloader 工具在 Flashloader_i.MXRT1050_GAFlashloader_RT1050_1.1Tools 目錄下
1.2 三種引導(dǎo)方式
其實引導(dǎo)啟動 Flashloader 的方式并不唯一,F(xiàn)lashloader 就是一段運行在 SRAM 中的應(yīng)用程序而已,只要能有工具將 Flashloader 下載進 SRAM,并將 CPU 的 PC 指針指向 Flashloader 的程序入口便可啟動 Flashloader。下面痞子衡分別介紹 3 種引導(dǎo)方式:
1.2.1 標(biāo)準(zhǔn)方式:通過 sdphost
第一種引導(dǎo)方式是通過 BootROM 的 Serial Downloader 模式和 sdphost.exe 工具,這是恩智浦官方推薦的方式,這種方式在上一篇文章里已經(jīng)詳細(xì)介紹過了,這里不再贅述。
這種方式的優(yōu)點是不需要外接調(diào)試器,缺點是涉及到 BootROM 啟動以及 IVT 的知識,需要有 BootROM 相關(guān)知識儲備。
1.2.2 簡便方式:通過 J-Link Commander
第二種引導(dǎo)方式是通過外接 J-Link 調(diào)試器和 J-Link Commander 工具(JLink.exe)。i.MXRTyyyy 芯片 JTAG 口連接上 J-Link 調(diào)試器后,安裝好 Jlink 驅(qū)動(痞子衡安裝的是 v6.30e 版本),打開 J-Link Commander(即 SEGGERJLink_V630eJLink.exe),連接上 i.MXRTyyyy 的 Core,按順序執(zhí)行如下 JLink 命令:
J-Link>loadfile C:Flashloader_i.MXRT1050_GAFlashloader_RT1050_1.1Flashloaderflashloader.srec
Downloading file [C:Flashloader_i.MXRT1050_GAFlashloader_RT1050_1.1Flashloaderflashloader.srec]...
O.K.
J-Link>mem32 0x20002000 2
20002000 = 20215A70 20014B91
J-Link>wreg MSP 20215A70
MSP = 0x20215A70
J-Link>wreg PSP 20215A70
PSP = 0x20215A70
J-Link>SetPC 20014B91
J-Link>g
到這里 Flashloader 就已經(jīng)被成功啟動了,有朋友看不懂上面的一串 JLink 命令,痞子衡為大家解釋一下:
- loadfile 命令用于將 Flashloader 程序數(shù)據(jù)(.srec 格式,含地址信息)下載進 SRAM(0x20002000)中;
- mem32 命令用于從起始下載地址(0x20002000)讀回部分?jǐn)?shù)據(jù)(8 字節(jié))確認(rèn)上一步的下載操作是否成功,并且獲取 Flashloader 的起始 SP 和 PC 值。
- wreg 命令用于設(shè)置 R13(MSP/PSP)寄存器的值,使其等于 Flashloader 的初始 SP 值。
- SetPC 命令用于設(shè)置 R15(PC)寄存器的值,使其指向 Flashloader 的初始 PC。
- g 命令用于讓 Core 開始執(zhí)行代碼(Flashloader 程序)。
這種方式的優(yōu)點是不需要借助 BootROM(你可以不用了解 BootROM 相關(guān)工具用法),缺點是需要額外準(zhǔn)備一個 J-Link 調(diào)試器。
Note:關(guān)于 JLink 命令的詳細(xì)解釋請查閱 JLink 驅(qū)動軟件安裝目錄下 SEGGERJLink_V630eDocUM08001_JLink.pdf 文檔里的 3.2 J-Link Commander (Command line tool)一節(jié)。
1.2.3 高級方式:通過 Ozone
前兩種引導(dǎo)方式都是把 Flashloader 程序當(dāng)做黑盒子,只需要將其啟動運行即可,接下來痞子衡介紹的引導(dǎo)方式可以讓你看到 Flashloader 源代碼并且可以讓你調(diào)試 Flashloader。這第三種引導(dǎo)方式還是通過外接 J-Link 調(diào)試器,但還需要一個特殊的軟件,即 SEGGER 公司提供的 Ozone 軟件,去 SEGGER 先下載 Ozone 軟件(痞子衡下載的版本是 v2.56c),下載安裝后打開 Ozone 軟件,第一步選擇 CM7,第二步選擇 SWD,第三步選擇 elf 文件時要選擇 Flashloader 下載包里的 flashloader.elf
確認(rèn) elf 文件后,點擊“Download & Reset Program”
此時 Flashloader 程序已經(jīng)被下載進 i.MXRTyyyy 中,并且在 Disassembly 窗口可以看到 Flashloader 匯編源程序,底下你就可以開始調(diào)試執(zhí)行 Flashloader 程序。由于下載包里的 flashloader.elf 文件并沒有包含所有 Flashloader 工程的信息(至少沒有包含 C 代碼信息,應(yīng)該是恩智浦官方故意這么做的),所以我們使用 Ozone 軟件調(diào)試看不到 C 代碼,稍微有點遺憾。
1.3 支持的通信外設(shè) pinout
Flashloader 支持的通信外設(shè)與 BootROM 支持的通信外設(shè)是一模一樣的,也是 USB-HID 和 UART,并且 pinout 也一樣(Pinout 適用 RT105x 和 RT102x):
Note: 如果硬件板上 UART_RX 引腳沒有接上拉電阻,可能會導(dǎo)致 USB-HID 設(shè)備枚舉成功率降低,因為 UART_RX 懸空輸入會有干擾數(shù)據(jù)使得 Flashloader 誤以為 UART 是 active peripheral,所以安全起見,請保證 UART_RX 引腳連接上拉電阻。
二、blhost/elftosb/mfgtool 的使用
Flashloader 配套上位機工具有 3 個,elftosb.exe 用于生成 sb 格式文件(這個工具后續(xù)會詳細(xì)介紹),mfgtool 是 GUI 軟件(上一篇文章已經(jīng)介紹過,其主要配合 sb 文件使用),blhost.exe 是痞子衡在這里要著重介紹的軟件。
blhost.exe 是命令行工具,使用 blhost 既可以通過 UART 口也可以通過 USB 口與 Flashloader 進行通信與命令交互。
在命令行下打開 blhost.exe,輸入 -?命令可以看到 blhost 使用幫助,相比 sdphost,blhost 支持的命令更多:
PS C:Flashloader_i.MXRT1050_GAFlashloader_RT1050_1.1Toolsblhostwin> .blhost.exe -?
usage: C:Flashloader_i.MXRT1050_GAFlashloader_RT1050_1.1Toolsblhostwinblhost.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=COM1,57600)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?If -b, then port is BusPal port
? -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)
? 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
? ? 8 ? ? ? ? ? ? ? ? ? ? ? ? ? ?SEMC NOR 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)
? ? 256 (0x100) ? ? ? ? ? ? ? ? ?SEMC NAND Memory
? ? 257 (0x101) ? ? ? ? ? ? ? ? ?SPI NAND Memory
? ? 272 (0x110) ? ? ? ? ? ? ? ? ?SPI NOR/EEPROM Memory
? ? 273 (0x111) ? ? ? ? ? ? ? ? ?I2C NOR/EEPROM Memory
? ? 288 (0x120) ? ? ? ? ? ? ? ? ?uSDHC SD Memory
? ? 289 (0x121) ? ? ? ? ? ? ? ? ?uSDHC MMC Memory
** Note that not all memories are supported on all
? ? ? Kinetis Bootloader platforms.
Command:
? reset ? ? ? ? ? ? ? ? ? ? ? ?Reset the chip
? get-property <tag> [<memoryId> | <index>]
? ? 1 ? ? ? ? ? ? ? ? ? ? ? ? ?Bootloader version
? ? 2 ? ? ? ? ? ? ? ? ? ? ? ? ?Available peripherals
? ? 7 ? ? ? ? ? ? ? ? ? ? ? ? ?Available commands
? ? 10 ? ? ? ? ? ? ? ? ? ? ? ? Verify Writes flag
? ? 11 ? ? ? ? ? ? ? ? ? ? ? ? Max supported packet size
? ? 12 ? ? ? ? ? ? ? ? ? ? ? ? Reserved regions
? ? 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.
? set-property <tag> <value>
? ? 10 ? ? ? ? ? ? ? ? ? ? ? ? Verify Writes flag
? 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>
? 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>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?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
? ? ?
Kinetis Bootloader platforms.
讓我們嘗試一下使用 blhost 與 Flashloader 通信(通過 USB-HID),如果能得到如下結(jié)果,說明 Flashloader 工作正常,可以進行后續(xù)操作。
PS C:Flashloader_i.MXRT1050_GAFlashloader_RT1050_1.1Toolsblhostwin> .blhost.exe -u 0x15a2,0x0073 -- get-property 1
Inject command 'get-property'
Response status = 0 (0x0) Success.
Response word 1 = 1258422528 (0x4b020100)
Current Version = K2.1.0
三、下載更新 Application 示例
因為 BootROM 支持啟動的外部存儲器很多,所以 Flashloader 支持下載更新的外部存儲器也與 BootROM 一一對應(yīng)。在上一節(jié) blhost 的命令幫助里,我們可以看到 Memory ID 里已經(jīng)給各種外部儲存器分配了 ID 號,在使用 blhost 命令時使用不同的 ID 號即可操作相應(yīng)外部存儲器。
其實 Flashloader 已經(jīng)把外部存儲器的下載更新 Application 操作封裝得很簡單也很統(tǒng)一,我們其實只需要 3 步操作即可完成 Application 的下載。以 Block Size 為 128KB 的 Raw NAND 為例(即 SEMC NAND Memory,Memory ID=0x100):
// 在 SRAM 里臨時存儲 Raw NAND 配置數(shù)據(jù)
blhost -u -- fill-memory 0x2000 0x4 0xD0010101 // ONFI 1.0, non-EDO, Timing mode 0, 8bit IO, CSX0, HW ECC Check, inital HW ECC is enabled
blhost -u -- fill-memory 0x2004 0x4 0x00010101 // image copy = 1, search stride = 1, search count = 1
blhost -u -- fill-memory 0x2008 0x4 0x00020001 // block index = 2, block count = 1
// 使用 Raw NAND 配置數(shù)據(jù)去配置 Raw NAND 接口
blhost -u -- configure-memory 0x100 0x2000
// 擦除 Raw NAND 并將 image 下載進 Raw NAND
blhost -u -- flash-erase-region 0x40000 0x20000 0x100 ? ?// Erase 1 block starting from block 2
blhost -u -- write-memory 0x40000 ivt_image.bin 0x100 ? ?// Program ivt_image.bin to block 2
其中 image.bin 是包含 IVT 的 Application 鏡像數(shù)據(jù),關(guān)于上述命令的具體意義痞子衡會在后續(xù) Raw NAND 啟動的文章里詳盡解釋,這里只是給大家一個初步體驗。