4

我有一些嵌入式代码将命令写入内存地址以控制外围设备,如下所示:

void intelStartEraseBlock(uint16_t *wordAddress) {
  *wordAddress =  0x20;  //block erase
  *wordAddress =  0xD0;  //block erase confirm
}

我怀疑优化器正在跳过第一个分配。这是 volatile 的工作吗?还是有更好的解决方案...

注意:这是遗留的 api 代码,所以我不打算重构太多。我在这里寻找“本地”修复。

4

3 回答 3

10

这正是创建 volatile 关键字的原因。这是其用法的经典例子。

于 2012-07-05T22:36:45.323 回答
6

是的,只需声明wordAddress为指向volatile数据的指针:

void intelStartEraseBlock(volatile uint16_t *wordAddress) {
   ...
}

关键字告诉编译器volatile语义必须与 C 语言指定的抽象虚拟机相匹配——换句话说,每次写入volatile变量时,代码都必须实际写入内存,每次读取时从volatile变量中,代码必须实际从内存中读取。

不允许编译器优化这些读取和写入,即使它认为它们是多余的。

请注意,声明的必须是指向的数据volatile,而不是指针本身。就像const关键字一样,它有很大的不同。由于wordAddress它本身是堆栈上的一个变量,我们并不关心它的读/写实际上是否会进入堆栈内存,但我们确实关心它指向的内存(可能是某种类型的内存映射 I/O)实际上是读/写的。

于 2012-07-05T22:40:54.303 回答
2

除非您的操作系统提供了一些其他机制来执行此类操作,否则是的,volatile 是一个很好的解决方案。

void intelStartEraseBlock(volatile uint16_t *wordAddress) {
  *wordAddress =  0x20;  //block erase
  *wordAddress =  0xD0;  //block erase confirm
}
于 2012-07-05T22:39:42.717 回答