电子产业一站式赋能平台

PCB联盟网

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

写个单片机程序,居然被优化了!

[复制链接]

334

主题

334

帖子

3287

积分

四级会员

Rank: 4

积分
3287
发表于 2023-11-15 11:45:00 | 显示全部楼层 |阅读模式
关注+星标公众,不错过精彩内容
# A4 x/ L+ [4 Q$ u/ t

vcg11mt52ac64013505640.jpg

vcg11mt52ac64013505640.jpg
. s1 E7 r& ?! w- ^8 P
作者 | strongerHuang微信公众号 | 嵌入式专栏/ n+ O# g" [! {; Z5 j: N
最近看到小伙伴讨论【我的代码不按照流程执行】相关的话题。。。
* V* @- R: G3 Q这类问题,有经验的工程师肯定能想到是什么原因导致的,那就是编译器把你代码优化了。5 ?3 S; X/ d' n6 h" c
本文围绕Keil MDK优化选项,以及相关拓展知识(微库、实际应用、调试)进行讲述,希望对你项目开发有所帮助。
8 x% N" l( I  B8 }& \概述
/ ~; x6 w# X$ V- w# ]. I. S我们所指的优化,主要两方面:
  • 代码大小(Size)
  • 代码性能(运行时间)
    5 v+ d1 H- M( u$ _9 F& u
    : A8 |( R0 p! n1 }# {7 y* s# \
    在MDK-ARM中,优化相关的配置选项:
    * X, p9 M  @9 Z" G, S' Y

    rrfun252eec64013505740.png

    rrfun252eec64013505740.png
    # m% @. j6 l: K7 o+ [& Q- u

    fprjslzlzd364013505840.jpg

    fprjslzlzd364013505840.jpg

      X' s' G% A7 R* o& b3 H+ u当然,如果选择编译器(AC5、AC6)不同,优化选项也有差异(下面讲述)。
    9 j  ^8 S3 o! K' @9 I) D  X# N举例:某些项目MCU容量有限时,你除了修改代码(优化开支),同时你有必要使用优化选项。) r; c- x* R7 N4 [, E
    某些项目(比如某算法)需要高效(最短时间)运行,此时有必要使用优化选项。: o9 `) _1 f1 Q9 ?9 z; t
    优化选项说明# S3 \% u; J5 K3 V" ]9 P6 F* }
    本节详细讲述优化相关选项,同时,编译器选择AC5和AC6时有差异,下面也会针对AC5和6分别讲述。
    7 j  e3 q- f- p1.Use Cross-Module Optimization:使用跨模块优化使用跨模块优化可以启用链接器反馈文件(进行两次编译),从而允许进一步的代码优化。
    . }2 d8 q8 v/ U) j9 l* ^) s3 S提示:& S! f1 B2 X: x4 O, m6 o" T
    A.不针对库目标执行跨模块优化。B.跨模块优化将增加构建项目所需的时间,因为会自动执行多个编译和链接步骤。
    0 w# p' W/ l( X; h4 k6 C2.Use MicroLIB:使用微库它是ISO标准C运行时库的子集(其中一部分),提供了性能和代码大小之间的权衡。/ J* w8 G1 w  N9 ?& n
    微库并不完全兼容ANSI,但对于大多数小型嵌入式应用程序来说已经足够了。7 V- _4 a8 [/ z9 x- ?" j& ^6 A
    3.Use Link-Time Code Generation:使用链接时代码生成(优化)在V5版本之前有这个优化选项,多文件编译,链接时进行优化:
  • 函数跨模块内联
  • 删除未引用的变量和函数
  • 通过重新排列变量优化内存访问
  • 在可能的情况下重用内存* C6 l) @7 m' F, C$ e3 Y6 i
    4.Execute-only Code:生成只执行的代码不包含未使用(函数、变量等)代码段。* h* U9 [' X& M; r
    仅限于:; K5 P( F8 a9 b6 A8 e$ h* g1 W( I/ l
    C、Thumb代码基于Cortex-M3、M4的处理器编译器5.04以上$ Q: X# k* ^2 v$ @: [  y
    5.Optimize for Time:优化时间* x& g. O7 z, `' K* ~" Q
    以更大的代码大小为代价,减少执行时间。比如:使用内联函数。
    " j; s7 \/ T* Z' I6 _编译器为AC6时,此选项为【Link-Time Optimization】,在链接状态下执行模块间优化。
    1 w% T2 Y6 ?7 ]' j+ b" A/ B6.Split Load and Store Multiple:分割加载和多存储指示编译器将LDM和STM指令拆分为两个或多个LDM或STM指令,以减少延迟,此选项可以提高系统的总体性能。
    ! ^, l; j' s' _% b5 Z6 ]7.The One ELF Section per Function:每个函数一个ELF段ELF代码段通常包含许多函数的代码,此选项告诉编译器将所有函数放入它们自己的ELF段,这允许链接器删除未使用的ELF段(而不是未使用的函数)。' f8 f; |2 ]3 c- ?
    8.AC5时:Optimization优化选项默认值,以优化性能为主。% h+ d! e% Z5 {# Y% n: C
    Level 0 (-O0):关闭大部分优化,除了一些简单的转换,生成的代码具有最佳的调试视图。* w$ E) |/ n1 ~5 `0 L
    Level 1 (-O1):应用受限优化。比如:删除未使用的内联函数和静态函数,删除冗余代码和重新排序指令等。生成的代码经过合理优化,具有良好的调试视图。4 N9 ?3 I- w. N; f9 F
    Level 2 (-O2): 高度优化,目标代码到源代码的映射并不一定对应,因此,不利于调试。( @* i4 {" x% o4 c, Z& b
    Level 3 (-O3):最大级别优化,级别3与时间优化相结合可能生成比级别2更多的代码。2 B$ E+ G' B& `; B  m' S+ B
    9.AC6时:Optimization优化选项当编译器选择AC6时,优化选项有差异(有更多优化选项):
    * T6 Q6 y6 f1 z: l

    jsdhs2qp0hg64013505940.jpg

    jsdhs2qp0hg64013505940.jpg

    : }5 s3 g: X! C: XAC6优化选型中前面5项(default、-O0 ~ 3)和AC5的作用基本一样,但AC6多了三个选项。
      x% f7 b3 i6 [  M) o/ T-Ofast:启用-O3的所有优化,以及其他可能违反语言标准(严格遵守)的优化。9 w; J% `. A9 b' w5 g/ b  N4 ~: L
    -Os balanced:平衡代码大小与代码速度。默认情况下,编译器执行优化以提高性能,但可能会增加image文件大小。
    * L; U8 g3 l- G( u4 v; Q-Oz image size:优化代码大小。
    3 t1 P8 x) E; a; n" }6 r, Z. W如何优化6 W3 m( p$ C7 Q3 Z  m5 M
    本节讲述三种编译优化,使其达到最优(代码最小、性能最好)
  • 代码大小
  • 代码性能(速度)
  • 代码平衡(大小和速度)
    + q" n9 l8 N( x8 V  Z4 Z) Y) W6 a1.优化代码大小针对AC5编译器:1 T( q! X, O/ o4 ]
  • Use MicroLIB
  • Use Cross-module optimization
  • Optimization:level 2 (-O2)$ p0 D" ]0 ~5 s2 s7 h7 e
    针对AC6编译器:
  • Use MicroLIB
  • Optimization:-Oz image size" `% H, F3 `, W+ c/ S& S2 O7 t2 n& c
    说明:A.代码量大(ELF代码段通常包含许多函数的代码),可考虑使用The One ELF Section per Function选项减小代码。' K2 D0 O2 G% S7 `
    B.AC6编译器改进了优化功能(可以理解为增加的3个选项集成了优化功能)。  _0 Q2 M; t2 G/ l
    代码优化大小(对比):
    4 L" r. @4 F$ x

    sa15wgadujd64013506040.png

    sa15wgadujd64013506040.png

    " ^+ n4 \( ~* Q& D1 }1 y: _; ~2.优化代码性能: \  Q* v! m: @. p5 M& e4 x
    针对AC5编译器:
  • Use Cross-module optimization
  • Optimization:level 3 (-O3)
  • Optimize for Time
    + `; L; s$ _% I8 I6 K* H! [针对AC6编译器:
  • Optimization:-Ofast
  • Link-Time Optimization6 H9 v4 I( W: |7 T: L
    代码优化性能(对比):
    7 |- V4 Y6 k; V+ j6 x

    q0k0wbrrcky64013506140.png

    q0k0wbrrcky64013506140.png

    6 q9 U' [3 x- J# h3.代码平衡这种情况下,在满足代码大小的同时,我们应尽量满足性能。
    . G1 w$ g( ]6 V* b, \  T这里其实就是一个相关平衡的关系,结合上面两种优化方式根据自己实际情况出发,一般优化考虑如下配置。" K! Q; e% I& l) A: _- z8 [7 ^* z' r
    针对AC5编译器:
  • Use Cross-module optimization
  • Optimization:level 3 (-O3)
  • Optimize for Time; g. F' y1 j- t5 w  G$ `5 P# a4 t
    针对AC6编译器:
  • Optimization:-Os balanced
  • Link-Time Optimization
    " |3 z, A$ m9 M: a当然,AC6中-Os balanced优化选项更智能。: \& T- T( Z# Q& c/ {' i
    拓展4 K3 h' q: b' e7 j+ Q2 W# i
    Keil MDK的优化功能需要结合项目实际情况进行优化。对一些项目能起到很大帮助作用,但优化之后也可能带来一些影响。
    " z7 Y7 y9 i  ]; @1.使用高度优化(-O1以上),可能会影响Debug调试(因为优化之后,编译输出和实际代码不匹配)。
    5 v! c% @, y- H  q1 a: g2.指定源文件/文件组优化有些代码不需要优化,我们优化指定的源文件/文件组就行。
    3 U7 @$ z) Y* E& \+ }

    hzyniaczkft64013506240.jpg

    hzyniaczkft64013506240.jpg
    ! x* I* w6 B/ E* u4 I' d7 b
    ------------ END ------------+ h  M, y2 s! E( ^
    5 h9 D; p! H% j7 I+ E; ^

    jho4tjigpdp64013506340.gif

    jho4tjigpdp64013506340.gif
    & c9 x- g' e# q* a7 I3 T4 w
    ' q" D2 s. X6 z$ _
    ●专栏《嵌入式工具3 |  d7 ~- p3 J
    ●专栏《嵌入式开发》: U0 ?1 ]4 h/ S1 r2 f* M
    ●专栏《Keil教程》; c: a* l. C2 |5 Q7 X% Y6 L
    ●嵌入式专栏精选教程
    3 o- X) H* L/ V' R0 |% a( E( z* p% o3 l
    关注公众号回复“加群”按规则加入技术交流群,回复“1024”查看更多内容。
    : Y9 e8 Y: a1 [5 I5 J' }6 u, ]

    4vp3obun5qz64013506440.jpg

    4vp3obun5qz64013506440.jpg
    : n( _, a( F( m8 {  {) l5 [
    / J6 ^5 m) e4 Y4 q+ i6 O

    drvnsxjuqkb64013506540.png

    drvnsxjuqkb64013506540.png

    5 W* t5 O2 F! {9 |; g3 {8 O: m/ U! S1 h1 D; N- Q, A% V
    点击“阅读原文”查看更多分享。
  • 回复

    使用道具 举报

    发表回复

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

    本版积分规则


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