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

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

搜索
查看: 62|回復(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ù)重定向失效分析。
3 _/ }6 G$ q0 M  i痞子衡舊文 《在IAR下將關(guān)鍵函數(shù)重定向到RAM中執(zhí)行的方法》 里介紹了三種關(guān)鍵函數(shù)重定向方法,不過這三種方法只是寫法形式不同,本質(zhì)上沒啥區(qū)別,都是利用 IAR 鏈接器特性將函數(shù)重定向到工程數(shù)據(jù)段(RW)所在 RAM 里。
' y# J0 J* X0 P6 ~* ]$ r- J) |對于 i.MXRT 這種擁有多塊地址非連續(xù)的 RAM 的芯片,其實(shí)我們也可以單獨(dú)將這些重定向函數(shù)放到一個指定的 RAM 里,不一定非得跟數(shù)據(jù)段放在同一個 RAM 里。具體實(shí)現(xiàn)也很簡單,只需要在鏈接文件里額外加一句 place in 語句處理即可,恩智浦官方 SDK 包里就是這么做的。8 Q+ b9 g, q+ U  b
然而痞子衡最近在移植一個 i.MXRT1170  RT-Thread 工程時發(fā)現(xiàn),在 IAR 鏈接文件里用自定義段來單獨(dú)指定重定向函數(shù)到 ITCM 竟然失效了,這是怎么回事?今天我們一起來看一下:& h( Q) b# W9 J9 }2 u+ P9 N5 }
  • 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 - )。
    " Q1 p" K1 a: M' o在時鐘初始化函數(shù) BOARD_BootClockRUN() 里會調(diào)用如下 UpdateSemcClock() 函數(shù),這個函數(shù)需要重定向到 RAM 里執(zhí)行,在代碼里先將它放到自定義 CodeQuickAccess 段里。
    ; J) f' r8 E5 I" O  G#define AT_QUICKACCESS_SECTION_CODE(func) func @"CodeQuickAccess", z6 T9 y" F( R# l6 m$ f1 n
    #if defined(XIP_BOOT_HEADER_ENABLE) && (XIP_BOOT_HEADER_ENABLE == 1)
    3 J$ Q& s; }" \$ h& a1 g#if defined(XIP_BOOT_HEADER_DCD_ENABLE) && (XIP_BOOT_HEADER_DCD_ENABLE == 1)( w( T3 I3 w* o/ B' r1 z
    AT_QUICKACCESS_SECTION_CODE(void UpdateSemcClock(void));
    " y' {2 h' _( N3 Qvoid UpdateSemcClock(void)% P4 R0 L& z/ U' e! e4 f- a
    {
    # E8 n7 O# n5 s+ N+ b    SEMC->IPCMD = 0xA55A000D;/ r. M4 \1 C0 b' f; E& l
        while ((SEMC->INTR & 0x3) == 0);
    6 s8 a! P$ M, i' x    SEMC->INTR                                = 0x3;' s) M' g/ y- A  ~$ w/ ~. e# T
        SEMC->DCCR                                = 0x0B;
    ! a/ W% H/ ~  A! H1 x5 `. A    CCM->CLOCK_ROOT[kCLOCK_Root_Semc].CONTROL = 0x602;
    2 j: n0 e3 |6 X/ T3 Z3 o5 ?  K8 [* X}
    . m/ [  d" N( p, K. I#endif' J: M6 ?, G8 h
    #endif  d: m1 B' u* F9 I) a/ x1 Q5 W, p; K
    然后在工程鏈接文件 MIMXRT1176xxxxx_cm7_flexspi_nor_sdram.icf 里(僅摘錄部分),再將 CodeQuickAccess 段單獨(dú)放在 ITCM 里(0x00000000 - ),這就是官方 SDK 里的做法。& `- r: g+ l  k2 @" x
    define symbol m_data3_start            = 0x80000000;
    ' s7 {0 M& x& c7 N4 w% s: zdefine symbol m_data3_end              = 0x82FFFFFF;
    ' T$ }8 ~* l0 Wdefine symbol m_qacode_start           = 0x00000000;% U1 C* g  m- L
    define symbol m_qacode_end             = 0x0003FFFF;
    : ?! o6 @5 {& k* ?9 odefine region DATA3_region  = mem:[from m_data3_start to m_data3_end-__size_cstack__];
    : m+ @! U: q! Jdefine region QACODE_region = mem:[from m_qacode_start to m_qacode_end];
    7 ^3 d( P6 v: Z0 e5 ?define block RW            { first readwrite, section m_usb_dma_init_data };
    8 u* y0 `( }% o0 g! M1 v) }& ndefine block QACCESS_CODE  { section CodeQuickAccess };; ]$ B) D1 @3 c' O: R3 V: `
    initialize by copy         { readwrite, section .textrw, section CodeQuickAccess };- \, y/ n1 Z$ E
    place in DATA3_region                  { block RW };( H' ?$ P9 f8 l( j, I; P" q
    place in QACODE_region                 { block QACCESS_CODE };
    2 H2 i" Y2 }% `* s編譯鏈接 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。6 N% q; u& M1 l  j( p* s. [; O
    *******************************************************************************
    1 H: K. I+ j# G# @( n+ _5 I*** PLACEMENT SUMMARY* W4 R/ V+ Y- d# L! a+ k
    ***8 [: x. b. _1 B5 I) R
    define block QACCESS_CODE { section CodeQuickAccess };* `5 h3 P+ o1 t5 y
    "P7":  place in [from 0x0 to 0x3'ffff] { block QACCESS_CODE };# v- q% r- v* Q
      Section              Kind         Address      Size  Object
    ) @* G/ S$ C4 E  g; P5 n4 h  b  -------              ----         -------      ----  ------; K3 ]+ w9 y3 d. d1 f
    "P7":                                            0x3c1 P1 A' h. }0 X0 R
      QACCESS_CODE                          0x0      0x3c  [B]
    $ d' v2 e/ W! C6 G    QACCESS_CODE-1                      0x0      0x3c  [I]- h& R$ {& y; n' j& ?) f% h
          CodeQuickAccess  inited           0x0      0x3c  clock_config.o [1]
    + r/ H1 }4 ~( F1 I% p                                     - 0x3c      0x3c4 f* x  l! F$ y  ^$ Q3 _
    *******************************************************************************. r3 @6 C9 l$ h# j6 z4 D
    *** MODULE SUMMARY7 b- _, b; `8 s) z* N% v) a% B
    ***
    1 A/ U+ j8 ?3 {8 v& A+ p    Module                              ro code  rw code  ro data  rw data
    ! M% S  R8 d3 S6 l    ------                              -------  -------  -------  -------# c" v" E3 w* m8 X* _; O
        clock_config.o                        2'644       60      844
    # ~8 n+ T9 h0 ~' ^8 U*******************************************************************************8 I( X: s7 @/ `$ I6 e9 W5 i2 x* ?9 D
    *** ENTRY LIST
    6 ^$ }# I- G) _5 O( L1 q% Q' F# e***. L' p  ]6 D4 Z' B% R% {
        Entry                       Address   Size  Type      Object" b  \  \/ T: O
        ----                       -------   ----  ----      ------
    3 {. y2 e- \, ^    UpdateSemcClock                 0x1   0x3c  Code  Gb  clock_config.o [1]2 v+ U% X. R8 G3 e& H
    二、引出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 }; 語句沒起作用,這顯然就是一個分散鏈接而已。
    ; S3 s0 v5 i7 y: T2 @* a*******************************************************************************
    9 D! Q) t1 v8 R  G2 _0 D*** PLACEMENT SUMMARY9 [. P  t) S2 ^* {! |+ C5 J
    ***
    - q. G$ F. V+ Tdefine block QACCESS_CODE { section CodeQuickAccess };
    - D& K- \" C" n"P7":  place in [from 0x0 to 0x3'ffff] { block QACCESS_CODE };
    8 W% m0 ?" D9 ]# a( s0 i6 g6 {  Section              Kind         Address    Size  Object& f5 Q# x9 x' G& ]; |* U# C( g
      -------              ----         -------    ----  ------
    ' G2 d2 J6 |( a- t0 e"P7":                                          0x3c
    9 ?! x  Y' S; d3 B6 `7 u1 b5 V  QACCESS_CODE                          0x0    0x3c  [B]
    ( t/ ^$ J  V" e# N  E5 s* Z    CodeQuickAccess    ro code          0x0    0x3c  clock_config.o [4]3 `; T9 H7 h. F: A, O* U# T
                                         - 0x3c    0x3c
    $ E. |+ y7 ^9 M1 C' s*******************************************************************************
    ! T0 e" U  ~7 b6 {( U8 `*** MODULE SUMMARY
      R! T4 v1 E' I9 G* d***. r) o* y5 V# T, Q) w
        Module                              ro code  ro data  rw data
    . ~; Y6 n& [* a    ------                              -------  -------  -------/ Y6 w6 h6 v7 K4 w. o$ \
        clock_config.o                        2'768      784- k" X% u1 p* X  H& J# q7 E
    *******************************************************************************
    + f. k" f) w' m9 c9 m% N*** ENTRY LIST  i( e" j4 p4 |; R6 H, h
    ***
    1 ^, `$ u. ]  j9 G    Entry                       Address   Size  Type      Object
    $ Z1 h4 s5 x4 L! w) t( r+ F/ h    ----                       -------   ----  ----      ------  I7 `8 V, S" I) M* p
        UpdateSemcClock                 0x1    0x3c  Code  Gb  clock_config.o [4]% D+ G- ~3 O: k2 p+ v
    三、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è)計(jì)有關(guān)。/ ]7 g  s* R; z
    經(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è)計(jì)有某種內(nèi)在關(guān)聯(lián)。9 I8 o- a& i' Q2 e- |" L/ _
  • RT-Thread 代碼:https://gitee.com/rtthread/rt-thread/blob/gitee_master/src/components.c
  • 回復(fù)

    使用道具 舉報

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

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

    本版積分規(guī)則


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