如何优化嵌入式平台ARM的C代码

发布于:2024-07-17 编辑:匿名 来源:网络

本文将介绍如何优化ARM平台的C代码,从数据类型选择、数据结构组织、局部变量选择、函数内联内联、编译器选项、循环扩展、条件从执行、数据操作转换、内存优化、代码大小优化等角度给出了常用的优化方法。

  C数据类型  C语言程序优化与编译器和硬件系统都有关系。

设置某些编译器选项是最直接、最简单的优化方法。

默认情况下,armcc 启用所有优化功能,而 GNU 编译器的优化默认关闭。

ARM  C编译器中定义的char类型是8位无符号的,这与流行编译器的默认char类型不同,后者是8位有符号的。

因此,当循环中使用char变量和条件i≥  0时,就会出现无限循环。

为此,您可以使用 fsigned - char(对于 gcc)或 -zc(对于 armcc)将 char 更改为有符号。

  其他变量类型如下:   char 无符号 8 位字节数据   short 有符号 16 位半字节数据   int 有符号 32 位字数据   long 有符号 32 位字数据  long long 有符号 64 位双字数据   局部变量尽可能使用 32 位数据类型   ARM 指令集支持有符号/无符号 8 位、16   位和 32 位位整数和浮点变量。

正确使用变量类型不仅可以节省代码,还可以提高代码运行效率。

应尽可能避免使用char和short  类型的ARM局部变量,因为操作8位/16位局部变量往往比操作32位变量需要更多的指令。

  大多数 ARM 数据处理操作都是 32 位的。

局部变量应尽可能使用32位数据类型(int或long)。

即使处理8位或16位值,也应避免使用char和short。

边界对齐,除非char或short的数据归零(如=0,多用于取模运算)。

否则,编译器将添加代码来处理大于 Short 和 char 值范围的情况。

另外,在处理表达式时,还必须谨慎选择数据类型。

请比较以下 3   函数及其汇编代码。

  Int wordinc(inta) wordinc  { ADD a1,a1,#1  return a + 1; MOV pc,lr  }  短路  短shortinc(shorta) ADD a1,a1,#1  { MOV a1,a1,LSL #16  return a + 1; MOV a1,a1,ASR #16ARM  } MOV pc,lr  Char charinc(chara) charinc  { ADD a1,a1,#1  返回 a + 1; AND a1,a1,#&ff  } MOV pc,lr   可以看出,操作 3 2 位变量比操作 8 位和 16 位变量需要更少的指令。

另外,对于加载16位数据  如果使用LDRH指令,则无法使用桶形移位器,所以只能先进行偏移操作,然后寻址(可以使用指针增量寻址,而不使用数组)在下表中,增量寻址a=data[i++]不如a=*(data++)),同样会导致性能不佳。

但使用指针代替数据操作可以避免这个问题。

声明全局变量时,需要考虑最优的内存布局,使得各类变量能够在32位空间的基础上对齐,从而减少不必要的存储空间浪费,提高运行效率。

  关于函数参数类型  函数参数和返回值应尽量使用int类型。

ARM中函数的前四个整数参数通过寄存器r0、r1、r2和r3传递,后续的整数参数通过堆栈传递。

因此,尽量限制函数参数不超过四个,也可以将相关参数组织在一个结构体中传递。

  对于比较小的被调用函数和调用函数,可以放在同一个源文件中并限制为静态调用,编译器可以对其进行优化。

使用_inline内联对性能影响较大的重要函数,可以有效减少函数调用的额外开销。

对于编译器来说,armcc符合ATPCS的要求。

第一到第四个参数依次通过r0~r4传递,其他参数通过堆栈传递,返回值通过r0传递。

因此,为了在寄存器中完成大部分操作,参数最好不要超过4个。

另外,可用的通用寄存器有12个,所以尽量将局部变量控制在12个以内,效率会提高。

同时,由于编译器比较保守,指针别名会造成冗余的读操作,所以尽量少用。

  循环优化部分  循环是编程中非常常见的结构。

在嵌入式系统中,微处理器很大一部分执行时间是在循环中运行的,因此非常有必要关注循环的执行效率。

