在痞子衡舊文 《IAR下RT-Thread工程自定義函數(shù)段重定向失效分析》 里,我們知道 IAR 鏈接器處理自定義程序段重定向是有一些限制的,只要用戶重寫了底層 __low_level_init() 函數(shù),那么這個(gè)函數(shù)里不能調(diào)用任何與自定義程序段相關(guān)的代碼,否則自定義程序段就不會(huì)被 IAR 鏈接器(initialize by copy)正常處理。這其實(shí)對(duì)用戶來說不太友好,既然如此,我們干脆就不用 IAR 鏈接器來做代碼重定向了,今天痞子衡教大家手動(dòng)拷貝程序段到 RAM 中的方法。
手動(dòng)拷貝自定義程序段除了解決 IAR 鏈接器限制之外,還有另外一個(gè)用處,那就是拷貝的位置可以由用戶決定。比如我們希望將程序重定向到外部 PSRAM 執(zhí)行,但是在拷貝之前是需要先初始化外部 PSRAM 的,這時(shí)候我們完全可以在 main 函數(shù)里做完 PSRAM 初始化之后再做程序段的拷貝。
Note 1:閱讀本文前需要對(duì) 《IAR鏈接文件(.icf)》、《IAR映射文件(.map)》 這兩種文件有所了解。
Note 2:本文使用的 IAR EWARM 軟件版本是 v9.30.1。
一、源文件里自定義程序段
首先我們要將需要重定向到 RAM 中執(zhí)行的全部關(guān)鍵函數(shù)放到同一個(gè)自定義程序段里,具體方法參見痞子衡舊文 《在IAR下將關(guān)鍵函數(shù)重定向到RAM中執(zhí)行的方法》 里 2.2 小節(jié)。
我們以最經(jīng)典的 SDK_2.13.1_MIMXRT1170-EVKoardsevkmimxrt1170demo_appshello_worldcm7iar 例程( flexspi_nor_debug build)為例,將其 SysTick_DelayTicks() 函數(shù)放到自定義程序段 UserRelocateCode 里,寫法如下:
#pragmalocation="UserRelocateCode" voidSysTick_DelayTicks(uint32_tn) { g_systickCounter=n; while(g_systickCounter!=0U) { } }
二、鏈接文件里處理自定義程序段
有了自定義程序段 UserRelocateCode 后,現(xiàn)在我們需要告訴 IAR 鏈接器,這個(gè)程序段將由用戶自己做初始化處理。打開工程鏈接文件 MIMXRT1176xxxxx_cm7_flexspi_nor.icf 添加如下語句。即將 UserRelocateCode 段重定向到 EXTRAM_region 里執(zhí)行,并且這里最關(guān)鍵的是 initialize manually 這一句(區(qū)別于 SDK CodeQuickAccess 段重定向做法所用的 initialize by copy)。
define symbol m_external_ram_start = 0x60000000; define symbol m_external_ram_end = 0x6003FFFF; define region EXTRAM_region = mem:[from m_external_ram_start to m_external_ram_end]; initialize manually { section UserRelocateCode }; place in EXTRAM_region { section UserRelocateCode };
編譯修改后的工程,查看其映射文件(.map),其中和 UserRelocateCode 段相關(guān)的內(nèi)容如下,這里可以看到除了 P10 之外,P1 里還多了一個(gè)名為 UserRelocateCode_init 的段,這其實(shí)就是自定義程序段機(jī)器碼在 Flash 里的存放位置(拷貝數(shù)據(jù)源)。
******************************************************************************* *** PLACEMENT SUMMARY *** "P10": place in [from 0x6000'0000 to 0x6003'ffff] { section UserRelocateCode }; initialize manually with packing = none { section UserRelocateCode }; Section Kind Address Size Object ------- ---- ------- ---- ------ "P1": 0x4738 UserRelocateCode_init 0x3000'6800 0x10Initializer bytes const 0x3000'6800 0x10 "P10": 0x10 UserRelocateCode 0x6000'0000 0x10 UserRelocateCode-1 0x6000'0000 0x10 UserRelocateCode inited 0x6000'0000 0x10 led_blinky.o [7] - 0x6000'0010 0x10
三、手動(dòng)拷貝自定義程序段
上一節(jié)我們?cè)谟成湮募锟吹?UserRelocateCode_init 段的出現(xiàn),這其實(shí) IAR 的默認(rèn)規(guī)定,可在 IAR SystemsEmbedded Workbench 9.30.1armdocEWARM_DevelopmentGuide.ENU.pdf 文檔找到相應(yīng)規(guī)則,即重定向的自定義段,其初始化值將被放到名為原自定義段名 + _init 后綴的段里。
一切準(zhǔn)備就緒,拷貝代碼的實(shí)現(xiàn)還是比較簡單的,下面是示例拷貝函數(shù) user_code_init()。有了它,我們就可以在 main 函數(shù)里自由決定其調(diào)用位置了。
#pragmasection="UserRelocateCode" #pragmasection="UserRelocateCode_init" voiduser_code_init(void) { uint8_t*dest_start,*src_start,*src_end; uint32_tcodebytes; dest_start=__section_begin("UserRelocateCode"); src_start=__section_begin("UserRelocateCode_init"); src_end=__section_end("UserRelocateCode_init"); codebytes=src_end-src_start; while(codebytes--) { *dest_start++=*src_start++; } } intmain(void) { psram_init(); user_code_init(); //代碼省略... }
審核編輯:劉清
-
RAM
+關(guān)注
關(guān)注
8文章
1368瀏覽量
114702 -
IAR
+關(guān)注
關(guān)注
5文章
352瀏覽量
36684 -
PSRAM
+關(guān)注
關(guān)注
0文章
35瀏覽量
13351
原文標(biāo)題:IAR下如何手動(dòng)拷貝自定義程序段到RAM中執(zhí)行?
文章出處:【微信號(hào):pzh_mcu,微信公眾號(hào):痞子衡嵌入式】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論