部分易变变量?
Partially volatile variable?
假设我有一个带有主循环和 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
没有其他副作用的情况下有效。如果确实如此,则必须在成功提交 Status 后记录和执行这些内容。
cli();
do {
auto lastStatus = Status;
sei ();
auto nextStatus = lastStatus;
nextStatus.UpdateStuff();
nextStatus.UpdateOtherStuff();
...
cli ();
} while (lastStatus != Status);
Status = nextStatus;
sei();
假设我有一个带有主循环和 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
没有其他副作用的情况下有效。如果确实如此,则必须在成功提交 Status 后记录和执行这些内容。
cli();
do {
auto lastStatus = Status;
sei ();
auto nextStatus = lastStatus;
nextStatus.UpdateStuff();
nextStatus.UpdateOtherStuff();
...
cli ();
} while (lastStatus != Status);
Status = nextStatus;
sei();