FPGAローダーはLabVIEWで作成します。 パート2

USB経由で構成をFPGAにダウンロードするか、FTDI MPSSEを逆アセンブルします

FPGAローダーはLabVIEWで作成します。 パート1











最初の記事では、古き良きCでロードアルゴリズムをテストし、2番目の記事では、LabVIEWでプログラムを整理し、シンプルなユーザーインターフェイスを実装する方法を見つけました。 今回は、LabVIEWの新しい作業方法に精通し、エラー処理の機能を分析してプロジェクトを完了します。構成ファイルをFPGAにロードするためのプロトコルを実装します。



エラー処理



ソースコードを開き、関数MPSSE_openを分析します。 アルゴリズムの単純さ(関数は次々に呼び出されます)にもかかわらず、インポートする必要があるD2XX API要素は非常に多くあります。 前の記事で示したように、関数のインポートはCall library Function



ノードを使用して実行されます。 このノードには、エラー制御専用のターミナルがあります。 LabVIEWには1つの簡単なルールがあります。すべてのVIはエラーを追跡し、エラー端子から返されるエラーを報告する必要があります。 ほとんどの組み込みVIは、厳密にこれに従います。 特にデバッグ段階で、エラーを制御および処理することがどれほど重要かを誰もが理解してくれることを願っていますが、これが非常に重要であるもう1つの理由があります。 LabVIEWのブロック図には厳密なシーケンスのデバイスがありません。入力でデータが準備されると、デバイスが実行されます。 1つのVIの出力からのデータが別のVIの入力に送信される場合、最初のVIは2番目のVIの後にのみ機能することは明らかです。 しかし、データ転送がなく、VIが独立したアクションを実行するとどうなりますか? もちろん、面倒な「フラットシーケンス構造」を使用できますが、エラーのストリームによってデバイスを相互に接続する方がはるかに便利です。







D2XX関数をインポートすると、2種類のエラーが発生します。 最初の-これは直接インポートエラーですCall library Function



ブロック自体を返します。 2番目はライブラリ自体のエラーであり、ほとんどすべての関数によってFT_STATUS



を介してFT_STATUS



ます。 可能なすべての値は、ヘッダーファイルftd2xx.hに列挙として記述されています。 FT_OK



値にエラーがないこと、および他のすべての値がエラーコードであることを知るだけで十分ですが、エラーの事実だけでなく、発生したエラーと正確に発生した場所も追跡したいと思います。







LabVIEWでは、エラーデータはerror



クラスタを介して伝播されerror



。 これは非常に特別な専用データタイプであり、LabVIEWにはそれを操作するための多くのVIと関数があります。 エラークラスターは3つの要素で構成されます。論理変数-ステータスの表示、符号付き整数-エラーコード、文字列-エラーのソース。 ステータスはエラーが発生したかどうかを示し、エラーコードはそのタイプを決定し、レポートを生成するために特別なVIによって使用されます。 この行は、エラーが発生した正確な場所をより詳細に示しています。 ステータスがTRUE



場合、これはエラーであり、ステータスがFALSE



場合、これはエラーですが、コードはゼロではなく、説明行は空ではありません。ステータスがFALSE



、コードがゼロ、行が空の場合、これは警告です-エラーはありません











LabVIEWには、各エラーコードがその説明に関連付けられている内部データベースが含まれています。 エラーの種類ごとに特別な範囲のコード値が割り当てられます。 たとえば、ネットワークの動作に関連するエラーには、-2147467263〜-1967390460、61〜65、116〜118および122、1101、1114、1115、1132〜1134、1139〜1143、1178〜1185の範囲が割り当てられます。ユーザー定義エラーの場合、-8999〜8000および5000〜9999の2つの範囲が予約されています。これらの範囲から、D2XXライブラリのエラーコードの値を選択できます。







入力としてD2XX関数のステータスを受け取り、このステータスをLabVIEWエラークラスタに変換するVIを作成しましょう。 Error In



入力でTRUE



ステータスを受け取ったLabVIEWのほとんどの関数とVIは、コードを実行せず、エラー情報をError Out



端子に転送します。 これにより、ソースに関する情報をチェーン全体を通じてエラーハンドラに効率的に転送でき、緊急モードでのコードの実行が不要になります。 VIが同様に動作することが望ましいです。







