【发布时间】:2019-11-09 11:55:53
【问题描述】:
让x 和y 成为主代码和中断代码之间共享的变量。
我对@987654323@ 的想法是,它仅且始终需要用于也在主代码中使用的硬件变量和中断变量。
通过禁用中断,保证主代码中x 和y 的每次使用都是原子的。
x 和y 是否真的需要为volatile,或者在使用它们强制从 RAM 重新加载变量之前设置内存屏障是否足够?
一)
volatile bool x;
volatile int y[100];
int main(void)
{
while (true) {
disable_interrupts();
if (x)
work(y);
x = false;
enable_interrupts();
}
}
B)
bool x;
int y[100];
int main(void)
{
while (true) {
memory_barrier();
disable_interrupts();
if (x)
work(y);
x = false;
enable_interrupts();
}
}
目标是:
让编译器优化
work()。能够使用标准库函数,例如
memcpy()(这些函数不能与volatile变量一起使用)。
编辑:添加中断示例
interrupts.c:
extern volatile? int x;
extern volatile? int y;
void interrupt(void)
{
x = true;
REGY1 = y[7];
y[23] = REGY2;
}
【问题讨论】:
-
您如何看到这段代码被有害地重新组织,既没有易失性也没有内存障碍?即使
work被内联?谁来更新变量? -
据我所知,您只显示了一个可能访问变量的上下文。只有不止一个才会有趣。请展示另一个可能访问变量的上下文示例。
-
My idea of volatilenee,仅当编译器优化它们时。您不需要 volatile 所有变量,只需要那些您不想对其应用优化的变量。those aren't made to be used with volatile variables- 通过非易失性句柄访问易失性对象无论如何都是 UB。无论如何,编译器不应该优化memcpy,因为它会看到它访问一个易失性对象。让我们标记它:应该。is it enough to put a memory barrier- 不,不是。在您的第二个代码中,sn-p 编译器将完全删除if (x)语句,因为它是if (false)。 -
@Lundin 是的,但是如果中断被阻止,我们在这里试图避免的优化究竟是什么?
-
请注意,与嵌入式系统编译器不同,桌面系统编译器往往从不假设不会调用中断/回调。因此,对于您的普通 PC 编译器,您不需要
volatile限定与回调共享的变量,因为作为编译器扩展,编译器确保它意识到这些变量可以随时更新。但这绝不是任何标准的保证。
标签: c interrupt atomic volatile memory-barriers