OpenOCD入門:組み込み開発者のための基本ガイド


OpenOCD入門:組み込み開発者のための基本ガイド

はじめに:組み込み開発とデバッグの重要性

組み込みシステム開発は、限られたリソースの中で特定の機能を実装する高度な技術分野です。マイクロコントローラーやDSPといったハードウェアを直接制御し、ソフトウェアとハードウェアが密接に連携して動作するシステムを構築します。しかし、この密接な連携こそが、開発におけるデバッグを非常に困難なものにしています。

従来のPCアプリケーション開発とは異なり、組み込みシステムでは画面表示やファイルアクセスなどの高レベルなI/Oが制限されることが多く、問題発生時に内部の状態を把握するのが容易ではありません。フリーズ、予期せぬリセット、不正なメモリアクセス、タイミンングの問題など、ハードウェアとソフトウェアが絡み合ったデバッグは、開発者の頭を悩ませる最大の要因の一つです。

このような組み込みシステムのデバッグにおいて、不可欠なツールとなるのが「デバッグアダプター」とそれと連携するソフトウェアです。デバッグアダプターは、開発用PCとターゲットとなるマイクロコントローラーを物理的に接続し、CPUの停止/実行制御、メモリやレジスタの読み書き、ブレークポイントの設定といった低レベルな操作を可能にします。そして、そのデバッグアダプターを制御し、高レベルなデバッグ環境(GDBなど)と連携させるソフトウェアが、OpenOCDです。

OpenOCDとは何か? なぜOpenOCDなのか?

OpenOCD(Open On-Chip Debugger)は、オープンソースのオンチップデバッガーです。その主な役割は、デバッグアダプター(JTAG/SWDプローブ)を介してターゲットのマイクロコントローラーやプロセッサーに接続し、デバッグやプログラミング(フラッシュ書き込み)の機能を提供することです。

なぜOpenOCDが組み込み開発者にとって重要なのでしょうか?

  1. 多様なハードウェア対応: OpenOCDは非常に多くの種類のデバッグアダプターとターゲットデバイスをサポートしています。安価なFTDIベースのアダプターから、Segger J-Link、STMicroelectronics ST-Link、FTDI FT2232/FT232H、CMSIS-DAP、そして様々なベンダー固有のアダプター(NXP LPC-Link2など)まで、幅広いハードウェアに対応しています。ターゲットデバイスも、ARM Cortex-M/R/A、RISC-V、MIPS、MSP430など、多様なアーキテクチャの多くのマイクロコントローラーやプロセッサーをサポートしています。これにより、開発者は特定のハードウェアベンダーに縛られることなく、様々なボードやチップで共通のデバッグ環境を構築できます。
  2. オープンソースとカスタマイズ性: オープンソースであるため、OpenOCDは自由に利用、改変、配布が可能です。特定のターゲットやアダプターが公式にサポートされていなくても、ソースコードを修正したり、カスタム設定ファイルを作成したりすることで対応できる可能性があります。また、内部の動作が透明であるため、問題発生時の原因特定や、高度なデバッグシナリオの実装が容易になります。
  3. GDBとの強力な連携: OpenOCDは、標準的なGDB (GNU Debugger) リモートデバッグプロトコルをサポートするGDBサーバーとして機能します。これにより、コマンドライン版GDBだけでなく、Eclipse、VS Code、STM32CubeIDE、Keil MDK (一部設定が必要) など、GDBをバックエンドとして利用する多くのIDEから透過的に利用できます。開発者は使い慣れたIDEのデバッグインターフェースを通じて、OpenOCDが提供する低レベルなデバッグ機能を利用できます。
  4. スクリプト機能: OpenOCDはTclスクリプトエンジンを内蔵しており、複雑なデバッグ手順や自動化されたテストシナリオをスクリプトとして記述できます。フラッシュ書き込み後の自動リセット、特定のレジスタ設定、複数ターゲットの同期制御など、応用範囲は広いです。
  5. コスト効率: 安価なデバッグアダプターとOpenOCDを組み合わせることで、高価な商用デバッグツールに匹敵するデバッグ環境を構築できます。これは特に、趣味の開発者や小規模なチームにとって大きなメリットとなります。

OpenOCDは万能薬ではありませんが、その柔軟性、対応範囲の広さ、オープンソースという利点から、現代の組み込み開発において非常に重要なツールとなっています。本記事は、この強力なツールを初めて使う開発者が、基本的な概念から応用的な使い方までを理解し、実際にデバッグ環境を構築できるようになることを目的としています。

組み込みデバッグの基礎知識

OpenOCDを理解するためには、組み込みデバッグの基本的な概念をいくつか押さえておく必要があります。

JTAGとSWD:物理的な接続とプロトコル

デバッグアダプターとターゲットデバイスは、通常、JTAG(Joint Test Action Group)またはSWD(Serial Wire Debug)と呼ばれるインターフェースを介して接続されます。

  • JTAG (IEEE 1149.1): もともとは基板上の回路テスト(バウンダリスキャンテスト)のために開発されましたが、後にオンチップデバッグにも応用されました。通常、以下の信号線を使用します(必須信号以外は省略)。

    • TCK (Test Clock): クロック信号。
    • TMS (Test Mode Select): 状態遷移を制御。
    • TDI (Test Data In): デバッグアダプターからターゲットへのデータ入力。
    • TDO (Test Data Out): ターゲットからデバッグアダプターへのデータ出力。
    • TRST (Test Reset): JTAGステートマシンをリセット(オプション)。
    • SRST (System Reset): ターゲットシステム全体をリセット(オプション)。
      JTAGはフル機能を利用する場合に多くのピンを必要としますが、柔軟性が高く、バウンダリスキャンテストとデバッグの両方に利用できる利点があります。
  • SWD (Serial Wire Debug): ARMによって開発されたデバッグインターフェースで、JTAGよりも少ないピンで同等のデバッグ機能を提供することを目指しています。

    • SWCLK (Serial Wire Clock): クロック信号。
    • SWDIO (Serial Wire Data I/O): 双方向のデータ線。
    • SRST (System Reset): ターゲットシステム全体をリセット(オプション)。
      SWDは2ピン(SWCLK, SWDIO)で済むため、ピン数の少ないマイクロコントローラーでデバッグインターフェースを確保しやすいという利点があります。現在の多くのARM Cortex-Mマイクロコントローラーで広く採用されています。

OpenOCDは、これらのインターフェースを介してターゲットデバイスのデバッグモジュール(ARMの場合、Debug Access Port: DAPなど)と通信します。

デバッグプローブ/アダプターの役割

