● 実験テーマ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へ →