大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是超級下載算法開發筆記番外篇之JLinkScript妙用。
JLinkScript 文件是配套 J-Link 調試器使用的腳本,這個腳本適用於需要定制 J-Link 執行操作的場景,它可以幫助用戶完成 J-Link 標准工具做不到的一些事情(比如 J-Link 連接順序或者執行復位的方式,或者一些定制的硬件板需要一些特殊處理),關於 JLinkScript 文件詳細解釋參見痞子衡舊文 《JLink Script文件基礎》。
痞子衡在開發 《RT-UFL - 一個適用全平台i.MXRT的超級下載算法設計》 項目時,遇到幾個難點問題,幸好有 JLinkScript 文件幫忙才得以輕松解決,今天痞子衡就跟大家分享一下解決問題過程:
一、解決默認RAM空間分配不適的問題
超級下載算法工程是 MIMXRT_FLEXSPI_UV5.uvprojx,基於 Keil MDK uVision5,在工程選項設置里,IROM空間是 0x1000 地址開始的 60KB(0x0 - 0xFFF空間留有它用)、IRAM 空間是 0x20000000 開始的 64KB,總空間大小是 124KB。

在整個 i.MXRT 系列里,i.MXRT1011的內部 RAM 空間最小,但也有 128KB,大小符合超級下載算法需求。但是其默認 RAM 分配是 32KB ITCM(0x0 - 0x7FFF), 32KB DTCM(0x20000000 - 0x20007FFF), 64KB OCRAM(0x20200000 - 0x2020FFFF),這就不符合超級下載算法需求了。PS: 除了i.MXRT1011之外,其他 i.MXRT 型號默認 RAM 空間都符合算法要求。
如何解決這個默認 RAM 空間分配不適的問題?當然是調整 FlexRAM 配置了,在《百變星君FlexRAM》 一文里,我們知道 i.MXRT1011 里有兩種調整 FlexRAM 分配的方式,一種是燒寫 eFuse(靜態方式,一次性地,冷啟動系統自動完成),另一種是改寫 IOMUXC_GPR 寄存器(動態方式,可多次,軟復位仍然保持有效),所以很自然地我們想到了通過 JLinkScript 文件來改寫 IOMUXC_GPR 寄存器方式來達成目的,這樣對芯片后續運行沒有根本性影響。文件路徑在 JLinkDevices.xml 里指定:

iMXRT1011_CortexM7.JLinkScript 內容就比較簡單了,按要求改寫 IOMUXC_GPR16/17 即可:
void ReconfigFlexRAM()
{
unsigned int base;
unsigned int value;
base = 0x400AC000;
value = 0xFA;
MEM_WriteU32(base + 0x44, value);
value = MEM_ReadU32(base + 0x44);
JLINK_SYS_Report1("GPR17:", value);
value = MEM_ReadU32(base + 0x40);
value |= 0x4;
MEM_WriteU32(base + 0x40, value);
value = MEM_ReadU32(base + 0x40);
JLINK_SYS_Report1("GPR16:", value);
JLINK_SYS_Report("J-Link script: FlexRAM has been reconfigured to 64KB ITCM, 64KB DTCM");
}
void SetupTarget(void) {
ReconfigFlexRAM();
}
void AfterResetTarget(void) {
ReconfigFlexRAM();
}
- Note:這種方法也可以用來解決客戶應用程序存在動態調整 FlexRAM 的代碼導致軟復位后 IDE 無法再次下載的問題,因為下載算法需要的 RAM 空間被重新分配掉了,我們需要在 JLinkScript 再將其改回來。
二、解決ROM空間不重疊帶來的型號識別問題
在 《 識別當前i.MXRT型號》 一文中,痞子衡詳細描述了超級下載算法設計里是如何識別具體 i.MXRT 型號的,簡單概括就是因為芯片本身沒有固定地址寄存器來標明型號,因此我們用比對 ROM 空間里指定地址內容的方式來替代(每個 i.MXRT 型號 ROM 內容都不一樣,且同內核型號 ROM 起始地址是一致的),文中僅用 RT600 和 RT1060 兩個型號來做了示例,但在增加 i.MXRT1010 和 i.MXRT1170 兩款型號支持時,我們發現這兩款 ROM 可讀空間竟然沒有重疊。
i.MXRT1011 的 ROM 空間是 0x200000 - 0x20FFFF(64KB),i.MXRT117x 的 ROM 空間是 0x200000 - 0x23FFFF(256KB),乍一看,這不是有重疊的嘛。但是很可惜的是,i.MXRT117x 前 64KB ROM 空間被刻意保護起來了,代碼無法訪問,因此比對 ROM 空間內容的方法對 i.MXRT1170 來說就失效了,必須新找其他方法來做型號識別。
痞子衡有考慮過用讀芯片外設寄存器的方式來區分 i.MXRT 型號(找有差異的那個即可),但是在 Memory Map 里找了一圈也沒找到合適寄存器,因為 i.MXRT10xx 與 i.MXRT11xx 在外設寄存器地址分配上差異很大,也是幾乎沒有地址重疊的外設。
無奈之下,痞子衡又想到了通過 JLinkScript 文件來在固定 RAM 地址處寫標識的方式來達成目的,痞子衡選擇了 0xFFFC - 0xFFFF 地址空間里的四個字節來存放標識,因此我們在超級下載算法工程選項設置里將這個地址先留出來:

然后對超級下載算法源代碼里 ufl_get_imxrt_chip_id() 函數做一點小改動,這里我們用了 0x5AA60FF0 來標識 I.MXRT1170,實測是可行的,當然如果覺得不放心,可以將標識空間再拓大一些,標識符也相應長一些。
#define FP_FLAG_ADDR (0x0000FFFCu)
#define FP_FLAG_RT117X (0x5AA60FF0u)
rt_chip_id_t ufl_get_imxrt_chip_id(void)
{
rt_chip_id_t chipId = kChipId_Invalid;
core_type_t coreType;
coreType = ufl_get_core_type();
if (kCoreType_CM7 == coreType)
{
uint32_t rt117xFlag = *(uint32_t *)FP_FLAG_ADDR;
if (rt117xFlag == FP_FLAG_RT117X)
{
return kChipId_RT117x;
}
else
{
// 代碼省略...
}
}
else if (kCoreType_CM33 == coreType)
{}
// 代碼省略...
與第一小節一樣,在 JLinkDevices.xml 里指定好 JLinkScript 文件路徑,然后 iMXRT117x_CortexM7.JLinkScript 內容也比較簡單,按要求將標識符寫進 RAM 里即可:
void SetFlagInITCM()
{
MEM_WriteU32(0xFFFC, 0x5AA60FF0);
JLINK_SYS_Report("J-Link script: 0x5AA60FF0 has been written to address 0xFFFC");
}
void SetupTarget(void) {
SetFlagInITCM();
}
void AfterResetTarget(void) {
SetFlagInITCM();
}
- Note:標識符似乎不能放在 0x0 - 0xFFF 空間里,這個空間在當前超級下載算法設計里被 JLink 占用了,痞子衡測試了 0x0 - 0x3 和 0xFFC - 0xFFF 兩處空間地址,均失敗了。
至此,超級下載算法開發筆記番外篇之JLinkScript妙用痞子衡便介紹完畢了,掌聲在哪里~~~
歡迎訂閱
文章會同時發布到我的 博客園主頁、CSDN主頁、知乎主頁、微信公眾號 平台上。
微信搜索"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦。

