电子产业一站式赋能平台

PCB联盟网

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

【反复横跳】从AC5到AC6转型之路(1)-补救和准备

[复制链接]

359

主题

364

帖子

2887

积分

三级会员

Rank: 3Rank: 3

积分
2887
发表于 2025-3-7 11:27:00 | 显示全部楼层 |阅读模式

tzbmf1zy4vg6401916532.png

tzbmf1zy4vg6401916532.png

( U/ ]. @+ s; a/ N/ D/ w  L- P
, ~, h9 R6 f! |* k【说在前面的话】9 Q; Z4 O: C" u" l/ D
时间大约在2015年,Arm第一次在 MDK 5.20 中引入了Arm Compiler 6(那时候的版本是 6.9),正式拉开了Arm官方编译器从第五版(armcc)到第六版(armclang)升级替换的序幕……嵌入式行业的长尾效应是及其突出的,且不说都2022年了还有很多人在坚持 MDK4,即便是从“Arm在2017年对外宣布停止维护 Arm Compiler 5”算起,如今5年过去了,坚持使用 armcc 的用户仍然不在少数。
3 |. K+ W* d: w9 NArm Compiler 5,也就是大家口中的 armcc,它很弱么?相对免费的工具链 arm gcc来说,它还是强很明显;但你要说它非常能打么?作为一个“理论上”收费的编译器,它甚至已经全方位落后于最新发布的“免费开源”编译器LLVM Embedded ToolChain For Arm 14.0.0(clang),更不用说现在的当红贵人Arm Compiler 6(armclang)了。
: o, a8 v: l" m: [: X3 P1 I/ k0 y$ e9 D% a) o
如果非要我给出一份“不负责任”的编译器性能对比的话,这是独属于我的答案:2 r6 I7 o1 o/ n9 b  E4 P8 ~
arm gcc
, z7 d/ @. Q/ m8 i7 o3 W: ~7 P9 s' f$ q  Q/ j7 F4 z4 J4 D' p! B, Z
别问我为什么,问就是谁用谁知道。: U/ ?. s" Y! Q1 ^& s; h1 g( @5 L: I
如果不是因为产品存在 Golden Code(屎山),只要你选定了Arm Compiler 而不是IAR,既然横竖要使用付费编译器,为什么不用Arm例行维护(几乎每半年不到就发布一个新版本)的Arm Compiler 6,而继续死守Arm Compiler 5呢?( P3 j  R2 {# S4 Y$ Z) ~
有的人说“Arm Compiler 6不如Arm Compiler 5”稳定。这里给出我的几个反驳的几个理由,但我不指望能说服那些抱有这类想法的人
$ u7 P. q" L( g: E) R' d( {* ]
  • Arm Compiler 5已经停止维护,Arm Compiler 6还在持续更新。没有bug的编译器是不存在的,一个生命周期已经结束的编译器就几乎不在存在修复已有bug和未发现bug的可能性;而一个积极维护的编译器则可以及时的将发现的问题进行修复;
  • Arm Compiler 5过去只有Arm维护,而 Arm Compiler 6是基于LLVM(clang)的商业化改进版,这里LLVM是一个开源项目,由众多的个人和商业组织共同维护,参考过去gcc的成功——这么多“大聪明”在盯着的项目,即便发现错误,估计也是“分分钟”就被拿去“邀功请赏”了吧?, Z. m' D. `% u- x

    . g  U8 t& r$ F  P# O! {! s; b7 B5 z3 q& O

    tmcvxvucvrh6401916632.png

    tmcvxvucvrh6401916632.png

    9 T) n% J  f2 T1 z/ c. z
  • 虽然我在实际使用中抓到(报告并得到修复)的Arm Compiler 6 bug的数量超过在座99%的人,但正因如此,我知道要遇到一个Arm Compiler 6的bug有多难——更多时候,其实是我们自己对编译器理解不深刻,甚至是基于自己对C语法的错误认知导致的“乌龙”。在我看来,与其怀疑Arm Compiler 6不稳定,不如怀疑下自己对C语言的理解
  • 不要屈服于由“未知带来的恐惧”,不要拿“污名化”当做掩盖自己“偷懒和无知”的遮羞布(对这句话感到愤怒的人,我送你一句:爱听不听,欢迎取关,谢谢)。
    4 O/ ]) k3 h. m( E' }2 c4 `! B

    $ x3 B7 t  t7 ^% T看到这里,如果你决定继续往下阅读,我就假设你已经有兴趣去尝试使用Arm Compiler 6 来逐步取代已有的 Arm Compiler 5了。基于这一前提,我们将用随后的一系列文章来介绍:
    2 `) R  d6 v( l( N% o
  • 短期内:MDK 5.37 抛弃 armcc 的补救措施
  • 中期:从 armcc 向 armclang 进行过渡时期的一些快速应对的方法
  • 面对一些 armcc 独有的编译器特性的应对方法
    4 m. y' I% ~2 l; Y- X" L& B

    5 L$ ~' F0 F; Y" h/ J/ _
    5 O/ h- ?3 G3 B& f2 b! Q' u/ c

    kei5bxg5mm26401916733.gif

    kei5bxg5mm26401916733.gif

    , ]- ^" H7 q) Q* U" Y% x8 t6 u; B  M5 l; {& s7 ^; X" q% c
    2 u5 q6 x4 m( p
    【临时补救】0 ^/ Z7 d1 I' v& i# p# _6 S
    虽然最新的 MDK 抛弃了Arm Compiler 5,但它仍然允许我们通过手动添加的方法将其请回来,具体方法我在《惊爆内幕:老MDK也可以使用新编译器》文章中已经详细介绍过,这里就不再赘述,值得补充说明的是:, \+ I- H$ V8 i, ~( V
    1、新MDK也可以手工添加老版本的编译器,不要被文章的标题限制住了思路2、Arm Compiler 5的下载链接如下:https://developer.arm.com/downloads/-/legacy-compilers
      |4 X8 R: X& z9 A% Z5 Q6 }3 c2 M; u2 U
    【几颗定心丸】2 i3 a3 w- o! ~1 ]0 E

    + c; K/ Z/ b% d: [1 @. c% h1、“接头霸王”9 I3 f) e5 s& w  F9 _* s8 A) [8 }
    我们知道MDK是一个集成开发环境(Integrated Development Environment),它默认原生支持Arm Compiler 5(armcc)Arm Compiler 6(armclang)arm gcc。虽然这三个编译器都是由Arm所维护和提供的,但前两者算是彼此兼容的编译器:
    - b+ W$ i/ ~5 O- a2 Q( b使用共同的 armlink0 P6 m" Y' _3 I+ V- H
    使用相同的方式来描述地址空间布局(分散加载脚本 scatter script)
    5 f8 }: H2 N9 f: Y& k$ U/ PArm Compiler 6.14开始,armclang甚至开始支持armasm的汇编语法了
    8 c7 T# F9 V) w% o1 n& A
    9 E0 P( p7 L' m' C& ]5 K" `1 ~
    实际上可以认为,armccarmclang是一对连体兄弟,身子是armlink,而两个脑袋分别是 armccarmclang。大约是这种感觉,你体会下。" r/ e7 @) ~& ~, X1 W
    # f9 N3 i- o, b. g

    uppozjgbkmb6401916833.jpg

    uppozjgbkmb6401916833.jpg

    3 C; s4 j. U7 W  @4 y
    ( m) c% b7 d0 l4 y作为定心丸的结论是:
    . @6 j! E1 x2 S% Q9 |& J
  • 原来 Arm Compiler 5 项目下的所有库(*.lib)都可以在 Arm Compiler 6 下直接使用
  • 原来由 Arm Compiler 5 生成的对象文件(*.o)都可以在 Arm Compiler 6 下直接使用
  • 原来 Arm Compiler 5下所用到的“几乎所有” armlink 相关的特性都可以在 Arm Compiler 6 直接使用(因为基本就是同一个armlink,所以几乎不存在“移植”的说法)1 i9 }. @5 |4 e. j! v  I. u' o
    当然,还是有一些特例的,比如 __attribute__((at(地址))) 语法,这个我们将出一个专题来介绍应对方式。 $ m0 i; w) c8 h

    " R9 d4 N5 n% A: A+ i# p$ ~; {2 A) o, q7 {' y# \/ p: S" {9 [* Y  A
    2、“偷懒是第一生产力”5 `: x6 ]5 u. s% w% Q
    由于 Arm Compiler 6 脱胎于LLVM,因此在汇编语法上它也继承了 clang 的特性——使用 GNU Assembly Syntax,而非 Arm 此前一直尝试推广的 Unified Assembly Language(UAL)汇编语法。由于 Arm Compiler 5 一直使用的是 UAL 汇编语法,广大用户长时间来积累了大量使用该语法编写的 .s 文件。
    & z# \$ @  _9 I* ?汇编原本就是个头疼的东西——不到万不得已谁写汇编啊?对很多项目来说,且不说汇编原本就是少数大牛才敢碰的东西——几乎就是“Golden Code(屎山)”的代名词,实际上,这些“历史尘埃”的作者可能早就已经离职了——就算你把本人找回来,恐怕很多时候连当事人自己也是狗咬刺猬无法下嘴了。1 ]: k7 @/ `8 U

    xtmcyhba0a46401916933.jpg

    xtmcyhba0a46401916933.jpg

    - s9 r8 [# v: c8 z/ d* u! }) l7 p- _& o8 v8 v8 q7 Y
    尽管 Arm 专门写了一个名为《Migrating from armasm to the armclang Integrated Assembler》的文档来“教大家做事”,但社区的反馈可想而知……
    $ @2 `6 t0 ]+ a9 S. y. d# [/ @# ?: z) O/ a. C

    w2oqx0g12bf6401917033.jpg

    w2oqx0g12bf6401917033.jpg

    ( P1 a) w: W; R, i* J9 W+ k+ i' X, _文章链接如下:( ?5 J6 V! V% d0 p$ a; _
    https://developer.arm.com/documentation/100068/0618/Migrating-from-armasm-to-the-armclang-Integrated-Assembler?lang=en
    ' y# p, d) w3 _* _9 N, ^- `在众多“我不想,你求我啊……”的声音中,Arm Compiler 6从 6.14版本开始,重新把 UAL 的支持加了回来,并在 MDK 中引入了这样一个选项:; z$ ?- V4 ]; }, @7 K
    ) H+ G/ G) Y3 |/ [- t9 Q
    4 P- Q5 V1 b2 Z8 w

    l2nrkp5b04j6401917133.png

    l2nrkp5b04j6401917133.png

    * W/ K% o- Z3 ~' U" }0 C! N0 X这里几个选项的意义如下:6 U' t2 ^3 F" O1 `9 f- x7 @( }/ [2 r
  • armclang(Auto Select):使用 armclang 来编译汇编源代码(对应命令行选项 -masm=auto),然后armclang会根据语法风格自动决定是当做 GNU Assembly Syntax 来处理,还是使用 UAL 语法来解析。我吐血推荐使用这个选项
  • armclang (GNU Syntax):使用 armclang 来编译汇编源代码(对应命令行选项 -masm=gnu),然后强制使用 GNU 汇编语法风格。
  • armclang (Arm Syntax):使用armclang来编译汇编源代码(对应命令行选项 -masm=armasm),然后强制使用 UAL 汇编语法风格。# ?9 R8 q' E7 i1 H, T5 U1 Q+ t  ?, z
    其实,这里 armclang 也是个二道贩子——它也是调用 armasm 来完成编译的,只不过在这之前,它会默认用C预编译器对汇编源代码进行预处理,换句话说,折磨armasm很多年的“如何在汇编代码中使用C语言宏和预处理”的问题,得到了根治——你可以大大方方的在汇编代码里用 #include、各类宏定义和 #if 了。: l0 L2 }1 l" k% P" x1 X! o! m
  • armasm(Arm Syntax):直接使用 armasm 来编译汇编源代码。该选项对 老的 UAL 源代码文件兼容性最好。如果使用 armclang(Arm Syntax)遇到问题,不妨用这个选项来试一下——一般都可以顺利解决问题。
    # ?: P! Z  s" {& k/ f

    8 \/ Q5 a8 X; X/ B2 _/ e% P怎么样,不用修改屎山了,是不是如释重负?1 U3 b* i4 Y* p3 A8 {
    # S% _5 ?2 o# M- ~/ O
    3、在线汇编(Inline Assembly)和嵌入C代码的汇编(Embedded Assembly)
    " ?$ B* P2 F3 e+ O4 q: P无论你是否了解 Arm Compiler 5所支持的这两种在C语言中使用汇编的方法,也不用关心它们的区别,结论是——任何Arm Compiler 5下的C代码只要使用了上述两种方法之一,基本上就是“需要手工干预”的。3 p- i& R5 ~# x4 \, M
    这里我给出一个万能药方:. U% \1 t  q# [* N6 w5 b
    对这部分C源文件,请使用 armcc 编译,生成 .o 后扔到 Arm Compiler 6里直接参与链接即可/ }1 H: |! t+ o6 o- Y
    8 [5 v6 V; j6 d4 z& X* r, a
    当然,如果你有兴趣依照前面文档里的介绍进行改写,我祝你好胃口。
    6 O1 \1 {- R8 I. u

    4r40sykik1c6401917234.png

    4r40sykik1c6401917234.png

    % ]- _5 _3 ]6 u0 C* Z/ C6 l9 Q8 u& W" R  F& w3 @) E; K5 H- H8 l
    至于如何让改写后的C代码同时兼容 Arm Compiler 5 Arm Compiler 6,就离不开下面的内容了——它也是我们后续一系列差异化改造的基础
    + a6 c, R6 l1 D$ ~/ e* q6 k% P7 `- P. j4 K
    【如何检测编译器】
    * m' }; }7 c  H1 O( a. }( h一般来说,当我们要对某一部分代码进行跨编译器移植的时候,当然可以按照新语法一改了之,但对很多人来说,老的编译器总是会让大家萌生一种说不上来的留念之情,
    ) g- M" p9 k/ Z" h) P

    ipdrhszvkxo6401917334.jpg

    ipdrhszvkxo6401917334.jpg
    ) s$ e/ r3 G2 Z- E' \  q+ [
    继而抱有:
    4 L* o; ?+ u1 x9 G/ X' b2 Y# q“我要让修改后的代码仍然兼容过去老编译器”;
    : q1 N  ^2 q5 e  Q" r/ U! ^或是:
    ! S" x, c( u& D$ T$ J* ]“老代码删除太可惜了,我要留下来,以后万一有用呢?”
    5 E6 i, A/ N0 n" o/ x; c这样的想法。我也是这么想的。
    ) F2 @* f5 |7 X, O% k: s

    ilppkbm0qkl6401917434.gif

    ilppkbm0qkl6401917434.gif
    - P) F& Y0 I6 h7 d  j: z: j
    要做到这一点,就绕不开一个核心问题:如何可靠的检测出当前编译器版本呢?
    7 P* P4 a; R: p! z6 {: D& X5 u' X. k
    一般来说,编译器的宏检测有两个思路:, j- X6 _& n) V; o& _
    借助某一编译器独有的特征宏来判断编译器' ^* A" ~/ p- _- Y
    借助多个编译器共有但值不同的宏来判断) q* A& J1 l( Z/ w2 F3 J4 O- k. {* c
      t) a' w5 A; ^2 n
    对于第一种思路,有两个比较有名的宏:__GNUC____clang__ 。过去,很多人喜欢用下面的代码来判断编译环境是否是GCC或者CLANG- z2 z) R$ f. i
  • #if defined(__GNUC__)    /* 我觉得编译器gcc */#endif7 H1 l. H" e  @; v. j6 Y
    #if defined(__clang__)    /* 我觉得编译器是 clang */#endif然而,遗憾的是,由于很多编译器都在某种程度上对 GCC 扩展提供支持,因而也会定义宏__GNUC__,比如 armccarmclangclangIAR都定义了该宏……因此,它几乎失去了GCC特征宏的价值,退化为“当前编译器支持GCC扩展(但具体哪些GCC扩展,这就看我心情了)”的标志。其实 __clang__ 宏也是类似的情况,因为 armclang 也会定义该宏,毕竟Arm Compiler 6是从LLVM中派生而出的。
    # i9 _# [4 h& ?! ?当然,更为常见和有用的编译器特征宏是 __IAR_SYSTEMS_ICC__ ,借助它的帮助,我们可以判断当前开发环境是否为 IAR:
  • //!
    0 F7 z% M! ?/ c, m5 W9 c" ]ote for IAR#undef __IS_COMPILER_IAR__#if defined(__IAR_SYSTEMS_ICC__)#   define __IS_COMPILER_IAR__                  1#endif# Q3 }9 c  u( x) a* K/ }) X
    Arm Compiler 5Arm Compiler 6 都是 Arm Compiler,区别它们二者有很多方法,但官方推荐的方法是判断宏 __ARMCC_VERSION 的值。从名字上就可以看出,这是一个自 armcc 以来一直延续到 armclang 的共有宏,它保存了编译器的版本,因此我们很容易编写出如下的宏:
    ; G) e) P$ G6 l
  • //! 1 P9 N" |5 z( z
    ote for arm compiler 5#undef __IS_COMPILER_ARM_COMPILER_5__#if ((__ARMCC_VERSION >= 5000000) && (__ARMCC_VERSION #   define __IS_COMPILER_ARM_COMPILER_5__       1#endif//! @}6 w9 A  x) o+ a/ F! o
    //!
    1 Y5 }8 `1 g1 n& @+ @0 j7 Mote for arm compiler 63 P4 M, F* V6 @: d, N: r
    #undef __IS_COMPILER_ARM_COMPILER_6__#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)#   define __IS_COMPILER_ARM_COMPILER_6__       1#endif0 |3 O# A  H" ~' S* v
    #undef __IS_COMPILER_ARM_COMPILER__#if defined(__IS_COMPILER_ARM_COMPILER_5__) && __IS_COMPILER_ARM_COMPILER_5__   \||  defined(__IS_COMPILER_ARM_COMPILER_6__) && __IS_COMPILER_ARM_COMPILER_6__
    1 y7 e6 A; L7 A#   define __IS_COMPILER_ARM_COMPILER__         1
    ) _  R2 Q5 k& [. C#endif借助它们的帮助,我们可以很容易的通过判断 __IS_COMPILER_ARM_COMPILER_5____IS_COMPILER_ARM_COMPILER_6__ 的值是否为“1”来确定当前的编译器版本。在只关心当前编译器是否为Arm Compiler,而不在乎它具体是哪个版本时,可以借助 __IS_COMPILER_ARM_COMPILER__ 来进行判断。
    4 {$ g0 g$ b2 y# \- i' {- C8 S7 C# ?( Y/ S3 `7 `2 Y  x7 c
    假设我们的代码只考虑支持 gccclangiararmccarmclang,那么利用排除法,我们就可以轻松的判断当前编译环境是否是 GCCLLVM了:( R6 H* c8 w! i, C, d9 \% M, ~" g8 o
  • #undef  __IS_COMPILER_LLVM__#if defined(__clang__) && !__IS_COMPILER_ARM_COMPILER_6__#   define __IS_COMPILER_LLVM__                 1#else//! 8 v, t7 Z0 f/ T+ ]3 Z2 A2 n
    ote for gcc#   undef __IS_COMPILER_GCC__#   if defined(__GNUC__) && !(  defined(__IS_COMPILER_ARM_COMPILER__)           \                            ||  defined(__IS_COMPILER_LLVM__)                   \                            ||  defined(__IS_COMPILER_IAR__))#       define __IS_COMPILER_GCC__              1#   endif//! @}#endif简单说一下这里的思路:" J# g& @+ R8 b. O6 H& o7 E6 v3 V
    1、在排除了 Arm Compiler 6 的前提下,根据 __clang__ 来判断当前编译器是否为 LLVM(即:__IS_COMPILER_LLVM__);
    , J) Q6 e% d$ V) r2 n2、在排除了 LLVMArm CompilerIAR的前提下,根据 __GNUC__ 来判断当前编译器是否为 GCC* D( R% u$ I# t- P
    : Q+ h2 u% M$ c  z" R
    为了方便大家理解,下面介绍几个上述宏的应用场景:
    ; I3 G3 l# R( e6 l$ \2 @+ P5 b3 b6 p. }/ H
    如何在 Arm Compiler 6 下告知编译器 main() 函数不带输入参数- A5 o1 P/ h' E% p
    默认情况下(使用默认的 libc),Arm Compiler 6会认为 main() 函数是带有标准的输入参数的:4 h/ y% |! I' P
  • int main (int argc, char *argv[]);哪怕你强行把 main() 函数写成无需输入参数的情况,编译器也还是会准备好参数——而准备参数的过程很有可能会导致 hardfault(这里会涉及到semihosting的问题,比较头疼,暂时不表)。为了解决这一问题,我们一般这么做:
    " S( P) E8 K, b, u, J) t' P
  • #if __IS_COMPILER_ARM_COMPILER_6____asm(".global __ARM_use_no_argv
    2 \' C5 u' I. R& V6 x# c9 X        ");#endif又因为 MicroLib 不存在该问题,因为我们可以根据(MDK会追加的一个宏)__MICROLIB,来做一个小小的区分:
    : S% M3 q5 e4 J$ o7 f' K* V
  • #if __IS_COMPILER_ARM_COMPILER_6__#   ifndef __MICROLIB__asm(".global __ARM_use_no_argv
    . [" y7 m+ G! h+ X$ N: M2 ?        ");#   endif#endif也就是当且仅当我们使用 Arm Compiler 6,且不使用MicroLib的时候,通过专门的语法结构来告诉编译器:main() 函数没有传入参数。4 S6 v. Q* y9 g& ^

    , b. R2 c- U  o如何关闭 Semihosting
    0 Y1 c1 p: d  r4 Z! c' n4 I: O
    你有没有遇到过这样神奇的情景:在调试模式下,程序可以正常运行;一旦退出调试模式,系统就死机了,重新进入调试模式后,发现系统进入了Hardfault。恭喜你,这很可能就是(默认开启的)semihosting 在作怪。关于Semihosting的内容,篇幅过大,不在本文讨论之列。今天我们只介绍一下如何关闭它。
    ) g# J8 W' G* j2 Y5 a3 ]Arm Compiler 5Arm Compiler 6关闭 Semihosting的方法是不同的:
    % a5 q  E0 Y  S
  • #if __IS_COMPILER_ARM_COMPILER_6__    __asm(".global __use_no_semihosting");#elif __IS_COMPILER_ARM_COMPILER_5__    #pragma import(__use_no_semihosting)#endif一旦关闭了 SemihostingArm Compiler 6 就可能会报告类似如下的错误:
    $ R3 s. t4 S, L, e% t
  • Error: L6915E: Library reports error: __use_no_semihosting was requested, but _sys_exit was referenced简单解释下原因:Arm Compiler 6 依赖的一个函数 _sys_exit() 原本是用Semihosting方式默认提供的,现在你把 Semihosting 关闭了,所以你要负责到底。知道了原因,解决方法也很简单——缺这个函数,我们提供一个就行:
    7 ~) o  N; E$ D+ y: l
  • #if __IS_COMPILER_ARM_COMPILER_6__void _sys_exit(int ret){    (void)ret;    while(1) {}}#endif类似的情况还会发生在一个叫 _ttywrch() 的函数上,我们可以如法炮制:
  • ) n* y0 L6 K8 }8 i" g- W  o; Y
    /* 为 arm compiler 5 和 arm compiler 6 都添加这个空函数 */#if __IS_COMPILER_ARM_COMPILER__void _ttywrch(int ch){    ARM_2D_UNUSED(ch);}#endif
    ( m9 l$ t: m: V+ B' p! V$ u' m9 H9 N% D, z
  • 如何解决使用 assert.h 引发的问题
    ) Z% V9 J1 [% S$ b! k; s2 Z% Y
    很多代码都有使用 assert() 来截获错误的习惯,当我们使用 Arm Compiler 6 且开启 MicroLib的时候,由于 MicroLib并不提供对 assert() 底层函数的具体实现,当我们没有定义 NDEBUG 来关闭 assert() 时,会在链接阶段看到如下的编译错误:: j. U- h9 U" s+ ^: c
  • Error: L6218E: Undefined symbol __aeabi_assert (referred from main.o).知道原因后,解决也很简单:既然MicroLib没提供实现,我们就自己提供一个好了:
    0 u* M) j) _* _+ Z
  • #if __IS_COMPILER_ARM_COMPILER_6__ && defined(__MICROLIB)void __aeabi_assert(const char *chCond, const char *chLine, int wErrCode) {    (void)chCond;    (void)chLine;    (void)wErrCode;        while(1) {        __NOP();    }}#endif0 a% [! d# Y/ ?+ c+ `# w
    既然上述这套 __IS_COMPILER_xxxx__ 这么好用,我们可以从哪里获得呢?
    : a/ ?6 E$ p7 k# ]
    3 {( u) v* n8 U1 x, k4 k3 w

    s44opiegq2q6401917534.jpg

    s44opiegq2q6401917534.jpg
    6 {3 b0 |5 k6 ]
    ! Y, a0 \* W$ g0 L, w, i
    目前已知的获取渠道包括但不限于5 |* o5 V7 I4 G& e$ M/ l
  • 从本文抄下来
  • 包含获取perf_counter 并包含 perf_counter.h
  • 在存在 arm-2d 的情况下,直接包含 arm_2d.h 或者 arm_2d_utils.h
    - e* \* i3 s8 w2 s4 \
    ……& x+ k5 k% U5 R9 U5 R
      M( a/ t, P/ V7 [! |
    【说在后面的话】$ r6 h) I( z! t  u
    我承认 Arm Compiler 5 迁移到 Arm Compiler 6 不是一个轻松的过程,但也绝非大家想象的那样痛苦,很多时候,也许只是在 MDK 中更换一个选项那么简单:; y; ~( `* q( S  A/ T8 O8 j& Y

    - |8 i" G5 x+ o# ^

    p1k5nkmgcff6401917634.png

    p1k5nkmgcff6401917634.png

    # n& ^: P9 d) x& S1 ^3 b4 e+ g" d- Y  y+ n  P9 \: b
    不试一试怎么知道呢?  d/ g, J% F: P
    ; d3 v' f' N( s( ^- f" O# A8 m

    whlx0xhdobm6401917734.jpg

    whlx0xhdobm6401917734.jpg
    * {6 i' T4 A3 N; ~

    : w; V+ V8 G2 E! |" X对主流芯片大厂,比如 ST和NXP来说,它们的库早就完成了对 Arm Compiler 6的支持,可以说如果你遇到编译器兼容问题,应该首先考虑下载最新版本的驱动库
    5 k$ N' M' X4 U" r+ U本文介绍的方法,基本上可以应对常见的从Arm Compiler 5Arm Compiler 6可能遇到的问题。这当然不是一份万能的解药,对于一些特殊的情况,我们将在后续文章中进行专题讨论。1 |& B  M- t* g' I0 p( Y
    最后附上各类编译器的下载链接:
    / N3 o& Y3 s! I! U: `Arm Compiler 5:https://developer.arm.com/downloads/-/legacy-compilers8 q" p3 Z" H: f' b) K0 }
    Arm Compiler 6:https://developer.arm.com/downloads/-/arm-compiler-for-embedded9 z9 O* U& y+ E( j
    Arm GCC:
    ( `4 {; x. h  r/ I/ @3 j/ ~https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/downloads- c" l3 ]6 B8 T; D2 r
    LLVM Embedded ToolChain for Arm 14.0.0https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/releases
  • 回复

    使用道具 举报

    发表回复

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

    本版积分规则


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