電子產(chǎn)業(yè)一站式賦能平臺

PCB聯(lián)盟網(wǎng)

搜索
查看: 61|回復(fù): 0
收起左側(cè)

RT-Thread下IAR工程函數(shù)重定向?yàn)楹问В?/span>

[復(fù)制鏈接]

394

主題

394

帖子

2197

積分

三級會員

Rank: 3Rank: 3

積分
2197
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2021-11-14 22:52:00 | 只看該作者 回帖獎勵 |倒序?yàn)g覽 |閱讀模式
大家好,我是痞子衡,是正經(jīng)搞技術(shù)的痞子。今天痞子衡給大家分享的是在IAR開發(fā)環(huán)境下RT-Thread工程函數(shù)重定向失效分析。
2 b7 ~+ e9 ]/ b, [$ Q# a* {痞子衡舊文 《在IAR下將關(guān)鍵函數(shù)重定向到RAM中執(zhí)行的方法》 里介紹了三種關(guān)鍵函數(shù)重定向方法,不過這三種方法只是寫法形式不同,本質(zhì)上沒啥區(qū)別,都是利用 IAR 鏈接器特性將函數(shù)重定向到工程數(shù)據(jù)段(RW)所在 RAM 里。! j" H9 b' s  r  Y5 y- f) x+ a
對于 i.MXRT 這種擁有多塊地址非連續(xù)的 RAM 的芯片,其實(shí)我們也可以單獨(dú)將這些重定向函數(shù)放到一個指定的 RAM 里,不一定非得跟數(shù)據(jù)段放在同一個 RAM 里。具體實(shí)現(xiàn)也很簡單,只需要在鏈接文件里額外加一句 place in 語句處理即可,恩智浦官方 SDK 包里就是這么做的。
+ ^, E- `  @8 a/ u4 |然而痞子衡最近在移植一個 i.MXRT1170  RT-Thread 工程時發(fā)現(xiàn),在 IAR 鏈接文件里用自定義段來單獨(dú)指定重定向函數(shù)到 ITCM 竟然失效了,這是怎么回事?今天我們一起來看一下:& U3 V" b8 I  k' H3 A$ |, h4 e
  • Note 1:閱讀本文前需要對 《IAR鏈接文件(.icf)》、《IAR映射文件(.map)》 這兩種文件有所了解。
  • Note 2:本文使用的 IAR EWARM 軟件版本是 v9.10.2。一、回顧SDK里函數(shù)重定向做法我們以最經(jīng)典的 \SDK_2.11.0_MIMXRT1170-EVK\boards\evkmimxrt1170\demo_apps\hello_world\cm7\iar 例程來看,工程 Build 選擇 flexspi_nor_sdram_debug(僅該 build 預(yù)編譯宏里有 XIP_BOOT_HEADER_DCD_ENABLE=1),即代碼段放在 Flash 里(0x30000000 - ),數(shù)據(jù)段放在 SDRAM 里(0x80000000 - )。1 x$ ]; ]3 q- B6 ^+ A
    在時鐘初始化函數(shù) BOARD_BootClockRUN() 里會調(diào)用如下 UpdateSemcClock() 函數(shù),這個函數(shù)需要重定向到 RAM 里執(zhí)行,在代碼里先將它放到自定義 CodeQuickAccess 段里。
    % {3 P# s$ }0 t' B#define AT_QUICKACCESS_SECTION_CODE(func) func @"CodeQuickAccess"
    . t& b" y+ k) a# n#if defined(XIP_BOOT_HEADER_ENABLE) && (XIP_BOOT_HEADER_ENABLE == 1)
    ; F+ z/ t1 a3 L" {0 v" c2 x+ H#if defined(XIP_BOOT_HEADER_DCD_ENABLE) && (XIP_BOOT_HEADER_DCD_ENABLE == 1)& j8 v# j; W7 b: v( a
    AT_QUICKACCESS_SECTION_CODE(void UpdateSemcClock(void));% f) j( p$ Z. f" q; J
    void UpdateSemcClock(void)
    % C! {" [/ Q2 n, i; t4 N{
    & N7 V, A  e3 ]# F    SEMC->IPCMD = 0xA55A000D;4 R  [4 P- G, F& ^  G; |( F
        while ((SEMC->INTR & 0x3) == 0);" `8 O* g( t3 @7 m& @
        SEMC->INTR                                = 0x3;
    / g- @: J/ }+ M# X0 F! ?    SEMC->DCCR                                = 0x0B;- ]8 ]' d0 Z% h. w: q" g
        CCM->CLOCK_ROOT[kCLOCK_Root_Semc].CONTROL = 0x602;/ F/ K" e, J  {2 C* y* l' m  d. y
    }
    * U( ^! `( V# M3 y#endif- P. x1 G7 P  t* ?
    #endif
    + c$ Z, E, t, o' Z+ C然后在工程鏈接文件 MIMXRT1176xxxxx_cm7_flexspi_nor_sdram.icf 里(僅摘錄部分),再將 CodeQuickAccess 段單獨(dú)放在 ITCM 里(0x00000000 - ),這就是官方 SDK 里的做法。# j# ], ~2 g0 |& I! D$ g- p& Q9 t
    define symbol m_data3_start            = 0x80000000;
    $ K- l' \6 {: {) {1 Idefine symbol m_data3_end              = 0x82FFFFFF;" M$ r4 p% [- n6 f/ d' q
    define symbol m_qacode_start           = 0x00000000;/ ~+ m9 y0 E, |+ m; u3 @
    define symbol m_qacode_end             = 0x0003FFFF;
    , l9 P. t6 k3 k  A& C2 f- l! e. pdefine region DATA3_region  = mem:[from m_data3_start to m_data3_end-__size_cstack__];: }; C, P/ D& s; G
    define region QACODE_region = mem:[from m_qacode_start to m_qacode_end];
      U' c# l# ?$ idefine block RW            { first readwrite, section m_usb_dma_init_data };; O9 r& Y0 x' T, j  i" ~; J2 {
    define block QACCESS_CODE  { section CodeQuickAccess };6 y4 a6 K) v- S  q7 g
    initialize by copy         { readwrite, section .textrw, section CodeQuickAccess };' K: ~& i6 s( ^# j. r$ z
    place in DATA3_region                  { block RW };
    % e) Y8 s, Z* g$ Tplace in QACODE_region                 { block QACCESS_CODE };
    % R  c, P# O: s, Z9 u/ b編譯鏈接 hello_world_demo_cm7.ewp 工程,然后查看其映射文件(hello_world_demo_cm7.map)找到跟 UpdateSemcClock() 函數(shù)相關(guān)的內(nèi)容如下,顯然這是符合預(yù)期的。這里特別注意一下,CodeQuickAccess 的類別顯示的是 inited,表明其不是常見的 ro code,而是經(jīng)過重定向的,而且 UpdateSemcClock() 函數(shù)所在 clock_config.o 里包含了 60個字節(jié)的 rw code。0 L4 G, {) n  `& p) T" P
    *******************************************************************************% S% X/ q/ u; q; i- y$ Q6 O( y
    *** PLACEMENT SUMMARY2 \7 f* L! t/ a; s$ \3 `$ J
    ***
    - J( P) u  {- M- Cdefine block QACCESS_CODE { section CodeQuickAccess };
    + ?/ o+ l( E1 I/ u6 `; H0 O"P7":  place in [from 0x0 to 0x3'ffff] { block QACCESS_CODE };1 U" i3 \9 p6 O$ K/ ]( B$ f
      Section              Kind         Address      Size  Object6 C) g  }: ]. V" m) ^  ^
      -------              ----         -------      ----  ------# g  S) k* a' [4 U6 N0 e. E
    "P7":                                            0x3c
    ) y' O  B6 _; k8 s. M9 n  QACCESS_CODE                          0x0      0x3c  [B]9 F% c, x8 p) W( @1 J% L$ L3 g
        QACCESS_CODE-1                      0x0      0x3c  [I]
    ; Z3 r& m7 U. ?. P      CodeQuickAccess  inited           0x0      0x3c  clock_config.o [1]5 y9 _; d" J" R9 @  ?. Z
                                         - 0x3c      0x3c
    - {' s1 S* f* P. z% F*******************************************************************************
    & k" n1 W" e; l( w3 k*** MODULE SUMMARY
    7 ]1 }- W0 x5 F! {7 v***
    9 F& R7 f6 p, _0 |; Q$ _9 a    Module                              ro code  rw code  ro data  rw data
    ; F# a* @; V# D1 G, c9 Z+ p9 m    ------                              -------  -------  -------  -------2 h( m6 O; g1 I# k
        clock_config.o                        2'644       60      844' q" A9 G2 z& y/ Y6 ^8 Q
    *******************************************************************************
      B8 p( E- G: C* t, n# A*** ENTRY LIST
    & p6 D2 H6 @$ }1 a1 p) Y6 g% V***; o) ^! c2 D$ V' E/ f) M
        Entry                       Address   Size  Type      Object
    ( T( B' W  g% O9 Q- T    ----                       -------   ----  ----      ------* A( _* J1 e0 X9 U$ F
        UpdateSemcClock                 0x1   0x3c  Code  Gb  clock_config.o [1]4 W9 E3 v( @: r
    二、引出RT-Thread下函數(shù)重定向失效問題現(xiàn)在來看 RT-Thread 工程,也是一個簡單的 hello world(具體工程略去不表),其中 i.MXRT1170 芯片 BSP 部分直接來自于官方 SDK,鏈接文件也與 SDK 里一致,但是編譯鏈接工程后查看其映射文件,發(fā)現(xiàn)跟 UpdateSemcClock() 函數(shù)相關(guān)的內(nèi)容如下,CodeQuickAccess 的類別顯示的是 ro code, UpdateSemcClock() 函數(shù)所在 clock_config.o 里干脆連 rw code 都沒有。顯然函數(shù)重定向失效了,鏈接文件里 initialize by copy { section CodeQuickAccess }; 語句沒起作用,這顯然就是一個分散鏈接而已。
    ( U# {6 c  ^' g3 H- a# \* y* j******************************************************************************** U/ P; z! T1 N9 ]" a& B
    *** PLACEMENT SUMMARY9 K* |* ]8 E( |7 X0 J
    ***
    6 W: b$ A4 F% d5 T& U2 ydefine block QACCESS_CODE { section CodeQuickAccess };9 o$ e/ K% M: D. _% {
    "P7":  place in [from 0x0 to 0x3'ffff] { block QACCESS_CODE };+ R0 V- n- X) Z
      Section              Kind         Address    Size  Object; g7 z- }' e% \
      -------              ----         -------    ----  ------
    # |2 [3 b5 o) m! y) K" r5 ~! i" B"P7":                                          0x3c1 |- k8 u& f/ U9 [: |
      QACCESS_CODE                          0x0    0x3c  [B]) H) b3 I1 ~6 M( o) m3 d2 V6 @1 t4 }
        CodeQuickAccess    ro code          0x0    0x3c  clock_config.o [4]5 ?9 B: G. X, w
                                         - 0x3c    0x3c+ m3 @9 a* r: x
    *******************************************************************************7 c3 ^: `  ]" g4 T
    *** MODULE SUMMARY% I# Q5 E1 a  Z9 X; H. [) n5 Z  d
    ***5 W0 ?: v# d& Y4 O) L) `) G
        Module                              ro code  ro data  rw data
    2 S0 L+ x) v# G5 L/ ]# m    ------                              -------  -------  -------/ G& c  [0 M; L4 L
        clock_config.o                        2'768      784
    4 U; m: Y' a7 _- S: T; v*******************************************************************************
    ( d+ M( c, D! j. u  ^+ p*** ENTRY LIST1 ^  P0 _/ R8 c* S0 ^& T8 y) p! V! t
    ***
    ( ~' W1 h( E0 `6 m, B1 J    Entry                       Address   Size  Type      Object
    / z. f) v- h" b& ~* m    ----                       -------   ----  ----      ------
    5 j6 p9 D& F4 G( l& q6 D    UpdateSemcClock                 0x1    0x3c  Code  Gb  clock_config.o [4]
    : d% T7 Y* F. W: ~  B三、RT-Thread下函數(shù)重定向失效分析第一節(jié)里 SDK 裸機(jī)環(huán)境下函數(shù)重定向做法不會失效,RT-Thread 環(huán)境下同樣的做法就失效了,難道 IAR 對 RTOS 支持不友好?但是痞子衡在 \SDK_2.11.0_MIMXRT1170-EVK\boards\evkmimxrt1170\rtos_examples\freertos_hello 下做了相同實(shí)驗(yàn),F(xiàn)reeRTOS 下這種函數(shù)重定向方式也是沒有問題的(FreeRTOS 內(nèi)核啟動是在 main() 里),所以這個問題主要跟 RT-Thread 內(nèi)核代碼結(jié)構(gòu)設(shè)計有關(guān)。' Y7 x/ C7 ], _5 E6 m# @7 w
    經(jīng)過裸機(jī)工程、RT-Thread 工程、FreeRTOS 工程三者對比,痞子衡找到了問題所在。RT-Thread 內(nèi)核啟動是在 /src/components.c 文件中的 __low_level_init() 函數(shù)里,而這個 __low_level_init() 函數(shù)本應(yīng)是 IAR 入口函數(shù) __iar_program_start() 中的一部分(IAR 系統(tǒng)庫里有一個內(nèi)置 PUBWEAK 版本),但是 RT-Thread 重實(shí)現(xiàn)了這個 __low_level_init() 函數(shù),很不幸的是 IAR 鏈接器對于自定義段的函數(shù)重定向認(rèn)定與原內(nèi)置 __low_level_init() 函數(shù)設(shè)計有某種內(nèi)在關(guān)聯(lián)。9 i5 y) I2 ]! _
  • RT-Thread 代碼:https://gitee.com/rtthread/rt-thread/blob/gitee_master/src/components.c
  • 回復(fù)

    使用道具 舉報

    發(fā)表回復(fù)

    您需要登錄后才可以回帖 登錄 | 立即注冊

    本版積分規(guī)則


    聯(lián)系客服 關(guān)注微信 下載APP 返回頂部 返回列表