除了在保证系统正常工作的同时尽可能简化核心循环体的流程之外,正确高效的循环结束标志条件也非常重要。

  * 使用递减至零的循环体来节省指令和寄存器的使用;   * 使用无符号循环计数值,并以条件 i != 0 终止,这样编译器就可以使用一条 BNE(不为零则跳转)指令替代 CMP(比较)和 BLE 两条指令  (小于则跳转),不仅减少了代码大小,还加快了ARM的运行速度;   * 如果循环体至少执行一次,请优先选择 do-while,这样编译器就不会生成额外的代码来处理循环次数为 0 的情况;   * 如果需要,展开循环体;虽然会增加循环的代码量,但是会减少循环跳转的开销;  * 尽量使用数组大小??为4或8的规范,并利用这个倍数来扩展循环体寄存器分配;  * 尽量限制函数内循环使用的局部变量数量不超过12个,这样编译器就可以将变量分配到寄存器;   * 可以引导编译器通过检查变量是否属于最内层循环来判断变量的重要性;   * 使用局部变量保存公共子表达式的值,确保表达式只计算一次;   * 避免使用局部变量的地址,否则访问该变量的效率会较低;   结构的处理  小元素放在结构的开头,大元素放在结构的末尾;避免使用过大的结构,而代之以分层的小结构;手动向 API 结构添加填充位以提高可移植性;    项 请谨慎使用引发类型,因为其大小取决于编译器。

  对于位域,尽量使用define或者enum来代替位域;使用逻辑运算对边界未对齐的数据和字节排列进行位域运算;尽量避免使用边界未对齐的数据; use char *   指向任何字节对齐的数据,并且可以与逻辑运算一起使用以访问任何边界和排列的数据。

  数据运算的处理  除法和余数  ARM指令集不提供整数除法。

除法是通过C语言函数库(有符号_rt_sdiv和无符号_rt_udiv)中的代码实现的。

一次 32 位除法需要 20~ 个周期,具体取决于分子和分母的值。

除法运算所用的时间是时间常数乘以每一位除法所需的时间:   时间(分子/分母)=C0+C1×log2(分子/分母)  =C0+C1× (log2(分子)-log2(分母))  因为除法执行周期长,消耗大量资源,所以在编程中应避免除法。

以下是一些避免调用 Division 的解决方法:  在一些具体的编程中,除法可以改写为乘法。

例如:(x/y)>z,当已知y为正数且y×z为整数时,可写为x>(z×y)。

  尽可能使用2的幂作为除数。

编译器使用移位操作来完成除法,比如比比较合适。

在编程中,无符号除法比有符号除法更快。

  使用余数运算的目的之一是进行模计算。

此类操作有时可以使用if判断语句来完成。

考虑以下应用:   Uint counter2(uint count)  {   if(++count>=) count=0;  return(count);  }  对于某些特殊的除法和余数运算,查表法也能取得良好的运算效果。

  除以某些常量时,编写特定的函数来完成此操作将比编译生成的代码高效得多。

ARM的C语言库中有两个这样的将有符号数和无符号数除以10的函数,用于完成对十进制数的快速运算。

在toolkit子目录下的examples\explasm\div.c和examples\thumb\div.c文件中,有这两个函数的ARM版本和Thumb版本。

  其他运算  使用左移/右移运算,而不是乘除2。

运算:通常,ARM乘法或2次方除法可以通过左移或右移n  位来完成结束。

事实上,当乘以任何整数时,您可以使用移位和加法来代替乘法。

如何优化嵌入式平台ARM的C代码

ARM 7中的加法和移位可以用一条指令完成,并且执行时间比乘法指令少。