D2XXステータスのリストをenum



の形式で整理し、別のタイプに配置します(前の記事でこれをFTDIタイプで行いました)。







列挙型FT_Status






新しいVIをFT_error.viという名前で保存します。 2つのクラスターError In



Error Out



フロントパネルに追加します。それらは[Array、Matrix&Cluster]パネルで見つけることができます。 前の記事ですでに述べたように、それらをそれぞれ左下隅と右下隅の接続パネルの端子に接続します。これはLabVIEWで採用されているエラーフロー端子の場所です。 Case



構造をブロック図に追加し、 Error In



クラスターをCase selector



入力に送信します。その後、 Case



構造の色が変わり、「エラーなし」-緑、「エラー」-赤の2つのサブダイアグラムに分割されます。 エラーケース内で、エラークラスターをセレクターターミナルから直接右境界の出力トンネルに転送します。 そして緑のケースでは、ステータスに応じて別のCase



を追加し、エラーを作成するか(ステータスがFT_OKに等しくない)、そのままにするかを決定します。入力エラークラスターをスキップして変更せずに終了します。







エラーコードを技術的にクラスターに変換するには、エラーコードError Cluster From Error Code VI



VI Error Cluster From Error Code VI



VIを使用できます。 このSubVIはエラーの説明に呼び出しチェーンを追加するため、 が起こったのだけでなく、 どこで起こったのかを判断できます。







入力ステータス(FT_Status)に対応するテキストを選択するには、プロパティブロックを使用します: "RingText.Text"を選択します。 エラーテキストは、 Error Cluster From Error Code VI



error message



入力に送信されerror message





「話す」アイコンを描くことを忘れないでください。







FT_error.vi



フロント(フロント)サブインストルメントパネル









ブロック図。 入力エラー









ブロック図。 入力にエラーはなく、ステータスはFT_OKです









ブロック図。 入力にエラーはありませんが、ステータスはFT_OKとは異なります









FT_errorをテストするには、空のVIを作成し、作成したVIをそこに追加し、さまざまなステータスが適用された場合に起動時に値がどのように変化するかを確認します。







FT_error.viテスト



デバイスのフロント(フロント)パネル









ブロック図







ここで、D2XX APIから関数を呼び出した後、SubVI FT_error.viを使用します。 エラーのクラスターは、呼び出し階層全体のすべてのVIを通過します。







トップレベルVIでは、検出されたエラーの処理方法を決定する必要があります。ダイアログボックスにメッセージを表示したり、レポートファイルに書き込んだり、無視したり、単に「サイレント」にアプリケーションを終了したりできます。 ダイアログボックスは、エラーを報告する最も簡単で最も一般的な方法です。 また、何もする必要がないので、初心者のプログラマーにとっても便利です。 各VIでは、 自動エラー処理モードがデフォルトで有効になっています(VIプロパティメニューの実行カテゴリにある自動エラー処理を有効にする)。 これは次のように機能します。一部のノードでError Out



出力出力端子がどこにも接続されておらず、このノードでエラーが発生した場合、LabVIEWはアプリケーションを一時停止してダイアログボックスを表示します。 ノードのError Out



端子が接続されている場合、エラーストリームはプログラムされたとおりに伝播し、追加のアクションは発生しません。 ただし、メッセージウィンドウはプログラムで呼び出すことができます。そのためには、 General Error Handler



およびSimple Error Handler



VI(ダイアログとユーザーインターフェースパネルにあります)を使用する必要があります。 この場合、エラー情報を使用してプログラムを完了することができます。 ブロック図では、次のようになります。









クリック可能な画像







エラーが発生すると、プログラムは中断され、レポートウィンドウが表示されます。ウィンドウを閉じた後、プログラムは正しく終了します。







レポートウィンドウ







FTDIの開閉



したがって、 MPSSE_open



関数にMPSSE_open



ます。 新しいVIを作成します。 まず、エラーストリーム用のターミナルを追加します。 選択構造を追加し、セレクターで[ Error In



入力]を選択します。 緑色の場合、Sishnyプロトタイプの場合と同じ順序でパラメーターを使用して関数をインポートします。 Call Library Function Node



ノードのすべてのノードは、エラーのストリームによってチェーンで接続されています。 トンネルを通る赤いケースでは、エラー入力をError In



