编译器执行顺序

compiler execution sequence

我正在用C语言编写一个微控制器,我遇到过以下情况:对于enable/disable内部时钟发生器,我需要先写一个保护密钥到一个特定的寄存器,然后制作enable/disable操作,写入另一个寄存器。 用户手册对此操作指定以下内容: snip from user manual

正如您在文本中突出显示的部分所看到的,进行这两个操作(写保护密钥和启用振荡器)的代码非常敏感,因为任何操作都应该在这两个寄存器访问之间执行.因此,我开始担心可能导致这两个操作的非顺序执行的任何情况。 我知道在执行敏感代码时临时禁用中断是很常见的,但我想知道是否有任何编译器优化可以在这两个寄存器访问之间插入另一个操作。那么,在C编程中,有什么编译器指令可以保证它不会发生吗?

实际上,我什至不知道认为编译器会混合用C语言编写的指令序列是否有意义。我记得已经听说在速度优化过程中有时会发生这种情况。如果我错了,请提前致歉并感谢您的澄清。

C 中切换位的过程涉及读取-修改-写入指令序列。 这些指令之间可能会发生一些不需要的操作,通常的方法是禁用中断或使用位带。

什么是位带,它允许您使用一条指令切换位(无需详细说明它是如何发生的)。

如果您的微控制器允许您使用位带,那么这应该可以解决您的所有问题。

如果你不能使用bit-banding,那你就得坐下来想一想哪些中断可能会给你带来问题并暂时禁用它们。

回到问题的核心——您必须将所有寄存器声明为易变的,主要原因有两个:

  1. 不同于仅由程序自身修改的普通内存,存储在这些内存映射寄存器中的值可以随时更改,编译器将做的只是优化掉所有对寄存器的读写。 Volatile 阻止 this.By 声明变量 volatile,您实际上是在要求编译器在读取或写入该变量时尽可能低效。具体来说,编译器应该生成代码来执行每次从 volatile 变量读取以及每次写入 volatile 变量,即使您连续写入两次或读取它并忽略结果也是如此。不能跳过任何一次读取或写入。换句话说,不允许针对 volatile 变量进行编译器优化。
  2. 简而言之,目标代码中volatile变量A和B的访问顺序必须与源代码中的访问顺序相同。不允许编译器出于任何原因重新排序 volatile 变量访问。 (考虑一下如果引用的内存位置是像本例中那样的硬件寄存器,可能会出现什么问题)。 Volatile 保证一切都按照您在代码中指定的顺序发生,并且不会进行重新排序。

总结一下 - 使用位带并声明寄存器为易失性。