例如: i = i *5   可以使用关系 i = (i=0, x==0, x!=0; 对于无符号变量,x==0, x!=0( 或 x >0) 关系运算符。

对于编程中的条件语句,应尽可能简化if和else判断条件,它是面向ARM的。

,关系表达式中相似的条件应该组合在一起,以便编译器优化判断条件,由于ARM指令可以有条件地执行,因此充分利用cpsr指令将使程序更加高效。

所有指令都可以包含一个可选的条件代码,当程序状态寄存器(PSR)中的条件代码标志满足指定条件时,通常可以省略对ARM指令的单独判断,从而减少代码。

规模和提高程序效率  管道优化  每个ARM处理器都有自己的流水线结构,参考ARM核心流水线——ARM7、ARM9E、ARM11、Cortex-A系列处理器(/zixunimg/eepwimg/houh-.blog..com/blog/static//)。

管道延迟或阻塞会影响处理器的性能,因此管道应尽可能保持顺畅。

流水线延迟是不可避免的,  ,但是延迟周期可以用于其他 ARM 操作。

LOAD/STORE   指令中的自动索引功能旨在利用 ARM 流水线延迟周期。

当流水线处于延迟周期时,处理器的执行单元被占用,但算术逻辑单元ARM(ALU)和桶形移位器可能空闲。

这时就可以利用它们来完成基地址寄存器的加法。

供后续指令使用的偏移操作。

例如:指令LDR  R1,[R2],#4完成R1=*R2和R2+=4这两个操作,这是后索引的一个例子;以及指令 LDR R1, [R2,  #4]!完成两个运算R1 = *(R2 + 4)和R2 +=4  ,这是预索引的一个例子。

管道阻塞的情况可以通过循环扩展以及添加其他操作来改善。

可以展开循环,减少循环指令中跳转指令的比例,从而提高代码效率。

下面用一个内存复制函数来说明ARM。

  void memcopy(char *to, char *from, unsigned int nbytes)  {  while(nbytes--)ARM  *to++ = *from++;  }  很简单为了方便起见,这里假设nbytes是16的ARM倍数(余数的处理省略)。

上面的函数每处理一个字节都要进行一次判断并跳转。

  循环体可以如下扩展:   void memcopy(char *to, char *from, unsigned int nbytes)  {  while(nbytes) {  *to++ = *from++ ;  *to++ = *from++;  *to++ = *from++;  *to++ = *from++;  n字节 - = 4;  }  }  结果,循环体中的指令数量增加,但循环数量减少。

ARM跳转指令的负面影响已经减弱。

利用ARM 7处理器的32位字长特性,  上述代码还可以进一步调整为:   void memcopy(char *to, char *from, unsigned int nbytes)   {  int * p_to = (int *)to;  int *p_from = (int *)from;  while(nbytes) {  *p_to++ = *p_from++;  *p_to++ = *p_from++;   *p_to++ = *p_from++;  *p_to++ = *p_from++;  nbytes - = 16;  }  }  优化后,一个循环可以处理16个字节。

跳转指令对ARM的影响进一步减弱。

不过可以看出,调整后的代码,代码量有所增加。

  内存相关的优化方法  其他与存储相关的操作可以加快程序执行速度,比如使用查表代替计算。

当处理器资源紧张而内存资源相对丰富时,  可以牺牲存储空间来换取运行速度。

例如,当需要频繁计算正弦或余弦函数值时,可以预先计算出函数值并将其放置在内存中以供后续ARM搜索。

充分利用片内ARM芯片中的高速RAM,即ARM芯片中的指令和数据TCM  或L1 RAM和L2 RAM。

处理器对片内RAM的访问速度比对外部RAM的访问速度要快,因此应尽可能将程序转移到片上RAM  。

如果程序太大,无法完全放入片内RAM,可以考虑ARM将最常用的数据或程序段转移到片内RAM  ,以提高程序运行效率。

这就是Cache的概念,它还可以通过优化数据和代码的组织来提高数据和代码的访问效率。

  代码大小优化  精简指令集计算机的一个重要特征是指令长度是固定的。

  这样可以简化指令解码过程,但很容易导致代码大小的增加。

为了避免这个问题,可以考虑采取以下措施来减少程序ARM代码量。

  1)、使用多寄存器操作指令  ARM指令集中的多寄存器操作指令LDM/STM可以加载/存储多个寄存器,这是保存的/  当恢复寄存器组的状态和复制大块数据时,它非常有效。

例如,将寄存器R4~R12和R14的内容保存到堆栈中,总共需要10条STR指令,以及1条STMEA  R13!, {R4 ?? R12,R14}指令也可以达到同样的目的。

节省的指令存储空间是相当可观的。

不过需要注意的是,虽然一条LDM/STM  指令可以替代多条LDR/STR指令,但这并不意味着程序运行速度得到了ARM的提升。

事实上,处理器在执行LDM/STM  指令时,仍然将其拆分成多个单独的LDR/STR指令来执行。

  2)、合理安排变量的顺序  ARM 7处理器要求ARM程序中的32位/16位变量必须是字/半字对齐的,也就是说如果变量的顺序不对齐合理排列,  可能会造成存储空间的浪费。

