部分波动变量

Partially volatile variable?

本文关键字:变量      更新时间:2023-10-16

假设我有一个微控制器,它有一个主循环和1毫秒的中断(如果你不知道那是什么,它只是一个中断主循环执行的任务,而它做了一些事情……它是一个1毫秒的断开,因为它每毫秒发生一次(。

我有一个变量,用于在主循环和毫秒中断之间进行通信:

volatile status_t Status;

现在,我在主循环中有一段代码更新Status变量,它对它进行了大量转换:

cli();    // This temporarily turns off interrupts, so we don't 
          // modify the variable unsafely
Status.UpdateStuff();
Status.UpdateOtherStuff();
//etc.
sei();    // Turn interrupts back on

问题是,这些对Status的函数调用中的每一个都会重写Status。。。。。。编译器无法在本地内存中缓存Status的值。

这个问题的一个可能的解决方案是:

cli();
status_t* localStatus = (status_t*)&Status;
localStatus->UpdateStuff();
localStatus->UpdateOtherStuff();
//etc.
Status = *localStatus;
sei();

这里真正的问题是:

这会达到我希望的效果吗?或者有更好的方法来解决不断刷新变量的问题,而不是允许优化器缓存变量?

您的第二个版本可能仍然会多次写入微控制器,因为编译器可能没有意识到它可以在方法调用之间缓存值(它可能只有在方法是内联的情况下才能确定这一点(。所以我建议制作一个显式的本地副本,而不仅仅是一个本地指针。

cli();
status_t localStatus = Status;
localStatus.UpdateStuff();
localStatus.UpdateOtherStuff();
...
Status = localStatus;
sei();

一个最小化处理器在禁用中断的情况下运行时间的示例。只有当nextStatus没有其他副作用时,这才有效。如果成功提交了状态,则必须记录并执行这些状态。

cli();
do {
  auto lastStatus = Status;
  sei ();
  auto nextStatus = lastStatus;
  nextStatus.UpdateStuff();
  nextStatus.UpdateOtherStuff();
  ...
  cli ();
} while (lastStatus != Status);
Status = nextStatus;
sei();