の出力端子に接続します。









クリック可能な画像









VI MPSSE_open.vi







FTDIのDescription



Description



)を含む行がSubVIの入力に送信され、出力はHandle



およびMPSSEモードの初期化されたFTDIチップです。







FTDIの使用を終了するVPを作成してみましょう。ハードウェアのパフォーマンスを既に確認できます。







FT_Close.vi



ブロック図









フロントパネル







前回の記事で、インターフェースをデバッグするために、VIスタブSP_FT_MPSSE_FPGA.viを作成しました。今度は、それを埋めるときです。 MPSSE_open.viおよびFT_Close.viをブロック図に追加します。 この段階では、初期化が正しいかどうかを評価するのは非常に困難ですが、MPSSE_open.viの出力のHandle



ゼロ以外の値とエラーがないことは、多くを教えてくれます。









フローチャートSP_FT_MPSSE_FPGA.vi







Handle



の値を確認するには、「Probe Watch Window」を使用できます。 これは、デバイスの実行中に任意の(ほぼすべての)ワイヤにデータの値を表示できる便利なデバッグツールです。 行にサンプルを設定するには、この行のコンテキストメニューで[プローブ]を選択する必要があります。 「Probe Watch Window」ウィンドウが開き、行にサンプル番号付きの番号が表示されます。 上の図では、「3」です。







プローブウォッチウィンドウ



ハンドル行の値698389336







いいね! トップレベルVIを起動し、デバッグボードをコンピューターに接続します。 接続されたFTDIチップの説明が[デバイスの選択]リストに表示され、[プログラム]ボタンをクリックしても...何も起こりません。 「Probe Watch」ウィンドウでのみ、値Handle



が表示されました。 そしてそれは良いことです。







ボードをオフにすると、デバイスのリストがクリアされます。 [プログラム]をクリックします。 ここで、エラーレポートウィンドウが表示されます。







レポートウィンドウ







「続行」ボタンをクリックすると、VIは作業を完了します。







デバイスが見つからない場合、ボタンを押すことは禁止されています。 ケースの「タイムアウト」イベントハンドラを変更します。 PCに接続されたFTDIチップが検出され、FPGAのプログラミングに使用できる場合、その記述子はStrings[]



プロパティを介してDevices list



追加されます。 「プログラミング」のDisabled



プロパティを作成し、適切なデバイスが見つからない場合は、ボタンをオフにして暗くします。







ケースのタイムアウト



写真はクリック可能です







GPIOをマスターする



MPSSEがアクティブになった後、いわゆる "op-code"を使用してFT_Write



が行われ、 FT_Write



API関数ではFT_Write



FT_Read



、およびFT_Queue



のみが使用されます(レシーバーバッファーのステータスを確認するため)。 作成したトラックに沿って、FT_Write.vi、FT_Read.vi、FT_Queue.viに対応するVIを作成します。







ちょっとしたルーチン



FT_Write.vi









ブロック図。 FT_Write.vi









FT_Read.vi









ブロック図。 FT_Read.vi









FT_Queue.vi









ブロック図。 FT_Queue.vi







これら3つのブリックから、パラレルポートの読み取りと書き込みのためのVIをレイアウトします。 値は、ブール変数の配列として便利に表されます。







MPSSE_Set_LByte.viおよびMPSSE_Get_LByte.vi



MPSSE_Set_LByte.vi









ブロック図。 MPSSE_Set_LByte.vi









MPSSE_Get_LByte.vi









ブロック図。 MPSSE_Get_LByte.vi







私はすべてのオペコードの名前付きリストを作成するのが面倒だったと告白したので、それらをマジックナンバーの形で残しました。







最初の記事で述べたように、パッシブシリアルFPGAブートプロトコルは、フラグ操作を追加したSPIにすぎません。 合計で5つのレッグが使用されます: DCLKDATA [0]nCONFIGラインは出力、 nSTATUSCONF_DONEラインは入力として設定する必要があります。







テーブルレイアウトのピン配置
FPGAピン ピン名 ピン MPSSE 方向 デフォルト
DCLK BDBUS0 38 TCK / SK アウト 0
データ[0] BDBUS1 39 TDI / DO アウト 1
nCONFIG BDBUS2 40 TDO / DI アウト 1
nSTATUS BDBUS3 41 TMS / CS 1
CONF_DONE BDBUS4 43 GPIOL0 1