例如:一个结构体中有四个32位int类型变量i1~i4和四个8位char类型变量c1~  c4,如果根据i1,c1,i2,c2,i3,c3,i4,c4时顺序交错存储时,由于整型变量的对齐方式,位于两个整型变量中间的8位char  变量实际上占用了32位内存,导致存储空间的浪费。

为了避免这种情况,int类型变量和char  类型变量应该按照类似i1,i2,i3,i4,c1,c2,c3,c4的顺序连续存储。

  3)、使用Thumb指令  为了从根本上减少ARM的代码大小,ARM开发了16位Thumb指令集。

Thumb 是 ARM 架构的扩展。

Thumb   指令集是最常用的 32 位 ARM 指令压缩为 16 位宽指令的集合。

在执行时,16 位指令会透明地实时解压缩为 32 位 ARM   指令,不会造成任何性能损失。

而且,程序在Thumb状态和ARM状态之间切换的开销为零。

与等效的 32 位 ARM 代码相比,Thumb 代码可节省高达 35% 的内存空间。

  以上就是今天分享的如何针对嵌入式平台优化C代码。

如何优化嵌入式平台ARM的C代码

站长声明

版权声明:本文内容由互联网用户自发贡献,本站不拥有所有权,不承担相关法律责任。如果发现本站有涉嫌抄袭的内容,欢迎发送邮件 举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。

标签:

