C++ 部分易失变量?

C++ 部分易失变量?,c++,optimization,volatile,C++,Optimization,Volatile,假设我有一个带有主循环和1毫秒中断的微控制器(如果你不知道那是什么,它只是一个中断主循环执行的任务,而它做了一些事情…..它是一个1毫秒的中断,因为它每毫秒发生一次) 我有一个变量,用于在主循环和毫秒中断之间进行通信: volatile status_t Status; 现在,我在主循环中有一段代码,用于更新Status变量,该变量对其进行了大量转换: cli(); // This temporarily turns off interrupts, so we don't

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

在第二段中,我想您的意思是
&状态
。顺便说一句,我认为没有更好的选择。让计时器插入作业在队列中,让主线程读取队列并处理作业。您只需要在队列操作上使用互斥锁。@MatteoItalia是的,这就是我的意思……我不知道它是否有效,但您可以尝试将您的状态变量声明为普通变量,并在需要时通过“volatile”指针访问它
*(volatile status\u t*)和status
。无论如何,Barmar的答案是更好的。使用这种方法,您可以潜在地将必须在禁用中断的情况下运行的代码范围减少到只将新版本状态移动到共享位置的代码。