PSoC 4200 Prototyping Kit (21)

アプリケーション・ノート AN68272 では、次のふたつのタイプの UART Bootloader Host のサンプル・コートについて説明されています。

  • Bootloader Host コア部分の C ソース・コード
  • Visual C# 2010 による UART Bootloader Host GUI サンプル・アプリケーション

1 番目は Bootloader Host のコア部分を C 言語で記述したもので、それだけではアプリケーションとしては成立しません。
アプリケーションに仕立てるには、「足回り」となるシリアル通信部分と、ユーザー・インターフェース部分を追加する必要があります。
このコア部分の C ソース・コードは、何もしなくても、すでに PSoC Creator 本体とともにインストールずみであり、その場所は PSoc Creator 3.0 SP2 では

... PSoc Creator\3.0\PSoC Creator\cybootloaderutils

のフォルダです。 PSoC Creator 3.1 (SP1) では、上記のパスの「3.0」を「3.1」に変えたパスになります。
3.0 と 3.1 とでファイルの内容に一部相違がありますが、外部から見た API 関数の仕様や動作に変わりはありません。
AN68272 では、ターゲット・チップとは別の PSoC チップを Bootloader Host として機能させるためのプロジェクトの例を取り上げており、関連するアーカイブ・ファイル AN68272.zip の中ににプロジェクト・ファイル一式が含まれています。
今回は、Visual C++ 2008 Express Edition を使用して、Win32 コンソール・アプリケーションとして実現しました。 といっても、C++ の機能は一切使わずに、すべて C 言語で記述してあります。
Bootloader Host コア部分では、足回りのシリアル通信レイヤーと次の 4 つの関数を通してインターフェースします。

/* Function used to open the communications connection */
    int OpenConnection( void );

/* Function used to close the communications connection */
    int CloseConnection( void );

/* Function used to read data over the communications connection */
    int ReadData(unsigned char *buf, int cnt);

/* Function used to write data over the communications connection */
    int WriteData(unsigned char *buf, int cnt);

実際には、「関数ポインタ」を渡すので、関数名自体は任意に選べます。
Bootloader Host からターゲットへコマンド・パケットを投げて、ターゲットからレスポンス・パケットを受け取ることを繰り返してホストとターゲットとの間の通信を成立させています。
ターゲットに投げるコマンド・パケットの種類により、ターゲットが返すべきレスポンス・パケットのサイズは決まっているので、ReadData() 関数では読み込むべきバイト数を引数で指定するようになっています。
コア部分では、返されたレスポンス・パケットを解析し、エラーがなければ次のコマンド・パケットを送るという作りになっているので、Write / Read はオーバーラップすることはありません。
したがって、Write / Read ともに同期 / ブロッキング / ノン・オーバーラップ入出力ですむことになり、非同期 / ノンブロッキング / オーバーラップ 動作は不要で、スレッドを使う必要もなくプログラムが簡単になります。
ただし、受信キャラクタが欠損するなどして、レスポンス・パケットが損傷をうけると、足りないバイトを永久に待つことになってしまいますから、ReadData() 関数では「タイムアウト機能」を利用して、指定されたバイト数まで受信しなくても、タイムアウトが生じた場合にはリターンするようにします。
前回、CDC ドライバを Microsoft 製のものに差し替えたら確実性が増したが 100 % ではないと述べましたが、どうやら、確率は低いのですがタイムアウトすべきでない状態でタイムアウトになって、レスポンス・パケットの途中でリターンしてしまうのが原因のようです。
指定バイト数まで受信しないうちにタイムアウトになった場合にすぐに帰らずに、もう一回だけパケットの残りを受信するような変更を施したら改善しました。
UART Bootloader Host GUI アプリケーションについては次回に回します。