-
Notifications
You must be signed in to change notification settings - Fork 3
PIC32 サポート
Shuta Kimura edited this page Oct 6, 2018
·
16 revisions
TinyThreadsはMIPS32(r2以上)を採用したPIC32シリーズCPUに対応しています。 MPLAB X IDEのMPLAB Harmony Configuratorに統合させ、サードパーティーのライブラリとして選択できるようになります。
- Harmonyのインストール先にある、
third_party
フォルダを開いて下さい。- 例えばWindowsなら、
C:\microchip\harmony\v2_06\third_party
などです。
- 例えばWindowsなら、
-
リリース一覧から必要なバージョンのzipやtarballを取得し、上記のフォルダに展開して下さい。
- zipやtarballの代わりに、
third_party
フォルダ下でgitリポジトリを直接クローンしても構いません。- その場合は使用するバージョンのタグをチェックアウトしてください。masterブランチは開発途中の状態が含まれる場合があるため推奨しません。
-
tinythreads
フォルダの中身だけではなく、フォルダ階層ごと展開してください。 - フォルダの名前は必ず
tinythreads
にしてください。
- zipやtarballの代わりに、
- 次のフォルダ構成になっているか確認してください。階層構成やフォルダ名が異なると、正しく動作しません。
harmony/ +-- vX_XX/ +-- third_party/ +-- tinythreads/ +-- README.md +-- config/ +-- templates/ +-- TINYTH/ +-- : (省略)
-
third_party/config/third_party.hconfig
をテキストエディタで開き、次の一行をmenu
~endmenu
の間に挿入し、保存してください。source "$HARMONY_VERSION_PATH/third_party/tinythreads/config/tinythreads.hconfig"
- MPLAB IDE X で32-bit MPLAB Harmony Projectから生成されたプロジェクトを開き、Harmony Configuratorを起動してください。
- まだプロジェクトが無い場合は、「使い方」の最初の手順で先にプロジェクトを作成してください。
- 以下のように、「Third Party Libraries」内に「Use TinyThreads?」の項目が表示されていればインストール完了です。
- MPLAB IDE X で「File」→「New Projects...」から「32-bit MPLAB Harmony Project」を選択し、「Next」で進んでください。
- プロジェクトの生成場所やデバイスの種類は任意です。適切に設定をして「Finish」でプロジェクトを作成してください。
- プロジェクト作成直後にHarmony Configuratorが起動しますので、「Third Party Libraries」→「Use TinyThreads?」にチェックを入れてください。すぐ下にTinyThreadsの詳細設定を行う項目「TinyThreads Configuration」が追加されます。
- 「TinyThreads Configuration」内の設定を設定してください。
- 「Device & Project Configuration」→「Project Configuration」→「XC32 (Global Option)」→「xc32-ld」→「General」を開き、「Heap Size (bytes)」にヒープの容量を設定してください。TinyThreadsはmalloc/freeを使用するため、十分なヒープ容量が必要です。
- ヒープを最大限に確保する場合、
ヒープ容量 = デバイスのRAMサイズ - (Data Memoryの使用量 + メインスレッドのスタック確保サイズ)
で決定してください。Data Memoryの使用量はプロジェクトのコンパイルを行うとDashboardウィンドウに表示されます。 - 初回の設定値に見当がつかない場合、一旦ヒープ容量を初期値のまま後ろのステップを進めてください。コンパイルしてData Memoryの使用量を確認してから、再度Harmony Configuratorで設定し直して下さい。
- ヒープを最大限に確保する場合、
- Generate Codeボタンを用いてコードを生成してください。
- プロジェクトのプロパティを開き、「XC32 (Global Options)」の「Additional Options」に
-newlib-libc
と設定してください。(もし「Use Legacy libc」にチェックがされている場合は、チェックを外してください。)- プロジェクトのプロパティは、左側プロジェクト内容一覧のプロジェクト名を右クリックし「Properties」を選択すると開きます。
以下に設定項目一覧を示します。なお、プロジェクトで選択しているデバイスが対応していない機能や、オプションの組み合わせにより不要となった設定項目は表示されません。
グループ | 名前 | 説明 |
---|---|---|
Features | Enable pthread_cond*() APIs | 条件付き変数関連API(pthread_cond_* )を有効にします。 |
Features | Enable pthread_mutex*() APIs | ミューテックス関連API(pthread_mutex_* )を有効にします。 |
Features | Enable sem_*() APIs | セマフォ関連API(sem_* )を有効にします。 |
Features | Enable pthread_once*() APIs | Onceコントロール関連API(pthread_once_* )を有効にします。 |
Features | Enable pthread_rwlock*() APIs | 無視されます。現段階ではreader-writerロックは未実装です。 |
Features | Enable pthread_spin*() | 無視されます。現段階ではスピンロックは未実装です。 |
Features | Enable sleep() and usleep() APIs | スリープ関連API(sleep , usleep )を有効にします。 |
Features | Enable internal profiling (Switch counter) | タスク切り替え回数カウントを有効にします。(デバッグ向け) |
Features | Enable thread name for debugging | スレッド名設定機能を有効にします。(デバッグ向け) |
Scheduling | Enable preemption based on system tick | プリエンプションを有効にします。 |
Scheduling | Interval of preemption (in milliseconds) | プリエンプションの間隔をミリ秒単位で設定します。 |
Timer | Timer Type | プリエンプションやスリープ関数制御に用いるタイマーの種類を指定します。 |
Timer | Timer Module ID | 使用するタイマーの番号を指定します。 |
Timer | Timer Priority | タイマー割り込みの優先度を指定します。 |
Timer | Timer Sub-priority | タイマー割り込みの副優先度を指定します。 |
Timer | CPU Clock Speed (Hz) | CPUの動作クロックが表示されます。ユーザーによる設定項目ではありません。 |
Timer | Peripheral Clock Speed (Hz) | タイマーの動作クロックが表示されます。ユーザーによる設定項目ではありません。 |
Timer | Timer Resolution (in microseconds) | タイマーの分解能をマイクロ秒単位で設定します。プリエンプションやスリープ関数の待ち時間はこの値の倍数に切り上げられます。 |
Advanced | Maximum priority value | 優先度の最大値(最も優先度が低い)を指定します。有効な範囲は1~255です。 |
Advanced | Minimum priority value | 優先度の最小値(最も優先度が高い)を指定します。有効な範囲は1~255です。 |
Advanced | Default priority value | 優先度を明示的に変更しない場合の、デフォルトの優先度を指定します。有効な範囲は上記のmin~maxです。 |
Advanced | Default scheduling policy | デフォルトのスケジューリング方式を選択します。 |
Advanced | Minimum stack size for threads | デフォルトのスタックの大きさをバイト数で指定します。 |
Advanced | Require thread safe C library | スレッドセーフなnewlibへのアクセスを有効にします。この設定を無効にするとRAM使用量を削減できますが、一部のAPIがスレッドセーフではなくなります。スレッドの処理内容が限定的であるなど、安全が担保されている場合のみ無効にしてください。詳しくは制約を参照ください。 |
Advanced | Enable assertion check | TinyThreads内部でのアサーションチェックを追加します。 |
Advanced | Issue WAIT instruction in idle thread | 有効にすると、アイドルスレッドでWAIT命令を発行します。 |
Advanced | Use shadow register set to store context | Shadow register setを利用した高速なスレッド切り替えを有効にします。 |
Advanced | Enabled delayed switch for FPU registers | FPU関連レジスタの遅延切り替えを有効にします。 |
Advanced | Disallow FPU usage in ISR | ISR内でのFPU関連命令の使用を禁止します。 |
Advanced | Enabled delayed switch for DSP registers | DSP関連レジスタの遅延切り替えを有効にします。 |
Advanced | Disallow DSP usage in ISR | ISR内でのDSP関連命令の使用を禁止します。 |
TinyThreadsはFPU/DSPコンテキストの遅延切り替えに対応しています。遅延切り替えとは、スレッドの切り替えやISR実行時にはFPU/DSPレジスタの待避・復帰を行わず、実際にFPU命令やDSP命令を用いてレジスタにアクセスを行った際に初めて切り替えを行う仕組みです。
FPU/DSP関連レジスタはサイズが大きいため、切り替え(待避・復帰操作)に時間がかかります。そのため、必要になった場合のみ切り替えを行うことで、スレッド切り替えやISRの出入りにかかる時間を削減します。アプリケーション内でFPU/DSPを用いるスレッドが少数の場合に特に効果を発揮します。
本機能はFPU/DSP使用時にわざと例外を発生させ、それをTinyThreads側で捕捉することで実現しています。ユーザー側プログラムでは特別な操作は必要ありません。
- ISRでのAPI利用に関して
- TinyThreadsが提供するAPIのうち、ISR(割り込みハンドラ)内で使用が許可されているのは
sem_post()
のみです。 - 他の関数をISR内で使用した場合、動作は未定義です。
- TinyThreadsが提供するAPIのうち、ISR(割り込みハンドラ)内で使用が許可されているのは
- libcの種類としてはnewlibのみに対応します。デフォルトのlibcやLegacy libcには対応していません。
- コンパイルオプションから-legacy-libcは外し、-newlib-libcを追加してください。
- XC32プロジェクトではデフォルトでヒープがごく少量(2KB)しか設定されませんが、TinyThreadsはmalloc/freeですべてのメモリを確保するため、もっと多くのヒープ領域が必要です。
- Harmony ConfiguratorのXC32 (Global Options)からヒープサイズを設定してください。
- プロジェクトのプロパティのxc32-ldから設定すると、Harmony Configuratorでコード生成する度に上書きされてしまうためご注意ください。
- v1.3時点では、ISA(Instruction Set Architecture) ModeはMIPS32のみ対応です。microMIPSには対応していません。
- Shadow register set利用時特有の制約
- 同時に存在できるスレッドはShadow register setの個数が最大となります。これにはmain()関数が実行されるデフォルトスレッドと、動作すべきスレッドが無い場合に時間を消費するアイドルスレッドも含まれます。
- 例えば、Shadow register setが7個の場合、
pthread_create()
で同時に生成できるスレッドはそこから2を引いた5個が最大です。 - この制約のため、GPRセットを2個(つまりShadow registerは1個)しか持っていないPIC32MMシリーズなどでは、この機能を利用できません。
- 同時生成スレッド数の上限を越えてスレッドを生成しようとすると、
pthread_create()
はEAGAIN
を返して失敗します。
- 例えば、Shadow register setが7個の場合、
- 同時に存在できるスレッドはShadow register setの個数が最大となります。これにはmain()関数が実行されるデフォルトスレッドと、動作すべきスレッドが無い場合に時間を消費するアイドルスレッドも含まれます。