部分易变?

时间:2016-08-05 23:38:21

标签: c++ optimization volatile

假设我有一个带有主循环和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();

真正的问题是:

这会做我希望它会做什么,还是有更好的方法来解决不断刷新变量的问题,而不是让优化器缓存变量?

2 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:0)

一个示例,用于最小化处理器在禁用中断的情况下运行的时间。仅当nextStatus没有其他副作用时才有效。如果确实如此,那么一旦状态成功提交就必须记录并执行。

cli();
do {
  auto lastStatus = Status;
  sei ();

  auto nextStatus = lastStatus;
  nextStatus.UpdateStuff();
  nextStatus.UpdateOtherStuff();
  ...

  cli ();
} while (lastStatus != Status);
Status = nextStatus;
sei();