OpenOCD、GDB、および(強力な)リモートデバッグ

想定:ARM926E-JS(Cypress FX3)を搭載したデバイスがあります。 デバイスは別の大陸にあります。 デバイスはLinuxコンピューターに接続されます(JTAG + USB + COM)。 コンピューターにはSSHアクセスがあります(SSHポートのみです)。



問題:デバイスのデバッグとコードの記述が必要です。 そして、これを行うことは、できれば便利です。



OpenOCD、GDB、およびQt Creatorを使用したソリューションと、そのパスの説明がカットされています。



この問題には多くの解決策があります。 最も速くて簡単な方法:sshセッションを介してリモートコンピューターでGDB + OpenOCDバンドルを起動します。 利便性はあまりない コードをローカルで編集する方が便利です。デバッグするには、scpまたはrsyncを使用してサーバーにコードを常にアップロードする必要があります。



少し考えた後、アイデアが浮かび上がります。しかし、SSHを使用してサーバー上でコマンドをリモートで実行できます。

ssh user@host some-command some-arguments
      
      





うーん...また、GDBはOpenOCDをパイプモードで実行して通信できます。 そのため、OpenOCDだけでなくsshを介してリモートのものを起動し、結果として得られた束をデバッグに使用するようにできます。



残念ながら、このオプションは実行不可能であることが判明しました。接続はタイムアウトによって絶えず落ちました。



次のアイデアは、どういうわけかVPNを上げて、それを使用してサーバー上の任意のポートに接続し、OpenOCDをリモートで実行することでした。



しかし、SSH以外のポートがない場合にVPNを上げる方法は? OK、SSHがポートを転送できることを知っています。 OpenOCDをリモートで起動し、ポートを転送します...はい、パイプラインモードで起動するよりも少し良いです。 しかし、それは少しだけです。 仕事には適していません。



私はこのビジネスをやめ、最初の、シンプルで、信頼できるが、不便なソリューションを使用することにほぼ決めましたが、その後、Googleの束にダイヤルしました:SSH VPN。 私が驚いたと言うことは、何も言わないことです。 探しているものは何でも、これらの2つのリンクで十分です。



設定後、アドレス192.168.100.1のTap8インターフェースがリモートマシンにローカルに表示されます:アドレス192.168.100.2のtap7インターフェース(アドレスは後で便利になります)。



実行しようとしている...ああ奇跡! ソリューションは機能していることが判明しました! コードがロードされ、すべてが機能し、ブレークポイントが設定されます。 問題は1つだけあります。ゆっくりです。 そして、状態の更新(スタックトレース、ローカル変数など)の期待に耐えることができる場合、300 kBのelfのダウンロードには6分以上かかります。 ローカルで高速。 かなり。



いずれにせよ、このスキームを実装するスクリプトをいくつか紹介します(SSH設定は提供していません)。

  1. openocd-remoteは、sshを介してリモートOpenOCDを実行するための単なるシェルです。 私は場所に注意してください

    ローカルマシンとリモートのファイルとディレクトリを同じように作成しました。 そうでなければ

    sedを使用したパラメーターの前処理は、置換を行うために同じスクリプトに追加されます。 プラス

    OpenOCDはGitからコンパイルされ、 ~/bin/openocd-git/{bin,share}





    コピーされ~/bin/openocd-git/{bin,share}





    ~/bin/openocd-git/{bin,share}





    (対応するディレクトリ)。

    FX3の構成(後で詳しく説明します)は~/bin/openocd-git/





    ~/bin/openocd-git/





    ~/bin/





    ~/bin/





    実行可能ファイルへのsimlink

    openocdファイル。

     #!/bin/sh ssh user@host -T killall -9 openocd exec ssh -TC user@host bin/openocd $@
          
          



  2. gdb-remote-リモートOpenOCDに接続し、コードをロードします。

     #!/bin/sh gdbcfg=fx3_gdb.ini elf=some-code.elf cat > $gdbcfg << EOF set prompt (arm-gdb) set remotetimeout 30 target remote 192.168.100.1:3333 monitor halt monitor soft_reset_halt monitor adapter_khz 1000 set endian little load EOF arm-none-eabi-gdb -x $gdbcfg $elf
          
          





