● 実験テーマ24

「PIC32MX_FreeRTOSの基本動作確認」
(後閑哲也 著「PIC32MX活用ハンドブック」の製作記事による)

■ 2012.12.14〜 2012.12.19
  ・後閑氏の本の「7-1 FreeRTOSの概要」に載っている手順に従い、FreeRTOS.orgサイト
   にアクセスし  この時点の最新バージョン(V7.3.0)のZip(FZip)ファイルをダウンロード
   した。

   Zipファイルを展開して得たFreeRTOSファイル内で、必要なものをプロジェクトフォルダに
   コピーし準備を始めたが・・・・

   最新バージョンでは、何故かうまく動かない??

 

 

 

 

 

 

 


■ 2012.12.20
  ・これまで、フリー版のRTOS:「FreeRTOS」の最新版: V7.2.0で、後閑氏の本の、sample1
   プロジェクトを試してきたが、うまく行かず。
   ここで、これまでの概要を、まとめてみたいと思う。
   尚、
「sample1」プロジェクトの動作仕様は、vTaskDelyを使用し、3つのタスクで使っているLEDを、
   それぞれ異なる周期で点滅させるという単純なもの。

    @ V7.2.0(この時点での最新版)
       何故か、xTaskCreate未定義エラー出たが、メイン関数の頭に、
       このdefine文を追加し、HEXまで焼けた。
       しかし動作せず。
      原因不明

    A V5.4.2(後閑氏の本の記事で使用しているバージョン)
       何故か、T1Interrupt Handrer未定義エラーが出てHEX焼きまで至らず。
       原因不明

    B V5.2.0(後閑氏HPで使用しているバージョン)
       コンパイルエラー最初からなくポート割付の変更のみで動作確認OK

     → とりあえず、このバージョンが動くのでこれで先々進めることにする。

  「sample2」及び、「sample3」プロジェクトに移行
   <sample1との相違点>
    ■ sample1プロジェクト
       @ 各タスクの優先順位を全て同じにしている。
       A API遅延関数:
vTaskDelay() を使用
       B T1割込みで順番にタスクが切替わるのでLEDの点滅間隔は、長い間隔のタスクの間に
          短い間隔のタスクが実行され、設定した時間より長くなる。

    ■ sample2プロジェクト
       @ どれか一つのタスクの優先順位を高くする(この例ではタスク2)
       A 通常のループ遅延を使用
       B この場合、ループ待ちの間も、タスクとして実行時間を占有してしまうので、優先順位を
          高くした、タスク2のLEDしか点滅しない。

    ■ sample3プロジェクト
       @ タスク3、タスク2、タスク1の順に優先順位を付けている。
          (タスク3が高く、次にタスク2、タスク1の順)
       A API遅延関数:
vTaskDelayUntil() を使用
       B この場合、Tickカウンタの間隔をベースにして起動するので比較的正確な時間間隔になる。


■ 2012.12.21
  ・
sample2プロジェクトの動作確認を行った。
  → 確かに優先順位の高い、タスク2のLEDしか点滅しないが点滅間隔を、自作オシロで確認すると、
     約0.2秒のはずが、30mSほどしかない。
  → この原因は、どうも後閑氏HPのソフト記述に誤りがあるようで、次の通り修正でOKになる。
     尚、後閑氏の本では、ちゃんとこの定数に修正されておりました。

     タスク1_LED: 0.1秒間隔のループ回数設定=1000000 → 720000に修正
     タスク2_LED: 0.2秒間隔のループ回数設定=2000000 → 1400000に修正
     タスク3_LED: 0.5秒間隔のループ回数設定=10000000 → 3600000に修正

・次に、sample3プロジェクトの動作確認を行った。
 → このプロジェクトのファイル一式は、後閑氏HPでは提供されてない。
    本に付属しているCDROMの、SAMPLE3フォルダをコピーして使った。
 → 動作確認OKである。
    時間も正確なことを確認


■ 2012.12.22
  ・
