gja*_*ain 5 c embedded volatile
以下是在运行Barrelfish操作系统时在Pandaboard上闪烁LED的一些代码.我的问题是,为什么不把LED的闪光灯,如果"挥发"关键字是从的定义中删除gpio_oe和gpio_dataout.
static volatile uint32_t *gpio_oe = (uint32_t *)(GPIO_BASE + 0x0134);
static volatile uint32_t *gpio_dataout = (uint32_t *)(GPIO_BASE + 0x013C);
void led_flash
{
// Enable output
*gpio_oe &= (~(1 << 8));
// Toggle LED on and off till eternity
while(true)
{
*gpio_dataout ^= (1 << 8); // Set means LED on; Clear means LED off
time_delay(); // To give blinking effect
}
}
Run Code Online (Sandbox Code Playgroud)
我知道如果变量的值可以通过程序外的源自发地改变,则需要使用volatile.但我在这里看不到这样的情况.编译器执行什么优化会使整个while循环闪烁LED无意义?这种优化背后的逻辑是什么,即.这种优化有意义的合法案例?
您还需要volatile强制执行内存写入和生成代码访问volatile变量的顺序.对于常规变量,编译器可能会认为写入是不必要的,要么将它们丢弃,要么只保留最后一个.
从注释中移出:如果编译器看不到变量的读取,它可能根本不写任何内容,它甚至可以删除变量.
至于编译器可以告诉,值*gpio_oe和*gpio_dataout被写入,但从来没有读过.对于普通数据存储器,这种访问模式完全是冗余的,因此可以进行优化.类似地,对于读取但从未写入的位置.
对于内存映射I/O,但是对"内存"位置的访问具有编译器不知道的副作用.声明位置volatile告诉编译器必须完全按照代码描述显式访问该位置.
除了内存映射I/O之外,在单独的线程(例如RTOS任务或中断处理程序)之间共享的内存也会出现类似的问题,因为语言同样没有意识到这些上下文.
Embedded.com涵盖了许多文章中的主题: