平成27年 1月 11日
MPLAB Harmonyの使い方(12) USBライブラリの導入(5) プログラムへの疑問
MPLAB Harmonyプログラムは非常に良く出来たプログラムだと思うのですが、どうもUSBライブラリに関しては疑問符がつく部分が見受けられます。
このプログラムのアプリケーションレベルでのIF関数はUSB_DEVICE_CDC_Read()とUSB_DEVICE_CDC_Write()です。
適切な引数をつけて呼び出します。処理の終了はappData.appCOMPortObjects[com_no].isReadCompleteおよびappData.appCOMPortObjects[COM1].isWriteComplete
の値によって確認できます。
ここまでは普通の関数です。
疑問点1.読み出し要求によって取得した文字数を知る術がない。
問題はRead要求で読み出した文字数を知る術がアプリケーションレベルにはないのです。逆のWrite要求では全てを書き出すまで完了を返すことはないので問題はありません。普通なら読み出し要求の引数に実際に読み出した文字数を返すかグローバル変数内のアプリケーションレベル変数に値を記憶してくれることを期待したのですが、これがありません。
仕方がないのでプログラムを割り込み処理ルーチンから逆に追跡して受信文字数を記録している変数を見つけました。
グローバル変数の中にはあるのですが、プログラムの階層からみるとドライバレベルの階層に変数が置かれているように思えます。
プログラムの見通しを良くするなら、アプリケーションレベルでこれを読み出す関数かマクロを用意しておくべきでしょう。
疑問点2. 構造体内部の変数型の決め方が理解できない。
MPLAB Harmonyではライブラリ変数の大半をappDataという名前の構造体に保管しています。この中のCDC関連の変数がAPP_COM_PORT_OBJECTという構造体です。下記にその内容を示します。
app.h 110行目付近
typedef struct
{
USB_DEVICE_CDC_INDEX cdcInstance;
/* Set Line Coding Data */
USB_CDC_LINE_CODING setLineCodingData;
/* Get Line Coding Data */
USB_CDC_LINE_CODING getLineCodingData;
/* Control Line State */
USB_CDC_CONTROL_LINE_STATE controlLineStateData;
/* Break data */
uint16_t breakData;
/* Read transfer handle */
USB_DEVICE_CDC_TRANSFER_HANDLE readTransferHandle;
/* Write transfer handle */
USB_DEVICE_CDC_TRANSFER_HANDLE writeTransferHandle;
/* True if a character was read */
bool isReadComplete;
/* True if a character was written*/
bool isWriteComplete;
}APP_COM_PORT_OBJECT;
ここで疑問視しているのは型USB_DEVICE_CDC_TRANSFER_HANDLEです。
この型の変数は二つあり、その変数名からもこれが送信および受信に関する情報を記憶しているであろうことは予想できます。
この型の定義は以下のように定義されています。
usb_device_cdc.h 506行目
typedef uintptr_t USB_DEVICE_CDC_TRANSFER_HANDLE;
HANDLEという命名やunsigned int へのポインタという型から、実体もunsignedintへのポインタと思いたかったのですが、記憶されているのはドライバレベルで使用される構造体へのポインタです。階層構造上の見通しから下位の構造体の中身を隠したいのならvoid*(void型へのポインタ)とした方が適切でしょう。
このデバッグの中で幾つか使い勝手の良い機能やその制約が見つかりました。次回それについて少し書いてみます。