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

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

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

RT-Thread下IAR工程函數(shù)重定向為何失效?

[復制鏈接]

394

主題

394

帖子

2197

積分

三級會員

Rank: 3Rank: 3

積分
2197
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2021-11-14 22:52:00 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
大家好,我是痞子衡,是正經(jīng)搞技術的痞子。今天痞子衡給大家分享的是在IAR開發(fā)環(huán)境下RT-Thread工程函數(shù)重定向失效分析。
8 _$ ]& T- }9 z7 q* o& \痞子衡舊文 《在IAR下將關鍵函數(shù)重定向到RAM中執(zhí)行的方法》 里介紹了三種關鍵函數(shù)重定向方法,不過這三種方法只是寫法形式不同,本質(zhì)上沒啥區(qū)別,都是利用 IAR 鏈接器特性將函數(shù)重定向到工程數(shù)據(jù)段(RW)所在 RAM 里。
: a; l0 |% ~9 s$ _- a6 W" J; f對于 i.MXRT 這種擁有多塊地址非連續(xù)的 RAM 的芯片,其實我們也可以單獨將這些重定向函數(shù)放到一個指定的 RAM 里,不一定非得跟數(shù)據(jù)段放在同一個 RAM 里。具體實現(xiàn)也很簡單,只需要在鏈接文件里額外加一句 place in 語句處理即可,恩智浦官方 SDK 包里就是這么做的。: o0 W% r6 B# O" u9 @! O7 D: @
然而痞子衡最近在移植一個 i.MXRT1170  RT-Thread 工程時發(fā)現(xiàn),在 IAR 鏈接文件里用自定義段來單獨指定重定向函數(shù)到 ITCM 竟然失效了,這是怎么回事?今天我們一起來看一下:
/ k' A* O6 l: S. o
  • 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 預編譯宏里有 XIP_BOOT_HEADER_DCD_ENABLE=1),即代碼段放在 Flash 里(0x30000000 - ),數(shù)據(jù)段放在 SDRAM 里(0x80000000 - )。
    4 e# h& W4 {9 ?0 _在時鐘初始化函數(shù) BOARD_BootClockRUN() 里會調(diào)用如下 UpdateSemcClock() 函數(shù),這個函數(shù)需要重定向到 RAM 里執(zhí)行,在代碼里先將它放到自定義 CodeQuickAccess 段里。
    / y* V( T* C( |2 W#define AT_QUICKACCESS_SECTION_CODE(func) func @"CodeQuickAccess"
    + p8 e+ ^4 S$ Y8 R3 |% e#if defined(XIP_BOOT_HEADER_ENABLE) && (XIP_BOOT_HEADER_ENABLE == 1)
      ]& e- n4 e$ J. I6 d/ V#if defined(XIP_BOOT_HEADER_DCD_ENABLE) && (XIP_BOOT_HEADER_DCD_ENABLE == 1)
    2 ]% K1 o' J& jAT_QUICKACCESS_SECTION_CODE(void UpdateSemcClock(void));1 `% m6 B0 o* m7 R, N/ D0 Z9 Q$ D
    void UpdateSemcClock(void)
    + k) j: j% Q5 t9 J8 R% ^4 b9 b{4 f# A7 E5 j( u: f7 P8 z
        SEMC->IPCMD = 0xA55A000D;
    . ?- _0 L8 s* N' n, N0 _    while ((SEMC->INTR & 0x3) == 0);* j1 J! b7 e6 X6 m2 ?+ c
        SEMC->INTR                                = 0x3;3 B! H  d  N9 F, u
        SEMC->DCCR                                = 0x0B;# @* N- s) {+ Z6 p  v
        CCM->CLOCK_ROOT[kCLOCK_Root_Semc].CONTROL = 0x602;1 \$ b' _7 x4 r3 @7 [' {+ |
    }2 B0 I7 [& q# J1 a2 {2 f
    #endif7 s3 C) Y1 W! B, L7 k
    #endif! @; l7 j/ I; e! |/ z2 {3 `
    然后在工程鏈接文件 MIMXRT1176xxxxx_cm7_flexspi_nor_sdram.icf 里(僅摘錄部分),再將 CodeQuickAccess 段單獨放在 ITCM 里(0x00000000 - ),這就是官方 SDK 里的做法。
    + r5 |  R  S7 P5 ~0 K$ }( H$ [define symbol m_data3_start            = 0x80000000;
    $ G* _: a) a0 {! R5 rdefine symbol m_data3_end              = 0x82FFFFFF;
    ! d2 Q" x0 Z, ]9 b: Tdefine symbol m_qacode_start           = 0x00000000;( I& m5 O* P7 N
    define symbol m_qacode_end             = 0x0003FFFF;# o  T8 s- w. v3 b7 q' `
    define region DATA3_region  = mem:[from m_data3_start to m_data3_end-__size_cstack__];1 ?5 J4 w! S! S! k& p
    define region QACODE_region = mem:[from m_qacode_start to m_qacode_end];( {3 M: R/ r# I: C
    define block RW            { first readwrite, section m_usb_dma_init_data };8 Z3 E! L. C0 P$ L) o) J8 g* X
    define block QACCESS_CODE  { section CodeQuickAccess };
    . l8 o" w& ^; Y8 zinitialize by copy         { readwrite, section .textrw, section CodeQuickAccess };4 u5 a' h( w1 |0 V2 ~. B  Q
    place in DATA3_region                  { block RW };
    ! Q$ _6 Q; u/ oplace in QACODE_region                 { block QACCESS_CODE };
    ( Y0 t+ }" \7 i! H, c/ m編譯鏈接 hello_world_demo_cm7.ewp 工程,然后查看其映射文件(hello_world_demo_cm7.map)找到跟 UpdateSemcClock() 函數(shù)相關的內(nèi)容如下,顯然這是符合預期的。這里特別注意一下,CodeQuickAccess 的類別顯示的是 inited,表明其不是常見的 ro code,而是經(jīng)過重定向的,而且 UpdateSemcClock() 函數(shù)所在 clock_config.o 里包含了 60個字節(jié)的 rw code。
    , c  ^; N2 H- F+ a( p*******************************************************************************
    3 c- u" w. w. I1 ^+ W6 Y0 t*** PLACEMENT SUMMARY. @( X( f) e) H+ b6 v* p
    ***
    7 x" w# N0 [0 J  i  i+ adefine block QACCESS_CODE { section CodeQuickAccess };8 h) X6 b9 J) L' ^2 Y
    "P7":  place in [from 0x0 to 0x3'ffff] { block QACCESS_CODE };
    1 s7 H( u6 H4 ~8 A3 s- r  Section              Kind         Address      Size  Object! I0 P3 J7 \, a1 W3 D' q
      -------              ----         -------      ----  ------
    4 B& V2 f% a1 g* A8 k"P7":                                            0x3c
    $ O, s/ S& P. Z) I7 t# u, {  QACCESS_CODE                          0x0      0x3c  [B]3 q( F& h  y- N' |
        QACCESS_CODE-1                      0x0      0x3c  [I]  s' S4 X. R- |9 [6 V
          CodeQuickAccess  inited           0x0      0x3c  clock_config.o [1]
    3 _4 S5 b8 @; o1 Z; s% w                                     - 0x3c      0x3c
    ' |0 s* z$ `, p9 C, G/ q*******************************************************************************
      r7 D- F! t1 B, Y! N5 W*** MODULE SUMMARY
    % Q( Z- u5 D# O4 U***
    & n+ R" @, `$ e: M    Module                              ro code  rw code  ro data  rw data
    1 |8 m& o& e. k+ {0 e    ------                              -------  -------  -------  -------
    1 ~0 K3 L* r( Z2 r+ n7 ?  q! Q    clock_config.o                        2'644       60      844  I. P. x6 P5 J% v6 t) i- ]; @7 T
    *******************************************************************************7 H# U( M0 Q9 g' `2 E" L
    *** ENTRY LIST
    / M" m$ N5 C* F) z***7 l. X% V. ]0 F# L& d  v9 b
        Entry                       Address   Size  Type      Object
    # B' w8 h# B4 \6 p: k7 T    ----                       -------   ----  ----      ------* k7 _& r' I; t) I4 h! ^
        UpdateSemcClock                 0x1   0x3c  Code  Gb  clock_config.o [1]
    7 Y  v1 m" J) O$ S# A- G二、引出RT-Thread下函數(shù)重定向失效問題現(xiàn)在來看 RT-Thread 工程,也是一個簡單的 hello world(具體工程略去不表),其中 i.MXRT1170 芯片 BSP 部分直接來自于官方 SDK,鏈接文件也與 SDK 里一致,但是編譯鏈接工程后查看其映射文件,發(fā)現(xiàn)跟 UpdateSemcClock() 函數(shù)相關的內(nèi)容如下,CodeQuickAccess 的類別顯示的是 ro code, UpdateSemcClock() 函數(shù)所在 clock_config.o 里干脆連 rw code 都沒有。顯然函數(shù)重定向失效了,鏈接文件里 initialize by copy { section CodeQuickAccess }; 語句沒起作用,這顯然就是一個分散鏈接而已。/ |  c) o" b2 M; K2 X
    *******************************************************************************2 S% J. n4 B4 ~
    *** PLACEMENT SUMMARY* g4 b! I7 E. ^' Q- l3 _. a
    ***
    5 s6 f5 G  b6 G+ z5 qdefine block QACCESS_CODE { section CodeQuickAccess };
    - e7 U9 P4 h5 u; p; `/ E$ u! t"P7":  place in [from 0x0 to 0x3'ffff] { block QACCESS_CODE };
    ' y! g9 y. I8 a" T  Section              Kind         Address    Size  Object/ [9 n$ [, B! j- @" g# @' v
      -------              ----         -------    ----  ------, s( b0 p. u9 T) _" T; `
    "P7":                                          0x3c
    & W7 U6 i$ Y4 w  QACCESS_CODE                          0x0    0x3c  [B]
    # X* N. p% K7 X* {# C$ J! R    CodeQuickAccess    ro code          0x0    0x3c  clock_config.o [4]% t9 D1 g9 {4 d
                                         - 0x3c    0x3c/ D& v- I: e- K+ O5 f
    *******************************************************************************; A- \; W& @7 _0 `0 s7 O
    *** MODULE SUMMARY
    6 K9 G+ \) H. A% ]+ z# B& }% r***
    3 q9 l; W2 T4 X( z5 l    Module                              ro code  ro data  rw data& J$ `: e- @% p1 x
        ------                              -------  -------  -------
    " c4 \& p4 [- S3 ]  w5 C" ~% a9 W    clock_config.o                        2'768      784
    7 l' I& N# }5 c* J: h* o5 k  V*******************************************************************************
    . C2 e/ q- p  s. I5 a0 c*** ENTRY LIST
    6 ], S" o6 k" l6 ]* ]. d# Q***' C0 p7 _  N- E4 ]
        Entry                       Address   Size  Type      Object6 x+ d. t. w' H* o
        ----                       -------   ----  ----      ------1 S4 u: ], F, s0 ?( G
        UpdateSemcClock                 0x1    0x3c  Code  Gb  clock_config.o [4]
    : V0 \* @( r2 [! O! W三、RT-Thread下函數(shù)重定向失效分析第一節(jié)里 SDK 裸機環(huán)境下函數(shù)重定向做法不會失效,RT-Thread 環(huán)境下同樣的做法就失效了,難道 IAR 對 RTOS 支持不友好?但是痞子衡在 \SDK_2.11.0_MIMXRT1170-EVK\boards\evkmimxrt1170\rtos_examples\freertos_hello 下做了相同實驗,F(xiàn)reeRTOS 下這種函數(shù)重定向方式也是沒有問題的(FreeRTOS 內(nèi)核啟動是在 main() 里),所以這個問題主要跟 RT-Thread 內(nèi)核代碼結(jié)構設計有關。
    + V& ?2 B' L* r4 U+ g) h3 K經(jīng)過裸機工程、RT-Thread 工程、FreeRTOS 工程三者對比,痞子衡找到了問題所在。RT-Thread 內(nèi)核啟動是在 /src/components.c 文件中的 __low_level_init() 函數(shù)里,而這個 __low_level_init() 函數(shù)本應是 IAR 入口函數(shù) __iar_program_start() 中的一部分(IAR 系統(tǒng)庫里有一個內(nèi)置 PUBWEAK 版本),但是 RT-Thread 重實現(xiàn)了這個 __low_level_init() 函數(shù),很不幸的是 IAR 鏈接器對于自定義段的函數(shù)重定向認定與原內(nèi)置 __low_level_init() 函數(shù)設計有某種內(nèi)在關聯(lián)。
    1 e; Z8 F/ w& j! P! B/ q
  • RT-Thread 代碼:https://gitee.com/rtthread/rt-thread/blob/gitee_master/src/components.c
  • 回復

    使用道具 舉報

    發(fā)表回復

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

    本版積分規(guī)則


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