起動の高速化について考えると、次のようになりました。単に、elfファイルをリモートサーバーにコピーするのに10秒かかります。 しかし、画像をサーバーにアップロードし、そこから既にデバイスにダウンロードするのはクールです...



OpenOCDのドキュメントを調べると、OpenOCD自体がコードをデバイスにロードでき、GDBが接続してファームウェアを起動するコマンドを与えるだけです。 マジックコマンド: load_image







最初の実験は残念でした。ダウンロードは非常に不安定です。 コードがロードされ、高速でロードされます:1分間対6尾。 ただし、ファームウェアは起動または失敗します。 同時に、同じGDBセッションでload



行われた場合、すべてが正常に開始されます。



彼は違いを探し始めました。 ロードからload



最後の行に興味がある:

 Start address 0x40035948, load size 298456
      
      





これは、コードをload



およびload_image



(OpenOCD経由)でロードした後、レジスタ$pc



内容を開始( continue



)する前にログを記録するように促しました。 そして...違いが見つかりました: load



$pc



この「開始アドレス」に設定されますが、 load_image



load_image



$pc



load_image



、その時点でダウンロードが開始されます。 pc



を正しい値に設定した後、ダウンロードが安定しました。 疑問は残ります:マジックナンバーは賑やかではありません。 しかし、GDBでは文字を指定でき、そのアドレスが取得されるのに役立ちました。 FX3の場合、このシンボルは次のCyU3PFirmwareEntry



ですCyU3PFirmwareEntry



(ちなみに、ローカルアプリケーションでは_start



なります)、 $pc



インストールコマンドは次のようになります。

 set $pc = CyU3PFirmwareEntry
      
      



さらに、GDBにはシェルコマンドを呼び出す機能があります。そのため、起動時にelfファイルをリモートサーバーに簡単かつ簡単にアップロードし、実行中のOpenOCDにコマンドをロードしてそれをロードできます(OpenOCDのコマンドはすべて、単語monitor



先頭に付けたGDBから提供できます)。



GDBを実行する最終スクリプト:

 #!/bin/sh gdbcfg=fx3_gdb.ini elf=some-code.elf #    GDB cat > $gdbcfg << EOF set prompt (arm-gdb) set remotetimeout 30 target remote 192.168.100.1:3333 shell scp $elf user@192.168.100.1: monitor halt monitor soft_reset_halt monitor sleep 1000 monitor load_image %elf 0x00 elf set $pc = CyU3PFirmwareEntry EOF arm-none-eabi-gdb -x $gdbcfg $elf
      
      



OpenOCDを実行するスクリプトは同じままです。



リモートデバッグを開始するために今必要なもの:

  1. openocd-remoteスクリプトを実行します。 必要に応じて再起動できます。
  2. 上記のスクリプトを使用してコードをビルドし、gdbを実行します。
  3. ...
  4. 利益