相关文章

  • 数字服务商“冰鲸科技”完成千万融资,云时光资本

    数字服务商“冰鲸科技”完成千万融资,云时光资本

    投资社区(ID:pedaily)领投 2月22日消息,近日,家庭级数字资产管理协作服务商“冰鲸科技”完成” ”完成数千万元Pre-A轮融资。 本轮融资由云石资本领投,上轮投资人奇绩创坛也参与投资。 Minerva Capital 继续担任长期独家投资者。 本轮融资将用于供应链投资、产品研发和市

    06-17

  • 紫光展锐发布新产品品牌“虎贲”、“常春藤”

    紫光展锐发布新产品品牌“虎贲”、“常春藤”

    2020年9月19日 /美通社/ -- 9月19日,由南京江北新区政府主办,紫光展锐集团、紫光展锐承办的“中国芯片发展高峰论坛上,以“芯时代共成长”为主题,紫光展锐正式推出“虎贲”、“常春藤”两大产品线品牌。 这意味着,今年6月完成品牌整合后,紫光展锐开始加速中高端产品线布

    06-06

  • WeIntell完成数千万元A轮融资,腾讯、京东共同投资

    WeIntell完成数千万元A轮融资,腾讯、京东共同投资

    据投资界3月8日消息,WeIntell今日宣布完成数千万元A轮融资,由腾讯和京东联合投资。 据悉,本轮融资将用于团队扩充和大数据智能产品研发,并深化营销和供应链端的产品和服务。   Microwire成立于2007年,是基于数据智能的智慧零售全场景SaaS平台。 微汇创始人王志国拥有十

    06-17

  • 专注中国细胞培养核心,「Ekosage Bio」完成近亿元B++轮战略融资

    专注中国细胞培养核心,「Ekosage Bio」完成近亿元B++轮战略融资

    据投资界(ID:pedaily)5月10日消息,继完成B+轮融资后,融资数亿元 今年1月,苏州艺圣生物科技有限公司(简称“艺圣生物”)近日正式完成近亿元B++轮战略融资。 本次融资的参与机构包括Puenzerui、Gimpo Muhe、农银国际和深投控资本。 多维资本担任本轮融资独家投资方。 募

    06-18

  • 特朗普隔空喊话他不要的无人水下航行器是什么?

    特朗普隔空喊话他不要的无人水下航行器是什么?

    12月16日,美国国防部官员表示,中国海军在南海捕获了一艘美国水下无人潜艇。 中国国防部回应称,为防止不明装置危及过往舰艇航行安全和人员安全,中国海军一艘救生艇对该装置进行了识别验证,并将通过适当的手段。 然而,一向推崇推特治国政策的特朗普却发文:我们不要这艘潜

    06-18

  • PCIM Asia 2018——上海国际功率元件及可再生能源管理展览会圆满落幕,知名企业鼎力支持

    PCIM Asia 2018——上海国际功率元件及可再生能源管理展览会圆满落幕,知名企业鼎力支持

    依托电力电子行业众多知名企业的鼎力支持和信赖,PCIM Asia——上海国际电力元件、可再生能源管理展能源管理展继续成为行业专家和决策者聚集和交流行业先进知识的中心。 与展会同期举办的PCIM Asia国际研讨会也持续推动中国电力电子行业的发展。 第十七届PCIM Asia上海国际功

    06-06

  • 苏州高新区与苏州基金设立100亿元集成电路产业母基金

    苏州高新区与苏州基金设立100亿元集成电路产业母基金

    创头条获悉,苏州高新集成电路产业发展有限公司日前正式揭牌。 同时,总规模1亿元的苏州高新区集成电路产业基金成立。 据悉,苏州高新区集成电路产业母基金由苏州高新区和苏州基金共同发起设立。 基金总规模1亿元,首期10亿元。 在集成电路产业中市场空间大,具有行业引领作用

    06-17

  • 据悉,台积电等芯片代工厂将降价20%

    据悉,台积电等芯片代工厂将降价20%

    据台湾媒体报道,业内人士透露,中国大陆和台湾几大芯片代工厂,包括联华电子(UMC)和台积电(SMIC) 、先锋国际半导体(VIS)、华虹半导体和力晶科技有限公司已开始下调代工报价,以吸引更多订单来填补今年第一季度的工厂产能。 消息人士指出,半导体供应链库存水平高于预期

    06-06

  • 轻喜之家完成数千万元A+轮融资

    轻喜之家完成数千万元A+轮融资

    据投资界8月10日消息,据36氪报道,家居服务品牌轻喜之家近日完成数千万元A+轮融资< titlesplit > A+轮融资。 轻喜之家创始人王有峰透露,本轮融资将主要用于建设专业培训基地——轻喜国际家政培训,并建设信息管理系统,提高轻喜之家的服务水平和专业品质。 和用户交互体验

    06-18

  • 中国宝武发起设立碳中和主题基金,总规模500亿元

    中国宝武发起设立碳中和主题基金,总规模500亿元

    投资界(ID:pedaily)7月15日报道,中国宝武携手国家绿色发展基金有限公司,中国太平洋保险(集团)股份有限公司与建信金融资产投资有限公司联合发起宝武碳中和股权投资基金,15日在上海签约成立,总规模1亿元,首期1亿元人民币。 据了解,宝武碳中和股权投资基金未来将重点

    06-18

  • 4700万对夫妇的背后,这首曲目火了

    4700万对夫妇的背后,这首曲目火了

    三胎时代,辅助生殖火了。 最新融资的是辅助生殖品牌韦拓生物,刚刚完成1亿元C轮融资。 由中金资本旗下中金启辰基金领投,张科禾润、向融资本跟投。 令人惊讶的是,这是韦拓生物今年的第二轮融资。 调查发现,今年至少有5家辅助生殖公司完成融资——韦拓生物、女娲生命、何万

    06-18

  • AI新趋势:AI将能够以240倍的速度创建自己的AI

    AI新趋势:AI将能够以240倍的速度创建自己的AI

    雷锋网注:【图片来源:IEEE所有者:iStockphoto】自2016年以来,研究人员一直在使用AI神经网络来帮助设计更好更快人工智能神经网络。 迄今为止,该应用程序主要是学术研究,主要是因为该方法需要数万个 GPU 小时。 然而,下个月,麻省理工学院 (MIT) 的一组研究人员将展示一

    06-18