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

Why there shall be no more than one read access with volatile-qualified type within one sequence point?

给定以下代码:

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);
    }
}

我发现 MISRA C 2012 Rule-13.2 存在问题,因此我决定进行一些研究。我在这里 (http://archive.redlizards.com/docs/misrac2012-datasheet.pdf) 发现:

there shall be no more than one read access with volatile-qualified type within one sequence point

这里的问题是,我无法找到一个示例或解释来阐明为什么在一个序列点内不应有超过一个具有 volatile 限定类型的读取访问。

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

我现在知道在一个序列点内最多只能有一个具有volatile限定类型的读访问。问题是,为什么?我需要知道为什么才能实施解决方案并向这里的每个人解释我为什么要更改代码。

此致。

该规则的理由是:

(Required) The value of an expression and its persistent side effects shall be the same under all permitted evaluation orders

如果在序列点之间读取了多个 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);
    }
}

获取函数调用的参数之间没有序列点。 因此,标准未定义它们的获取顺序。 OTOH,编译器必须维护对易失性对象的访问顺序,所以这是矛盾的。

将变量获取到非易失性临时变量并将其用于函数调用:

float32_t t1 = tst_mtr_dutycycle;
uint8_t t2 = tst_mtr_direction;
MTR_SetDC(t1, t2);

请注意,这实际上是标准 C 的问题,而不仅仅是与 MISRA 合规性有关。

由于您在标准合规性方面似乎存在多个问题,您可能希望将 standard 放在枕头下。