为什么在一个序列点内只有一个具有volatile限定类型的读访问权限?

m4l*_*90n 7 c volatile misra

给出以下代码:

static volatile float32_t tst_mtr_dutycycle;
static volatile uint8_t tst_mtr_direction;
static volatile uint32_t tst_mtr_update;

void TST_MTR_Task(void)
{
    if (tst_mtr_update == 1U)
    {
        tst_mtr_update = 0;

        MTR_SetDC(tst_mtr_dutycycle, tst_mtr_direction);
    }
}
Run Code Online (Sandbox Code Playgroud)

我发现了MISRA C 2012 Rule-13.2的问题,我决定做一些研究.我在这里找到了(http://archive.redlizards.com/docs/misrac2012-datasheet.pdf):

在一个序列点内,只有一个具有volatile限定类型的读访问权限

这里的事情是我无法找到一个例子或解释,清楚地说明为什么在一个序列点内不得有多于一个具有volatile限定类型的读访问.

我需要找到违规代码的解决方案,但我不清楚该怎么做.

我现在知道在一个序列点内只有一个具有volatile限定类型的读访问权.问题是,为什么?我需要知道为什么要实现解决方案并在此解释每个人为什么要更改代码.

问候.

eca*_*mur 5

该规则的理由是:

(必需)在所有允许的评估订单下,表达式的值及其持久性副作用应相同

如果在序列点之间读取多个volatile限定变量,则不指定首先读取的变量.读取volatile变量是一个副作用.

解决方案是明确地对读取进行排序:

void TST_MTR_Task(void)
{
    if (tst_mtr_update == 1U)
    {
        tst_mtr_update = 0;

        float32_t dutycycle = tst_mtr_dutycycle;
        uint8_t direction = tst_mtr_direction;
        MTR_SetDC(dutycycle, direction);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @ m4l490n,因为那是`volatile`的用途 - 它指定不能缓存或重新排序写入和读取.一个例子是硬件寄存器,其中读取可以在连续读取时返回不同的值,并导致发生任意动作. (2认同)
  • @ecatmur:实际上,标准并没有这样说.它仅指编译器对抽象机器的重新排序.除非程序本身获得正确的值,否则不包括外部硬件的缓存和缓冲或重新排序.这是使用带有中断的线程或多处理器时"volatile"不足的原因之一.原子进入游戏,包括障碍/围栏和其他系统范围的同步. (2认同)