LPC1114FN28/102 (21) -- ICSP 接続で PIC32MX のフラッシュに書き込む (6)

「Psuedo Operation」の「SendCommand()」は JTAG TAP (Test Access Port) のインストラクション・レジスタ (IR) に値を設定するもので、「XferData()」はデータ・レジスタ (DR) に値を設定すると共に、その値が書かれる前の DR の値を読み出す操作です。
両者は、対象が IR と DR の違いだけであり、対象のレジスタに対してシフト入力ステートに遷移させる TMS のシーケンスとしては、1 ビットだけ異なります。
具体的には、

  • (Run-Test/Idle) → (Shift-IR) : TMS = 4'b0011
  • (Run-Test/Idle) → (Shift-DR) : TMS = 3'b001

という違いだけです。
したがって、それぞれの Pseudo Operation での違いは、この TMS ヘッダ (プロローグ) 部分だけです。
Shift-IR / Shift-DR ステートで TMS = 0 を維持する限りは、Shift ステートにとどまり続けます。 転送すべきコマンド / データの MSB を TDI から送出するタイミングで TMS = 1 を送ると、TAP コントローラは Exit1-DR / Exit1-IR ステートへ遷移し、DR / IR へのシフト入力が終了します。
Update-IR / Update-DR ステートを経由して、 IR / DR の値の変更を有効にした後、最初の Run-Test/Idle ステートに遷移する TMS シーケンスは、IR / DR どちらに対しても TMS = 2'b01 となります。
C の関数として ICSP_SetCommand() 関数と、ICSP_XferData() 関数を具体的に書くと下のリストのようになります。

uint32_t ICSP_SetCommand(uint32_t len, uint32_t command)
{
  uint32_t oData;

  ICSP_SetMode(4, 0x03); // TMS header = 4'b0011
  oData = ICSP_2w_xmit(len, command, (1UL << (len - 1)));
  ICSP_SetMode(2, 0x01); // TMS footer = 2'b01
  return(oData);
} // uint32_t ICSP_SetCommand()

uint32_t ICSP_XferData(uint32_t len, uint32_t iData)
{
  uint32_t oData;

  ICSP_SetMode(3, 0x01); // TMS header = 3'b001
  oData = ICSP_2w_xmit(len, iData, (1UL << (len - 1)));
  ICSP_SetMode(2, 0x01); // TMS footer = 2'b01
  return(oData);
} // uint32_t ICSP_XferData()

SetCommand() では戻り値は必要なく、void 型で構いませんが、単に呼び出し側で関数値を捨てるだけとして、XferData() に合わせて関数の形にしています。
この 2 つの関数の差はごくわずかなので、実際のプログラムでは、XferFastData() 関数とも統合した下請けの関数ひとつにまとめています。
その関数の呼び出し時に追加のパラメタを指定することで 3 種の機能のどれを実行させるかを選びます。
前回示した IDCODE 読み出しを XferData() 関数を使って書き直すと、次のように簡潔になります。

uint32_t ICSP_read_IDCODE2( void )
{
  ICSP_SetMode(6, 0x1F);
  return(ICSP_XferData(32, 0));
} // uint32_t ICSP_read_IDCODE2()

XferFastData() と XferInstruction() については、もう少し前提となる話が必要になるので、説明は後に回します。
ホスト PC 上の「書き込みプログラム」としては、Microchip 社のアプリケーション・ノート AN1388 に示されている PIC32 上のブートローダの「相棒」となる PC アプリケーション「PIC32UBL.exe」を使うことにしました。
つまり、LPC1114 上の書き込みプログラムはシリアルで接続されているホスト PC 上の PIC32UBL に対しては、あたかも PIC32 に書き込まれているブートローダのように振舞って通信し、ターゲットの PIC32MX チップにたいしては ICSP 接続でフラッシュ書き込みを行います。
PIC32UBL は Microsoft Visual Studio .NET 2003 を使って書かれており、ソース一式も付属しているので、変更を加えることも可能ですが、何も手を入れなくても利用できる見込みです。
LPC1114 側はブートローダのように振舞うといっても、本当のブートローダではないので、PIC32MX に書き込むオブジェクトはブートローダを使わず「自力」でリセット・ベクタから立ち上がるものでなければなりません。
一般的に、ブートローダは自分自身が使用しているフラッシュ領域への書き込みは拒否し、アプリケーション・プログラムと「共用」すべきコンフィギュレーション・ワードの書き込みも拒否します。
ホスト PC 上の書き込みアプリケーションがブート・フラッシュ領域や、コンフィグ領域への書き込みに対して厳密に検査を行ってターゲット側に送らないような作りでは、「ブートローダ偽装」モードではうまく動作させることはできません。
その点、PIC32UBL はいい意味で「ルーズ」です。
PIC32UBL では、フラッシュ書き込みデータとして読み込む intel HEX ファイルの中身については何も検査せず、単にバイナリに変換するだけでターゲットへ送信します。
したがって、ブート・フラッシュ領域や、コンフィグ領域への書き込みも削除されることはありません。
「ベリファイ」(実態は CRC 照合) に関しては、PIC32UBL では intel HEX ファイルの内容をメモリに読み込み、ブート・フラッシュ領域 (0x1FC00000 〜) については除外し、プログラム・フラッシュ領域 (0x1D000000 〜) のみをベリファイの対象としています。
つながっているブートローダに対しても、バージョン番号を問い合わせて表示するだけで、実際にどのチップが接続されているかに関しては何の検査も行いません。
また、ブランク・チェックの機能もないなど、書き込みアプリケーションとしての機能は低いのですが、「110 円マイコンで 220 円マイコンに書き込む」プロジェクトにとっては一番の近道だと思います。
LPC1114 側のプログラムの状況としては、PIC32UBL との通信 (request/response) は問題なく実現できており、ベリファイについては正常に動作しています。
イレース / プログラムについては、ほぼ出来上がっていますが、まだ実際にフラッシュに書き込み動作を行う試験は実施していません。