zoukankan      html  css  js  c++  java
  • 在ADS上由于volatile惹得祸

      C语言关键字volatile是一个危险的东东,笔者再用ADS做S3C2440定时器中断实验就因为这个关键字出了错。出现错误情况的准确描述是:定义一个变量时没有用volatile关键字,而且紧接着while(1)循环里边就有对这个变量的读操作。

       这个实验想实现的功能是:定时时间为1s,用一个led灯显示这个时间,亮一秒钟,然后再灭一秒钟。程序实现思路是:开irq中断,开定时器0中断,并设置定时器0中断时间为1s;在中断服务程序中利用一个全局变量flag来传递定时时间到信号,每中断一次flag翻转一次;主循环中读取flag标志,根据flag标志决定led灯的亮灭。

    中断服务程序

    void __irq Timer0_Isr(void)
    {
        flag=!flag;
        rSRCPND|=1<<10;
        rINTPND|=1<<10;    
    }

    flag定义在主程序中

    unsigned int flag=0;

    主循环程序

    int Main()
    {
        IO_Init();
        while(1){
            if(flag){
                Led1_Off();
            }
            else{
                Led1_On();     
            }
        }
       return(0);
    }

        经测试定时1s,中断服务程序都是能正常工作的,但是led不能闪烁,一直亮。试了很多办法,无果。

        后来将变量的定义更改了一下,加一个关键字volatile。就解决了问题。但是,什么原因不得而知。

    volatile unsigned int flag=0;

        走投无路的情况下,只能求助于反汇编代码。

    对比源程序

    对比反汇编(图片太大,网页浏览时无法完全显示,可以对着图片单击右键,选择图片另存为桌面查看)

        看到反汇编代码,很容易知道错误出现在哪儿。没加volatile时候,执行while循环需要重新读取flag的值时,不是从flag对应的内存单元中读的,而是读取保存flag临时数据的r2。虽然中断服务程序会将flag值更改,但是由于读取的是r2而且r2在主循环中始终不变,也就是说不能读到中断服务程序对flag的更新,所以led灯也不可能改变。

        当加了volatile后,执行while循环需要重新读取flag的值时,是从flag对应的内存单元中读的,所以主循环能读到中断服务程序对flag的更新,led也能正常工作了。

    结论:ADS对加没加volatile的变量处理是有区别的,但是我认为ADS对这种情况的处理不是很正确

        之所以这样说,我源于下面三个实验。我用keil和gcc分别作了类似上边的实验,看编译器对没有加volatile的变量处理情况,发现这两个编译器都能正确编译,而唯独ADS对没有加volatile的变量处理的过分。

    keil对没有加volatile的变量处理

    测试程序

    反汇编代码

    gcc对没有加volatile的变量处理

    第三个实验,在 if(flag) 前边加一个delay_time()函数,发现能够正常工作

     试想,ADS仅仅因为在 if(flag)前边加了一个delay()函数,就更改了它的策略,我真觉得ADS对这种情况(定义一个变量时没有用volatile关键字,而且紧接着while(1)循环里边就有对这个变量的读操作)处理的有问题。而且,我认为编译器对volatile的处理好像也不是这样的。我对ADS的编译还存在疑惑,我对编译器对volatile的处理还存在疑惑。

    附实验源码下载地址:timeirq.zip

  • 相关阅读:
    petshop4.0(转)
    分层依据(转)
    如何让一个函数返回多个值
    谁访问过我的电脑
    博客第一帖!
    开发辅助工具大收集
    VC 通过IHTMLINTEFACE 接口实现网页执行自定义js代码
    vi命令大全
    #include <sys/types.h>
    #include <arpa/inet.h>
  • 原文地址:https://www.cnblogs.com/amanlikethis/p/3433701.html
Copyright © 2011-2022 走看看