• 正文
  • 相關(guān)推薦
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

IAR下如何將整個(gè)源文件代碼重定向到任意RAM中?

2022/01/13
882
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

大家好,我是痞子衡,是正經(jīng)搞技術(shù)的痞子。今天痞子衡給大家分享的是在IAR開(kāi)發(fā)環(huán)境下將整個(gè)源文件代碼重定向到任意RAM中的方法。

痞子衡舊文 《在IAR下將關(guān)鍵函數(shù)重定向到RAM中執(zhí)行的方法》 里介紹了三種關(guān)鍵函數(shù)重定向方法,不過(guò)這三種方法只是寫(xiě)法形式不同,本質(zhì)上沒(méi)啥區(qū)別,都是利用 IAR 鏈接器特性將函數(shù)重定向到工程數(shù)據(jù)段(RW)所在 RAM 里。

對(duì)于 i.MXRT 這種擁有多塊地址非連續(xù)的 RAM 的芯片,其實(shí)我們也可以單獨(dú)將這些重定向函數(shù)放到一個(gè)指定的 RAM 里,不一定非得跟數(shù)據(jù)段放在同一個(gè) RAM 里。具體實(shí)現(xiàn)也很簡(jiǎn)單,只需要在鏈接文件里額外加一句 place in 語(yǔ)句處理即可,恩智浦官方 SDK 包里就是這么做的。

然而痞子衡最近在支持 i.MXRT1170 客戶過(guò)程中,不使用恩智浦 SDK 里那種自定義函數(shù)段處理的方法,而是在 IAR 鏈接文件里使用指定源文件 object 的方式將代碼重定向到 ITCM 竟然失效了,這是怎么回事?今天我們一起來(lái)看一下:

  • Note 1:閱讀本文前需要對(duì) 《IAR鏈接文件(.icf)》、《IAR映射文件(.map)》 這兩種文件有所了解。Note 2:本文使用的 IAR EWARM 軟件版本是 v9.10.2。

一、回顧SDK里函數(shù)重定向做法

我們以最經(jīng)典的 SDK_2.11.0_MIMXRT1170-EVKboardsevkmimxrt1170demo_appshello_worldcm7iar 例程來(lái)看,工程 Build 選擇 flexspi_nor_debug,即代碼段放在 Flash 里(0x30000000 - ),數(shù)據(jù)段放在 DTCM 里(0x20000000 - )。

我們現(xiàn)在新建一個(gè)名為 ram_code.c 的源文件,在這個(gè)源文件里定義如下兩個(gè) delay1/2() 函數(shù),然后將這個(gè)源文件添加進(jìn)工程使用。按照 SDK 里做法,如果我們想將這兩個(gè)函數(shù)重定向,需要加 AT_QUICKACCESS_SECTION_CODE 宏來(lái)修飾,其實(shí)就是將函數(shù)放到名為 CodeQuickAccess 的自定義段里。

#define AT_QUICKACCESS_SECTION_CODE(func) func @"CodeQuickAccess"

AT_QUICKACCESS_SECTION_CODE(void delay1(void));
void delay1(void)
{
     __NOP();
}

AT_QUICKACCESS_SECTION_CODE(void delay2(void));
void delay2(void)
{
    __NOP();
    __NOP();
}

然后工程鏈接文件 MIMXRT1176xxxxx_cm7_flexspi_nor.icf 里(僅摘錄部分),CodeQuickAccess 段單獨(dú)放在 ITCM 里(0x00000000 - ),這就是官方 SDK 里的實(shí)現(xiàn)。

define symbol m_data_start           = 0x20000000;
define symbol m_data_end             = 0x2003FFFF;
define symbol m_itcm_start           = 0x00000000;
define symbol m_itcm_end             = 0x0003FFFF;
define region DATA_region   = mem:[from m_data_start to m_data_end-__size_cstack__];
define region ITCM_region   = mem:[from m_itcm_start to m_itcm_end];
define block RW            { first readwrite, section m_usb_dma_init_data };
define block QACCESS_CODE  { section CodeQuickAccess };
initialize by copy         { readwrite, section .textrw, section CodeQuickAccess };
place in DATA_region                 { block RW };
place in ITCM_region                 { block QACCESS_CODE };

編譯鏈接 hello_world_demo_cm7.ewp 工程,然后查看其映射文件(hello_world_demo_cm7.map)找到跟 delay1/2() 函數(shù)相關(guān)的內(nèi)容如下,顯然這是符合預(yù)期的。這里特別注意一下,CodeQuickAccess 的類別顯示的是 inited,表明其不是常見(jiàn)的 ro code,而是經(jīng)過(guò)重定向的,而且 delay1/2() 函數(shù)所在 ram_code.o 里包含了 10 個(gè)字節(jié)的 rw code。