sample4プロジェクト(Qバッファ)の動作確認
   Queue(キュー: FIFOバッファによる、待ち合わせ行列)
   ハンドル名で、Qバッファを指定

    <sample4の動作概要>
     @ 3つのタスク構成で、2つのタスクから非同期に、LCDに表示要求を出す。
     A LCDに、タスク内でのカウント値を表示する。
     B タスク2は、タスク1の倍の待ち時間(200mS)にして カウンタを更新
     C タスク3では、Qバッファからカウントデータを取り出し、LCDに表示する。

  ・プロジェクトを組み、コンパイル〜HEX書込みOK
  → タスク2のカウント値の倍が、タスク1のカウント値になっていることを確認

   ・sample5プロジェクト(T2割込み処理内でのQバッファの使用例)の動作確認
    <sample5の動作概要>
     @ タスク1は1秒間隔で、カウンタ値を表示する。メッセージを表示キュー(lcdQueue)に送り、
        同時に数値キュー(numQueue)へ4個のカウント値を送る。
     A 200mS周期のT2割込みで、数値キューの内容をチェックしキューに数値データがある場合は、
        それをLCDに表示。
        キューバッファが空の時は何もせずリターン
      B タスク2では、表示キューバッファにデータが送られてくるのを常時待っていて表示データの
        場合は1行目に表示しT2割込みからの表示データの場合は、2行目に表示

  → 特に問題なくうまく行く。


■ 2012.12.23
  ・
sample6プロジェクト(単発セフォマの使用例)の動作確認
   動作確認の前に、セフォマという聞きなれない言葉の意味と、その概要を学習(以下、後閑本からの抜粋です)
    <セフォマとは?>
     @ タスクが、イベント発生を待合わせる。これを、「Take」と呼ぶ。
     A 他のタスクの実行完了を待合わせて同期を取る。
        待合わせを解除することを「Give」と呼ぶ。
     B セフォマには、次の2種類がある。
        単発待合わせ: Binary Semaphore
        複数回待合せ: Counting Semaphore(Tale, Giveカウンタ付)

    <sample6の動作概要>
     @ タスク3は、キューバッファに送られたメッセージをLCDに表示するだけ
     A タスク1は、無条件に1秒ごとに表示メッセージをキューバッファに」送る。
        これで、LCDの1行目に、1秒間隔で表示されることになる。
     B タスク2は、セフォマをTakeしてT2割込みによる、Giveを待合せ、Qiveされて、待合せが解除されたら
        メッセージをキューバッファに送る。
        このセフォマをGiveするために、T2を、200mSインターバルで動作させ、その割込みでセフォマをGive
          C これで、LCDの2行目は、T2の、0.2秒間隔で表示が更新
        結果として、1行目の表示は1秒ごとにカウントアップし
        2行目の表示は、0.2秒ごとにカウントアップする。
        よって、2行目は常に、1行目の、5倍の値+1を示す。

  → 特に問題なくうまく行く。

  ・sample7プロジェクト(排他制御:Mutex)の動作確認
   内蔵モジュールなどのリソースを複数で使う場合、競合が起きても、いずれかの使用が完了するまで、待たせる
   ための機能

   <sample7の動作概要>
    @ タスク1とタスク2から、UART2に互いに独立にメッセージを出力する構成
    A タスク1は、0.2秒周期で、タスク2は、0.4秒周期で、UART2 にメッセージを出力
       この出力する直後で、Mutexを使ってUART2を確保し出力後解放している。
    B このプログラムの実行結果は、タスク1が、0.2秒間隔で、タスク2の倍の早さになっているので
       タスク1が、2回連続になる。
       これに対し、MutexセフォマのTaleとGive文をコメントアウトした場合は、タスクの出力途中でもう一方のタスク
             が重なると出力が乱れることが解る。


■ 2012.12.24
  ・
sample8プロジェクト(ゲート・キーパー・タスク)の動作確認
   排他制御の問題点
    @ 各タスク中で待合せが発生しタスクの実行遅れが予想できない。
    A 複数タスクが互いに待ち状態になり先に進まなくなるという、デット・ロックが起きうる。

   そのため、通常Mutexは使われず、代替えの方法として「ゲート・キーパー・タスク」がある。
   内蔵モジュールなどを使うタスクを1つのタスクに限定して複数タスクから、キューバッファを使って入出力要求する。

   <sample8の動作概要>
    @ タスク1では、0.2秒ごとにカウンタ1のメッセージを作成しては送信キューバッファに出力
    A タスク2も同様に、0.4秒ごとにカウンタ2のメッセージを作成しては送信キューバッファに出力
    B タスク3は、単純に送信キューバッファからメッセージを取り出しては、UART2に出力

   この結果も、sample7と同じになる。
   この方法では、デットロックの心配も、タスク1やタスク2がリソース確保のために待たされることがない。

  → 特に問題なくうまく行く。

  ・ここまで一応、RTOSの一通りの、sample(1〜8)までを、学習できたので
   次期テーマでは、この応用として後閑氏の本に掲載されている、「MP3プレーヤ」を
   PIC32MXトレーニング基板で実験してみたいと思う。(若干、仕様を変える予定です。)


← 実験テーマ1に戻る   TOP PAGEに戻る   実験テーマ25へ →