PIC32MM CPUを活用する

令和 3年 6月

    PIC32MMにAmazon FreeRTOSを実装する

 今までは自作の簡易OSを使用していました。この簡易OSではタスク切り替えとしてコルーチン(非プリエンプティブ方式)のみを使用してきました。これはプリエンプティブ方式が要求するタスク毎のスタックメモリの合計が組み込み用のマイコンが内蔵できるRAM容量に対して厳しい要求であったためです。
 しかし、マイコンの内蔵できるRAM容量も徐々に拡大を続けており、現在は100kBを超えるRAMを内蔵している製品も珍しくない状態です。これだけの容量があるならプリエンプティブ方式を排除する理由にはなりません。
 更に組み込み装置といえどもEthernetのようにPCやWSなどで開発された技術が使用されることが増えてきています。
今後は、より一層このような傾向になると考えると、PCで採用されているプリエンプティブ方式を排除することのデメリットは益々大きくなってきます。どのタイミングかでプリエンプティブ方式を導入することが必要です。

 自分でプリエンプティブ方式を実装することも出来るとは思いますが、自作システムでは将来的なメンテナンスが問題になります。今までは単純さを維持することでこの問題に対処してきたのですが、今後は可能であればユーザーの多い汎用的なシステムを採用した方が良い。
 このため、Amazon FreeeRTOSを採用します。Amazon FreeeRTOSはライセンスがGPLからMITに変更されたため商用利用におけるソースコードの開示義務の問題がありません。また、この数年で日本語の情報量も格段に増えているようです。将来的にも直ちに廃れてしまうような事にはならないでしょう。

 Amazon FreeeRTOSについてはネットからも多くの情報を得る事ができます。初期の設定方法や機能については、ネットから情報を得ているものとして省略しています。

 1.Amazon FreeeRTOSの移植を検討する

 Amazon FreeeRTOSは多数のマイコンに移植されていますが、PIC32MM用には移植例がありません。同じmicroMIPSコアを採用しているPIC32MZマイコン用の移植サンプルならあります。が、PI32MZのCPUコア部分は確かにPIC32MMと同じですが、DSPやFPUなど多くの拡張機能を含んでいます。対してPIC32MMシリーズのCPUコアにはこれらの多くが含まれていない。そのままでは使えないでしょう。従って、移植する事を検討します。

 まず、PIC32MMのCPUコア部分について調べます。

https://ednjapan.com/edn/articles/1311/22/news065.html

 上記の記事はPIC32MZシリーズの記事ですが、記事中に「同CPUコアはキャッシュメモリを内蔵したものと、キャッシュメモリがないものの2種類を用意しており、」との記述があり、複数のCPUコアの存在が示されています。(「」内は上記記事からの引用)

 PIC32MZとPIC32MMは異なるCPUコアが採用されていると考えられます。
 他にPIC32MZにあってPIC32MMに無いと考えられるものは他に以下があります。これはアセンブラから見たときの違いです。
