打印

看原子的开发板的程序也是volatile的问题

[复制链接]
408|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
第8号打板工|  楼主 | 2020-4-26 15:02 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
这个很重要,有时候你程序莫名其妙的问题都是这个导致的。
我在做外置sram实验的时候没有注意,导致从sram里面出来的数据和写进去的不一样,像sram芯片有坏块一样。

//读LCD数据

//返回值:读到的值

u16 LCD_RD_DATA(void)

{

        vu16 ram;                        //防止被优化

        ram=LCD->LCD_RAM;        

        return ram;         

}                                       

像这种的代码,明显的问题,自己都写了开了高等级优化选项会被优化掉。

正确的写法是

u16 LCD_RD_DATA(void)

{

        volatile u16 ram=LCD->LCD_RAM;//或者__IO u16 ram=LCD->LCD_RAM;

        return ram;         

}               

地址操作的时候也是这样,像下面这个正确应该这么写

typedef struct

{

volatile u16 LCD_REG;

volatile u16 LCD_RAM;

} LCD_TypeDef;

//使用NOR/SRAM的 Bank1.sector4,地址位HADDR[27,26]=11 A18作为数据命令区分线

//注意设置时STM32内部会右移一位对其!                             

#define LCD_BASE        ((u32)(0x60000000 | 0x0007FFFE))

#define LCD             ((volatile LCD_TypeDef *) LCD_BASE)



vu16 其实就是typedef __IO uint16_t vu16;  已经给你加了volatile。#define     __IO    volatile

还有就是在sdram里面的变量,外设寄存器的变量,中断中改变的变量都要加。

如果你-o0的情况下正常的程序,一开-o3就不正常了,那一般都是volatile这个问题。



原因:

编译器会优化代码的

比如你往一个地址写个数值,后面的程序没有去读他。或者你从一个地址读,但是前面没有往这个地址写东西。编译器都会认为你这个读写操作是无用的操作,直接给你优化掉。

加了volatile就是告诉编译器,每次都必须去读写这个变量。

其他的道理都一样,你程序流程里没有明确改变的变量,编译器都可能不生成掉读他或者写他的代码。所以在你程序流程外有可能改变的变量都要加volatile。比如中断里面改变的变量。

修改寄存器也是一样的,你写了个数值到外设寄存器里面,后面又没有读他。编译器认为你这个写操作没有意义,无效代码,直接给你省略掉了。所以你看人家库里面的寄存器地址都是带volatile。
编译器这个逻辑其实很正常。比如你建立了一个全局变量,但是你的程序根本没有用他,那为了节省内存当然是不建立这个变量。你往一个地址写数据后面又从来没有用过他,编译器当然认为这个写操作是可以省略掉的。

使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

393

主题

393

帖子

0

粉丝