*******************************************************************************
*** PLACEMENT SUMMARY
***
define block QACCESS_CODE { section CodeQuickAccess };
"P8":  place in [from 0x0 to 0x3'ffff] { block QACCESS_CODE };

  Section              Kind         Address      Size  Object
  -------              ----         -------      ----  ------
"P8":                                           0xc
  QACCESS_CODE                          0x0     0xc  <Block>
    QACCESS_CODE-1                      0x0     0xa  <Init block>
      CodeQuickAccess  inited           0x0     0xa  ram_code.o [6]
                                      - 0xc     0xc

*******************************************************************************
*** MODULE SUMMARY
***
    Module                              ro code  rw code  ro data  rw data
    ------                              -------  -------  -------  -------
    ram_code.o                                        10       10

*******************************************************************************
*** ENTRY LIST
***
    Entry                       Address   Size  Type      Object
    ----                       -------   ----  ----      ------
    delay1                          0x1    0x4  Code  Gb  ram_code.o [6]
    delay2                          0x5    0x6  Code  Gb  ram_code.o [6]

如果你打開(kāi)工程鏡像文件 hello_world_demo_cm7.srec 查看,這里也只有一段連續(xù)的 Flash 地址空間數(shù)據(jù),沒(méi)有 RAM 地址空間數(shù)據(jù),所以這個(gè)鏡像文件是符合獨(dú)立工具(比如 MCUBootUtility)下載以及 BootROM 啟動(dòng)條件的。

 

二、引出源文件Object方式重定向失效問(wèn)題

現(xiàn)在來(lái)看客戶遇到的問(wèn)題,客戶不想在源文件里逐一修飾需要重定向的函數(shù)(即 ram_code.c 文件里 delay1/2() 函數(shù)不加 AT_QUICKACCESS_SECTION_CODE 修飾),這種情況下我們需要改動(dòng)一下鏈接文件,將 object ram_code.o 放到 initialize by copy 語(yǔ)句和 place in ITCM_region 語(yǔ)句里。

initialize by copy         { readwrite, section .textrw, section CodeQuickAccess, object ram_code.o };
place in ITCM_region       { object ram_code.o };

這時(shí)候重新編譯鏈接工程,查看映射文件,找到跟 delay1/2() 函數(shù)相關(guān)的內(nèi)容如下,這個(gè)結(jié)果跟第一小節(jié)里結(jié)果有點(diǎn)區(qū)別,雖然 delay1/2() 確實(shí)鏈接在了 ITCM 里(0x00000000 - ),但是同時(shí)也增加了 0x0 - 0xb 區(qū)域的 Initializer bytes。

*******************************************************************************
*** PLACEMENT SUMMARY
***
define block QACCESS_CODE { section CodeQuickAccess };
"P8":  place in [from 0x0 to 0x3'ffff] { block QACCESS_CODE };
"P9":  place in [from 0x0 to 0x3'ffff] { object ram_code.o };

  Section              Kind         Address    Size  Object
  -------              ----         -------    ----  ------
"P8-P9":                                       0x18
  Initializer bytes    const            0x0     0xc  <for P8-P9-1>
  P8-P9-1                               0xc     0xa  <Init block>
    .text              inited           0xc     0xa  ram_code.o [6]
                                     - 0x16    0x16

*******************************************************************************
*** MODULE SUMMARY
***
    Module                              ro code  ro data  rw data
    ------                              -------  -------  -------
    ram_code.o                                        10       10

*******************************************************************************
*** ENTRY LIST
***
    Entry                       Address   Size  Type      Object
    ----                       -------   ----  ----      ------
    delay1                          0xd    0x4  Code  Gb  ram_code.o [6]
    delay2                         0x11    0x6  Code  Gb  ram_code.o [6]

如果此時(shí)再打開(kāi)工程鏡像文件 hello_world_demo_cm7.srec 查看,除了 Flash 地址空間數(shù)據(jù),還新增了 RAM 地址空間數(shù)據(jù),很顯然這個(gè)鏡像文件不符合獨(dú)立工具(比如 MCUBootUtility)下載以及 BootROM 啟動(dòng),僅能用于 IDE 中在線下載調(diào)試(即分散加載了)。

 

三、源文件Object方式重定向失效分析

我們?cè)僮鲆粋€(gè)實(shí)驗(yàn),按 《在IAR下將關(guān)鍵函數(shù)重定向到RAM中執(zhí)行的方法》 一文 2.3 針對(duì)源文件中全部函數(shù) 方法,在鏈接文件中僅將 object ram_code.o 放到 initialize by copy 語(yǔ)句里,那么 ram_code.o 中的內(nèi)容會(huì)被統(tǒng)一重定向到工程數(shù)據(jù)段 RW 所在 RAM 區(qū)域里(即 DTCM 0x20000000 -),這種情況下 delay1/2() 函數(shù)重定向是成功的。

initialize by copy         { readwrite, section .textrw, section CodeQuickAccess, object ram_code.o };
//place in ITCM_region       { object ram_code.o };

所以我們能夠得出結(jié)論,在不自定義函數(shù)段名的情況下,object ram_code.o 中內(nèi)容會(huì)在默認(rèn) RO、RW 段里,在做函數(shù)重定向時(shí),IAR 鏈接器無(wú)法將對(duì)應(yīng) ram_code.o 的 Initializer bytes 從默認(rèn) RO 段里單獨(dú)提取出來(lái)拷貝到非 RW 段所在區(qū),它只能統(tǒng)一處理 RO 段 Initializer bytes 到 RW 區(qū)的拷貝。如果硬要將 object ram_code.o 重定向到非 RW 所在 RAM 區(qū),IAR 鏈接器會(huì)直接將其 Initializer bytes 也從 RO 段里抽出來(lái),與其 RW 屬性的 .text 放在一起,這其實(shí)幾乎等效于分散加載了。

四、源文件Object方式重定向失效解決方案

分析到這里,解決方案清晰了,還是需要自定義程序段,不過(guò)既然不想單個(gè)函數(shù)加修飾,那有沒(méi)有整個(gè)文件范圍內(nèi)代碼統(tǒng)一加修飾呢?當(dāng)然是有的,這時(shí)候需要借助如下 #pragma default_function_attributes 語(yǔ)法,將這一對(duì)語(yǔ)句放置到源文件首行和末行,那么該源文件里所有函數(shù)都進(jìn)入了 .myCodeSection 自定義段里:

// 作用全部函數(shù)
#pragma default_function_attributes = @ ".myCodeSection"
// 作用全部變量(如有必要)
//#pragma default_variable_attributes = @ ".myVariSection"

void delay1(void)
{
     __NOP();
}

void delay2(void)
{
    __NOP();
    __NOP();
}

#pragma default_function_attributes =
//#pragma default_variable_attributes =

然后在工程鏈接文件 MIMXRT1176xxxxx_cm7_flexspi_nor_sdram.icf 里直接將 section .myCodeSection 放到 ITCM 里就可以了:

initialize by copy         { readwrite, section .textrw, section CodeQuickAccess, section .myCodeSection };
place in ITCM_region       { section .myCodeSection };

這時(shí)候再編譯鏈接工程查看映射文件,函數(shù)重定向結(jié)果就符合預(yù)期了,這個(gè)結(jié)果跟第一小節(jié)里的結(jié)果一致。

*******************************************************************************
*** PLACEMENT SUMMARY
***
"P8":  place in [from 0x0 to 0x3'ffff] { block QACCESS_CODE };
"P9":  place in [from 0x0 to 0x3'ffff] { section .myCodeSection };

  Section              Kind         Address    Size  Object
  -------              ----         -------    ----  ------
"P8-P9":                                        0xc
  P8-P9                                 0x0     0xc  <Init block>
    .myCodeSection     inited           0x0     0xa  ram_code.o [6]
                                      - 0xc     0xc

*******************************************************************************
*** MODULE SUMMARY
***
    Module                              ro code  rw code  ro data  rw data
    ------                              -------  -------  -------  -------
    ram_code.o                                        10       10

*******************************************************************************
*** ENTRY LIST
***
    Entry                       Address   Size  Type      Object
    ----                       -------   ----  ----      ------
    delay1                          0x1    0x4  Code  Gb  ram_code.o [6]
    delay2                          0x5    0x6  Code  Gb  ram_code.o [6]

至此,在IAR開(kāi)發(fā)環(huán)境下將整個(gè)源文件代碼重定向到任意RAM中的方法痞子衡便介紹完畢了,掌聲在哪里~~~

相關(guān)推薦

登錄即可解鎖
  • 海量技術(shù)文章
  • 設(shè)計(jì)資源下載
  • 產(chǎn)業(yè)鏈客戶資源
  • 寫(xiě)文章/發(fā)需求
立即登錄

碩士畢業(yè)于蘇州大學(xué)電子信息學(xué)院,目前就職于恩智浦(NXP)半導(dǎo)體MCU系統(tǒng)部門,擔(dān)任嵌入式系統(tǒng)應(yīng)用工程師。痞子衡會(huì)定期分享嵌入式相關(guān)文章