痞子衡嵌入式:超級下載演算法(RT-UFL)開發筆記番外(1) - JLinkScript妙用

痞子衡發表於2021-06-18

  大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是超級下載演算法開發筆記番外篇之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主頁知乎主頁微信公眾號 平臺上。

微信搜尋"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦。

相關文章