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

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

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

在MDK開發(fā)環(huán)境下將關(guān)鍵函數(shù)重定向到RAM中執(zhí)行的幾種方法

[復(fù)制鏈接]

365

主題

365

帖子

1944

積分

三級會員

Rank: 3Rank: 3

積分
1944
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2021-9-12 22:52:00 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
大家好,我是痞子衡,是正經(jīng)搞技術(shù)的痞子。今天痞子衡給大家分享的是在MDK開發(fā)環(huán)境下將關(guān)鍵函數(shù)重定向到RAM中執(zhí)行的幾種方法。; M, T9 o6 X0 a' B
這個關(guān)鍵函數(shù)重定向到 RAM 中執(zhí)行系列文章,痞子衡已經(jīng)寫過 《IAR篇》、《MCUXpresso IDE篇》,今天一鼓作氣把 Keil MDK 篇也寫了,做個全家桶。" J7 h# K4 T! [- R7 j0 V
把 Keil MDK 放到最后來寫,其實(shí)痞子衡是有用意的。第一篇寫 IAR,我們基本上是要純手工改鏈接文件。第二篇寫 MCUXpresso IDE,我們除了手工改鏈接文件,也在利用它的鏈接文件配置自動生成功能,F(xiàn)在到了 Keil MDK,這個 IDE 其實(shí)跟 MCUXpresso IDE 一樣也支持鏈接文件配置自動生成,但是具體功能設(shè)計上有各有千秋,今天我們就來了解下:
; G7 ~2 O: E2 ]
  • Note:本文使用的 Keil uVision 軟件版本是 v5.31.0.0。一、準(zhǔn)備工作為了便于描述后面的函數(shù)重定向方法實(shí)現(xiàn),我們先做一些準(zhǔn)備工作,選定的硬件平臺是恩智浦 MIMXRT1170-EVK,主芯片內(nèi)部有2MB RAM,外掛了 16MB Flash 和 2 片 32MB SDRAM。這些存儲設(shè)備在芯片系統(tǒng)中映射地址空間如下:# g) O' B5 @9 m2 K  S4 ?
    NOR Flash: 0x30000000 - 0x30FFFFFF (16MB)" J4 g% v- ?8 S6 H" ?! o+ ]
    ITCM RAM:  0x00000000 - 0x0003FFFF (256KB)$ S4 a4 O: y: Y6 Y
    DTCM RAM:  0x20000000 - 0x2003FFFF (256KB)& N0 v$ V( e/ B! @
    OCRAM:     0x20200000 - 0x2037FFFF (1.5MB)6 I4 x) {  p( }' {7 H( F
    SDRAM:     0x80000000 - 0x83FFFFFF (64MB)8 c5 h0 V5 L' z0 I
    我們隨便選擇一個測試?yán)蹋篭SDK_2.10.0_EVK-MIMXRT1170\boards\evkmimxrt1170\demo_apps\hello_world\cm7\mdk,其中 flexspi_nor 工程是最典型的代碼鏈接場景(見 MIMXRT1176xxxxx_cm7_flexspi_nor.scf 文件),全部的 readonly 段分配在 0x30000000 - 0x30FFFFFF 空間(在 Flash 中),全部的 readwrite 段分配在 0x20000000 - 0x2003FFFF 空間(在 DTCM 中)。鏈接文件精簡如下:
    - Q3 e3 h( t9 s) k7 ?LR_m_text 0x30002000 0x00FFE000 {' M7 H7 `. O3 o! [; ^- t( H
      VECTOR_ROM 0x30002000 FIXED 0x00000400 {# X1 v) G5 W( Y; b8 P0 v" [3 B6 O
        * (.isr_vector,+FIRST)) e. |$ @/ v# \: c3 c) Q4 ^
      }
    0 B) Y* X5 p$ y/ Z: I  ER_m_text 0x30002400 FIXED 0x00FFDC00 {& u0 E0 B; q+ r" \/ R" o
        * (InRoot$$Sections)
    8 w8 ?+ I" k+ W    .ANY (+RO)$ x) G# v, H; X: C9 o7 f9 n
      }
    " ~0 r3 D) E1 r# g  RW_m_data 0x20000000 0x0003F800 {, Q/ C) b# U3 c  C! Z
        .ANY (+RW +ZI). u+ f6 P2 Q+ |0 N
      }" N; I4 U1 B8 V5 q# v4 F
      ARM_LIB_HEAP +0 EMPTY 0x00000400 {! Z' o% U- [* ~" d9 l9 i9 y1 x  z3 D
      }
    , y2 v/ Y; k, |+ Z4 }  ARM_LIB_STACK 0x20040000 EMPTY -0x00000400 {
    . }9 b3 f" C! y# }  }8 x8 z; {6 E3 O; k9 r
    }; c1 _) Y; \! U! z' |: o) [. V- Z
    現(xiàn)在我們再創(chuàng)建一個新源文件 critical_code.c 用于示例關(guān)鍵函數(shù),將這個源文件添加進(jìn) hello_world_demo_cm7.uvprojx 工程里,critical_code.c 文件中只有如下三個測試函數(shù)(它們在 main 函數(shù)里會被調(diào)用):
    8 e' z; r* H: A) E6 l. Cvoid critical_func1(uint32_t n)3 K: ~/ s* B* k) z4 U
    {
    0 ^2 I7 v* }1 _$ d  Q    PRINTF("Arg = %d .\r
    ; C/ S/ N$ x/ K6 L. z3 d* T9 z% ^", n);) J6 c; X. P: K: w9 Q- a  c
    }
    # t5 h) s6 B. R; rvoid critical_func2(uint32_t n)- u, \1 K$ T) Z/ p4 B
    {
    , O% s) R5 D# g6 y1 N1 ^( S    PRINTF("Arg * 2 = %d .\r
    . X! r7 K: s( c0 Z" y; P- d", 2 * n);, H0 i" f, _& Z2 W" x, N
    }" O' u+ i$ P% @, o% \
    void critical_func3(uint32_t n)
    . Z7 X; K/ ?2 h: b9 T5 U+ a{
    ( B' y2 U  @; q& Q    PRINTF("Arg * 3 = %d .\r
    5 _+ z, Q' Q0 _0 K" Q", 3 * n);
    7 P2 B3 Z7 k* ^! c* ^- ^}
    6 ^! r" T; p# _5 U編譯鏈接修改后的工程,然后查看其映射文件(hello_world_demo_cm7.map)找到跟 critical_code.c 文件相關(guān)的內(nèi)容如下,顯然 critical_code.c 中的三個函數(shù)都會被鏈在 Flash 空間里(均在 .text 段里)。
    $ I1 W: s- i8 q7 C===============================================================================
    + v8 q1 ]' a' G" `9 ?Image Symbol Table* @% H9 A4 O; I- S. f/ M) C
        Global Symbols* R4 A. w# }+ i4 e" n1 u: z/ a
        Symbol Name                              Value     Ov Type        Size  Object(Section)% ^2 {" s6 w  z3 I" w
        critical_func1                           0x30005429   Thumb Code    28  critical_code.o(.text.critical_func1)
    " a( t0 T# g7 K( j. }) [# F% I    critical_func2                           0x30005449   Thumb Code    32  critical_code.o(.text.critical_func2)8 Z" d4 n) D' _  _
        critical_func3                           0x30005469   Thumb Code    36  critical_code.o(.text.critical_func3). {5 @! B8 \5 T5 ~
    ===============================================================================: W4 i) w1 B! L4 E
    Memory Map of the image3 ^" i, `. z( Q
        Execution Region ER_m_text (Exec base: 0x30002400, Load base: 0x30002400, Size: 0x00003b68, Max: 0x00fbdc00, ABSOLUTE, FIXED)# d& v! i+ |4 v# j" ~
        Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object! K8 r$ j. C7 p. f/ l
        0x30005428   0x30005428   0x0000001c   Code   RO           17    .text.critical_func1  critical_code.o
    & Q' b7 {/ B+ {5 |$ z    0x30005444   0x30005444   0x00000004   PAD; w) z% r, Z/ C2 B
        0x30005448   0x30005448   0x00000020   Code   RO           19    .text.critical_func2  critical_code.o* x0 D5 B7 {; m! R
        0x30005468   0x30005468   0x00000024   Code   RO           21    .text.critical_func3  critical_code.o
    . r1 N8 ~6 I; Y$ m    0x3000548c   0x3000548c   0x00000004   PAD
    . U/ w% \! d) D===============================================================================% G4 E* @+ y9 u: H+ {2 W: L% q  f
    Image component sizes
    ; I. E8 R# ~( x$ J; M) B6 C, d/ u% e      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Object Name
    1 N: v9 B9 N% z        96         56          0          0          0        903   critical_code.o8 g$ u9 R: ~6 M* x
    二、重定向到RAM中方法我們現(xiàn)在要做的事就是將 critical_code.c 文件中的函數(shù)重定向到 RAM 里執(zhí)行,原鏈接文件 MIMXRT1176xxxxx_cm7_flexspi_nor.scf 中指定的是 DTCM 來存放 readwrite 段,那我們就嘗試將關(guān)鍵函數(shù)放到 DTCM 里(如需改到 ITCM、OCRAM、SDRAM,方法類似)。
    # y0 [2 D- j1 q2.1 自定義section指定函數(shù) - 針對單個函數(shù)第一種方法是用 __attribute__((section("UserSectionName"))) 語法來修飾函數(shù)定義,將其放到自定義程序段里。這種方法主要適用重定向單個關(guān)鍵函數(shù),比如我們將 critical_func1() 函數(shù)放到名為 .criticalFunc 的自定義段里:4 l% A$ j4 f8 w' e. ]- G: Q
    __attribute__((section(".criticalFunc"))) void critical_func1(uint32_t n)$ |. k% J& j- n
    {  m& X! e2 k: f* r
        PRINTF("Arg = %d .\r
    + x3 g1 y4 X$ M", n);
    2 ]$ Y+ e1 P' L* r2 R}
    ; N* A; y% {5 k0 evoid critical_func2(uint32_t n)/ [$ ~* C5 B( d' Q- W0 F+ O( g7 f0 D
    {
    + l$ W  @( R1 h3 b: ?- T+ H! g    PRINTF("Arg * 2 = %d .\r
    ! |# d* L+ n  C/ g/ a8 u4 W", 2 * n);7 S$ L1 a  r( {2 j" T/ n
    }
    % `8 {0 O( a. a: S8 Nvoid critical_func3(uint32_t n)
    ' G. T; o2 {# p$ }9 g: l{4 g$ I  F3 Z6 _" \3 I
        PRINTF("Arg * 3 = %d .\r5 c9 M6 q: ]2 B& Y5 {* F
    ", 3 * n);* l+ y. p% q% M  G9 r/ I- l
    }2 p  o7 n% d2 x2 M4 q0 g* T
    然后在工程鏈接文件 MIMXRT1176xxxxx_cm7_flexspi_nor.scf 里將這個自定義的 section .criticalFunc 也放進(jìn) RW_m_data 執(zhí)行域中:3 `) x  n; M7 p, w
    LR_m_text 0x30002000 0x00FFE000 {
    3 j; [1 ^# h+ l. k7 c- ]+ \  ; ...# [' w/ L7 u% u6 m) v
      RW_m_data 0x20000000 0x0003F800 {, e! ?1 v5 N$ n* H
        .ANY (+RW +ZI)
    + S- w( q* L- y4 V! Q: Q+ \% |    * (.criticalFunc)  ;添加 .criticalFunc 段
    * N/ U0 x5 x& _/ C" H* ^  B      ; 第二種寫法:*.o (.criticalFunc)
    4 G9 P- |& u2 v3 P# h  }
    / d! T1 u7 \) D: w  ; ...
    3 U* D9 J  }, O, L: d}
    1 d% `/ B) I# _$ C& j編譯鏈接修改后的工程,然后查看其映射文件(hello_world_demo_cm7.map)找到跟 critical_code.c 文件相關(guān)的內(nèi)容如下,此時 critical_func1() 已經(jīng)被放到自定義段 .criticalFunc 里,并且這個段被 MDK 底層鏈接器鏈接到了 RAM 里(RW_m_data 執(zhí)行域空間)。; N% A6 @, M3 X2 Q
    ===============================================================================
      E+ a2 C* W, w. |4 iImage Symbol Table
    7 H7 x8 b6 s9 z3 o    Global Symbols
      u5 n. `2 t+ a" [    Symbol Name                              Value     Ov Type        Size  Object(Section)
    ( W. f8 l+ b' A" @4 h8 r) S    critical_func1                           0x20000001   Thumb Code    28  critical_code.o(.criticalFunc)- x8 |. ~7 \  F
        critical_func2                           0x30005429   Thumb Code    32  critical_code.o(.text.critical_func2)7 [2 K. y% y6 k4 A( l
        critical_func3                           0x30005449   Thumb Code    36  critical_code.o(.text.critical_func3)
    : j; _6 R* Q) x1 W8 ?: g===============================================================================) S; y% X) Y( ?" A& t" M# _
    Memory Map of the image
    ' v% D: N/ ?( Z  V- s0 h    Execution Region RW_m_data (Exec base: 0x20000000, Load base: 0x30005f60, Size: 0x00000078, Max: 0x0003f800, ABSOLUTE)0 v6 U: R- ~$ w% d) Z) a( g
        Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object
    / z  k+ k7 J% p- O    0x20000000   0x30005f60   0x0000001c   Code   RO           17    .criticalFunc       critical_code.o
    / S3 a# O& `7 x$ c% _. |% Y+ h    Execution Region ER_m_text (Exec base: 0x30002400, Load base: 0x30002400, Size: 0x00003b60, Max: 0x00fbdc00, ABSOLUTE, FIXED)4 F4 o" _% S# S. A  c4 U+ h8 N' Q
        Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object. Y1 Z' p# ~4 |
        0x30005428   0x30005428   0x00000020   Code   RO           19    .text.critical_func2  critical_code.o! m5 [6 h  _: j! |8 v! J
        0x30005448   0x30005448   0x00000024   Code   RO           21    .text.critical_func3  critical_code.o
    # K0 @: d/ Y2 N    0x3000546c   0x3000546c   0x00000004   PAD  A( g% f7 W; w/ _
    ===============================================================================7 `! w7 J: Y  T* J. R# x1 w& f
    Image component sizes$ f& q" \/ R; [3 P
          Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Object Name, w6 U4 @% r8 G
            96         56          0          0          0        903   critical_code.o* F# D: i. F+ [( E/ P0 E% l, w" {
    2.2 自定義section指定函數(shù) - 針對同一文件里的多個函數(shù)第二種方法是利用 #pragma 語法來修飾函數(shù)定義(注意 AC5 編譯器 Armcc 和 AC6 編譯器 Armclang 語法不太一樣),將同一源文件里緊挨在一起的多個關(guān)鍵函數(shù)放到自定義段里。比如我們將 critical_func1() 和 critical_func2() 函數(shù)放到名為 .criticalFunc 的自定義段里:; L& g" ]& R% w. y0 p2 j
  • Note: 這種方法一般情況下不太推薦,代碼可移植性較差。
  • 回復(fù)

    使用道具 舉報

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

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

    本版積分規(guī)則


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