・FPU
・DSP

 但し、DSPに関してはこの時点で無いと判断しきれない部分があります。この件は後で説明します。

 PIC32MZ用のAmazon FreeeRTOSをPIC32MMに移植するには、これらに関係するCPUコアのレジスタ操作を削除すれば良い事になります。microchip社の日本語データシートのリストに[セクション 50. microAptiv コア採用デバイスの CPU」という文書がありますので、これを参考にします。
 また、従来製品であるPIC32MXシリーズのCPUコア(以降はM4Kコアと表記)の説明文書として「セクション 2. M4K コア搭載デバイス用 CPU」という文書も一緒に参考にします。当然、英語版のデータシートも併用します。

英語版のデータシートを比べてみるとPIC32MMとPIC32MXでは乗除算ユニットの記述内容は同じようです。対してPIC32MZのDSP機能はDSP ASE Extensionとして記述されています。DSP ASE ExtensionはPIC32MMには記述がありません。つまり、英語版の記述だけを見るとDSP ASE機能はPIC32MZのみにあるように見える。
 対して日本語版の[セクション 50. microAptiv コア採用デバイスの CPU」を見ると、「50.1 はじめに」にmicroAptivの2種類のコアの違いが書かれており、ここではDSP ASE機能は両方に実装されていると書かれています。

 今回のケースでは、英語版の方は特定のデバイスに対するデータシートであるのに対して、日本語の方はCPUコアに対する説明書であること、日本語資料の方がメンテナンス頻度が低く情報が古い可能性が高い事などを考えると英語版のデータシートの方が
正しい可能性が高そうです。

日本語のmicroAptivコア説明書を詳しく見ているとCP0のConfig3レジスタbit10,11にDSPおよびDSP2の実装ビットがあります。これを確認すればPIC32MMにDSP機能が実装されているかどうかが分かります。PIC32MMのConfig3レジスタの値読み出してみると0x80236068でDSPを実装していない事が分かります。

 また、この日本語資料からDSP機能を使用するためにはCP0のStatusレジスタbit24のMXビットを1にする必要があると書かれています。このことから、仮にPIC32MMにDSP機能が実装されていたとしても、MXビットを0のままにしておけばDSP機能が動作に影響する事はない事が分かります。

 以上の確認からPIC32MMにはDSP機能はないと判断します。そうするとPIC32MMはレジスタレベルではPIC32MXと同じ構成ということになります。機械語レベルでは一部の命令コードが異なるので再コンパイルは必要ですが、同じアセンブリコードで動作する事になります。


 2.Amazon FreeeRTOSを移植する

 結論としてPIC32MMはPIC32MXと類似しており、タスクコンテキストの退避・復帰は同じ処理内容で良い事になります。但し、PIC32MMとPIC32MXはCPUコア以外にも違いがあるので、これらの違いが影響しない事を確認する必要があります。
 
 Amazon FreeeRTOSはCPU以外に下記の機能を使用しています。
 ・タイマ
 ・割り込みおよび割り込み優先度制御
 ・例外処理機能

タイマと割り込みはタスクコンテキストの切り替え周期でタイマ割り込みを発生させています。例外機能はタスクコンテキストの切り替え処理時にSWI例外を使用しています。
割り込み優先度制御はタスクコンテキストの切り替えを一時的に禁止・解除するために使用しています。

 問題になるのは割り込み機能でPIC32MMとPIC32MXでは割り込み関連のレジスタやビット位置を指定する方法が異なっています。PIC32MMでは各割り込み要因に対するベクタ番号から上記を決めているのに対して、PIC32MXでは各割り込み要求に対するIRQ番号から上記を決めています。
 このためタイマの割り込み関連のレジスタ位置が違っているため、この部分を書き換える必要があります。SWIについてはIRQ=ベクタとなっており変更の必要がありません。

 移植に使用するのはVer.202012.00(FreeRTOS Kernel V10.4.3)です。他のVer.では細部で違いが出てくる可能性があります。
 具体的にはAmazon FreeeRTOSソースコードのport.cファイル222行目を以下のように変更します。

変更前:
IPC1bits.T1IP = configKERNEL_INTERRUPT_PRIORITY;
変更後;
#ifdef __PIC32MX__
IPC1bits.T1IP = configKERNEL_INTERRUPT_PRIORITY;
#elif defined __PIC32MM__
IPC4bits.T1IP = configKERNEL_INTERRUPT_PRIORITY;
#else
#error unsupport pic
#endif // __PIC32MX__

R03/06/12追記
追記ここまで


 上記の変更のみでPIC32MMへの移植作業は終了です。
比較的簡単にマルチタスクが動作します。
ただし、実機での動作確認が必要です。PIC32MMのシミュレーションは正しく動作してくれません。
PIC32MMのシミュレーションについてはこちらをご覧ください。
R03/06/12追記
 シミュレーションについての追加情報です。
追記ここまで

 これ以降もPIC32MMの評価を続けて行きますが実機での評価はシミュレーションに比べるとデータのロード・セーブに時間が掛かるのでPIC32MXのシミュレーションで代用できる分はPIC32MXのシミュレーションで代用していきます。


 3.PIC32MMでのRAM使用量とタスク数

 PIC32MMの弱い点としてはRAM容量が32kBとプリエンプティブマルチタスクを実装するには容量が少なめです。その分同時に実行できるタスク数が制限される事になります。
 ではいくつ位まで実装できそうか?
 10個あればごく小規模の機械制御は間に合いますが、出来れば20個程度実装できる方が安心感があります。当然多いに越した事はないのですが。

 これを評価するためには、ますタスク一つ当たりのスタックメモリ量がどの程度必要かを判断する必要があります。
Amazon FreeeRTOSのPIC32MXにおけるスタックメモリ量はFreeRTOSConfig.hファイル内で190(単位はWordで4byte)と定義されています。この中にはタスクコンテキストを保存する領域が含まれているので、その分約40個分のレジスタを差し引いた150wordがスタックの変数領域です。PIC32のスタック上の変数では1byte変数でも1wordを占有するので、PCの保存数を含めて150個の変数を記録できる事になります。関数のネスト数を15段と仮定すると1関数あたり9個程度の変数を使える事になります。スタック上にバッファ領域のような配列を取らないなら妥当な数字であろうと思います。バッファ領域のような大きな変数領域は別途heapや共通領域で用意することが前提になります。

 1タスク当たりのメモリ必要量はスタック領域が760B(190x4)に静的変数領域を加えて1kBと見積もると、30個ほどのタスクを実装できる計算になります。実際にはシステムのスタック領域やC++による例外処理用のメモリ領域・各タスクで共有するメモリなどが別に必要になるので、これらの合計を10kBと仮定すると約20個程のタスクを実装できる計算になります。
 これなら小規模システムでは十分に実用可能な値です。