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

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

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

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

[復(fù)制鏈接]

365

主題

365

帖子

1944

積分

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

Rank: 3Rank: 3

積分
1944
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2021-9-12 22:52:00 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
大家好,我是痞子衡,是正經(jīng)搞技術(shù)的痞子。今天痞子衡給大家分享的是在MDK開(kāi)發(fā)環(huán)境下將關(guān)鍵函數(shù)重定向到RAM中執(zhí)行的幾種方法
4 \6 [7 a: W6 G6 c. y% N這個(gè)關(guān)鍵函數(shù)重定向到 RAM 中執(zhí)行系列文章,痞子衡已經(jīng)寫(xiě)過(guò) 《IAR篇》、《MCUXpresso IDE篇》,今天一鼓作氣把 Keil MDK 篇也寫(xiě)了,做個(gè)全家桶。
3 H4 B5 b0 M. @8 n3 m把 Keil MDK 放到最后來(lái)寫(xiě),其實(shí)痞子衡是有用意的。第一篇寫(xiě) IAR,我們基本上是要純手工改鏈接文件。第二篇寫(xiě) MCUXpresso IDE,我們除了手工改鏈接文件,也在利用它的鏈接文件配置自動(dòng)生成功能,F(xiàn)在到了 Keil MDK,這個(gè) IDE 其實(shí)跟 MCUXpresso IDE 一樣也支持鏈接文件配置自動(dòng)生成,但是具體功能設(shè)計(jì)上有各有千秋,今天我們就來(lái)了解下:% a! @) e. ~: [8 S, w3 H
  • Note:本文使用的 Keil uVision 軟件版本是 v5.31.0.0。一、準(zhǔn)備工作為了便于描述后面的函數(shù)重定向方法實(shí)現(xiàn),我們先做一些準(zhǔn)備工作,選定的硬件平臺(tái)是恩智浦 MIMXRT1170-EVK,主芯片內(nèi)部有2MB RAM,外掛了 16MB Flash 和 2 片 32MB SDRAM。這些存儲(chǔ)設(shè)備在芯片系統(tǒng)中映射地址空間如下:# G3 h. {" `! e& H8 K; v1 Y1 x
    NOR Flash: 0x30000000 - 0x30FFFFFF (16MB)
    ! X, w7 X: B( ]4 O! K) [ITCM RAM:  0x00000000 - 0x0003FFFF (256KB)
    8 [' q( }3 a8 W. l1 g5 f- K5 NDTCM RAM:  0x20000000 - 0x2003FFFF (256KB)
    ; W- F/ a* T3 s( A! `1 `9 bOCRAM:     0x20200000 - 0x2037FFFF (1.5MB)
    ; o; z* y+ b* V) r' s! D9 hSDRAM:     0x80000000 - 0x83FFFFFF (64MB)
    8 \! f2 n( G$ F# n3 C/ H9 P我們隨便選擇一個(gè)測(cè)試?yán)蹋篭SDK_2.10.0_EVK-MIMXRT1170\boards\evkmimxrt1170\demo_apps\hello_world\cm7\mdk,其中 flexspi_nor 工程是最典型的代碼鏈接場(chǎng)景(見(jiàn) MIMXRT1176xxxxx_cm7_flexspi_nor.scf 文件),全部的 readonly 段分配在 0x30000000 - 0x30FFFFFF 空間(在 Flash 中),全部的 readwrite 段分配在 0x20000000 - 0x2003FFFF 空間(在 DTCM 中)。鏈接文件精簡(jiǎn)如下:1 @9 d8 y, R2 F- y) ]  a! h8 `* E
    LR_m_text 0x30002000 0x00FFE000 {# M! c$ c8 S  o7 K
      VECTOR_ROM 0x30002000 FIXED 0x00000400 {3 e5 G# j- }& y. g. c+ F
        * (.isr_vector,+FIRST)
    & J3 ?8 R9 N+ P  }
    % m- \/ x; x3 e: [* W  ER_m_text 0x30002400 FIXED 0x00FFDC00 {9 l8 T! K, c8 x/ V
        * (InRoot$$Sections)
    ; G* B# X- n. ]* h    .ANY (+RO)
    3 T9 Z& H# M% @$ L  }/ I2 w) M3 p) [0 `: W. q% ?
      RW_m_data 0x20000000 0x0003F800 {4 S/ i# Q4 G; n* c- A( C
        .ANY (+RW +ZI). f1 \1 J2 P; k' G- y' Q# O7 Z* y
      }
    * ?5 P% x) M) `$ T. T" _  ARM_LIB_HEAP +0 EMPTY 0x00000400 {! J: ]8 J5 k, z( N7 o) i5 c
      }
    * x1 o2 X% M( [1 w$ ~) U# j0 J  ARM_LIB_STACK 0x20040000 EMPTY -0x00000400 {+ ?- f. A5 o: }0 i( s: p2 {
      }2 X7 x0 U0 w9 E
    }
    6 Y( |/ q& v- d3 n8 ]現(xiàn)在我們?cè)賱?chuàng)建一個(gè)新源文件 critical_code.c 用于示例關(guān)鍵函數(shù),將這個(gè)源文件添加進(jìn) hello_world_demo_cm7.uvprojx 工程里,critical_code.c 文件中只有如下三個(gè)測(cè)試函數(shù)(它們?cè)?main 函數(shù)里會(huì)被調(diào)用):
    : U& l7 y" v* \4 F; V% ]void critical_func1(uint32_t n)
    ) Q8 |8 F# J# }' H: X{
    - {, @' d" ]2 g7 _4 g( D& `    PRINTF("Arg = %d .\r+ I5 i- H: B" G' o: l6 d
    ", n);$ _/ V( V% B1 r7 x0 u
    }1 @7 A% Q7 w, N! U% X* f  h2 H' D
    void critical_func2(uint32_t n)- p9 m8 W, F& H$ L. w6 }
    {# n+ p  }2 U% R- V! k" m& }6 a5 H
        PRINTF("Arg * 2 = %d .\r
    % s$ y+ y% n" V+ c  L* |/ O5 k", 2 * n);
    1 p7 I4 Z; }' H: z* k1 U}
    2 k7 O* h$ w& X! T$ f$ x) dvoid critical_func3(uint32_t n)
    + C  c; j4 K5 l{
    2 F3 G, |5 @1 ~% K+ {3 E1 q    PRINTF("Arg * 3 = %d .\r
    6 Y, w: t& M6 l7 y4 h5 P4 @! w", 3 * n);
    ; v, u. b1 v  K; d* B( W. s! H}
    + G! f% ^+ {5 |: p3 I& B編譯鏈接修改后的工程,然后查看其映射文件(hello_world_demo_cm7.map)找到跟 critical_code.c 文件相關(guān)的內(nèi)容如下,顯然 critical_code.c 中的三個(gè)函數(shù)都會(huì)被鏈在 Flash 空間里(均在 .text 段里)。
    # U* N) y+ V3 _+ j6 x; F. F; Q" p7 I===============================================================================/ C( n) R$ W- V) V5 B/ I+ E5 I# t
    Image Symbol Table" K7 \$ ~) d2 d
        Global Symbols
    8 {4 v; h2 s, _+ _) _% F  @+ G0 B    Symbol Name                              Value     Ov Type        Size  Object(Section)
    , z& f' H2 ~$ V    critical_func1                           0x30005429   Thumb Code    28  critical_code.o(.text.critical_func1)% N2 U; w7 \. W. Q$ @: Z2 l& g
        critical_func2                           0x30005449   Thumb Code    32  critical_code.o(.text.critical_func2)
    5 w) f' ~3 r$ W# d) i0 ?1 H4 t    critical_func3                           0x30005469   Thumb Code    36  critical_code.o(.text.critical_func3)
    9 e: n7 N/ {, n& g5 p3 t9 R$ V===============================================================================
    + Q3 h2 I* _& I; M4 HMemory Map of the image$ i( @& }) G8 h5 J0 a! _
        Execution Region ER_m_text (Exec base: 0x30002400, Load base: 0x30002400, Size: 0x00003b68, Max: 0x00fbdc00, ABSOLUTE, FIXED)
    ( }( U2 d5 O0 A! k6 ]    Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object
    * X' B& Q+ N: _) o    0x30005428   0x30005428   0x0000001c   Code   RO           17    .text.critical_func1  critical_code.o7 X) l. T9 g, b7 E
        0x30005444   0x30005444   0x00000004   PAD
    . n( j- I+ L( y7 ~* E6 {# G    0x30005448   0x30005448   0x00000020   Code   RO           19    .text.critical_func2  critical_code.o( w% q: x/ }/ R- [" V
        0x30005468   0x30005468   0x00000024   Code   RO           21    .text.critical_func3  critical_code.o
    9 Q8 W) |0 K2 f7 S    0x3000548c   0x3000548c   0x00000004   PAD
    . ?4 e) Z/ N& N3 E, G, d& c# g/ l) t===============================================================================
    6 m1 M8 _+ ^; K/ \! @, ZImage component sizes
    ' l, V" I6 ?; p0 I/ G      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Object Name+ v4 @3 c! a4 L/ j8 e
            96         56          0          0          0        903   critical_code.o
    ) e9 Z3 i8 b! \# _: g9 F% E0 d二、重定向到RAM中方法我們現(xiàn)在要做的事就是將 critical_code.c 文件中的函數(shù)重定向到 RAM 里執(zhí)行,原鏈接文件 MIMXRT1176xxxxx_cm7_flexspi_nor.scf 中指定的是 DTCM 來(lái)存放 readwrite 段,那我們就嘗試將關(guān)鍵函數(shù)放到 DTCM 里(如需改到 ITCM、OCRAM、SDRAM,方法類(lèi)似)。
    $ n0 ?* e4 X( e+ C2 a- e2.1 自定義section指定函數(shù) - 針對(duì)單個(gè)函數(shù)第一種方法是用 __attribute__((section("UserSectionName"))) 語(yǔ)法來(lái)修飾函數(shù)定義,將其放到自定義程序段里。這種方法主要適用重定向單個(gè)關(guān)鍵函數(shù),比如我們將 critical_func1() 函數(shù)放到名為 .criticalFunc 的自定義段里:
    & @. J+ x, v1 F  f5 {__attribute__((section(".criticalFunc"))) void critical_func1(uint32_t n)' k  L1 K) L# k
    {
    + e: ?' @. a+ ?- g7 {    PRINTF("Arg = %d .\r% D# k$ D# F8 @5 s7 C. P
    ", n);, W$ \7 d% K4 j3 ^! ]3 @+ u
    }
    2 t' d+ |1 G" {- q6 b; ^; M7 fvoid critical_func2(uint32_t n): t. r: @$ _4 r/ @
    {$ Q8 O( Z! J3 i' v" U
        PRINTF("Arg * 2 = %d .\r3 F1 q% Z. T9 u0 H
    ", 2 * n);
    ; c8 P  u( D4 m! N}4 m8 d# h# d. C$ n8 L
    void critical_func3(uint32_t n). s9 t0 `5 o0 ?9 {8 B, F' k4 Q
    {) [5 k  f, I( Z) S- k
        PRINTF("Arg * 3 = %d .\r
    8 `  H  p2 g. T( J' S+ ?", 3 * n);
    / _* Z! |/ o+ k/ m1 n}
    0 Y- Y! t6 ?- I然后在工程鏈接文件 MIMXRT1176xxxxx_cm7_flexspi_nor.scf 里將這個(gè)自定義的 section .criticalFunc 也放進(jìn) RW_m_data 執(zhí)行域中:
    + H9 I; N0 \6 t: q' M5 x; ~# j$ NLR_m_text 0x30002000 0x00FFE000 {! u9 G! ~' {+ w+ Z
      ; ...* F' W1 W7 @7 a. o% U, B+ e: e
      RW_m_data 0x20000000 0x0003F800 {
    : l# ?1 ~' l" \# v/ e: n2 n! k' C    .ANY (+RW +ZI)
    % ^6 J7 x, ]* Q" X! a    * (.criticalFunc)  ;添加 .criticalFunc 段
    # P& R1 O9 P. j- g9 z      ; 第二種寫(xiě)法:*.o (.criticalFunc)
    " z7 \( O; U* J; ~  }, {. s$ @/ \  D3 H' k
      ; ...) M' G. V2 M3 E/ q$ V, r' b1 v
    }
    % z+ P! _  X# F$ M' i8 m編譯鏈接修改后的工程,然后查看其映射文件(hello_world_demo_cm7.map)找到跟 critical_code.c 文件相關(guān)的內(nèi)容如下,此時(shí) critical_func1() 已經(jīng)被放到自定義段 .criticalFunc 里,并且這個(gè)段被 MDK 底層鏈接器鏈接到了 RAM 里(RW_m_data 執(zhí)行域空間)。
    7 l  t0 X4 Q- P- P/ J  r. N1 p9 f  C$ T===============================================================================
    8 O# Q! q1 |$ c7 m, bImage Symbol Table
    . I* w4 ?0 n9 N4 Q# e, I    Global Symbols, x/ H: w- Q3 ~7 a( L2 D
        Symbol Name                              Value     Ov Type        Size  Object(Section)7 g3 N) f" j% ~
        critical_func1                           0x20000001   Thumb Code    28  critical_code.o(.criticalFunc)$ W: b  W" O1 B- R
        critical_func2                           0x30005429   Thumb Code    32  critical_code.o(.text.critical_func2)
    7 O( n# ]6 T5 s0 o  F4 z    critical_func3                           0x30005449   Thumb Code    36  critical_code.o(.text.critical_func3)
    : |8 R# E% J9 m# |; I===============================================================================/ ^9 {# q& n# o! g3 b7 c3 {# o
    Memory Map of the image
    & B3 S% C* q' H- d    Execution Region RW_m_data (Exec base: 0x20000000, Load base: 0x30005f60, Size: 0x00000078, Max: 0x0003f800, ABSOLUTE)9 T2 U' x" p& o& q4 p; G. }$ T6 q
        Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object
    * W2 G$ S7 g8 f1 y/ Z9 T9 X    0x20000000   0x30005f60   0x0000001c   Code   RO           17    .criticalFunc       critical_code.o
    : B* e8 I- e8 N, j$ g% ~; P% K    Execution Region ER_m_text (Exec base: 0x30002400, Load base: 0x30002400, Size: 0x00003b60, Max: 0x00fbdc00, ABSOLUTE, FIXED)
    4 O# t" ~; t+ y1 |5 G    Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object
    : I7 F' T% J/ I4 a    0x30005428   0x30005428   0x00000020   Code   RO           19    .text.critical_func2  critical_code.o
    8 r1 B/ @0 r  h4 b: u3 X! `    0x30005448   0x30005448   0x00000024   Code   RO           21    .text.critical_func3  critical_code.o' Z# |  R7 a$ B; |! b5 A
        0x3000546c   0x3000546c   0x00000004   PAD
    8 X& x% _+ ^8 T  Y===============================================================================& w1 z+ h9 Y/ w+ G
    Image component sizes4 D5 o4 B& T! ]
          Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Object Name2 K: X7 }0 G, c( g- K" v( f
            96         56          0          0          0        903   critical_code.o: [4 p. V8 Q( s4 l/ K, j
    2.2 自定義section指定函數(shù) - 針對(duì)同一文件里的多個(gè)函數(shù)第二種方法是利用 #pragma 語(yǔ)法來(lái)修飾函數(shù)定義(注意 AC5 編譯器 Armcc 和 AC6 編譯器 Armclang 語(yǔ)法不太一樣),將同一源文件里緊挨在一起的多個(gè)關(guān)鍵函數(shù)放到自定義段里。比如我們將 critical_func1() 和 critical_func2() 函數(shù)放到名為 .criticalFunc 的自定義段里:
    " e  n0 ~( b$ K6 P0 f3 m- F
  • Note: 這種方法一般情況下不太推薦,代碼可移植性較差。
  • 發(fā)表回復(fù)

    本版積分規(guī)則


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