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)で次のことを見つけました:

1 つのシーケンス ポイント内で volatile 修飾された型の読み取りアクセスが 1 つだけであること

ここでの問題は、1 つのシーケンス ポイント内で volatile 修飾された型の読み取りアクセスが 1 つしかない理由を明確にする例や説明を見つけることができなかったことです。

違反しているコードの解決策を見つける必要がありますが、どうすればよいかわかりません。

これで、1 つのシーケンス ポイント内で volatile 修飾された型の読み取りアクセスが 1 つしかないことがわかりました。問題は、なぜですか?解決策を実装するために理由を知り、コードを変更する理由をここにいる全員に説明する必要があります。

よろしく。

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、コンパイラは揮発性オブジェクトへのアクセスの順序を維持する必要があるため、これは矛盾しています。

変数を非揮発性一時にフェッチし、それらを関数呼び出しに使用します。

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

これは実際には標準 C の問題であり、MISRA 準拠だけに関連するものではないことに注意してください。

標準への準拠に関して複数の問題を抱えているように見えるため、標準を枕の下に置いておくことをお勧めします。

于 2015-08-06T16:03:34.840 に答える