他のすべてに影響を与えることなく、選択したレッグの値を変更できるVPが必要です。 まず、ポート内のレッグのシリアル番号を使用してEnum



を作成し、SP_LBYTE_BITS.ctlファイルに「Strict Type Def」として保存します。 新しいVIを作成し、使い慣れたエラーフローターミナルを追加します。 MPSSE_Get_LByte.viを使用してパラレルポートの現在の値を読み取り、 Replace Array Subset



関数を使用して目的のビットを変更し、値をポート(MPSSE_Set_LByte.vi)に書き戻します。







SP_Set_Flag.vi



SP_Set_Flag.vi









ブロック図。 SP_Set_Flag.vi









列挙型SP_LBYTE_BITS.ctl







コンフィギュレーションを開始するには、MPSSEはnCONFIGラインでLowからHighへの遷移を生成する必要があります。 FPGAがデータを受信する準備ができるとすぐに、 nSTATUSラインで高レベルを形成します。 この段階では、すべてが鉄での実験の準備ができています。 ブロック図SP_FT_MPSSE_FPGA.vに、制御線nCONFIGを追加します-MPSSEの初期化の後、低レベルを与え、次に高レベルを与えます。 各操作の後(デバッグ用)、ポートレッグのステータスを読み取ります。







SP_FT_MPSSE_FPGA.vi



起動中









ブロック図







一般に、VIの起動中、FPGAがnCONFIGラインの遷移に応答することは明らかです。nSTATUSレッグにゼロが設定され、次に1が設定されます。 しかし、これをオシロスコープで監視することは不必要ではありません。 ほとんどすべての2チャンネルオシロスコープは、トリガー(スタンバイ)で実行する機能を備えています。 チャネルA (青いトラック)回路nCONFIGの制御点、チャネルB (赤いトラック)-チェーンnSTATUSに配置します。 トリガーは、チャンネルAの立ち下がりエッジに設定されます









写真はクリック可能です。 詳細に!







ファイルを操作する



FPGAは構成ファイルを受け入れる準備ができています。 ファイルをFPGAに転送する準備はできていますか?







LabVIEWには、ファイルを操作するための広範なツールセットが含まれています。 機能がすべてのタスクに絶対に十分であるとは言えませんが、 読み取り書き込みなどの基本的な操作は簡単かつ快適に実行されます。 ファイルを操作するためのVIの基本セットは、「ファイルI / O」パネルにあります。 問題を解決するには、構成ファイルを開き、そのサイズを評価し(FPGAに送信するバイト数を知る必要があります)、それを読み取って閉じます。 すべてがシンプルで、次々とあります。 Get File Size



Open/Create/Replace File



Get File Size



Get File Size



Get File Size



Read from Binary File



Get File Size



Get File Size



Close File



refnum



、それらをエラーフローチェーンとrefnum



と組み合わせます。ファイル記述子などの番号は、ファイルを開くときに作成され、他のVIの入力に転送する必要がありますこのファイル。







これまで、読み取ったデータを破棄する場所はありませんが、チェーンの操作性を本当に確認したい場合は、 String



型のインジケーターを作成して、少しセットアップすることができます。 コンテキストメニューで[16進表示]オプションを有効にし、垂直スクロールバーをオンにして([表示項目]-> [垂直スクロールバー])、起動後、バイナリ構成ファイルの内容を確認します。







SP_FT_MPSSE_FPGA.vi



フロントパネル ファイルの内容を見る









ブロック図。 カリンカクリッカブル







VIのブロック図では、コードの2つの独立した平行線が形成されているため、別々のエラーチェーンが使用されます。 並列フローを1つのError Out



端子に減らすために、 Error Out



Merge Errors



機能が使用されます。 この関数は、入力のエラーを上から下に検索し(はい、3つ以上の入力端子があり、マウスで引き伸ばされます)、最初に見つかったものを返します。 エラーがない場合、最初の警告メッセージを返します。 警告がない場合は、出力にエラーはありません。 Merge Errors



入力が接続される順序がMerge Errors



の優先度を決定し、2つのチェーンでエラーが同時に発生した場合、下位のエラーは無視されることに注意することが重要です。 これは慎重に扱う必要があります。







