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

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

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

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

[復(fù)制鏈接]

394

主題

394

帖子

2197

積分

三級(jí)會(huì)員

Rank: 3Rank: 3

積分
2197
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2021-11-14 22:52:00 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
大家好,我是痞子衡,是正經(jīng)搞技術(shù)的痞子。今天痞子衡給大家分享的是在IAR開(kāi)發(fā)環(huán)境下RT-Thread工程函數(shù)重定向失效分析
0 {; j, ^0 A1 g痞子衡舊文 《在IAR下將關(guān)鍵函數(shù)重定向到RAM中執(zhí)行的方法》 里介紹了三種關(guān)鍵函數(shù)重定向方法,不過(guò)這三種方法只是寫法形式不同,本質(zhì)上沒(méi)啥區(qū)別,都是利用 IAR 鏈接器特性將函數(shù)重定向到工程數(shù)據(jù)段(RW)所在 RAM 里。
3 K2 {' B" ~; ]* Q8 i# K對(duì)于 i.MXRT 這種擁有多塊地址非連續(xù)的 RAM 的芯片,其實(shí)我們也可以單獨(dú)將這些重定向函數(shù)放到一個(gè)指定的 RAM 里,不一定非得跟數(shù)據(jù)段放在同一個(gè) RAM 里。具體實(shí)現(xiàn)也很簡(jiǎn)單,只需要在鏈接文件里額外加一句 place in 語(yǔ)句處理即可,恩智浦官方 SDK 包里就是這么做的。
, a  w, U* Q- R然而痞子衡最近在移植一個(gè) i.MXRT1170  RT-Thread 工程時(shí)發(fā)現(xiàn),在 IAR 鏈接文件里用自定義段來(lái)單獨(dú)指定重定向函數(shù)到 ITCM 竟然失效了,這是怎么回事?今天我們一起來(lái)看一下:
' f; d9 B5 D. t  l$ o
  • Note 1:閱讀本文前需要對(duì) 《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 例程來(lái)看,工程 Build 選擇 flexspi_nor_sdram_debug(僅該 build 預(yù)編譯宏里有 XIP_BOOT_HEADER_DCD_ENABLE=1),即代碼段放在 Flash 里(0x30000000 - ),數(shù)據(jù)段放在 SDRAM 里(0x80000000 - )。+ F; {9 D; y* C: X4 A" H1 ?3 h4 h, i1 {& ^
    在時(shí)鐘初始化函數(shù) BOARD_BootClockRUN() 里會(huì)調(diào)用如下 UpdateSemcClock() 函數(shù),這個(gè)函數(shù)需要重定向到 RAM 里執(zhí)行,在代碼里先將它放到自定義 CodeQuickAccess 段里。
    # W8 ~) I: U' Y3 h#define AT_QUICKACCESS_SECTION_CODE(func) func @"CodeQuickAccess"
    3 o/ Z( o7 P( y1 @7 K5 ?#if defined(XIP_BOOT_HEADER_ENABLE) && (XIP_BOOT_HEADER_ENABLE == 1)/ Y; c; V+ _* a) J3 p
    #if defined(XIP_BOOT_HEADER_DCD_ENABLE) && (XIP_BOOT_HEADER_DCD_ENABLE == 1)0 J, a3 L6 o& }% y
    AT_QUICKACCESS_SECTION_CODE(void UpdateSemcClock(void));% _2 l! {8 s$ Y& c# ^
    void UpdateSemcClock(void)1 k2 g0 k% b' t
    {( b5 x' s2 T7 I( E6 K, m
        SEMC->IPCMD = 0xA55A000D;
    1 j9 h  D% O( ~) O    while ((SEMC->INTR & 0x3) == 0);
    4 t' S! v0 ?5 }6 f8 \$ x* w    SEMC->INTR                                = 0x3;7 q) L1 b/ N! m$ `- `
        SEMC->DCCR                                = 0x0B;
    % ?( y$ y0 G+ {6 n" q$ V" i* p  E. c    CCM->CLOCK_ROOT[kCLOCK_Root_Semc].CONTROL = 0x602;* p) q1 {5 a$ y
    }
    ; L, r6 E. _. d; F#endif5 w9 l2 b. N7 P$ V+ q8 `
    #endif
    ( Y; o4 q* }1 d! M- S0 S1 \3 X然后在工程鏈接文件 MIMXRT1176xxxxx_cm7_flexspi_nor_sdram.icf 里(僅摘錄部分),再將 CodeQuickAccess 段單獨(dú)放在 ITCM 里(0x00000000 - ),這就是官方 SDK 里的做法。
    2 A, F) ^$ e8 {define symbol m_data3_start            = 0x80000000;( I& K4 b+ _- ]/ I/ Y
    define symbol m_data3_end              = 0x82FFFFFF;- F3 F0 P+ G% {$ R
    define symbol m_qacode_start           = 0x00000000;5 X2 I- t3 |1 _
    define symbol m_qacode_end             = 0x0003FFFF;8 W" d# `5 O9 H5 a
    define region DATA3_region  = mem:[from m_data3_start to m_data3_end-__size_cstack__];
    & o: S( ~0 y! t8 ^% D4 Odefine region QACODE_region = mem:[from m_qacode_start to m_qacode_end];
    8 x# w& I1 E1 K: [+ Edefine block RW            { first readwrite, section m_usb_dma_init_data };
    $ o- x8 g2 ?& n& ?define block QACCESS_CODE  { section CodeQuickAccess };& b1 i. ~7 h/ C4 [0 y, k; Q, S
    initialize by copy         { readwrite, section .textrw, section CodeQuickAccess };
    ' h( {0 M9 z9 p# qplace in DATA3_region                  { block RW };" \* F# Y* w$ N) Z: j2 W
    place in QACODE_region                 { block QACCESS_CODE };
    , W/ \$ ?( U' V+ O2 Y/ V編譯鏈接 hello_world_demo_cm7.ewp 工程,然后查看其映射文件(hello_world_demo_cm7.map)找到跟 UpdateSemcClock() 函數(shù)相關(guān)的內(nèi)容如下,顯然這是符合預(yù)期的。這里特別注意一下,CodeQuickAccess 的類別顯示的是 inited,表明其不是常見(jiàn)的 ro code,而是經(jīng)過(guò)重定向的,而且 UpdateSemcClock() 函數(shù)所在 clock_config.o 里包含了 60個(gè)字節(jié)的 rw code。" q2 \" b" c6 r+ o" ~2 T$ T7 ?9 ]
    *******************************************************************************4 g$ J% @& U  l# f- O' b1 L
    *** PLACEMENT SUMMARY# V; z. P; q# d; S% Z) N+ @
    ***3 d+ T# s8 v- z6 e( Z' d" k
    define block QACCESS_CODE { section CodeQuickAccess };  v! \8 W' K4 H% V
    "P7":  place in [from 0x0 to 0x3'ffff] { block QACCESS_CODE };
    ) z+ W' W* [  Y0 r  Section              Kind         Address      Size  Object
    2 h6 K, @3 l5 t8 h( g  -------              ----         -------      ----  ------  Z! z. j6 u* M* k
    "P7":                                            0x3c
    $ F  d& K% Q5 W1 c  QACCESS_CODE                          0x0      0x3c  [B]
    * z5 e" P) T) m    QACCESS_CODE-1                      0x0      0x3c  [I]
    5 Y% p$ N7 B9 d% d8 D6 f& l      CodeQuickAccess  inited           0x0      0x3c  clock_config.o [1]' s" D6 `; p: b3 ~4 V
                                         - 0x3c      0x3c; M1 f, h2 ?2 M5 E& h9 h/ Y, m
    *******************************************************************************
    9 f+ o, ]. a; V: |/ a! |' W2 T*** MODULE SUMMARY
    ( y' G' C! l* a9 D! A***
    2 I3 ]: p4 Q! ^5 @3 p8 R: D    Module                              ro code  rw code  ro data  rw data6 ]& P5 k- z  m# P3 W5 Z9 Z
        ------                              -------  -------  -------  -------4 W4 Y7 |8 T3 ~2 i! [/ E- i
        clock_config.o                        2'644       60      844
    ; K* w; z- s8 e; c! O*******************************************************************************7 y8 |: S9 k2 V: w8 O3 b3 f0 O5 f
    *** ENTRY LIST. Y8 p8 |5 ]. @' v: d
    ***$ X  k1 q' G! N, p
        Entry                       Address   Size  Type      Object
    ' @% S# ]' v; ]    ----                       -------   ----  ----      ------
    8 r* h) U$ j! i& P* _+ T+ @    UpdateSemcClock                 0x1   0x3c  Code  Gb  clock_config.o [1]
    6 n* i1 b1 [: c( K  ?7 J5 a" o二、引出RT-Thread下函數(shù)重定向失效問(wèn)題現(xiàn)在來(lái)看 RT-Thread 工程,也是一個(gè)簡(jiǎn)單的 hello world(具體工程略去不表),其中 i.MXRT1170 芯片 BSP 部分直接來(lái)自于官方 SDK,鏈接文件也與 SDK 里一致,但是編譯鏈接工程后查看其映射文件,發(fā)現(xiàn)跟 UpdateSemcClock() 函數(shù)相關(guān)的內(nèi)容如下,CodeQuickAccess 的類別顯示的是 ro code, UpdateSemcClock() 函數(shù)所在 clock_config.o 里干脆連 rw code 都沒(méi)有。顯然函數(shù)重定向失效了,鏈接文件里 initialize by copy { section CodeQuickAccess }; 語(yǔ)句沒(méi)起作用,這顯然就是一個(gè)分散鏈接而已。
    ; L: B: s2 R. D. |) v. D4 d1 W*******************************************************************************8 _. k4 o+ b1 I: z" d2 C* C& r6 g
    *** PLACEMENT SUMMARY
      I) R$ b( j# {: B# Z2 v; y***
    ; L0 Q4 e$ a) X# T8 i+ udefine block QACCESS_CODE { section CodeQuickAccess };- {" v; l  s. @6 B( _* M% ?7 \9 i
    "P7":  place in [from 0x0 to 0x3'ffff] { block QACCESS_CODE };2 @0 L8 A  ^3 `9 Z" O, U
      Section              Kind         Address    Size  Object
    4 _3 h2 A2 f8 |2 u7 Y8 ^- k  -------              ----         -------    ----  ------. l) A" }" g  k, y/ }0 P/ V
    "P7":                                          0x3c
    * n( {' O. `) b$ O: w, j/ b  QACCESS_CODE                          0x0    0x3c  [B]
    ) O1 w6 b2 F9 Z" ?: w    CodeQuickAccess    ro code          0x0    0x3c  clock_config.o [4], c" S- K1 q7 S; w8 R5 q
                                         - 0x3c    0x3c7 C! h  o  o8 F  k+ S& p
    *******************************************************************************; @% ^2 p8 p7 b
    *** MODULE SUMMARY1 e* M% P; x% B  @( R
    ***4 y& e" b6 r( _9 s) D/ w
        Module                              ro code  ro data  rw data
    % j0 `' X& Y# x- _; V* C. G    ------                              -------  -------  -------
    # g  k1 [- U" X6 [. N/ I    clock_config.o                        2'768      7849 K) c) Z2 ]; F% E
    *******************************************************************************% K4 q. L3 X- l4 \
    *** ENTRY LIST6 j3 @0 }6 a/ [) j2 g- }
    ***
    * w7 x% K1 H, [0 P" y- z    Entry                       Address   Size  Type      Object
    5 o  _1 m2 o  z: j5 a$ z    ----                       -------   ----  ----      ------' v$ w) N; s+ h
        UpdateSemcClock                 0x1    0x3c  Code  Gb  clock_config.o [4]
    3 x! F: }* Z! W" t+ U$ [8 N# T三、RT-Thread下函數(shù)重定向失效分析第一節(jié)里 SDK 裸機(jī)環(huán)境下函數(shù)重定向做法不會(huì)失效,RT-Thread 環(huán)境下同樣的做法就失效了,難道 IAR 對(duì) RTOS 支持不友好?但是痞子衡在 \SDK_2.11.0_MIMXRT1170-EVK\boards\evkmimxrt1170\rtos_examples\freertos_hello 下做了相同實(shí)驗(yàn),F(xiàn)reeRTOS 下這種函數(shù)重定向方式也是沒(méi)有問(wèn)題的(FreeRTOS 內(nèi)核啟動(dòng)是在 main() 里),所以這個(gè)問(wèn)題主要跟 RT-Thread 內(nèi)核代碼結(jié)構(gòu)設(shè)計(jì)有關(guān)。
    : C* @+ X2 _7 [  k經(jīng)過(guò)裸機(jī)工程、RT-Thread 工程、FreeRTOS 工程三者對(duì)比,痞子衡找到了問(wèn)題所在。RT-Thread 內(nèi)核啟動(dòng)是在 /src/components.c 文件中的 __low_level_init() 函數(shù)里,而這個(gè) __low_level_init() 函數(shù)本應(yīng)是 IAR 入口函數(shù) __iar_program_start() 中的一部分(IAR 系統(tǒng)庫(kù)里有一個(gè)內(nèi)置 PUBWEAK 版本),但是 RT-Thread 重實(shí)現(xiàn)了這個(gè) __low_level_init() 函數(shù),很不幸的是 IAR 鏈接器對(duì)于自定義段的函數(shù)重定向認(rèn)定與原內(nèi)置 __low_level_init() 函數(shù)設(shè)計(jì)有某種內(nèi)在關(guān)聯(lián)。. Z) z3 t% B5 R; G; R5 b
  • RT-Thread 代碼:https://gitee.com/rtthread/rt-thread/blob/gitee_master/src/components.c
  • 發(fā)表回復(fù)

    本版積分規(guī)則


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