我的代码是用 C 编写的。我有一个 ISR(中断服务例程),它使用全局变量与主代码进行通信。ISR 与主代码位于不同的编译单元中。有什么理由我不能对主代码使用“易失性”,而是将其留在 ISR 中吗?
我的推理如下: volatile 限定符阻止编译器完全优化 ISR。从 ISR 的角度来看,该变量不是易失的 - 即在 ISR 期间它不能被外部更改,并且在 ISR 期间不需要输出值。此外,如果 ISR 在其自己的编译单元中,编译器必须让 ISR 在第一次使用之前从内存中读取全局,并且必须在返回之前将更改存储回来。我的理由是:不需要同时编译不同的编译单元,因此编译器不知道 ISR 范围之外发生了什么(或者它应该假装),因此它必须确保读取全局/写在 ISR 的边界。
也许,我误解了编译单元的意义?我发现的一个参考资料说 GCC 使这种易失性不匹配成为编译时错误;我不确定它怎么可能,如果它们在不同的编译单元中,它们不应该是独立的吗?我可以不单独编译库函数并稍后链接它吗?
也许可以从序列点的概念提出一个论据。我不完全理解序列点或副作用的概念;但是,C99 规范在 5.1.2.3 第 2 段中指出:“......在称为序列点的执行序列中的某些指定点处,先前评估的所有副作用都应是完整的,并且不应发生后续评估的副作用。 "
附件 C,列出了包括以下内容的序列点:
- 在评估参数之后对函数的调用。
- 紧接在库函数返回之前。
参考:WG14 文件:N1013,日期:2003 年 5 月 7 日
注意:上一个问题,相对于函数调用和返回的全局变量访问询问是否在函数调用和返回之前/之后存储/写入全局变量。但这是一个不同的问题,它询问全局变量在不同的编译单元中是否可能被不同地限定为“易失性”。我使用了很多相同的推理来证明我的初步结论是正确的,这促使一些读者认为这是同一个问题。