デバッグプローブ(またはデバッグアダプター、JTAG/SWDアダプター)は、開発用PCのUSBなどのインターフェースを、ターゲットデバイスのJTAG/SWDインターフェースに変換するハードウェアです。PC側ではUSBデバイスとして認識され、OpenOCDなどのソフトウェアがそのUSBデバイスを制御することで、ターゲットへの信号を生成・受信します。プローブの品質や機能によって、デバッグの安定性や速度が大きく異なります。代表的なプローブとしては、ST-Link (STM32 Discovery/Nucleoボードに搭載、または単体)、J-Link (Segger製)、FTDIベースのアダプター、CMSIS-DAP互換アダプターなどがあります。

GDBとデバッグフロー

OpenOCDは単体でグラフィカルなデバッグインターフェースを持つわけではありません。通常、GDB (GNU Debugger) と組み合わせて使用します。デバッグフローは以下のようになります。

  1. ファームウェアのビルド: C/C++などのソースコードをコンパイル、アセンブル、リンクして、実行可能なELF形式などのバイナリファイルを生成します。このファイルには、デバッグに必要なシンボル情報(変数名、関数名、行番号など)が含まれています。
  2. OpenOCDの起動: デバッグアダプターをPCに接続し、ターゲットボードに電源を供給します。その後、適切な設定ファイルを用いてOpenOCDをGDBサーバーモードで起動します。OpenOCDは指定されたTCPポート(デフォルトではGDB用に3333番、Telnet用に4444番)でGDBクライアントからの接続を待ち受けます。
  3. GDBの起動と接続: 開発用PC上で、ターゲットCPUアーキテクチャに対応したクロスGDBを起動します。そして、GDBからOpenOCDが待ち受けているポートにTCP/IPで接続します(例: target remote localhost:3333)。
  4. デバッグセッション: GDBはOpenOCDを通じてターゲットデバイスを制御します。GDBからのコマンド(プログラムのロード、ブレークポイント設定、実行、一時停止、メモリ/レジスタ参照など)は、OpenOCDによってJTAG/SWD信号に変換され、デバッグアダプターを介してターゲットに送られます。ターゲットからの応答(停止理由、レジスタ値など)は、デバッグアダプターとOpenOCDを経由してGDBに返され、開発者はGDBのインターフェース(CUIまたはIDEのGUI)で状態を確認できます。

このエコシステムにおいて、OpenOCDはGDBとハードウェアの間の重要な仲介役を果たします。

OpenOCDとは? そのアーキテクチャ

OpenOCDは、デバッグアダプターとターゲットデバイスの種類によらず、統一的なインターフェース(GDBサーバー、Telnetサーバー、スクリプト)を提供することを目標としています。その内部アーキテクチャは、大きく分けて以下の層に分けることができます。

  1. Interface Layer (インターフェース層): デバッグアダプターと通信する部分です。様々なベンダーや種類のデバッグアダプターに対応するためのドライバーが含まれています。FTDI、ST-Link、J-Link、CMSIS-DAPなど、アダプター固有のプロトコルやレジスタ操作を抽象化します。
  2. Target Layer (ターゲット層): ターゲットデバイス(CPUコア)固有のデバッグ機能を扱う部分です。ARM Cortex-M/R/A、RISC-V、MIPSなど、各アーキテクチャのデバッグレジスタの操作、ブレークポイント/ウォッチポイントの実装、リセット制御、フラッシュメモリプログラミングなどを担当します。ターゲットデバイスのシリコンベンダーや特定のデバイスファミリーごとに詳細な設定が必要になります。
  3. RTOS/Flash/Boundary Scan Layer (RTOS/フラッシュ/バウンダリスキャン層): RTOSのタスク情報取得、オンチップフラッシュメモリへの書き込み/消去、バウンダリスキャン機能などを提供します。フラッシュ書き込みは、ターゲットデバイスごとに異なるアルゴリズムや手順が必要となるため、この層で対応しています。
  4. Server Layer (サーバー層): 外部ツール(主にGDB)との通信インターフェースを提供します。GDBサーバーはGDBリモートデバッグプロトコルを実装し、開発用PC上のGDBクライアントからの要求を受け付け、Target Layerなどに処理を委譲します。Telnetサーバーは、OpenOCD独自のコマンドを受け付けるためのインターフェースで、スクリプト実行や状態確認などに利用されます。
  5. Scripting Layer (スクリプト層): Tclスクリプトエンジンを内蔵し、OpenOCDの様々な機能をスクリプトから呼び出せるようにします。設定ファイルの読み込みや、自動化されたタスクの実行に利用されます。

OpenOCDの設定ファイル(.cfgファイル)は、これらの層の各機能を設定するためのコマンド群から構成されています。例えば、interfaceコマンドでInterface Layerのドライバーと設定を指定し、targetコマンドでTarget LayerのCPUタイプやフラッシュ設定を指定します。

OpenOCDのインストール

OpenOCDを利用するためには、開発用PCにインストールする必要があります。OSによってインストール方法が異なります。

Linuxでのインストール

多くのLinuxディストリビューションでは、パッケージマネージャーを通じてOpenOCDをインストールできます。

  • Debian/Ubuntu:
    bash
    sudo apt update
    sudo apt install openocd
  • Fedora:
    bash
    sudo dnf install openocd
  • Arch Linux:
    bash
    sudo pacman -S openocd
  • その他: 各ディストリビューションのパッケージマネージャーを確認してください。

パッケージが古い場合は、ソースコードからビルドすることも可能です。ソースビルドは最新機能を利用したい場合や、特定のオプションを有効にしたい場合に必要となります。

  1. 依存関係のインストール(例: Ubuntu):
    bash
    sudo apt update
    sudo apt install build-essential pkg-config automake autoconf libtool texinfo libftdi-dev libusb-1.0-0-dev

    使用するアダプターによっては、追加のライブラリ(例: libhidapi-dev, libjaylink-devなど)が必要です。
  2. ソースコードの取得:
    bash
    git clone git://git.code.sf.net/p/openocd/code openocd
    cd openocd
    ./bootstrap # Autotools関連ファイルの生成
  3. ビルドとインストール:
    bash
    ./configure --prefix=/usr/local # インストール先を指定
    make
    sudo make install

    configure実行時に、サポートしたいアダプターに応じたオプション(例: --enable-stlink, --enable-jlink, --enable-ftdiなど)を指定します。./configure --helpで利用可能なオプションを確認できます。

Linuxでは、USBデバイス(デバッグアダプター)にアクセスするためのパーミッション設定(udevルール)が必要になる場合があります。OpenOCDのソースコードに含まれるcontrib/udev/rules.d/ディレクトリに各アダプターベンダー用のudevルールファイルがありますので、それらを/etc/udev/rules.d/にコピーし、udevデーモンをリロードしてください。

