RTOS のさまざまなタスクがグローバル変数を共有する

編集元: https://mp.weixin.qq.com/s/yoKauSQcbZMW_eVAT9H_fQ

この号のトピックス

グループ内の友人からの質問:Freertosで、優先度の高いタスクでグローバル変数の値が変更され、優先度の低いタスクを待つサイクルの値が変更されるのですが、ループが終わらないのはどうすればいいですか?そして下向きに実行しますか?

優先度の高いタスクのコードは、グローバル変数を変更します。

if(1000 <= Complete)
{
    update_flag = 1;
    printf("update_flag = [%d]\n”, update_flag);
}

vTaskDelay(10);

優先度の低いタスクのコードは、グローバル変数を判断します。

while(!update_flag); // 判断

......

while() が優先度の低いタスクで終了しない理由を知っていますか?

チャット

volatile というキーワードを思い浮かべることができれば、このキーワードを本当に理解できたことになります。

以前に共有した関連記事:組み込み C 言語でよく言及されるキーワード volatile

この小さな友達に、グローバル変数を定義するときに volatile を追加するように伝えます。問題が解決しました。まあ、すべてうまくいきます。

明らかに、私たちの推測を確認するために、段階的な分析を実行します。

まず、次の図に示すように、このプロジェクトのプロジェクト構成をチェックして、コンパイラの最適化が有効になっているかどうかを確認します。

写真

このプロジェクトはコンパイルレベルの最適化を有効にします。この方法では、説明が明確になり、コンパイラは最適化をオンにし、キーワード volatile は変数定義に追加されません。これら 2 つの点が組み合わさると問題が発生します。

コンパイラーが最適化を有効にすると、コンパイラーはループ中に誰も update_flag を変更しないと信じます。update_flag は変更されておらず、update_flag の初期値は 0 なので、update_flag は変更されない値となり、当然無限ループになります。どうやらコンパイラは、優先度の高いタスクが update_flag の値を変更することを認識していないようです。したがって、この場合、プログラマは、update_flag が変更される値であるため、そのような最適化を実行しないことをコンパイラに明示的に伝える必要があります。これが volatile キーワードの機能です。**注意: volatile はコンパイル段階でのみ機能し、実行時段階には影響しません。**この友人は、優先度の低いコードにコードを追加すると、実行結果は正常になる(変数定義は volatile を追加しない)と言いました。

while(!update_flag)
{
    printf("update_flag = [%d]\n”, update_flag);
    vTaskDelay(10);
}

前の分析によると、追加されたコードでは、while() ループ内の他のコードがこの変数を読み取り、コンパイルされたコードがその値をメモリから再度読み取ります。**補足知識:** 友人の中には、RTOS に基づく複数のタスクがグローバル変数にアクセスする場合、ミューテックスで保護する必要があるのではないかと尋ねる人もいるでしょう。簡単に言うと、複数のタスクが同じグローバル変数を変更する場合、変数の値が異常になるのを防ぐためにミューテックス保護が必要です。ただし、ここでは 1 つのタスクのみが変数を変更し、もう 1 つのタスクは読み取りだけを行うため、グローバル変数値の混乱の問題は発生しません。読んでくれてありがとう、さあ〜

組み込み C 言語でよく言及されるキーワード volatile

【C言語】メモリバリアと揮発性を徹底的に理解する

おすすめ

転載: blog.csdn.net/qq_41854911/article/details/131525282
おすすめ