7

给定以下代码:

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)发现:

在一个序列点内不得有超过一次具有 volatile 限定类型的读取访问

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

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

我现在知道在一个序列点内不应有超过一个具有 volatile 限定类型的读取访问。问题是,为什么?我需要知道为什么要实施解决方案并在这里向大家解释我为什么要更改代码。

问候。

4

2 回答 2

6

该规则的理由是:

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

如果在序列点之间读取了多个 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);
    }
}
于 2015-08-06T16:01:26.213 回答
2

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

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

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

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

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

于 2015-08-06T16:03:34.840 回答