1

プロセッサ用の SD カード SPI ドライバを作成しています。私は SPI ドライバーが優れていることを知っています。なぜなら、私はそれを LCD にも使用しており、今までは楽しくコマンドをカードに送信していたからです。ある特定のトランザクションで問題が発生していますが、これは他のトランザクションと何ら変わりはありません。

SPI バスにデータを書き出すと、受信と送信が完了したことを示す割り込みコールバックを待ちます。a の次のブール値フラグstructを trueに設定する 2 つのコールバックがあります。

m_transaction_status.sdts_rx_complete

m_transaction_status.sdts_tx_complete

通常のプログラム フローでは、これらのフラグが設定されるのを待ってから続行します。

while ((m_transaction_status.sdts_rx_complete == false) //
        || (m_transaction_status.sdts_tx_complete == false))
{
    // Check whether we've had an error.
    if (m_transaction_status.sdts_error == true)
    {
        LOG_ERROR(SD::MODULE,
                "transfer_data: Transaction error.");
        transfer_status = false;
        break;
    }
}

問題のトランザクションでは、コールバックにブレークポイントを設定し、両方のフラグが設定されていることを確認できますが、通常のフローに戻ると、変数が突然使用できなくなりfalse、ループに永遠に閉じ込められたように見えます。このループは、他のすべてのトランザクションで問題なく使用されます。

これらの変数が設定されているのに、(どうやら) クリアまたは割り当て解除されているか、またはその他の不都合な理由について調査できる理由はありますか?

編集:

割り込みは確かにマイクロのものです(正確にはRenesas RL78)。

構造体宣言は次のとおりです。

/**
 * The state of an SD SPI transaction.
 */
struct SDTransactionStatus
{
    /** Transaction error flag. */
    bool sdts_error;
    /** Transmission completion flag. */
    bool sdts_tx_complete;
    /** Reception completion flag. */
    bool sdts_rx_complete;
};

は、クラスstructのプライベート メンバーとして実装されます。SDフラグは、コールバックの単純なセッター関数を介して設定されます。

4

1 に答える 1

1

あなたの特定のマイクロコントローラーも、それと一緒に使用する必要がある C++ コンパイラーも知りませんが、これは私が言おうとしていることについて何も変わらないはずです。

問題は、ループ内でフラグの値を変更することはなく、フラグを読み取るだけなので、コンパイラーは自由に最適化し、ループ外で変数を一度だけ読み取る (つまり、キャッシュする) ことです。彼らが変わることができることを知りません。次のようなもの:

const bool complete = !m_transaction_status.sdts_rx_complete
                   || !m_transaction_status.sdts_tx_complete;
const bool error = m_transaction_status.sdts_error;
while (complete) {
  if (error) {
    //...
  }
}

これで良い結果が得られない理由がわかります。修正は、変数が「背後で」変更される可能性があること、およびコード内でアクセスするたびに変数を実際に再読み取りする必要があることをコンパイラーに伝えることです。

あなたはマルチスレッドなどをしていないのでvolatile、あなたの宣言で変数に修飾子を追加するだけでそれを行うことができますstruct:

struct SDTransactionStatus
{
    volatile bool sdts_error;
    volatile bool sdts_tx_complete;
    volatile bool sdts_rx_complete;
};

さて、なぜ以前にこの問題に遭遇しなかったのかは謎ですが、「コンパイラは自由に最適化できる」ということは常にそうしなければならないという意味ではないことを覚えておく必要があります。大げさな推測として、そのループを使用した他の場所はそのような最適化に適していませんでしたが、問題のある場所はそうです。

もちろん、私は全体について間違っている可能性がありますが、情報がほとんどないため、伝えるのが難しく、とにかく、この最適化/揮発性の問題は、現在の問題の原因ではない場合でもコードに存在するため、修正する必要があります。現在の問題が無関係であっても、私が説明したことはいつでも発生する可能性があります。

編集:ああ、おそらくコードベース全体を見直して、これが他の場所でも起こらないようにする必要があります.

于 2013-04-26T13:05:53.987 に答える