【发布时间】:2018-05-04 14:37:46
【问题描述】:
我正在用 C 语言编写一个微控制器,我遇到了以下情况:要启用/禁用内部时钟发生器,我需要先将保护密钥写入特定寄存器,然后进行启用/禁用操作,写在另一个寄存器中。 用户手册对此操作指定以下内容: snip from user manual
正如您在文本突出显示的部分中看到的那样,进行这两个操作(写保护键和启用振荡器)的代码非常敏感,因为任何操作都应该在这两个寄存器访问之间执行。因此,我开始关注可能导致这两个操作的非顺序执行的任何情况。 我知道在执行敏感代码时临时禁用中断是很常见的,但我想知道是否有任何编译器优化可以在这两个寄存器访问之间插入另一个操作。那么,在C编程中,有没有什么编译器指令可以保证不会发生呢?
实际上,我什至不知道认为编译器会混合用 C 语言编写的指令序列是否有意义。我记得听说过它有时会发生,在速度优化过程中。如果我错了,抱歉并提前感谢您的澄清。
【问题讨论】:
-
你可能需要
volatile关键字- -
确实,对
volatile的访问无法重新排序。但是编译器仍然可以随意订购非易失性访问,其中 AFAIR 包括 between 两个易失性访问。因此,我选择将此序列编码为汇编程序 sn-p 并将其内联到 C 代码中(例如__asm__ volatile(" ... ")) -
如果这是在您的目标平台上常见的事情,那么运行时库很可能已经有可用的功能,因此您不需要自己编写程序集。
-
该寄存器的指针已经是易失性的。但是,我知道我应该将操作寄存器的函数声明为 volatile 或使用带有 volatile 关键字的汇编命令,正如@FelixPalmen 指出的那样。对吗?
-
@LuisPossatti 谈到内联汇编时,标准中根本没有任何内容。在程序集块上使用
gcc、volatile会强制编译器包含程序集片段,即使它对 C 程序的可观察行为没有任何影响——否则,优化器可能会决定此代码不是需要:)
标签: c compilation microcontroller