ファイルを選択せず​​にトップレベルVIの「プログラム」ボタンを押そうとすると、入力SP_FT_MPSSE_FPGA.viは空のパスを受け取り、エラー「エラー1430。LabVIEW:(Hex 0x596)パスは空または相対です。絶対パス。」 私の幼なじみの友人が言うように:「トリッフル、これは世俗的なものです!」 そして、この間違いはまったくの間違いではなく、むしろユーザーの不注意です。 プログラムを停止せず、赤い十字の付いたウィンドウで誓います。このコードのエラーをストリームから削除するだけで、ダイアログボックスでファイルを選択することをお勧めします。 エラーをフィルタリングするには、「ダイアログとユーザーインターフェース」パレットの「エラーをクリア」VIを使用します。 メッセージを表示するには-「ワンボタンダイアログ」。













ブロック図



写真はクリック可能です







設定をダウンロード



シリアルデータ転送の場合、MPSSEプロセッサはop-code 0x18を送信する必要があります。コマンド引数は、送信されたシーケンスの長さ(下のバイトから始まる2バイト)とデータシーケンス自体になります。 長さは1を引いてエンコードされます。 VI MPSSE_sendとしてデータブロックを送信しましょう。







MPSSE_Send.vi



MPSSE_Send.vi









ブロック図







入力バッファーのArray Size



Array Size



)は2バイトタイプU16



に変換され、1を減算し、下位バイトと上位バイトをSwap Bytes



ます( Swap Bytes



)-最下位から開始して長さを送信し、2バイト数をシングルバイト配列に変換する必要があります( Type Cast



)。







Type Cast



関数には特別な注意が必要です。 これはそのような普遍的なタイプのコンバーターであり、その創意工夫は時には非常に驚くべきものです。 要するに:









プログラマー向けに視覚的に







ただし、これはデータを異なる型にキャストするだけでなく、ヒューリスティックな解釈でもあります。 この関数を使用すると、互換性のないデータ型間の変換を実行できますが、関数は入力データを整列させ、「余分な」部分を削除することをためらいません。 要求されたデータ型が入力データより多くのメモリを必要とする場合、関数は不足している量を割り当てます。 初心者の開発者にとって、LabVIEW Type Cast



は命の恩人になる可能性がありますが、成長するにつれてそのようなコンバーターを拒否する方が良いです-見えないように隠され、予期しないエラーの原因になります。 Coerce To Type



など、より明示的な変換メソッドを使用する方が適切です。







MPSSEプロセッサを初期化するとき、データ転送の最大許容バッファサイズを65536バイトに設定するため、構成ファイルを指定サイズを超えないサイズのフラグメントに分割する必要があります。 Array Subset



関数を使用します。この関数は、 index



要素とlong length



始まる配列からサブ配列を選択します。 While



ループで中断し、インデックスの各反復を65536ずつ増やします。反復の間にシフトレジスタに値を渡します。 メインアレイから65536バイトを挟むことができないとすぐに、残っているものをすべて取り出して送信し、サイクルを停止します。







ダウンロードプロトコルによると、すべてのデータが転送された後、FPGAの初期化を開始するには、さらに2つのクロックパルスを適用する必要があります。 これを行うには、ループの後、別の「空の」バイトを送信します。







SP_FT_MPSSE_FPGA.vi



写真はクリック可能です







ファームウェアの成功を理解するために、フラグを考慮し、 CONF_DONEが 1に設定されている場合、すべてが正常であることを最上位VIに報告します。







プログラムが完了しました。 FPGAが正常にフラッシュされ、ボードがLEDで楽しく点滅することを確認するために残っています。







VPの命名について



古典的なプログラミングでは、すべてのユーザーオブジェクトと関数に意味のある名前を付ける必要があることは秘密ではありません。特にLabVIEWについても同じことが言えます。特にSubVIがオブジェクトとして機能する場合。 . :









( ), . subVI .







おわりに



, , .













, LabVIEW, . , , , ( ). .









  1. . LabVIEW: . . 英語から . .– .:

    , 2008 – 400 .: .
  2. labview_mpsse . .
  3. .
  4. Software Application Development D2XX Programmer's Guide . API D2XX.



All Articles