中断过程中,一个容易忽略的错误
2016-06-05 09:05
204 查看
这是两年前开发的一个产品,一项功能是在通电后播放40秒的语音. 测试时发现,大约通电70-80次就有一次播放时间不够40秒就提前停止。 当时以为复位有问题,换了复位片,没好。又先后换了CPU,语音芯片,还有电源,都没有好转。排除了硬件芯片原因导致的此现象. 后来又从软件中查找原因。反复查找软件逻辑,也没发现问题。后来偶然发现在主while里增加大量延时后,稳定性提高。 几乎不再出现问题。但是我还是觉得不对劲,用了两天时间终于找到了原因。因为这是公司的程序,所以不能贴源码。 我把其他程序都略去,只把出错的程序大概写一下。大家看看能找到问题吗? unsigned int ms_counter; void T0() { //定时器程序每100毫秒中断一次,程序略 if (ms_counter<1000) ms_counter++; } void main(void) { //初始化定时器程序每100毫秒中断一次,程序略 unsigned char tt; ms_counter=0; tt=0;//用tt控制只响一次 while(1) { if (ms_counter<400) { if (tt==0) { tt=1; Sound_on(); } } else { Sound_off(); } //其他程序 //。。。。。。 } } 高手们不要笑,菜鸟们坐好 问题出在ms_counter不到400时,程序提前执行了Sound_off(); 原因分析:if (ms_counter<400)中的ms_counter是两字节的整型,而且在中断里有增一操作。 这就有一种错误的可能 if (ms_counter<400) //被编译器翻译成以下语句 +0000007C: E9E0 LDI R30,0x90 Load immediate +0000007D: E0F1 LDI R31,0x01 Load immediate +0000007E: 164E CP R4,R30 Compare +0000007F: 065F CPC R5,R31 Compare with carry +00000080: F428 BRCC +0x05 Branch if carry cleared 在ms_counter==255时 R4是255 R5是0 CP R4,R30 ;这时R4是255 注意!如果在这两条语句中间产生了中断 ms_counter增一 以后 R4是0 R5是1 CPC R5,R31 ;这时R5是1 简单的说是由于在整型数增一进位的时候,又受到中断的影响。 本来正确值 0x00ff或0x0100(ms_counter), 实际错误值 0x01ff(ms_counter) 先判断低位时低位是FF,中断后判断高位时高位是01 ms_counter在255时被误认为511(0x01ff)导致提示音提前关闭。 这是一大类故障,由于中断造成的操作数更改。在其他的数据类型或编译器中也可能出现,虽然出现的机率不大,但影响是不可预知的,也是更容易忽视的。 哈哈!提醒一下没学过汇编的朋友。用C写一条语句,实际是几条汇編语句。在语句中间是有可能产生中断的。 if (ms_counter<400) //这是好几条汇编 ms_counter++; //这是好几条汇编 ms_counter=45; //这是好几条汇编 解决方法:学过操作系统的人都知道,这是互斥访问的概念。 什么是互斥访问?简单来说,一个进程正在使用一组资源(对应到本案例中断里的ms_counter),另一个进程也要使用该资源(对应本案例中主函数对ms_counter进行判断),这时就需要慎重对待了。 设计程序时,脑中时刻要警惕这种互斥访问的问题。 操作系统中对这种问题有一种解决办法,即引入一个与ms_counter相同类 4000 型的临时变量: unsigned int tmp_counter; 在使用ms_counter做判断前先把它的值赋值到临时变量: do { tmp_counter = ms_counter; while (tmp_counter != ms_counter); 然后使用tmp_counter代替ms_counter进行判断,这样可以保证回避楼主所述问题。 本文转自网络。 |
相关文章推荐
- alert中断settimeout计时功能
- php 更新数据库中断的解决方法
- Java线程中断的本质深入理解
- JAVA多线程之中断机制stop()、interrupted()、isInterrupted()
- 详解Java编程中对线程的中断处理
- dos中断表
- 电脑主机板中断定义解释及其常用数语介绍
- Linux 中断
- ARM异常中断初探
- 中断之中断门初始化
- 进程kswapd0与events/0消耗大量CPU的问题
- ARM中的中断向量表
- LM3S 串口收发心得
- 汇编学习历程(int中断学习)
- PSoC中断
- Linux中断(Linux内核设计与实现学习笔记)
- linux kernel的中断子系统之(八):softirq
- 并发编程--线程的中断
- 关于ARM中断的具体的启动代码解释
- Linux 内核中断内幕