大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是超級下載演算法開發筆記番外篇之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主頁、知乎主頁、微信公眾號 平臺上。
微信搜尋"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦。