电子产业一站式赋能平台

PCB联盟网

搜索
查看: 278|回复: 0
收起左侧

RT-Thread下IAR工程函数重定向为何失效?

[复制链接]

396

主题

396

帖子

2398

积分

三级会员

Rank: 3Rank: 3

积分
2398
发表于 2021-11-14 22:52:00 | 显示全部楼层 |阅读模式
大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家分享的是在IAR开发环境下RT-Thread工程函数重定向失效分析; N7 r. _2 g7 P  d. ^1 }4 S( G
痞子衡旧文 《在IAR下将关键函数重定向到RAM中执行的方法》 里介绍了三种关键函数重定向方法,不过这三种方法只是写法形式不同,本质上没啥区别,都是利用 IAR 链接器特性将函数重定向到工程数据段(RW)所在 RAM 里。8 I: x. s5 K% H# |
对于 i.MXRT 这种拥有多块地址非连续的 RAM 的芯片,其实我们也可以单独将这些重定向函数放到一个指定的 RAM 里,不一定非得跟数据段放在同一个 RAM 里。具体实现也很简单,只需要在链接文件里额外加一句 place in 语句处理即可,恩智浦官方 SDK 包里就是这么做的。6 ?) F; H4 H8 @# w1 N% \3 f' g
然而痞子衡最近在移植一个 i.MXRT1170  RT-Thread 工程时发现,在 IAR 链接文件里用自定义段来单独指定重定向函数到 ITCM 竟然失效了,这是怎么回事?今天我们一起来看一下:+ J1 M4 u( P" v/ D
  • Note 1:阅读本文前需要对 《IAR链接文件(.icf)》、《IAR映射文件(.map)》 这两种文件有所了解。
  • Note 2:本文使用的 IAR EWARM 软件版本是 v9.10.2。一、回顾SDK里函数重定向做法我们以最经典的 \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 - ),数据段放在 SDRAM 里(0x80000000 - )。* [8 P' L& z1 [: f3 p" R
    在时钟初始化函数 BOARD_BootClockRUN() 里会调用如下 UpdateSemcClock() 函数,这个函数需要重定向到 RAM 里执行,在代码里先将它放到自定义 CodeQuickAccess 段里。
    ) P. O; V! i$ S- M5 K& q8 M#define AT_QUICKACCESS_SECTION_CODE(func) func @"CodeQuickAccess") L9 d! ^' K! P; [) B' V$ _
    #if defined(XIP_BOOT_HEADER_ENABLE) && (XIP_BOOT_HEADER_ENABLE == 1)
    ; h3 J- |/ j9 P6 J/ j#if defined(XIP_BOOT_HEADER_DCD_ENABLE) && (XIP_BOOT_HEADER_DCD_ENABLE == 1)
    * }% X6 s3 K6 QAT_QUICKACCESS_SECTION_CODE(void UpdateSemcClock(void));
    8 I. \7 s# T6 pvoid UpdateSemcClock(void)
    : u7 A* M0 X! a7 |& X* }* H{0 {: d( s) x: w9 h9 [, R
        SEMC->IPCMD = 0xA55A000D;7 W9 X' A& \# }* o+ [
        while ((SEMC->INTR & 0x3) == 0);; j  k/ I5 L1 E& c
        SEMC->INTR                                = 0x3;
    $ L+ F  k; t* Y) Q9 U+ q    SEMC->DCCR                                = 0x0B;1 [4 u) H; u$ p: c4 U: f
        CCM->CLOCK_ROOT[kCLOCK_Root_Semc].CONTROL = 0x602;3 n3 k% Z) B9 E6 _! H6 D; _6 p- b
    }& x  o7 ~8 Y+ L. C1 p1 a, v7 ?
    #endif6 W4 l" V; U( b" h) p
    #endif: Q. `3 f) K. u7 P7 u1 g
    然后在工程链接文件 MIMXRT1176xxxxx_cm7_flexspi_nor_sdram.icf 里(仅摘录部分),再将 CodeQuickAccess 段单独放在 ITCM 里(0x00000000 - ),这就是官方 SDK 里的做法。
    5 B) h: q3 K* k/ \2 \define symbol m_data3_start            = 0x80000000;. j) t9 x$ N( O. W
    define symbol m_data3_end              = 0x82FFFFFF;3 u. t; S9 }8 c: u' I  o
    define symbol m_qacode_start           = 0x00000000;8 L; z9 P9 x# `7 C& r( X
    define symbol m_qacode_end             = 0x0003FFFF;
    $ K! c* x) D, b" p# O2 Fdefine region DATA3_region  = mem:[from m_data3_start to m_data3_end-__size_cstack__];
      l  c9 j" p3 ?: mdefine region QACODE_region = mem:[from m_qacode_start to m_qacode_end];
    6 u. q5 H" n, @. q9 Odefine block RW            { first readwrite, section m_usb_dma_init_data };
    , L+ h' H0 B; Vdefine block QACCESS_CODE  { section CodeQuickAccess };
    $ x$ Y. |4 k3 Q5 R3 Y" einitialize by copy         { readwrite, section .textrw, section CodeQuickAccess };
    # K9 ?3 h7 _# t* @* d6 c$ B& lplace in DATA3_region                  { block RW };
    $ ~. {% l! ^6 M! @$ }0 J1 v2 Kplace in QACODE_region                 { block QACCESS_CODE };3 K9 T: H; T+ c- i( I
    编译链接 hello_world_demo_cm7.ewp 工程,然后查看其映射文件(hello_world_demo_cm7.map)找到跟 UpdateSemcClock() 函数相关的内容如下,显然这是符合预期的。这里特别注意一下,CodeQuickAccess 的类别显示的是 inited,表明其不是常见的 ro code,而是经过重定向的,而且 UpdateSemcClock() 函数所在 clock_config.o 里包含了 60个字节的 rw code。
    * F4 S( s4 n/ D9 L*******************************************************************************. B# r& k- d2 ~. m0 @
    *** PLACEMENT SUMMARY
    # \+ A! B/ _9 |  Q9 S' N***0 T7 x  x) O4 v0 U2 V0 L+ i
    define block QACCESS_CODE { section CodeQuickAccess };
    % H( b* |4 i5 w% ~3 ~. A/ x2 \1 G"P7":  place in [from 0x0 to 0x3'ffff] { block QACCESS_CODE };% ~9 K& O* a) ^" W. X9 D" k+ ]5 N
      Section              Kind         Address      Size  Object4 z. }( {3 m" A; |9 K1 p% z0 |
      -------              ----         -------      ----  ------9 F# @0 u0 w1 n. b, |
    "P7":                                            0x3c! Y3 [4 f- r2 [1 Y6 b: U5 ~1 O
      QACCESS_CODE                          0x0      0x3c  [B]3 g0 z) i/ u% E& q/ o  T& H
        QACCESS_CODE-1                      0x0      0x3c  [I]* a" Q# s! M. H: f  Y8 z8 |9 V, r
          CodeQuickAccess  inited           0x0      0x3c  clock_config.o [1]
    4 L) K5 _! D2 T3 L: T$ U  T                                     - 0x3c      0x3c
    * W& O% n0 o' E$ O+ P, B9 U. ~*******************************************************************************7 |: ]/ l7 i$ Q) c" I- j& `0 l5 y
    *** MODULE SUMMARY, E9 x" T" l3 H% y* L/ Q
    ***
    2 l# C- c+ ?6 Y7 M6 ?! D; [2 s    Module                              ro code  rw code  ro data  rw data, T2 L* ?% f! Y0 j; W' s. @9 F* z3 [+ ]
        ------                              -------  -------  -------  -------
    , H* x, _" r( n$ K  \; f    clock_config.o                        2'644       60      844
    " }( V5 B3 r7 Q( H1 d, Y, |*******************************************************************************
    2 H) w, Q, s" C3 w1 i*** ENTRY LIST
      ^/ z6 \& z% @( f6 ^***  u* g- g' u+ S7 m: e( H" M: z7 b
        Entry                       Address   Size  Type      Object
    : ~6 c! m3 ], d+ s    ----                       -------   ----  ----      ------: `" q9 w) y$ h6 J6 u$ ^
        UpdateSemcClock                 0x1   0x3c  Code  Gb  clock_config.o [1]
    " H. `2 `' u$ `1 s: o! G二、引出RT-Thread下函数重定向失效问题现在来看 RT-Thread 工程,也是一个简单的 hello world(具体工程略去不表),其中 i.MXRT1170 芯片 BSP 部分直接来自于官方 SDK,链接文件也与 SDK 里一致,但是编译链接工程后查看其映射文件,发现跟 UpdateSemcClock() 函数相关的内容如下,CodeQuickAccess 的类别显示的是 ro code, UpdateSemcClock() 函数所在 clock_config.o 里干脆连 rw code 都没有。显然函数重定向失效了,链接文件里 initialize by copy { section CodeQuickAccess }; 语句没起作用,这显然就是一个分散链接而已。
    . v( ^9 W' Y6 @6 _*******************************************************************************, [% i/ c7 x6 c! A
    *** PLACEMENT SUMMARY
    4 D0 |5 I- a! V, p% ?/ Y. @***0 H: Q. _- |2 n3 e9 b7 D
    define block QACCESS_CODE { section CodeQuickAccess };8 q0 O. p7 |9 W/ V4 Y+ s+ _' x6 H5 }
    "P7":  place in [from 0x0 to 0x3'ffff] { block QACCESS_CODE };
    + V8 b0 v) G: V  Section              Kind         Address    Size  Object
    6 F+ ^" k/ p- p8 z  {  -------              ----         -------    ----  ------
    6 ~) w3 j, w" o- I+ a: h9 H"P7":                                          0x3c! b7 L" b- s# R& ^: ]
      QACCESS_CODE                          0x0    0x3c  [B]
    % d% A5 _. e# K    CodeQuickAccess    ro code          0x0    0x3c  clock_config.o [4]
    0 \3 I5 F  R9 M0 J; B                                     - 0x3c    0x3c
    ; r0 N  `' L/ Z. e& o*******************************************************************************) x; q: ~# S+ s+ a0 m5 T" P% t
    *** MODULE SUMMARY
    5 j' N" Q8 C1 W5 |$ P***
    & h0 u# H% x" ?8 `* E7 C    Module                              ro code  ro data  rw data
    2 s6 H3 M: ^/ f. t; D" Y, g    ------                              -------  -------  -------3 A, A2 r, m( ~# X. h
        clock_config.o                        2'768      7843 V. n! Q+ S# Y1 v8 Z% ]
    *******************************************************************************8 K( B. t9 x0 a+ I5 }' q
    *** ENTRY LIST( Z+ G! J; |3 C' T7 X. g
    ***4 H+ H4 ?( o  r, j
        Entry                       Address   Size  Type      Object
    ' p( M/ i5 Q: |    ----                       -------   ----  ----      ------7 p9 E6 F" h0 _; ]1 m3 X
        UpdateSemcClock                 0x1    0x3c  Code  Gb  clock_config.o [4]
    & k- P* q2 o0 `, a5 `三、RT-Thread下函数重定向失效分析第一节里 SDK 裸机环境下函数重定向做法不会失效,RT-Thread 环境下同样的做法就失效了,难道 IAR 对 RTOS 支持不友好?但是痞子衡在 \SDK_2.11.0_MIMXRT1170-EVK\boards\evkmimxrt1170\rtos_examples\freertos_hello 下做了相同实验,FreeRTOS 下这种函数重定向方式也是没有问题的(FreeRTOS 内核启动是在 main() 里),所以这个问题主要跟 RT-Thread 内核代码结构设计有关。. g4 b' m' I" ]' \' O
    经过裸机工程、RT-Thread 工程、FreeRTOS 工程三者对比,痞子衡找到了问题所在。RT-Thread 内核启动是在 /src/components.c 文件中的 __low_level_init() 函数里,而这个 __low_level_init() 函数本应是 IAR 入口函数 __iar_program_start() 中的一部分(IAR 系统库里有一个内置 PUBWEAK 版本),但是 RT-Thread 重实现了这个 __low_level_init() 函数,很不幸的是 IAR 链接器对于自定义段的函数重定向认定与原内置 __low_level_init() 函数设计有某种内在关联。' C$ b% @+ @& ^+ S9 p/ g
  • RT-Thread 代码:https://gitee.com/rtthread/rt-thread/blob/gitee_master/src/components.c
  • 回复

    使用道具 举报

    发表回复

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则


    联系客服 关注微信 下载APP 返回顶部 返回列表