- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
跳不出的while循环pdf
跳不出的 while 循环
问题:
该问题由某客户提出,发生在 STM32F103VBT6 器件上。据其工程师讲述:在为 STM32 调试软件过程
中,遇到了一个怪现象:有如表(一)所示的一段程序中,KeyIn 是一个全局变量。当有按键按下
时,键盘的中断服务程序会将对应的键值放入其中,当按键释放后,键盘中断服务程序则把 RESET 值
放入该变量。行(1)的条件语句在主程序中,检测有无按键按下,并处理。行(2)则是等待按键释
放。调试时,在行(1)和行(2)处各设置一个断点,然后全速运行程序。当程序停在行(1)时按下
按键,继续全速运行程序。当程序停在行(2)时,放开按键,继续全速运行程序。这时,发现程序没
有向下执行,而是依然回到并停留在行(2)处。打开观察窗口,观察变量KeyIn 的值,确认其值为
RESET。再次起动全速运行,程序依然回到行(2),而不是向下执行。
调研:
检查其软件工程,确认其所使用的工具链为 IAR Embedded Workbench IDE 5.3,工程设置中的优化等
级为 High+Balanced。重复测试,确认现象如其所述。使用反汇编窗口检查编译器生成的指令,如图
(一)所示:
从图(一)中得知,由语句 while(KeyIn != RESET) 生成的指令位于地址区间 0x800032C-
0x8000330,共有 3 条。其中,指令 LDR R1,[R0]负责将变量 KeyIn 的值装载到寄存器 R1 中,指
令 CMP R1,#0 对该值进行检测,而跳转指令 BNE.N ??main_1 则是实现循环。进一步观察,发现 3
条指令中,只有后两条参与了循环,而指令 LDR 只执行一次,不参与循环。于是可以得出这样的结
论:如果在执行该循环语句的第一次循环时变量 KeyIn 的值非 0,那么装载到寄存器 R1 中的值就非
0,于是比较结果为“不相等”,从而进入下一次循环。由于从第二次开始,执行该循环时不更新寄存
器 R1 的值,所以无论变量 KeyIn 的取值如何,比较的结果都是“不相等”,都会再次进入下一次循
环。于是,一个无休止的循环诞生了。
将工程的优化选项更改为 High+Size,重新编译并观察反汇编结果,如图(二)所示:
这次由语句 while(KeyIn != RESET) 生成的指令变为 4 条,而且在每次循环中都重新向寄存器中装
载变量 KeyIn 的值。从实际执行的效果上看,符合源代码所描述的逻辑。
将工程的优化选项改回到 High+Balanced 模式,并修改源程序,将变量 KeyIn 定义成 volatile 型变
量,如表(二)所示:
重新编译并观察反汇编的结果,如图(三)所示:
这种情况下,语句 while(KeyIn != RESET) 生成的指令为 3 条,但每次循环都重新装载变量 KeyIn
的值到寄存器。测试其执行效果,符合源代码所描述的逻辑。
结论:
通过以上的测试可以得知,该问题是由于编译器对 C 语言代码进行高度的优化时,对某
些语句解析错误造成的。
处理:
将变量 KeyIn 定义成 volatile 型变量,如表(二)所示。
建议:
既然这是一种由编译器的编译错误造成的问题,可否期待新版本的编译器为我们加以改正?非常不幸
的是编译器真的很难做到这一点!更不幸的是几乎所有的编译器都有类似的问题!因为,在引用多个
变量做循环处理时,如果对每个变量在每次循环中都重新装载,势必大大的降低代码的效率,根本谈
不上优化。而编译器又无从分辨出哪些变量有可能发生改变,于是,只好认为只要在本循环中没有对
其更改的变量就不会发生变化。所以,不能寄期望于编译器为我们解决这类问题。但这一问题还是要
解决的,特别是基于多任务操作系的软件,其中有大量的变量由多个任务共享,如果发生此类问题将
导致严重的错误。如何解决?有一个关键的切入点,就是:虽然编译器分辨不出哪些变量有可有发生
改变,但是软件的设计者却是知道的。这样,完全可以通过某种方式告诉编译器,哪些变量有可以发
生改变,或者通过一些手段迫使编译器对某个变量重新装载。将变量定义成 volatile 型变量,是告
知编译器该变量有可以发生改变的一种方法。通常,外设的寄存器都定义成 volatile 型变量,因为
这些变量的值有可能被硬件改变。定义成 volatile 型的变量在使用时往往不如普通的变量方便,因
为要考虑对其读写的次序问题。比如表(三)所示的程序,编译器在对其编译的时候,会毫不客气的
给出的警告:
可以人为的为这些变量设定读写次序,而避免产生相关的警告。如表(四)所示:
从表(四)中可以看出,定义这个
您可能关注的文档
最近下载
- 2024年第十六届全国大学生数学竞赛初赛试卷及参考答案(非数学B类).pdf VIP
- 自考本科《小学综合性学习与跨学科教学》2025年4月模拟题附答案.docx VIP
- 高校教师培训教学设计模板.docx VIP
- 《野外辨别方向》课件.ppt VIP
- 2024年第十六届全国大学生数学竞赛初赛试卷及参考答案(非数学A类).pdf VIP
- 医务人员职业防护.ppt VIP
- 第42届全国中学生物理竞赛复赛试题.docx VIP
- 万科示范区验收移交指引.docx VIP
- 唐代僧人的法律规范-政大机构典藏.PDF
- 2025-2026学年高二地理上学期第一次月考卷5【测试范围:选择性必修一,第1~2章第1节】(原卷及解析).docx VIP
文档评论(0)