利益ですか? 私にとって Qt Creatorでコードを記述し、ワンクリックでこのすべてを実行したいです。 そして、それはワンクリックで行われます。 十分な:

  1. 設定ダイアログを開く
  2. ベアメタルを選択し、次のパラメーターを使用してOpenOCDタイプの新しいGDBサーバープロバイダーを追加します。
    • 名前:あなたの裁量で、FX3 Remoteにしましょう
    • 起動モード:TCP / IPでの起動
    • ホスト:192.168.100.1
    • ポート:3333
    • 実行可能ファイル:openocd-remoteへのパス、私はそれを持っています/ home / alexd / bin / openocd-remote
    • ルートスクリプトディレクトリ:/ home / alexd / bin / openocd-git / share / openocd / scripts-異なる場合があります。

      最も重要なことは、スマートチューナーがこれらのディレクトリの可用性をチェックすることです。

      ローカルコンピューターとリモートで同じツリーを実行しました。
    • 構成ファイル:/home/alexd/bin/openocd-git/share/openocd/scripts/interface/ftdi/olimex-arm-usb-ocd-h.cfg-at

      Olimex ARM-USB-OCD-Hデバッガを使用していますが、別のデバッガを使用している場合があります。 デバッガのセットアップは考慮しません。
    • 追加の引数:-f〜/ bin / openocd-git / fx3-common.cfg -f〜/ bin / openocd-git / fx3-threadx.cfg-これらのスクリプト

      以下に投稿します。
    • 初期化コマンド-最も興味深い:

       monitor echo "Upload image..." shell scp %{DebuggedExecutable:NativeFilePath} user@192.168.100.1: monitor halt monitor soft_reset_halt monitor sleep 1000 monitor echo "Load image..." monitor load_image %{DebuggedExecutable:FileName} 0x00 elf set $pc = CyU3PFirmwareEntry monitor echo "Run image..."
            
            



      ご覧のように、マクロの置換のみを使用してスクリプトのコードを完全に繰り返し、各ターゲットごとに書き換えないようにします。
    • リセットコマンド: monitor reset halt



      (デフォルトで残す)。
  3. 次に、[デバイス]に移動し、[追加]-> [ベアメタルデバイス]->名前を付けて(FX3デバイスリモート)、GDBサーバープロバイダー(FX3リモート)を割り当てます。
  4. 次に、Build&Runsに移動し、Cypress(またはARMまたはそこにあるもの)の使用済みセット(キット)で選択します。

    • デバイスタイプ:ベアメタルデバイス
    • デバイス:FX3 Device Remote
ここでは、ローカルおよびリモート開発用に、セット用に作成する必要がありました。 しかし、まあ...あなたは生き残ることができます。



プロジェクト設定に新しいセットを追加し、それを構成し、[実行]タブで「(GDBサーバーまたはハードウェアデバッガーを介して)」という名前の構成を追加し、F5キーを押すだけでデバッグを開始します。



便利な資料




スクリプトfx3-common.cfg、fx3-threadx.cfg、fx3-boot.cfg(ブートローダーのデバッグ用またはThreadXがない場合)それぞれ:

fx3-common.cfg
 ###################################### # Target: CYPRESS FX3 ARM926-ejs # Common part ###################################### if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME fx3 } if { [info exists ENDIAN] } { set _ENDIAN $ENDIAN } else { set _ENDIAN little } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x07926069 } #delays on reset lines adapter_nsrst_delay 200 jtag_ntrst_delay 200 adapter_khz 1000 #reset_config trst_only #reset_config trst_only combined #reset_config trst_and_srst combined #reset_config trst_and_srst srst_pulls_trst # From the Cypress SDK reset_config trst_and_srst srst_pulls_trst # My own well worked #reset_config trst_only jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID jtag_rclk 3
      
      







fx3-threadx.cfg
 ###################################### # Target: CYPRESS FX3 ARM926-ejs ###################################### #source [find fx3-common.inc] ###################### # Target configuration ###################### set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm926ejs -endian $_ENDIAN -chain-position $_TARGETNAME -rtos ThreadX adapter_khz 1000
      
      







fx3-boot.cfg
 ###################################### # Target: CYPRESS FX3 ARM926-ejs ###################################### #source [find fx3-common.inc] ###################### # Target configuration ###################### set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm926ejs -endian $_ENDIAN -chain-position $_TARGETNAME adapter_khz 1000
      
      









Qt CreatorのARM、FX3などのプロジェクトタイプはGenericにすることができますが、FX3のCMakeルールを作成しました: github.com/h4tr3d/fx3-cmakeおよびCMake Projectマネージャーを使用します。シャドウアセンブリと、複雑なプロジェクトのアセンブリパラメータを混同しない理由。



OpenOCDコマンド: openocd.org/doc/html/General-Commands.html



エントリポイントを自動的に計算するには、Pythonサポートを使用してGDBをコンパイルし、推奨事項を使用できます。




All Articles