MDK编译优化笔记
在一次使用MDk的编译优化等级比较高的时候发现编译不优化时功能正常,开了优化等级02就出现异常,调试中看了很多博客总结一下。
- 一个变量,如果你的主程序要用到,同时中断还要用到,要加volatile修饰。告诉编译器这个变量是可能随时发生变化的,使得编译器编译程序的时候,每次都从RAM里面读取数据,而不是使用之前缓存到寄存器里面的值。
- 对于多任务的程序,如果一个公共变量被多个任务用到也要加volatile修饰。
- 同时变量定义的时候用了关键字volatile修饰,但是在其他文件引用时不加volatile变量修饰一样会被编译器优化掉。现则反过来想想,原因还是很简单的,MDK编译多个文件时是分别编译,最后再用链接器链接,当编译的时候一个模块引用另外一个模块的变量,完全是靠的变量声明,如果声明都不加volatile,那么引用的模块肯定会把变量当成普通变量的,再反推一下,如果原变量没有加volatile,但是声明的时候加了volatile,是不是引用的模块会将这个变量当成volatile型变量呢
C编译器是以每个C文件作为基本编译单元的,称为模块,被编译为obj;而模块之间的函数或变量访问都是通过标号来实现的,标号本身没有任何属性,只是提供给链接器使用的一个符号名称而已,标号的属性完全就靠调用的地方的原型声明来决定的!因此,你在一个.C模块中定义为volatile,仅仅是在.C模块中告诉编译器不要优化而已,在另外的模块内使用了这个变量,而它们是不知道该变量是什么属性的,所以只有靠原型声明来告诉编译器这些信息了。
最后简单的给总结一下:别小看原型声明,它是联系各个模块的桥梁,是各种输出符号的属性信息所在。编译原理不懂就是比较亏啊。。。
最后补充一下MDK中关于编译的一些选项说明:
USE Cross-Module Optimization
跨模块优化从先前的构建中获取信息,并使用它将UNUSED函数放入其中在相应的目标文件中拥有自己的ELF部分。 此选项也称为链接器反馈,需要构建程序两次以利用它来减少代码大小。
USE MicroLIBMicroLIB
是一个针对嵌入式平台优化过的C库可以减少应用程序的大小。他是标准C库的一个子集,以提供功能和代码大小之间的权衡,比如一些标准C库的memcpy函数应用到微控制器上就运行速度来说比较慢。原文(Some of the standard C library functions such as memcpy() are slower, while some features of the default library are not supported.)这里还说默认的库还不支持一些特性:
包括:
- 操作系统功能,例如 abort(),exit(),time(),system(),getenv()
- 宽字符和多字节支持,例如 mbtowc(),wctomb()
- stdio文件I/O函数,stdin,stdout和stderr除外
- 位置无关且线程安全的代码
Link-Time Code Generation(这个选项新版好像没有了)
链接时代码生成指示编译器以中间格式创建对象,以便链接器可以执行进一步的代码优化。 这使代码生成器可以同时查看所有对象的跨文件依赖性,从而允许它应用更高级别的优化。 链接时代码生成可以减少代码大小,并使您的应用程序运行得更快。
Optimization Levels
不同的优化级别允许您在级别之间进行权衡已编译代码中可用的调试信息以及代码的性能。以下优化级别可用:
-O0应用最小优化。
大多数优化都被关闭,生成的代码具有最佳的调试视图。
-O1应用受限优化。
例如,删除未使用的内联函数和未使用的静态函数。在这个优化级别,编译器还应用自动优化,例如删除冗余代码和重新排序指令以避免互锁情况。生成的代码经过合理优化,具有良好的调试视图。
-O2应用高优化(这是默认设置)。
在此级别应用的优化利用了ARM对处理器体系结构的深入了解,利用给定目标的特定于处理器的行为。它生成优化良好的代码,但有限调试视图。
-O3应用最积极的优化。
优化符合用户的-Ospace / -Otime选择。默认情况下,多文件编译是启用,这会导致更长的编译时间,但会提供最高级别的优化。
Optimize for Time
“优化时间”复选框使编译器进行优化,更加注重实现最佳效果检查时的性能(-Otime)或未选中时的最小代码大小(-Ospace)。
取消选中Optimize for Time就意味着选择-Ospace选项,该选项指示编译器执行优化以可能增加的执行时间为代价来减小Image文件大小。例如,使用非内联函数调用而不是大型结构副本的内联代码。 这是默认选项。从中运行编译器时命令行,使用'-Ospace'调用此选项选中Optimize for -Otime选项,该选项指示编译器以最快的速度优化代码执行时间,有可能增加image文件大小。建议编译时间关键部分您的代码使用-Otime,其余使用-Ospace指令。
Split Load and Store Multiples
指示编译器将涉及大量寄存器的LDM和STM指令拆分为一系列较少多个寄存器的加载/存储。这意味着16个寄存器的LDM可以分成4个独立的LDM,每个LDM由4个寄存器组成。此选项有助于减少没有缓存或写缓冲区的ARM系统上的中断延迟,以及使用零等待状态32位内存的系统。
例如,ARM7和ARM9处理器只能在指令边界上执行异常。如果在无缓存的ARM7和ARM9系统中的16个寄存器的LDM开始时发生异常,则系统将在获取异常之前完成对存储器的16次访问。根据存储器仲裁系统,这可能导致非常高的中断延迟。将LDM拆分为4个寄存器的4个独立LDM意味着处理器在加载最多4个寄存器后将采用异常,从而大大减少中断延迟。选择此选项可提高系统的整体性能。
One ELF Section per Function
选项告诉编译器将所有函数放入它们各自的ELF部分。 这允许链接器删除未使用的函数.ELF代码部分通常包含许多函数的代码。 链接器通常只能删除未使用的ELF部分,而不是未使用的函数。 只有当所有内容都未使用时,才能删除ELF部分。因此,将每个函数拆分为自己的ELF部分允许编译器轻松识别哪些未使用,并将其删除。选择此选项会增加编译代码所需的时间,但可以提高性能。
常见优化目标选项
最小的目标代码:
选中
• The MicroLIB C library
• Cross-module optimization
• Optimization level 2 (-O2)
最好的代码表现性能:
选中
• Cross-module optimization
• Optimization level 3 (-O3)
• Optimize for time
最后总结一句话,只要代码逻辑够严密无论是多高的编译优化等级都是不会出问题的,所以在资源不是出现了必须要优化的时候不建议优化代码,自己增加实现难度而已,反之如果你追求功能的稳定可以在优化等级下发现0级优化下存在的问题进行完善在改回0级优化编译此时代码的逻辑漏洞会减少。
MDK编译优化笔记的更多相关文章
- 15个问题自查你真的了解java编译优化吗?
摘要:为什么C++的编译速度会比java慢很多?二者运行程序的速度差异在哪? 了解了java的早期和晚期过程,就能理解这个问题了. 本文分享自华为云社区<你真的了解java编译优化吗?15个问题 ...
- MDK的优化应用
MDK的优化应用 http://blog.163.com/zhaojun_xf/blog/static/300505802011291384721/ 使用Keil/MDK这么多年了,一直都没有使用它的 ...
- MDK的优化应用(转)
源:http://blog.163.com/zhaojun_xf/blog/static/300505802011291384721/ 使用Keil/MDK这么多年了,一直都没有使用它的代码优化功能. ...
- U3D开发性能优化笔记(待增加版本.x)
http://blog.csdn.net/kaitiren/article/details/45071997 此总结由自己经验及网上收集整理优化内容 包括: .代码方面: .函数使用方面: .ui注意 ...
- GCC 编译优化指南(转)
GCC 编译优化指南(转) http://www.jinbuguo.com/linux/optimize_guide.html 作者:金步国 版权声明 本文作者是一位开源理念的坚定支持者,所以本文虽然 ...
- 关于java字符串编译优化问题
情景一:不好的字符串拼接习惯 起因是这样的:一个大牛在写了一篇关于java字符串优化问题的讲解,他提到:不要使用strObj+otherValue的方法将otherValue转换为字符串形式,因 ...
- GCC 编译优化指南
转自: http://www.jinbuguo.com/linux/optimize_guide.html GCC 编译优化指南 作者:金步国[www.jinbuguo.com] 版权声明 本文作者是 ...
- Android App性能优化笔记之一:性能优化是什么及为什么?
By Long Luo 周星驰的电影<功夫>里面借火云邪神之口说出了一句至理名言:“天下武功,唯快不破”. 在移动互联网时代,同样如此,留给一个公司的窗口往往只有很短的时间,如何把握住 ...
- GCC编译优化指南【作者:金步国】
GCC编译优化指南[作者:金步国] GCC编译优化指南 作者:金步国 版权声明 本文作者是一位自由软件爱好者,所以本文虽然不是软件,但是本着 GPL 的精神发布.任何人都可以自由使用.转载.复制和再分 ...
随机推荐
- qtdomdocument找不到
- 11.web5
先补充点小知识: 关于jjencode 和 aaencode(颜文字) 1.什么是jjencode? 将JS代码转换成只有符号的字符串 2.什么是aaencode? 将JS代码转换成常用的网络表情 ...
- 手摸手教你bootstrap定制
老实说我一直不太喜欢使用bootstrap,bootstrap样式组件虽然丰富但实际开发使用到的不多:栅格系统虽然好用,满屏div也是看的头疼:所以当经理说要用bootstrap开发新项目的时候,我内 ...
- IT兄弟连 Java语法教程 数组 数组的使用
数组最常用的用法就是访问数组元素,包括对数组元素进行赋值和取出数组元素的值.访问数组元素都是通过在数组引用变量后紧跟一个方括号([]),方括号里是数组元素的索引值,这样就可以访问数组元素了.访问到数组 ...
- MySQL属性SQL_MODE学习笔记
最近在学习<MySQL技术内幕:SQL编程>并做了笔记,本博客是一篇笔记类型博客,分享出来,方便自己以后复习,也可以帮助其他人 SQL_MODE:MySQL特有的一个属性,用途很广,可以通 ...
- 使用configparser模块进行封装,构造配置文件处理器
from configparser import ConfigParser class HandleConfig: ''' 定义一个配置文件处理类 ''' def __init__(self, fil ...
- 拎壶学python3-----(1)输出与字符转换
一.输入自己的名字打印 二.数字和字符串是不能相加的如下 怎么解决上边的问题呢? 如果是相加我们要把字符串转成数字类型如下 如果不想让他相加可以写成这样如下: ok,关于转换就先讲到这里
- keras对图像数据进行增强 | keras data augmentation
本文首发于个人博客https://kezunlin.me/post/8db507ff/,欢迎阅读最新内容! keras data augmentation Guide code # import th ...
- Spring Boot 中如何支持异步方法
本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...
- selenium设置user-agent以及对于是否是浏览器内核进行反爬
(Session info: chrome=75.0.3770.90),不同版本方法可能会有些不同 推荐查资料网站必应可以避开一堆广告 一.user-agent设置 from selenium imp ...