bash
cd openocd
sudo cp contrib/udev/rules.d/* /etc/udev/rules.d/
sudo udevadm control --reload-rules
sudo udevadm trigger

Windowsでのインストール

Windowsでは、バイナリ配布版を利用するのが最も簡単です。OpenOCDの公式ウェブサイトやSourceForgeからダウンロードできます。

  1. SourceForgeのOpenOCDプロジェクトページ (https://sourceforge.net/projects/openocd/files/) から、最新版のWindows用バイナリ(通常はopenocd-*-x64.zipのようなファイル名)をダウンロードします。
  2. ダウンロードしたZIPファイルを任意の場所に解凍します(例: C:\openocd)。
  3. OpenOCDを実行するために、解凍したディレクトリ内のbinフォルダにパスを通しておくと便利です。または、コマンドプロンプトやPowerShellでbinフォルダに移動して実行します。

USBドライバのインストール: WindowsでUSB接続のデバッグアダプターを使用する場合、適切なドライバが必要になります。多くの汎用アダプターや、独自のドライバを提供しないアダプター(特にFTDIチップベースのものやCMSIS-DAP)では、Zadigというツールを使ってWinUSBやlibusbなどの汎用ドライバをインストールする必要がある場合があります。

  1. Zadigをダウンロード (https://zadig.akeo.ie/) して実行します。
  2. Optionsメニューから「List All Devices」を選択します。
  3. プルダウンメニューから、接続したデバッグアダプターに対応するUSBデバイスを選択します。デバイス名はアダプターによって異なります(例: ST-Link V2, J-Link, Dual RS232-HSなど)。
  4. インストールまたは置き換えるドライバとして、「WinUSB」や「libusb-win32」などを選択し、「Replace Driver」または「Install Driver」をクリックします。誤ったデバイスのドライバを置き換えないように注意してください。 特に、マウスやキーボード、ストレージデバイスなどは置き換えないでください。

macOSでのインストール

macOSでは、Homebrewパッケージマネージャーを利用するのが最も簡単です。

bash
brew update
brew install openocd

もしHomebrewで利用できるバージョンが古すぎる場合や、特定のオプションが必要な場合は、Linuxと同様にソースコードからビルドすることも可能です。依存関係のインストールにはHomebrewが利用できます(例: brew install libusb)。

OpenOCDの基本的な使い方

OpenOCDはコマンドラインツールです。基本的な使い方は、OpenOCD実行ファイルに、使用するデバッグアダプターとターゲットデバイスに対応した設定ファイルを指定して起動することです。

設定ファイル (.cfg)

OpenOCDの動作は、主に.cfgという拡張子を持つ設定ファイルによって制御されます。これらのファイルはTclスクリプトで記述されており、OpenOCDのコマンド(interface, target, init, programなど)を含んでいます。

  • Interface Configuration File: デバッグアダプターの種類や設定を指定します。通常、interface/ディレクトリ以下に配置されています(例: interface/stlink.cfg, interface/jlink.cfg, interface/ftdi/olimex-arm-usb-ocd.cfgなど)。
  • Target Configuration File: ターゲットデバイス(CPUアーキテクチャ、特定のチップ、フラッシュ情報など)の設定を指定します。通常、target/ディレクトリ以下に配置されています(例: target/stm32g4x.cfg, target/mimxrt1062.cfg, target/esp32.cfg, target/nrf52.cfgなど)。
  • Board Configuration File: 特定の評価ボードや開発キット向けの設定ファイルです。通常、使用するデバッグアダプターとターゲットデバイスの設定ファイルをインクルードし、さらにボード固有の設定(リセット方法、クロック周波数など)を追加します。通常、board/ディレクトリ以下に配置されています(例: board/stm32f4discovery.cfg, board/esp-wroom-32.cfgなど)。

基本的な起動コマンド

OpenOCDを起動するには、通常、少なくとも使用するデバッグアダプター(インターフェース)とターゲットデバイスの設定ファイルを-fオプションで指定します。

bash
openocd -f interface/<interface_file>.cfg -f target/<target_file>.cfg

例:ST-Link V2デバッグアダプターを使ってSTM32F4Discoveryボード上のSTM32F407VGをデバッグする場合。STM32F4DiscoveryボードにはST-Link V2がオンボードで搭載されており、OpenOCDにはこのボード専用の設定ファイルが用意されています。

bash
openocd -f board/stm32f4discovery.cfg

board/stm32f4discovery.cfgファイルの内容を見ると、おそらく以下のような行が含まれています。

tcl
source [find interface/stlink.cfg]
transport select hla_swd
source [find target/stm32f4x.cfg]

これは、ST-Linkインターフェースを使用し、SWDトランスポートを選択し、STM32F4シリーズのターゲット設定を読み込むことを意味します。

もし手持ちのアダプターがボード専用ではなく、かつボード設定ファイルがない場合は、インターフェースとターゲットの設定ファイルを組み合わせて指定します。例:汎用FTDIアダプター(Olimex ARM-USB-OCD-H相当)とNXP MIMXRT1062(EVKボード想定)を組み合わせる場合。

bash
openocd -f interface/ftdi/olimex-arm-usb-ocd-h.cfg -f target/mimxrt1062.cfg

OpenOCDの起動と接続テスト

コマンドを実行すると、OpenOCDが起動し、指定された設定ファイルに基づいてデバッグアダプターの初期化とターゲットへの接続を試みます。成功した場合、以下のようなログが出力されます(出力内容は設定やバージョンによって異なります)。

Open On-Chip Debugger <バージョン> (日付)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available adapter failed
Info : clock speed <速度> kHz
Info : STLINK V2JxxSxx (API vxx) vidUsb=xxxx pidUsb=xxxx
Info : Target voltage: x.xxV
Info : <アダプター名>: FW version : <バージョン>
Info : <アダプター名>: capabilities : <機能>
Info : <アダプター名>: STLINK SWD mode enabled
Info : SWD DP ID <ID>
Info : <ターゲット名>: hardware version <バージョン>
Info : <ターゲット名>: core index <インデックス>
Info : <ターゲット名>: ap index <インデックス>
Info : <ターゲット名>: DP AP v<バージョン> type <タイプ>
Info : <ターゲット名>: flash size = <サイズ> KB
Info : <ターゲット名>: halted on debug entry
...
Info : starting gdb server for <ターゲット名> on <ポート>
Info : Listening on port <ポート> for gdb connections
Info : Listening on port <ポート+1> for telnet connections

重要な点は、Info : Target voltage: ...VInfo : SWD DP ID ...Info : <ターゲット名>: flash size = ... KBといったターゲットに関する情報が表示されることです。これらの情報が表示されれば、OpenOCDがデバッグアダプター経由でターゲットデバイスと通信できていることを示します。

もし接続に失敗した場合は、エラーメッセージが表示されます。例えば「Error: No J-Link device found」や「Error: Target not examined yet」などです。これらのエラーメッセージは、後述のトラブルシューティングで詳しく扱います。

OpenOCDの終了

OpenOCDは通常、GDBやTelnetクライアントからの接続を待ち受けるサーバーとして動作します。終了するには、OpenOCDが実行されているターミナルでCtrl+Cを押します。

OpenOCDの設定ファイルの詳細

OpenOCDの設定ファイルはTclスクリプトで記述されます。これにより、簡単なパラメータ設定だけでなく、条件分岐やループを用いた複雑な初期化手順も記述可能です。

主要なTclコマンドとOpenOCD固有のコマンドを以下に示します。

Tclスクリプトの基本

  • コマンドはスペースで区切られます。
  • 行末に特別な記号は不要です。
  • コメントは#から行末までです。
  • 変数はset varname valueで設定し、$varnameで参照します。
  • 文字列はダブルクォーテーション"で囲みます。
  • リストは{item1 item2}で定義します。

例:
“`tcl

変数の設定

set my_speed 1000
set board_name “STM32F4 Discovery”

コマンドの実行

echo “Using board: $board_name”
adapter_khz $my_speed
“`

OpenOCD固有の主要コマンド

設定ファイルでよく使われるOpenOCD固有のコマンドをいくつか紹介します。

  • source <filename>: 別の設定ファイルを読み込みます。[find <filename>]と組み合わせることで、OpenOCDの検索パスからファイルを見つけて読み込めます。
    tcl
    source [find interface/stlink.cfg]
    source [find target/stm32f4x.cfg]

  • interface <driver_name>: 使用するデバッグアダプターのドライバーを指定します。
    tcl
    interface ftdi
    interface stlink

  • adapter_khz <speed_in_khz>: デバッグアダプターとターゲット間の通信速度(JTAG/SWDクロック周波数)をキロヘルツ単位で設定します。ターゲットの最高速度や、配線の品質に合わせて調整が必要です。低すぎる速度はデバッグセッションを遅くし、高すぎる速度は通信エラーの原因になります。
    tcl
    adapter_khz 1000 # 1MHz
    adapter_khz 8000 # 8MHz
    adapter_khz 0 # アダプターがサポートする最高速度 (推奨しない場合が多い)

  • transport select <type>: JTAGまたはSWDのどちらのトランスポートプロトコルを使用するかを指定します。多くの場合、アダプター設定ファイルまたはターゲット設定ファイルの中で指定されます。
    tcl
    transport select swd
    transport select jtag

  • target <arch>.<name> ...: ターゲットCPUを定義します。<arch>はアーキテクチャ(例: arm, riscvなど)、<name>はターゲット名(例: cortex_m, cortex_a, rv64など)です。オプション引数で、ターゲットの物理アドレス、 endianness、ワークエリアRAM、フラッシュバンクなどを設定します。
    tcl
    target arm.cortex_m main_target -endian little -dbgbase 0xE000EDF0 -ap 0

    ターゲット設定ファイルは通常、ターゲット固有の複雑な設定を含んでいます。

  • reset_config <mode> <options>: リセットの挙動を設定します。組み込みシステムのデバッグにおいて、ターゲットを安定した状態にするためのリセットシーケンスは非常に重要です。

    • srst / trst: SRST信号またはTRST信号(あるいはその両方)を使用するかどうか。
    • srst_only: TRST信号がないターゲットの場合。
    • srst_pullup: SRST信号にプルアップ抵抗が必要な場合。
    • trst_pullup: TRST信号にプルアップ抵抗が必要な場合。
    • connect_assert_srst: 接続時にSRSTをアサート(ローにする)するかどうか。
    • connect_deassert_srst: 接続時にSRSTをディアサート(ハイにする)するかどうか。
    • init: initコマンド実行時にリセットを実行するかどうか。
    • run_and_halt: リセット後、すぐにCPUを停止させるかどうか。
      tcl
      reset_config srst_only srst_pullup # SRSTのみ使用、プルアップが必要
      reset_config srst trst # SRSTとTRST両方使用
      reset_config srst_only connect_install_ap run_and_halt # リセット後HALTし、APをインストール
  • flash bank <name> <driver> <base> <size> <chip_width> <bus_width> ...: フラッシュメモリバンクを定義します。フラッシュ書き込み機能を利用するために必須の設定です。<driver>はフラッシュの種類に応じたドライバー名(例: stm32f1x, stm32lx, nxp_kv, esp32など)。<base>はメモリマップ上の開始アドレス、<size>はサイズ、<chip_width><bus_width>はデータ幅です。
    tcl
    flash bank stm32g4x.flash stm32g4x 0x08000000 0x40000 no_erase no_write no_protect
    flash bank stm32f4x.flash stm32f4x 0x08000000 0x100000 0 0 $_TARGETNAME

    フラッシュバンクの設定は非常にターゲット固有であり、通常はターゲット設定ファイルで定義されています。

  • init: 設定ファイルの読み込みが完了した後、デバッグアダプターとターゲットを初期化し、接続を確立するコマンドです。通常、設定ファイルの最後に記述されるか、GDB/Telnet接続後に自動的に実行されます。
    tcl
    init

    initコマンドが成功すると、OpenOCDはターゲットへの接続が確立され、デバッグやプログラミングが可能になった状態になります。

  • program <filename> <address> [<options>]: 指定されたファイルをターゲットのフラッシュメモリまたはRAMに書き込みます。<filename>は書き込むバイナリファイル(ELF、Intel Hexなど)。<address>は書き込み先のアドレスです(通常はフラッシュメモリの開始アドレス)。オプションでverify, reset, 0x...などを指定できます。
    tcl
    program build/firmware.elf verify reset 0x08000000

    このコマンドはOpenOCD起動時の-cオプションやTelnetインターフェース、GDBのmonitorコマンド経由で実行することが多いです。

例:簡単な設定ファイル

特定のボード用の設定ファイルは、通常以下のような構造になります。

“`tcl

デバッグアダプターの設定

例: ST-Link V2を使用

source [find interface/stlink.cfg]

トランスポートの選択 (SWDまたはJTAG)

transport select swd

ターゲットCPUの設定

例: STM32L4シリーズを使用

source [find target/stm32l4x.cfg]

アダプター速度の設定 (オプション、ターゲット/アダプターの組み合わせによる)

adapter_khz 4000

リセット設定 (オプション、ターゲットやボードによる)

reset_config srst_only srst_pullup

initコマンドを実行して、OpenOCDを初期化し、ターゲットに接続

init

init後にターゲットを停止させたい場合 (通常はターゲット設定ファイルで指定される)

targets $_TARGETNAME

halt

プログラムの書き込み (OpenOCD起動時に自動で実行したい場合)

program build/firmware.elf verify reset 0x08000000

GDBサーバーなどの起動 (通常、init後に自動的に開始される)

gdb_listen 3333

telnet_listen 4444

“`

実際の設定ファイルは、特定のターゲットデバイスのメモリマップ、フラッシュアルゴリズム、リセット回路など、より詳細な設定を含んでいます。OpenOCDのインストールディレクトリにあるinterface/, target/, board/以下の既存の.cfgファイルを参考にすると良いでしょう。

OpenOCDとGDBの連携

OpenOCDの最も一般的な使い方は、GDBのリモートデバッグターゲットとして機能させることです。OpenOCDはGDBサーバーとして起動し、指定されたTCPポートで接続を待ち受けます。開発用PC上で起動したGDBクライアントは、このポートに接続することで、OpenOCD経由でターゲットデバイスをデバッグします。

GDBサーバーの起動

OpenOCDはデフォルトでGDBサーバーをポート3333で、Telnetサーバーをポート4444で起動します。これらのポート番号は設定ファイルまたはコマンドラインオプションで変更できます。

bash
openocd -f <interface>.cfg -f <target>.cfg -c "gdb_listen 5000" -c "telnet_listen 5001"

-cオプションを使うと、設定ファイルを読み込んだ後に任意のOpenOCDコマンドを実行できます。

GDBからの接続

OpenOCDをサーバーモードで起動した後、別のターミナルを開き、ターゲットアーキテクチャに対応したGDBクライアントを起動します。例えば、ARM Cortex-Mターゲットの場合はarm-none-eabi-gdbのようなクロスGDBを使用します。

  1. GDBを起動します。
    bash
    arm-none-eabi-gdb
  2. GDBのコマンドプロンプト((gdb))で、OpenOCDが待ち受けているアドレスとポートに接続します。
    gdb
    (gdb) target remote localhost:3333

    もしOpenOCDを別のマシンで実行している場合は、localhostの部分をそのマシンのIPアドレスまたはホスト名に変更します。

接続に成功すると、GDBはターゲットに接続され、デバッグセッションを開始できます。OpenOCDのコンソールにもGDBからの接続があった旨のログが表示されます。

プログラムのロードと実行

GDBからターゲットにプログラムをロードするには、loadコマンドを使用します。GDBはOpenOCDに対してロード要求を送り、OpenOCDがターゲットのフラッシュメモリまたはRAMにバイナリデータを書き込みます。

gdb
(gdb) load <path/to/your/firmware.elf>

loadコマンドは、通常、フラッシュメモリへの書き込みとベリファイ(検証)を行います。ただし、OpenOCDの設定(フラッシュバンクの設定など)が正しく行われている必要があります。

プログラムをロードした後、または既にフラッシュに書き込まれているプログラムを実行する場合、GDBの標準的なデバッグコマンドが使用できます。

  • break <location>: ブレークポイントを設定します(関数名、ソースコードの行番号、アドレスなど)。
  • continue: プログラムの実行を再開します。
  • step: 現在の行を実行し、次の行で停止します(関数コールの中には入らない)。
  • stepi: 現在のCPU命令を実行し、次の命令で停止します。
  • next: 現在の行を実行し、次の行で停止します(関数コールがあれば最後まで実行する)。
  • nexti: 現在のCPU命令を実行し、次の命令で停止します。
  • info registers: CPUの全レジスタの値を表示します。
  • print <variable>: 変数の値を表示します。
  • x/<n><f><u> <address>: 指定されたアドレスのメモリ内容をダンプします(例: x/10xw 0x20000000でアドレス0x20000000から10ワードを16進数で表示)。

OpenOCD固有のGDBコマンド (monitor)

GDBには、リモートターゲットに固有のコマンドを送信するためのmonitorコマンドがあります。OpenOCDは、このmonitorコマンドを通じて独自の機能を提供します。これにより、GDBセッション中であっても、OpenOCDの低レベルな操作(リセット、レジスタ/メモリ操作、フラッシュ書き込みなど)を実行できます。

gdb
(gdb) monitor <openocd_command> [<args>]

よく使われるmonitorコマンドの例:

  • monitor reset: ターゲットをリセットし、設定に応じて停止させます。
  • monitor halt: ターゲットCPUを停止させます。
  • monitor resume: ターゲットCPUの実行を再開します。
  • monitor flash erase_sector <sector_number> <bank_name>: 指定したフラッシュセクタを消去します。
  • monitor flash write_image <filename> <address> <file_type> [<options>]: GDBのloadコマンドと同様にフラッシュ書き込みを行いますが、より詳細なオプション指定が可能です。
    gdb
    (gdb) monitor flash write_image firmware.hex 0x08000000 ihex
  • monitor mdw <address> [<count>]: 指定アドレスから指定数だけワード(32ビット)単位でメモリを読み出し、16進数で表示します。
    gdb
    (gdb) monitor mdw 0x20000000 16
  • monitor mww <address> <value>: 指定アドレスにワード単位で値を書き込みます。
  • monitor mrh <address> [<count>]: ハーフワード(16ビット)単位でメモリを読み出し。
  • monitor mwh <address> <value>: ハーフワード単位でメモリを書き込み。
  • monitor mrb <address> [<count>]: バイト(8ビット)単位でメモリを読み出し。
  • monitor mwb <address> <value>: バイト単位でメモリを書き込み。
  • monitor reg: CPUレジスタの値を表示します(GDBのinfo registersと似ていますが、OpenOCD側での表示)。
  • monitor arm core_state: ARMコアの状態に関する情報を表示します。
  • monitor adapter_khz <speed>: デバッグアダプターの速度を動的に変更します。
  • monitor config <variable>: OpenOCDの設定変数値を表示します。

monitorコマンドは非常に強力で、OpenOCDのほぼ全ての機能をGDBから利用できます。Telnetインターフェースでも同様のコマンドを実行できます。

OpenOCDの高度な使い方

フラッシュ書き込み

フラッシュ書き込みはOpenOCDの最も重要な機能の一つです。GDBのloadコマンドや、OpenOCDのprogramまたはflash write_imageコマンドで行います。

OpenOCDがフラッシュ書き込みを行うためには、ターゲットデバイスのフラッシュメモリに関する情報(開始アドレス、サイズ、ページ/セクタサイズ、消去/書き込みアルゴリズムなど)が必要です。これは通常、ターゲット設定ファイル (target/*.cfg) の中でflash bankコマンドなどによって定義されています。

  • GDB loadコマンド: GDBからload <filename>を実行すると、GDBはターゲットのメモリにファイルを書き込もうとします。OpenOCDは、ターゲットのメモリマップとフラッシュバンク定義を参照し、指定されたアドレスがフラッシュ領域であれば、自動的にフラッシュ書き込みアルゴリズムを実行します。これは最も一般的な方法です。
  • OpenOCD programコマンド: OpenOCD起動時の-c "program ..."オプションや、Telnet/GDB monitor program ...コマンドで実行します。
    bash
    openocd -f ... -c "program firmware.elf verify reset 0x08000000"

    verifyオプションは書き込み後に内容を読み出して検証、resetオプションは書き込み完了後にターゲットをリセットすることを指定します。アドレスは省略可能ですが、指定しない場合はELFファイルのエントリポイントなどが使われることが多いです。
  • OpenOCD flash write_imageコマンド: programコマンドと同様ですが、ファイル形式(ihex, elf, binaryなど)を明示的に指定できます。また、eraseオプションで書き込み前に領域を消去するかどうかを制御できます。
    bash
    monitor flash write_image firmware.bin 0x08000000 bin 0 erase

    0はフラッシュバンクのID(通常は0から始まる最初のバンク)、eraseは書き込み前にバンク全体を消去することを意味します。

フラッシュ書き込みが失敗する場合、設定ファイルのフラッシュバンク定義が間違っている、アダプター速度が速すぎる、ターゲットが正しくリセットされていない、電源供給が不安定、フラッシュメモリがロックされているなどの原因が考えられます。

メモリ/レジスタ操作

デバッグ中にメモリやレジスタの値を直接確認したり変更したりすることは、問題の原因特定や一時的な回避策の試行に非常に役立ちます。OpenOCDはTelnetインターフェースやGDBのmonitorコマンドを通じて、これらの機能を提供します。

  • メモリダンプ: mdw, mrh, mrbコマンドでメモリ内容を読み出します。
    gdb
    (gdb) monitor mdw 0x20001000 8 # 0x20001000から8ワード (32バイト) を読み出し
    0x20001000: 0x12345678 0xabcdef01 0x... ...
  • メモリ書き込み: mww, mwh, mwbコマンドでメモリ内容を書き換えます。
    gdb
    (gdb) monitor mww 0x20001000 0xDEADBEEF # 0x20001000に0xDEADBEEFを書き込み
  • レジスタ操作: regコマンドでCPUレジスタを読み書きします。引数なしで全レジスタ表示、レジスタ名を指定して特定のレジスタ値を表示/設定します。
    gdb
    (gdb) monitor reg # 全レジスタ表示
    (gdb) monitor reg pc # プログラムカウンタ(PC)の値を表示
    pc/32: 0x08001234
    (gdb) monitor reg r0 10 # R0レジスタに10を設定

    これらのコマンドは、特定のハードウェアレジスタ(GPIO制御レジスタなど)を直接操作して、デバッグ中のハードウェアの状態を一時的に変更する際にも利用できます。

ブレークポイントとウォッチポイント

GDBやOpenOCDは、ハードウェアまたはソフトウェアブレークポイント、およびウォッチポイントをサポートします。

  • ブレークポイント: 特定のコードアドレスまたは命令で実行を停止させます。ハードウェアブレークポイントはCPU内部のデバッグモジュールが提供する機能で、ROM上のコードやフラッシュ上のコードでも使用できますが、数に限りがあります。ソフトウェアブレークポイントは、ブレークしたい命令を特別なトラップ命令に一時的に置き換えることで実現されます。RAM上のコードでのみ有効です。GDBのbreakコマンドで設定できます。OpenOCDは、ターゲットがサポートする機能に応じて適切なタイプのブレークポイントを設定します。
  • ウォッチポイント: 特定のメモリ領域へのアクセス(読み出し、書き込み、または両方)が発生したときに実行を停止させます。これもCPUのデバッグモジュールによるハードウェア機能で、数に限りがあります。特定の変数がいつ、どこで書き換えられたかを追跡するのに非常に便利です。GDBのwatchコマンドで設定できます。

トレース機能

一部の高性能なターゲット(特にARM Cortex-M3以上の多くのモデル)は、ETM (Embedded Trace Macrocell) や ITM (Instrumentation Trace Macrocell) といったトレース機能を持ちます。OpenOCDは、適切なアダプター(SWOピンを持つものなど)と設定があれば、これらのトレース情報を取得し、GDBや他のツールに渡すことができます。

  • ITM: printfデバッグのように、プログラムから特定の情報を非侵襲的に出力するための機能です。SWO (Serial Wire Output) ピンを介してデータが出力されます。OpenOCDはSWOデータを収集し、それをTCPポート経由で表示したり、ファイルに保存したりできます。
    tcl
    # 設定ファイルでのITM/SWO設定例
    swo_telnet 4445 # SWOデータをポート4445に出力
    swo_baudrate 2000000 # SWO速度 (ターゲット側の設定と一致させる)
    swo_enable

    GDBセッション中にmonitor swo enableなどで有効化することも可能です。Telnetクライアントでポート4445に接続すれば、ITMからの出力を見ることができます。
  • ETM: 実行された命令のアドレスや分岐情報などを非侵襲的にトレースする機能です。SWV (Serial Wire Viewer) または高速なトレースポートを介して大量のデータが出力されます。ETMトレースデータの解析は複雑であり、OpenOCDのサポートもアダプターやターゲットに依存します。高度なデバッグや性能解析に利用されます。

トレース機能の利用は、ターゲットデバイス、デバッグアダプター、OpenOCDの設定(クロック設定やSWO速度設定など)が正しく行われている必要があり、しばしば設定が難しい場合があります。

リセットの制御

デバッグセッション中、特にフラッシュ書き込み後やプログラムの再起動時に、ターゲットをリセットする必要が生じます。OpenOCDはresetコマンドで様々な種類のリセットを実行できます。

  • monitor reset: 設定ファイルで定義されたデフォルトのリセットシーケンスを実行します(通常はSRSTまたはTRSTを使用し、必要なら停止させます)。
  • monitor reset run: リセット後、すぐにプログラムの実行を開始します。
  • monitor reset halt: リセット後、プログラムカウンタがリセットハンドラなどを指すアドレスで停止します。
  • monitor reset init: リセット後、ターゲット設定ファイルで定義された初期化シーケンス(initコマンドで実行される内容)を再度実行します。

どのリセット方法が適切かは、ターゲットデバイスの状態やデバッグの目的によって異なります。フラッシュ書き込み後は、通常resetまたはreset runで新しいファームウェアを起動させます。デバッグを開始する際は、reset haltでプログラムの先頭で停止させることが多いです。

よくある問題とトラブルシューティング

OpenOCDの使用中に発生する可能性のある一般的な問題と、その解決策を以下に示します。

  1. OpenOCDがデバッグアダプターを認識しない:

    • 確認事項:
      • デバッグアダプターがPCに物理的に接続されているか?
      • アダプターに電源が入っているか?
      • Windowsの場合、USBドライバは正しくインストールされているか?(ZadigなどでWinUSBなどが割り当てられているか)
      • Linuxの場合、udevルールは正しく設定されているか?(lsusbコマンドでデバイスが認識されているか確認)
      • OpenOCDのコマンドラインで指定しているインターフェース設定ファイルは、使用しているアダプターに対応しているか?
      • アダプターが故障していないか?(別のツールで認識されるか確認)
    • 解決策: ドライバ/udevルールの再設定、OpenOCDの再インストール、別のアダプターで試す。
  2. OpenOCDがターゲットデバイスに接続できない/Target not examined yetエラー:

    • 確認事項:
      • ターゲットボードに電源が入っているか?(ターゲット電圧がOpenOCDログに表示されるか)
      • デバッグアダプターとターゲットボード間のJTAG/SWD配線は正しいか?(結線ミス、信号線の損傷、ハンダ不良など)
      • ターゲットのJTAG/SWDピンは、開発ソフトウェアによってGPIOなど別の機能に設定されてロックされていないか?(特に一部のチップでは、フラッシュ書き込み前に特定のシーケンスが必要)
      • ターゲットのクロックは動作しているか?(外部クリスタルが正しく接続・発振しているか)
      • ターゲットのリセット回路は正しく動作しているか?(リセット信号が張り付いていないか)
      • OpenOCDコマンドラインで指定しているターゲット設定ファイルは、使用しているターゲットデバイスに正確に対応しているか?(同じシリーズでも微妙に違うことがある)
      • アダプター速度(adapter_khz)がターゲットの最高JTAG/SWD速度を超えていないか?(速度を下げて試す)
      • ターゲットデバイスが物理的に損傷していないか?
    • 解決策: 配線の確認・修正、アダプター速度の低下、ターゲットボードの初期化状態の確認、設定ファイルの確認・修正、ターゲットデバイスの交換。
  3. フラッシュ書き込みが失敗する/検証エラー:

    • 確認事項:
      • OpenOCD設定ファイルで、ターゲットのフラッシュバンクが正しく定義されているか?(開始アドレス、サイズ、フラッシュドライバーなど)
      • 書き込みたいバイナリファイルは正しいか?(ELF、Hex、Bin形式など)
      • 書き込みアドレスは正しいか?(通常はフラッシュの開始アドレス)
      • ターゲットのフラッシュメモリは書き込み可能状態か?(プロテクトがかかっていないか、消去が必要か)
      • 電源供給は安定しているか?(書き込み中は消費電流が増加することがある)
      • アダプター速度が速すぎて通信エラーが起きていないか?
    • 解決策: 設定ファイルのフラッシュバンク定義の確認・修正、バイナリファイルの確認、書き込みアドレスの確認、フラッシュプロテクトの解除(チップベンダー提供ツールなどで)、電源の安定化、アダプター速度の低下。
  4. OpenOCDが予期せず終了する/クラッシュする:

    • 確認事項:
      • OpenOCDのバージョンは安定版か?(開発版や古いバージョンはバグを含むことがある)
      • 使用しているデバッグアダプターのファームウェアは最新か?
      • PCのUSBポートやケーブルに問題はないか?
      • 複雑なスクリプトを実行している場合、スクリプトにエラーはないか?
    • 解決策: OpenOCDの安定版へのアップデート、アダプターファームウェアのアップデート、別のUSBポート/ケーブルで試す、スクリプトのデバッグ。
  5. GDBから接続できない/認証エラー:

    • 確認事項:
      • OpenOCDはGDBサーバーモードで起動しているか?
      • GDBクライアントから接続しようとしているIPアドレスとポート番号は、OpenOCDが待ち受けているものと一致しているか?(デフォルトはlocalhost:3333)
      • ファイアウォールがポートをブロックしていないか?
    • 解決策: OpenOCDの起動オプション確認、GDBのtarget remoteコマンドの引数確認、ファイアウォールの設定確認。

トラブルシューティングの際は、OpenOCDのコンソールに出力されるログメッセージが非常に重要です。Debug:レベルのログを有効にすると、さらに詳細な情報が得られる場合があります(OpenOCD起動時に-dオプションを追加)。エラーメッセージやInfo:メッセージを注意深く読み、何が問題なのかを特定する手がかりにしてください。OpenOCDの公式ドキュメントやメーリングリストのアーカイブも、トラブルシューティングの強力なリソースとなります。

OpenOCDのカスタマイズと拡張

OpenOCDの柔軟性は、カスタムハードウェアや特定のデバッグシナリオに合わせて設定をカスタマイズできる点にあります。

カスタム設定ファイルの作成

独自のボードや既存の設定ファイルではカバーされていないターゲットデバイスを使用する場合、カスタム設定ファイルを作成する必要があります。既存のOpenOCDインストールに含まれる.cfgファイルを参考にしながら作成するのが良い方法です。

基本的な手順:

  1. 使用するデバッグアダプターに対応するインターフェース設定ファイル(例: interface/stlink.cfg)を選択します。
  2. ターゲットデバイスのCPUアーキテクチャに対応するターゲット設定ファイル(例: target/cortex_m.cfg, target/riscv/riscv.cfgなど)を選択します。チップ固有のフラッシュ情報やメモリマップ、デバッグレジスタへのアクセス方法などは、特定のターゲット設定ファイル(例: target/stm32f4x.cfg, target/esp32.cfg)に含まれています。適切なファイルが見つからない場合は、類似のチップの設定ファイルを参考に、データシートを見ながら記述する必要があるかもしれません。
  3. 新しい.cfgファイルを作成し、上記1と2の設定ファイルをsourceコマンドで読み込みます。
    tcl
    source [find interface/stlink.cfg]
    source [find target/stm32f4x.cfg]
  4. 必要に応じて、アダプター速度(adapter_khz)、トランスポート(transport select)、リセット設定(reset_config)、ターゲットの初期化(init後に行う追加コマンドなど)を記述します。
  5. 特にカスタムボードの場合、ボード固有の接続ピンやリセット方法などを考慮した設定が必要になります。例えば、リセット信号の極性や使用するGPIOなどがOpenOCDコマンドで制御できる場合があります。
  6. 作成した設定ファイルをOpenOCDの検索パスが通っている場所(例えば、OpenOCD実行ディレクトリやそのサブディレクトリ)に配置するか、フルパスで指定してOpenOCDを起動します。
    bash
    openocd -f /path/to/your/custom_board.cfg

Tclスクリプトによる自動化

OpenOCDに内蔵されたTclスクリプトエンジンを利用すると、より複雑なタスクを自動化できます。

  • OpenOCD起動時の自動コマンド実行: -cオプションでOpenOCDコマンドを指定できます。
    bash
    openocd -f ... -c "init; program firmware.elf verify reset 0x08000000; exit"

    このように記述すると、OpenOCDは起動、初期化、フラッシュ書き込み、ベリファイ、リセットを実行し、成功すれば終了します。これはビルドシステムからの自動書き込みなどに便利です。
  • OpenOCD設定ファイル内でのスクリプト記述: 設定ファイル内でTclの手続き(proc)を定義し、それを呼び出すことができます。
    “`tcl
    proc program_and_run {} {
    echo “Programming flash…”
    program firmware.elf verify 0x08000000
    echo “Programming complete. Resetting…”
    reset run
    }

    init
    program_and_run
    * **Telnetインターフェースからのスクリプト実行**: OpenOCD起動中にTelnetクライアントで接続し、コマンドやスクリプトを対話的に実行できます。これは、様々なコマンドを試したり、デバッグ中に特定の操作を行ったりするのに便利です。bash
    telnet localhost 4444

    halt
    mdw 0x20000000 10
    resume
    program_and_run # 設定ファイルでprocが定義されていれば呼び出し可能
    “`

OpenOCDのソースコードへの貢献

OpenOCDは活発なオープンソースプロジェクトです。もし特定のターゲットデバイスやデバッグアダプターがサポートされていない場合、そのサポートを自分で追加し、プロジェクトに貢献することも可能です。これには、ターゲットデバイスのデータシートを読み込み、デバッグモジュールのレジスタ操作などを実装する必要があり、高度な知識と労力が必要になりますが、コミュニティに貢献し、より多くの開発者がその恩恵を受けられるようにすることは非常に価値のあることです。OpenOCDのメーリングリストや開発者向けドキュメント(Doxygenで生成されたものなど)が参考になります。

OpenOCDを取り巻くエコシステム

OpenOCDは単体で使われるだけでなく、様々な開発ツールと連携して使用されます。

IDE (統合開発環境) との連携

多くの組み込み開発向けIDEは、OpenOCDをデバッグバックエンドとして利用するための設定をサポートしています。

  • Eclipse (CDT): CDT (C/C++ Development Tooling) には、GDB Hardware Debuggingというプラグインが含まれており、OpenOCDと連携してデバッグセッションを開始できます。デバッグ設定で「GDB (OpenOCD) Debugging」タイプを選択し、OpenOCD実行ファイルのパス、使用するOpenOCD設定ファイル、GDBサーバーのポート番号などを指定します。
  • VS Code (PlatformIO, Cortex-Debugなど): VS Codeの拡張機能(特にPlatformIOやCortex-Debug)もOpenOCDをサポートしています。launch.jsonファイルなどで、OpenOCDの設定ファイルパス、GDBパス、ポート番号などを指定することで、VS Codeから直接デバッグを開始できます。
  • STM32CubeIDE: STMicroelectronics公式のIDEですが、内部的にはOpenOCDをベースにしたデバッグツールが使用されています。ST-Linkはもちろん、他のアダプターもOpenOCD経由で利用できる設定があります。
  • Keil MDK / IAR Embedded Workbench: これらの商用IDEも、外部ツールとしてOpenOCDを起動し、GDBサーバーとして連携させる設定が可能な場合があります。ただし、商用デバッグプローブ(ULINK, I-jetなど)との連携は、それぞれのベンダー独自のデバッグサーバー/ドライバを使用するのが一般的です。

IDEと連携することで、ソースコードを見ながらブレークポイントを設定したり、変数の値をリアルタイムに確認したりといった、グラフィカルで使いやすいデバッグ環境が実現できます。

Buildシステムとの連携

MakeファイルやCMakeなどのビルドシステムから、コンパイル・リンク後のバイナリファイルを自動的にターゲットボードにフラッシュ書き込みするために、OpenOCDを呼び出すことができます。

“`makefile
FLASH_TOOL = openocd
OPENOCD_CFG = -f interface/stlink.cfg -f target/stm32f4x.cfg

flash: $(BUILD_DIR)/$(TARGET).elf
$(FLASH_TOOL) $(OPENOCD_CFG) -c “program $< verify reset 0x08000000; exit”

debug: $(BUILD_DIR)/$(TARGET).elf
$(FLASH_TOOL) $(OPENOCD_CFG) -c “init; targets $_TARGETNAME; halt”
arm-none-eabi-gdb -ex “target remote localhost:3333” $(BUILD_DIR)/$(TARGET).elf
``
上記はMakefileの抜粋例です。
make flashと実行すると、OpenOCDが起動してファームウェアをフラッシュに書き込み、終了します。make debug`と実行すると、OpenOCDがサーバーとして起動・ターゲット停止までを行い、その後GDBが起動してOpenOCDに接続します。

このような連携により、開発ワークフローの自動化や効率化が図れます。

まとめ:OpenOCDを使いこなすために

OpenOCDは、組み込み開発におけるデバッグとフラッシュプログラミングのための、非常に強力で柔軟なツールです。その対応ハードウェアの幅広さ、オープンソースという性質、GDBとの強力な連携は、多くの開発者にとって大きなメリットとなります。

OpenOCDの習得には、デバッグアダプター、JTAG/SWDインターフェース、ターゲットデバイスのアーキテクチャやメモリマップに関する基本的な理解が役立ちます。また、設定ファイルはTclスクリプトで記述されるため、簡単なスクリプトの読み書きができると、より高度なカスタマイズや自動化が可能になります。

本記事では、OpenOCDの基本的な概念、インストール方法、基本的な使い方から、設定ファイルの詳細、GDBとの連携、高度な機能、そしてトラブルシューティングまでを解説しました。

OpenOCDを使いこなすための次のステップとしては、以下の点が挙げられます。

  • 公式ドキュメントを読む: OpenOCDの公式ドキュメントは非常に詳細で、すべてのコマンドやサポートされるハードウェアに関する情報が網羅されています。特定の機能や設定について詳しく知りたい場合は、公式ドキュメントが最終的な情報源となります。
  • 既存の設定ファイルを深く理解する: 使用しているボードやターゲットに対応する.cfgファイルの内容を詳しく読み解くことで、OpenOCDがどのようにターゲットを初期化し、フラッシュを扱っているかを理解できます。これがカスタム設定ファイル作成の基礎となります。
  • Telnetインターフェースを活用する: GDBだけでなく、Telnetインターフェースを介してOpenOCDコマンドを直接入力し、ターゲットの状態を確認したり操作したりする練習をすると、OpenOCDの内部的な動作やコマンド体系への理解が深まります。
  • 様々なデバッグシナリオを試す: ブレークポイント、ウォッチポイント、メモリ/レジスタ操作、リセットコマンドなど、OpenOCDが提供する様々なデバッグ機能を実際の開発で積極的に活用し、デバッグ効率を向上させてください。
  • コミュニティを活用する: OpenOCDのメーリングリストやフォーラム、Stack Overflowなどのコミュニティには、経験豊富なユーザーや開発者がいます。問題が行き詰まったときや、特定の機能について知りたいときに、コミュニティに質問してみることも有効です。

OpenOCDは確かに学習コストがゼロではありません。しかし、一度その強力な機能を理解し、使いこなせるようになれば、様々な組み込みシステム開発において、より効率的かつ効果的なデバッグが可能となり、開発プロセスを大きく改善できるでしょう。本ガイドが、皆さんのOpenOCD入門の助けとなれば幸いです。


コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール