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

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

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

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

[復(fù)制鏈接]

365

主題

365

帖子

1934

積分

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

Rank: 3Rank: 3

積分
1934
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2021-9-12 22:52:00 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
大家好,我是痞子衡,是正經(jīng)搞技術(shù)的痞子。今天痞子衡給大家分享的是在MDK開發(fā)環(huán)境下將關(guān)鍵函數(shù)重定向到RAM中執(zhí)行的幾種方法。9 S6 Y$ @# [7 {/ g, `* d
這個(gè)關(guān)鍵函數(shù)重定向到 RAM 中執(zhí)行系列文章,痞子衡已經(jīng)寫過(guò) 《IAR篇》、《MCUXpresso IDE篇》,今天一鼓作氣把 Keil MDK 篇也寫了,做個(gè)全家桶。
' I- V2 _& e+ ]( X把 Keil MDK 放到最后來(lái)寫,其實(shí)痞子衡是有用意的。第一篇寫 IAR,我們基本上是要純手工改鏈接文件。第二篇寫 MCUXpresso IDE,我們除了手工改鏈接文件,也在利用它的鏈接文件配置自動(dòng)生成功能,F(xiàn)在到了 Keil MDK,這個(gè) IDE 其實(shí)跟 MCUXpresso IDE 一樣也支持鏈接文件配置自動(dòng)生成,但是具體功能設(shè)計(jì)上有各有千秋,今天我們就來(lái)了解下:
. p/ I8 T9 @0 A. N, D6 K  R( z
  • 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)中映射地址空間如下:# k( M( Y2 p* c/ \% k) n, d+ s
    NOR Flash: 0x30000000 - 0x30FFFFFF (16MB)
    ' o! G  s* T7 A9 e( M( NITCM RAM:  0x00000000 - 0x0003FFFF (256KB)
      x' q' H& g, t* q5 UDTCM RAM:  0x20000000 - 0x2003FFFF (256KB)% [! g& L8 V% p% Q
    OCRAM:     0x20200000 - 0x2037FFFF (1.5MB)) a. \" \6 [  r
    SDRAM:     0x80000000 - 0x83FFFFFF (64MB)+ Z1 Z, A$ Q5 d! v7 l( U
    我們隨便選擇一個(gè)測(cè)試?yán)蹋篭SDK_2.10.0_EVK-MIMXRT1170\boards\evkmimxrt1170\demo_apps\hello_world\cm7\mdk,其中 flexspi_nor 工程是最典型的代碼鏈接場(chǎng)景(見 MIMXRT1176xxxxx_cm7_flexspi_nor.scf 文件),全部的 readonly 段分配在 0x30000000 - 0x30FFFFFF 空間(在 Flash 中),全部的 readwrite 段分配在 0x20000000 - 0x2003FFFF 空間(在 DTCM 中)。鏈接文件精簡(jiǎn)如下:3 T$ y( d/ \% q9 y3 b7 D# ?
    LR_m_text 0x30002000 0x00FFE000 {, p' m# D9 N" G; w; w
      VECTOR_ROM 0x30002000 FIXED 0x00000400 {
    : X- Z3 x: h- w! U) ^    * (.isr_vector,+FIRST)
    & d! A/ y  s  [4 \9 }3 N8 Z  }
    ' U/ ?) I9 t7 q4 ^  ER_m_text 0x30002400 FIXED 0x00FFDC00 {3 U2 |+ y% W& t/ g8 t2 }) _$ f
        * (InRoot$$Sections)
    9 \% E7 S9 w. b0 ?4 H& m7 R    .ANY (+RO)
    ; F& O; ^7 U  D' b6 M  }
    9 t! D. P7 u2 e( Q4 k; c/ Q  RW_m_data 0x20000000 0x0003F800 {& _* Q" o  }. a  I
        .ANY (+RW +ZI)
    ( s7 C& t9 P9 O" q3 i. ]( ^. X  }& l1 u" W$ V8 Z6 T
      ARM_LIB_HEAP +0 EMPTY 0x00000400 {
    2 G; D# `. E4 y5 j/ b# V, e1 n, x3 \6 s  }
    ; p! |5 F/ N+ m9 D7 \5 \  ARM_LIB_STACK 0x20040000 EMPTY -0x00000400 {
    0 Z1 c; y: _7 M4 z0 H  }
    3 j1 Y! {% v. c1 v* P}
    , w& T0 V2 h, |; o2 ~) M現(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)用):
    ) Y- B/ s0 g8 Q# Z$ N: f, s) @/ Ivoid critical_func1(uint32_t n)& H# f& A0 C/ k: Q  w% F' c
    {  z, h7 L# n- q8 x& f: [1 h  F/ Y4 E
        PRINTF("Arg = %d .\r
    / ]8 ]6 t+ x# _6 u! h5 ^) z9 K", n);
    * D5 H; M+ U$ n}* K3 r6 ]% a2 q) [
    void critical_func2(uint32_t n)* a! T. }" h$ l" S! x' K2 z
    {9 C, x7 L: i5 _
        PRINTF("Arg * 2 = %d .\r
    : H+ P: r/ A  S5 }4 R", 2 * n);5 o8 E6 h) ?7 h$ I2 @
    }
    + t5 }% X3 S: E  P  p% ]void critical_func3(uint32_t n)
    ! O1 k; c0 B6 n{
    # m& R: B+ A/ |7 D( e: o3 m8 b    PRINTF("Arg * 3 = %d .\r% J: k& E8 v. X4 t: [5 E8 S
    ", 3 * n);. u, k/ _$ y6 S( _$ Q9 q
    }2 _# \' V2 v' u: p& H9 u
    編譯鏈接修改后的工程,然后查看其映射文件(hello_world_demo_cm7.map)找到跟 critical_code.c 文件相關(guān)的內(nèi)容如下,顯然 critical_code.c 中的三個(gè)函數(shù)都會(huì)被鏈在 Flash 空間里(均在 .text 段里)。
    / [, P7 Y2 O- N: ?; |===============================================================================7 \9 D* U5 C! O& r9 R; y; E
    Image Symbol Table
    9 q5 s5 y3 C/ D* y. U- F4 k* i% C1 x( S    Global Symbols* ^0 f* k1 t; _' d" r( c% i( F) a8 N
        Symbol Name                              Value     Ov Type        Size  Object(Section). r" Z* v2 b0 Q4 v  D1 p4 M
        critical_func1                           0x30005429   Thumb Code    28  critical_code.o(.text.critical_func1)
    5 V8 C8 e: O. z* X( U7 p# ?    critical_func2                           0x30005449   Thumb Code    32  critical_code.o(.text.critical_func2)0 k' ?) C$ H6 J1 a9 z! O! ~( x2 z2 D; V
        critical_func3                           0x30005469   Thumb Code    36  critical_code.o(.text.critical_func3)
    7 y3 j; U/ i" `5 S6 t" D===============================================================================' Z4 L' D  I" o5 ]1 b  ^. I. Z
    Memory Map of the image
    * H$ _+ a3 `2 S% F& h0 j    Execution Region ER_m_text (Exec base: 0x30002400, Load base: 0x30002400, Size: 0x00003b68, Max: 0x00fbdc00, ABSOLUTE, FIXED)) H/ [7 a, X7 |" i: }. D9 |
        Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object6 i. U$ Z2 m5 l; ~) j# X* k
        0x30005428   0x30005428   0x0000001c   Code   RO           17    .text.critical_func1  critical_code.o
    - n. W( O  J$ A, {    0x30005444   0x30005444   0x00000004   PAD
    $ a: m: x4 m- J; F4 Z+ m  [0 P    0x30005448   0x30005448   0x00000020   Code   RO           19    .text.critical_func2  critical_code.o
    , @2 x( {2 ], Y. O( |    0x30005468   0x30005468   0x00000024   Code   RO           21    .text.critical_func3  critical_code.o; O/ r) \$ z# V3 j3 ~
        0x3000548c   0x3000548c   0x00000004   PAD
    5 A$ \  A  I. y6 _" M===============================================================================
    0 F/ I1 b  _& j% F  DImage component sizes/ q: q; p" Y% b; H, G
          Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Object Name
    . X7 {$ J6 i: o' U7 E        96         56          0          0          0        903   critical_code.o
    ) I. Q" j* y1 N  m二、重定向到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,方法類似)。& W1 r1 C6 m9 Z: M% i  b# e
    2.1 自定義section指定函數(shù) - 針對(duì)單個(gè)函數(shù)第一種方法是用 __attribute__((section("UserSectionName"))) 語(yǔ)法來(lái)修飾函數(shù)定義,將其放到自定義程序段里。這種方法主要適用重定向單個(gè)關(guān)鍵函數(shù),比如我們將 critical_func1() 函數(shù)放到名為 .criticalFunc 的自定義段里:) U  D. U3 E3 p: m$ R6 o. g
    __attribute__((section(".criticalFunc"))) void critical_func1(uint32_t n). z! Q1 @- n% o- {( T! z1 z
    {
    : i5 E0 S8 S0 u$ t1 G    PRINTF("Arg = %d .\r. _2 C2 [+ @) l3 p$ Z. H
    ", n);  ^- Q" V( m) l0 O6 D& |" `
    }8 ?. Z# K9 B, `
    void critical_func2(uint32_t n)$ J9 h6 T0 T* ]9 s$ Z
    {
    # Q# U6 E8 k) M/ N% G. K& S5 m    PRINTF("Arg * 2 = %d .\r
    + {! m1 v$ J0 x2 g. M", 2 * n);6 Y, L' p; \; K7 b" h6 b8 Y7 P
    }0 H) v4 l" m0 V' H. q3 N/ N" X
    void critical_func3(uint32_t n)
    ! O6 ^, B3 m$ W) n9 Y+ Q- C{
    : r4 ~  o" V" z) C5 H, F0 E    PRINTF("Arg * 3 = %d .\r
    / |- x3 `  p) b- N. ]# v5 T", 3 * n);0 e% P! E: w2 E1 L( _) {
    }
    3 ?, r% @6 G: E5 P然后在工程鏈接文件 MIMXRT1176xxxxx_cm7_flexspi_nor.scf 里將這個(gè)自定義的 section .criticalFunc 也放進(jìn) RW_m_data 執(zhí)行域中:# ?; p! J6 t- j7 N
    LR_m_text 0x30002000 0x00FFE000 {" y3 w5 @7 @) p( i
      ; ...% [0 C. d. @' y( \+ S/ k5 P0 [& A
      RW_m_data 0x20000000 0x0003F800 {4 ?4 ?; l/ g/ P, B) O
        .ANY (+RW +ZI)) n' [( Y# @9 u/ _
        * (.criticalFunc)  ;添加 .criticalFunc 段
    5 y' F3 Q. T) z      ; 第二種寫法:*.o (.criticalFunc)" {' v$ }# z9 c
      }
    8 K5 d! A) W. f$ h3 A8 L  ; ..." ~/ B& ~0 t; G
    }
    , \5 J8 K; K- ?$ D  K: ^, ~" ~編譯鏈接修改后的工程,然后查看其映射文件(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í)行域空間)。6 }/ n+ L( b8 x0 R. {, c- J
    ===============================================================================/ E; j: Q6 Y/ _2 m
    Image Symbol Table
    2 N1 E4 p- H' e( V1 Q: e. Y# C( x4 Y    Global Symbols! L/ \( r: o  x0 L) N0 D3 i& u
        Symbol Name                              Value     Ov Type        Size  Object(Section)
    % D! p4 M( G* s: p1 R    critical_func1                           0x20000001   Thumb Code    28  critical_code.o(.criticalFunc)
    # w3 b: A3 s5 w! O! _8 C    critical_func2                           0x30005429   Thumb Code    32  critical_code.o(.text.critical_func2)- t: t# ?$ l0 v: s( {3 q
        critical_func3                           0x30005449   Thumb Code    36  critical_code.o(.text.critical_func3)0 z' k6 H2 L) k1 b& N8 ?' i) z% Q
    ===============================================================================# Q" L, x# w  f: V4 A0 ?/ t! v, g+ Q
    Memory Map of the image' d4 ]" Q7 X7 \5 L8 `' [8 ^2 k
        Execution Region RW_m_data (Exec base: 0x20000000, Load base: 0x30005f60, Size: 0x00000078, Max: 0x0003f800, ABSOLUTE)
    ; s& K: A( G( q; e5 O# q9 l1 f    Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object2 C* B, J2 N  n0 z' V4 o
        0x20000000   0x30005f60   0x0000001c   Code   RO           17    .criticalFunc       critical_code.o
    . x4 V/ G' `% O6 m& w7 P' I1 o7 I    Execution Region ER_m_text (Exec base: 0x30002400, Load base: 0x30002400, Size: 0x00003b60, Max: 0x00fbdc00, ABSOLUTE, FIXED)
    $ t' K6 u8 y# E! Y5 e! r) f    Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object
    6 |9 l. X1 P* b    0x30005428   0x30005428   0x00000020   Code   RO           19    .text.critical_func2  critical_code.o
    3 s7 l: _0 e, i  g0 `8 L% [    0x30005448   0x30005448   0x00000024   Code   RO           21    .text.critical_func3  critical_code.o1 ?( V% J2 p' |+ @5 Y4 K
        0x3000546c   0x3000546c   0x00000004   PAD6 Z! u# y5 W( X; ?
    ===============================================================================
    * i7 E" M1 M8 n5 FImage component sizes/ D9 D( v' b  i$ p& A% U: j
          Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Object Name
    , S1 ~' _: t3 T3 M        96         56          0          0          0        903   critical_code.o
    $ t3 e4 h. L& B( p2.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 的自定義段里:7 }6 @8 q  P9 T9 D$ q$ D
  • Note: 這種方法一般情況下不太推薦,代碼可移植性較差。
  • 發(fā)表回復(fù)

    本版積分規(guī)則

    關(guān)閉

    站長(zhǎng)推薦上一條 /1 下一條


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