Windows IoT Coreドライバー制御ソフトを作る(DMAP Driver編)

何度もこのブログで言及していますが、Windows IoT Coreで「DMAP Driver」とLightning APIを使うとGPIOの処理速度が劇的に上がります。Lightning APIのソースコードはGithubで公開されているので、このコードを読み解くことで、なぜ高速な処理ができるのかがわかります。

ざっくり解説すると、LightningライブラリーではWin32 APIでGPIOコントローラーのレジスタを取得し、その値を直接書き換えることで迅速なアクセスを実現しています。また、C++/CXよりArduino言語の方がより高速なのは、C++/CXではウィンドウズランタイムが介入しているのに対し、Arduino言語はC++言語としてコンパイルされた上で、ライブラリ内のWin32 APIに直にアクセスしているためであることが理解できます。


前回紹介したサンプルプログラムはLightning APIを使用していないため、ドライバー制御ソフトはDMAP Driverでは動作しません。そこで今回はDMAP Driver環境で動くドライバー制御ソフトのソースコードを紹介したいと思います。

DMAP Driverコントローラーの作成は、Lightning APIの移植という形で実現しています。ただし、オリジナルのソースにはWinRT関連の命令が含まれているため、命令の一部をDeviceIoControl()に置き換えるといった最適化を独自に施しています。

また、Raspberry Piでは検証済みではありますが、MinnowBoard MAXについてはソースコードの移植のみで動作確認ができていないため、このハードウェアで使う場合はいくらかの修正が必要になります。

たとえば「BcmGpioControllerClass」はその名の通り、Raspberry Piに搭載されているBroadcom社のBCMシリーズのチップを低レベルで制御するためのGPIOクラスなので、BayTrailチップでは「BtFabricGpioControllerClass」に置き換えなくてはいけません。

こちらはRaspberry PiにおいてGPIO6への入力を調べるコード例です。関数のはじめが小文字であったり、WinRT APIにはあるPullDownに相当する定数が無いなど、Arduinoを意識した構成であるのが特徴的です。

BcmGpioControllerClass bgc;
ULONG state;
bgc.setPinMode(6, INPUT);
/* "setPinMode"は以下の関数と同義
setPinFunction(6, 0); // Use as GPIO
setPinDirection(6, DIRECTION_IN);
setPinPullup(6, FALSE);
*/
bgc.getPinState(6, state);
if(state == HIGH){}


DMAP対応版サンプル制御プログラムは前回とほぼ同じ振る舞い(可変抵抗で左右に移動、タクトスイッチでタッチのシミュレート)をします。ただし、GPIOの反応が相当速くなったことに伴い、タクトスイッチの反応もかなり敏感になっているため、いわゆるチャタリングが発生しやすくなっています。そのためinterruptによるハンドリングではなく、ループ内で非常に短い間隔での切り替えを排除したスイッチのチェックを行っています。


もちろん、デバイスマネージャーで「Direct Memory Mapped Driver」を有効にしておかないと動作しません。

サンプルソースのダウンロード(IoTプログラミングのページに移動します)
, | 2017年5月10日