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

PCB聯(lián)盟網

搜索
查看: 59|回復: 0
收起左側

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

[復制鏈接]

394

主題

394

帖子

2197

積分

三級會員

Rank: 3Rank: 3

積分
2197
跳轉到指定樓層
樓主
發(fā)表于 2021-11-14 22:52:00 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家分享的是在IAR開發(fā)環(huán)境下RT-Thread工程函數(shù)重定向失效分析。
$ _- W# V' b: p/ ]0 O痞子衡舊文 《在IAR下將關鍵函數(shù)重定向到RAM中執(zhí)行的方法》 里介紹了三種關鍵函數(shù)重定向方法,不過這三種方法只是寫法形式不同,本質上沒啥區(qū)別,都是利用 IAR 鏈接器特性將函數(shù)重定向到工程數(shù)據段(RW)所在 RAM 里。
+ \+ {, E4 X$ T5 U( @# P7 q對于 i.MXRT 這種擁有多塊地址非連續(xù)的 RAM 的芯片,其實我們也可以單獨將這些重定向函數(shù)放到一個指定的 RAM 里,不一定非得跟數(shù)據段放在同一個 RAM 里。具體實現(xiàn)也很簡單,只需要在鏈接文件里額外加一句 place in 語句處理即可,恩智浦官方 SDK 包里就是這么做的。$ t# U( [9 X! Y/ t# Y
然而痞子衡最近在移植一個 i.MXRT1170  RT-Thread 工程時發(fā)現(xiàn),在 IAR 鏈接文件里用自定義段來單獨指定重定向函數(shù)到 ITCM 竟然失效了,這是怎么回事?今天我們一起來看一下:
- C. B! a8 n- c3 l9 f
  • Note 1:閱讀本文前需要對 《IAR鏈接文件(.icf)》、《IAR映射文件(.map)》 這兩種文件有所了解。
  • Note 2:本文使用的 IAR EWARM 軟件版本是 v9.10.2。一、回顧SDK里函數(shù)重定向做法我們以最經典的 \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ù)據段放在 SDRAM 里(0x80000000 - )。: Y. q8 u8 u: W( G) B& H
    在時鐘初始化函數(shù) BOARD_BootClockRUN() 里會調用如下 UpdateSemcClock() 函數(shù),這個函數(shù)需要重定向到 RAM 里執(zhí)行,在代碼里先將它放到自定義 CodeQuickAccess 段里。7 D; Y; h/ r! X: Q
    #define AT_QUICKACCESS_SECTION_CODE(func) func @"CodeQuickAccess"
    & G5 I3 y% a) D- [! W#if defined(XIP_BOOT_HEADER_ENABLE) && (XIP_BOOT_HEADER_ENABLE == 1)
    " W/ O4 G8 A! B% _6 S#if defined(XIP_BOOT_HEADER_DCD_ENABLE) && (XIP_BOOT_HEADER_DCD_ENABLE == 1), f4 ^* `! w( q  m3 C
    AT_QUICKACCESS_SECTION_CODE(void UpdateSemcClock(void));
    # \7 Z/ U) E. E7 x4 Hvoid UpdateSemcClock(void)
    % s% U. |+ b+ Q1 a) h. C# F{
    ( M; r9 i5 G6 _3 c7 E' D9 w! N    SEMC->IPCMD = 0xA55A000D;
      B/ Q2 W" C2 l0 p    while ((SEMC->INTR & 0x3) == 0);2 b0 O0 \7 _- }1 y3 b
        SEMC->INTR                                = 0x3;0 p" E: \: z% \" \
        SEMC->DCCR                                = 0x0B;* [; R- }& K8 d7 r+ J9 l
        CCM->CLOCK_ROOT[kCLOCK_Root_Semc].CONTROL = 0x602;; t0 u9 P6 R: \3 N, ?
    }
    * A/ K: B% c: W6 H) L#endif
    - s( H  E- q6 A0 d$ n. V#endif  S: M; C2 Y* e4 r! u" W
    然后在工程鏈接文件 MIMXRT1176xxxxx_cm7_flexspi_nor_sdram.icf 里(僅摘錄部分),再將 CodeQuickAccess 段單獨放在 ITCM 里(0x00000000 - ),這就是官方 SDK 里的做法。
    + t+ e3 |# r* k; [define symbol m_data3_start            = 0x80000000;' u  X* ]5 L+ F
    define symbol m_data3_end              = 0x82FFFFFF;
    ! y9 h/ E3 |8 O& U" j5 x; j+ ddefine symbol m_qacode_start           = 0x00000000;9 e5 P5 t  P  Y5 Z! f& A  y
    define symbol m_qacode_end             = 0x0003FFFF;
    / a: e$ D' \' J! p  P, U  Udefine region DATA3_region  = mem:[from m_data3_start to m_data3_end-__size_cstack__];! y* H. o" p0 k6 t3 e8 ?7 Q" j
    define region QACODE_region = mem:[from m_qacode_start to m_qacode_end];, }+ Y) Z4 Y) c" D/ u( M/ ?- ?
    define block RW            { first readwrite, section m_usb_dma_init_data };
    ) W( E- J- Q7 h0 ^$ G& F2 _1 o9 tdefine block QACCESS_CODE  { section CodeQuickAccess };
    / Q+ g0 H$ t% K2 l* u" Winitialize by copy         { readwrite, section .textrw, section CodeQuickAccess };
    6 a; b$ D9 N# M. S! S% ?: M8 iplace in DATA3_region                  { block RW };9 w  K4 G% Q7 x( N: c
    place in QACODE_region                 { block QACCESS_CODE };! f/ o* i4 B/ J  ~. t$ m+ H! h7 l
    編譯鏈接 hello_world_demo_cm7.ewp 工程,然后查看其映射文件(hello_world_demo_cm7.map)找到跟 UpdateSemcClock() 函數(shù)相關的內容如下,顯然這是符合預期的。這里特別注意一下,CodeQuickAccess 的類別顯示的是 inited,表明其不是常見的 ro code,而是經過重定向的,而且 UpdateSemcClock() 函數(shù)所在 clock_config.o 里包含了 60個字節(jié)的 rw code。6 Y8 m8 }3 _. j5 P
    *******************************************************************************% d* |7 p% c" Z- z5 r9 D% ?
    *** PLACEMENT SUMMARY# p" U' F  N' C$ f  t. s
    ***/ ~  Q* f! d  @: n; G+ I
    define block QACCESS_CODE { section CodeQuickAccess };
    ; v( x8 u' g% y/ \- V"P7":  place in [from 0x0 to 0x3'ffff] { block QACCESS_CODE };. ^: C* v) }5 l1 b6 }$ u
      Section              Kind         Address      Size  Object" I0 v; P& r: P. t* [) P* f2 [
      -------              ----         -------      ----  ------
    9 O$ P$ T. |, J1 j3 B3 U"P7":                                            0x3c. v: p1 y2 j; F- }" H& U
      QACCESS_CODE                          0x0      0x3c  [B]8 Z& Q8 Z) V; ?0 D: E( ]
        QACCESS_CODE-1                      0x0      0x3c  [I]
    " t2 u5 \0 Q) l* R      CodeQuickAccess  inited           0x0      0x3c  clock_config.o [1]$ ]8 A. _; K" e# Q2 T
                                         - 0x3c      0x3c
    ' p1 B) p  d5 V0 |" @3 d) q*******************************************************************************
    1 f- A1 r3 ~! `: v2 E/ ?' F' H*** MODULE SUMMARY
    9 l4 @- K( [6 q***
      t) M6 ~, y+ ^+ ^2 `    Module                              ro code  rw code  ro data  rw data4 t5 {& ^& V9 n1 {( E
        ------                              -------  -------  -------  -------8 ~7 E7 E# O, ?6 @* M6 d! s
        clock_config.o                        2'644       60      844
    $ |2 A( S' p: Z*******************************************************************************# l( U" K- ^' V8 T/ @+ q
    *** ENTRY LIST* A3 ?" z1 m' `
    ***
    0 t6 Z" q& b8 H* Y9 O/ H! C    Entry                       Address   Size  Type      Object: n$ V  e8 x/ p
        ----                       -------   ----  ----      ------
    * f2 C$ `- _7 c$ U4 Q* B2 p7 \    UpdateSemcClock                 0x1   0x3c  Code  Gb  clock_config.o [1]
    % x* q% ~0 U9 y# y5 X" _二、引出RT-Thread下函數(shù)重定向失效問題現(xiàn)在來看 RT-Thread 工程,也是一個簡單的 hello world(具體工程略去不表),其中 i.MXRT1170 芯片 BSP 部分直接來自于官方 SDK,鏈接文件也與 SDK 里一致,但是編譯鏈接工程后查看其映射文件,發(fā)現(xiàn)跟 UpdateSemcClock() 函數(shù)相關的內容如下,CodeQuickAccess 的類別顯示的是 ro code, UpdateSemcClock() 函數(shù)所在 clock_config.o 里干脆連 rw code 都沒有。顯然函數(shù)重定向失效了,鏈接文件里 initialize by copy { section CodeQuickAccess }; 語句沒起作用,這顯然就是一個分散鏈接而已。
    6 Z! B" g: x" P5 K7 M******************************************************************************** ?9 g/ G( b" V, Y. F3 d
    *** PLACEMENT SUMMARY* p" ^4 v3 R  ?+ W5 ]& a
    ***6 w* y+ ^3 f/ L7 t& X
    define block QACCESS_CODE { section CodeQuickAccess };  C  Q$ l1 F8 W; }
    "P7":  place in [from 0x0 to 0x3'ffff] { block QACCESS_CODE };
    9 K$ @: j' F0 \6 |3 Y: w  P" b  Section              Kind         Address    Size  Object
    3 l1 r2 _8 k2 i) A: P. O  -------              ----         -------    ----  ------: }8 J2 o  f2 B' K# y
    "P7":                                          0x3c4 n. g6 u% S9 V
      QACCESS_CODE                          0x0    0x3c  [B]
    # [/ ?/ L4 ?+ l  g$ T, [" J    CodeQuickAccess    ro code          0x0    0x3c  clock_config.o [4]3 S' q$ m' D! S7 N; a! ~' t' W' H
                                         - 0x3c    0x3c- E) Y: l, ~: p" c; V2 H  u
    *******************************************************************************5 c: U1 y) U9 V3 F! j0 {2 Z" I0 u- S
    *** MODULE SUMMARY
    . u5 N9 x4 w* M* B, V) I8 K***
    ' f% t5 z% ]  `3 `. r    Module                              ro code  ro data  rw data# K. I8 [+ x* z
        ------                              -------  -------  -------
    / L, N. S  `9 ?    clock_config.o                        2'768      784
    5 W" k, F$ Z- o$ g*******************************************************************************
    " Y7 ^) I, _& t# d*** ENTRY LIST6 V/ ]: C( B% K3 ]6 ^2 d9 y. s
    ***
    + g0 U- D3 L4 H0 g9 i    Entry                       Address   Size  Type      Object0 m$ J8 U- t/ s/ `+ ?8 ^( n  m
        ----                       -------   ----  ----      ------5 v  {- `4 G" [
        UpdateSemcClock                 0x1    0x3c  Code  Gb  clock_config.o [4]
    4 D' R* R& H6 R' D# B3 M三、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 內核啟動是在 main() 里),所以這個問題主要跟 RT-Thread 內核代碼結構設計有關。( j- Q7 s* M- z/ H3 d+ p
    經過裸機工程、RT-Thread 工程、FreeRTOS 工程三者對比,痞子衡找到了問題所在。RT-Thread 內核啟動是在 /src/components.c 文件中的 __low_level_init() 函數(shù)里,而這個 __low_level_init() 函數(shù)本應是 IAR 入口函數(shù) __iar_program_start() 中的一部分(IAR 系統(tǒng)庫里有一個內置 PUBWEAK 版本),但是 RT-Thread 重實現(xiàn)了這個 __low_level_init() 函數(shù),很不幸的是 IAR 鏈接器對于自定義段的函數(shù)重定向認定與原內置 __low_level_init() 函數(shù)設計有某種內在關聯(lián)。
    % n) V' @2 H, ]
  • RT-Thread 代碼:https://gitee.com/rtthread/rt-thread/blob/gitee_master/src/components.c
  • 回復

    使用道具 舉報

    發(fā)表回復

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

    本版積分規(guī)則


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