OpenOCD入門:組み込み開発者のための基本ガイド
はじめに:組み込み開発とデバッグの重要性
組み込みシステム開発は、限られたリソースの中で特定の機能を実装する高度な技術分野です。マイクロコントローラーやDSPといったハードウェアを直接制御し、ソフトウェアとハードウェアが密接に連携して動作するシステムを構築します。しかし、この密接な連携こそが、開発におけるデバッグを非常に困難なものにしています。
従来のPCアプリケーション開発とは異なり、組み込みシステムでは画面表示やファイルアクセスなどの高レベルなI/Oが制限されることが多く、問題発生時に内部の状態を把握するのが容易ではありません。フリーズ、予期せぬリセット、不正なメモリアクセス、タイミンングの問題など、ハードウェアとソフトウェアが絡み合ったデバッグは、開発者の頭を悩ませる最大の要因の一つです。
このような組み込みシステムのデバッグにおいて、不可欠なツールとなるのが「デバッグアダプター」とそれと連携するソフトウェアです。デバッグアダプターは、開発用PCとターゲットとなるマイクロコントローラーを物理的に接続し、CPUの停止/実行制御、メモリやレジスタの読み書き、ブレークポイントの設定といった低レベルな操作を可能にします。そして、そのデバッグアダプターを制御し、高レベルなデバッグ環境(GDBなど)と連携させるソフトウェアが、OpenOCDです。
OpenOCDとは何か? なぜOpenOCDなのか?
OpenOCD(Open On-Chip Debugger)は、オープンソースのオンチップデバッガーです。その主な役割は、デバッグアダプター(JTAG/SWDプローブ)を介してターゲットのマイクロコントローラーやプロセッサーに接続し、デバッグやプログラミング(フラッシュ書き込み)の機能を提供することです。
なぜOpenOCDが組み込み開発者にとって重要なのでしょうか?
- 多様なハードウェア対応: 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など、多様なアーキテクチャの多くのマイクロコントローラーやプロセッサーをサポートしています。これにより、開発者は特定のハードウェアベンダーに縛られることなく、様々なボードやチップで共通のデバッグ環境を構築できます。
- オープンソースとカスタマイズ性: オープンソースであるため、OpenOCDは自由に利用、改変、配布が可能です。特定のターゲットやアダプターが公式にサポートされていなくても、ソースコードを修正したり、カスタム設定ファイルを作成したりすることで対応できる可能性があります。また、内部の動作が透明であるため、問題発生時の原因特定や、高度なデバッグシナリオの実装が容易になります。
- GDBとの強力な連携: OpenOCDは、標準的なGDB (GNU Debugger) リモートデバッグプロトコルをサポートするGDBサーバーとして機能します。これにより、コマンドライン版GDBだけでなく、Eclipse、VS Code、STM32CubeIDE、Keil MDK (一部設定が必要) など、GDBをバックエンドとして利用する多くのIDEから透過的に利用できます。開発者は使い慣れたIDEのデバッグインターフェースを通じて、OpenOCDが提供する低レベルなデバッグ機能を利用できます。
- スクリプト機能: OpenOCDはTclスクリプトエンジンを内蔵しており、複雑なデバッグ手順や自動化されたテストシナリオをスクリプトとして記述できます。フラッシュ書き込み後の自動リセット、特定のレジスタ設定、複数ターゲットの同期制御など、応用範囲は広いです。
- コスト効率: 安価なデバッグアダプターと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) と組み合わせて使用します。デバッグフローは以下のようになります。
- ファームウェアのビルド: C/C++などのソースコードをコンパイル、アセンブル、リンクして、実行可能なELF形式などのバイナリファイルを生成します。このファイルには、デバッグに必要なシンボル情報(変数名、関数名、行番号など)が含まれています。
- OpenOCDの起動: デバッグアダプターをPCに接続し、ターゲットボードに電源を供給します。その後、適切な設定ファイルを用いてOpenOCDをGDBサーバーモードで起動します。OpenOCDは指定されたTCPポート(デフォルトではGDB用に3333番、Telnet用に4444番)でGDBクライアントからの接続を待ち受けます。
- GDBの起動と接続: 開発用PC上で、ターゲットCPUアーキテクチャに対応したクロスGDBを起動します。そして、GDBからOpenOCDが待ち受けているポートにTCP/IPで接続します(例:
target remote localhost:3333
)。 - デバッグセッション: GDBはOpenOCDを通じてターゲットデバイスを制御します。GDBからのコマンド(プログラムのロード、ブレークポイント設定、実行、一時停止、メモリ/レジスタ参照など)は、OpenOCDによってJTAG/SWD信号に変換され、デバッグアダプターを介してターゲットに送られます。ターゲットからの応答(停止理由、レジスタ値など)は、デバッグアダプターとOpenOCDを経由してGDBに返され、開発者はGDBのインターフェース(CUIまたはIDEのGUI)で状態を確認できます。
このエコシステムにおいて、OpenOCDはGDBとハードウェアの間の重要な仲介役を果たします。
OpenOCDとは? そのアーキテクチャ
OpenOCDは、デバッグアダプターとターゲットデバイスの種類によらず、統一的なインターフェース(GDBサーバー、Telnetサーバー、スクリプト)を提供することを目標としています。その内部アーキテクチャは、大きく分けて以下の層に分けることができます。
- Interface Layer (インターフェース層): デバッグアダプターと通信する部分です。様々なベンダーや種類のデバッグアダプターに対応するためのドライバーが含まれています。FTDI、ST-Link、J-Link、CMSIS-DAPなど、アダプター固有のプロトコルやレジスタ操作を抽象化します。
- Target Layer (ターゲット層): ターゲットデバイス(CPUコア)固有のデバッグ機能を扱う部分です。ARM Cortex-M/R/A、RISC-V、MIPSなど、各アーキテクチャのデバッグレジスタの操作、ブレークポイント/ウォッチポイントの実装、リセット制御、フラッシュメモリプログラミングなどを担当します。ターゲットデバイスのシリコンベンダーや特定のデバイスファミリーごとに詳細な設定が必要になります。
- RTOS/Flash/Boundary Scan Layer (RTOS/フラッシュ/バウンダリスキャン層): RTOSのタスク情報取得、オンチップフラッシュメモリへの書き込み/消去、バウンダリスキャン機能などを提供します。フラッシュ書き込みは、ターゲットデバイスごとに異なるアルゴリズムや手順が必要となるため、この層で対応しています。
- Server Layer (サーバー層): 外部ツール(主にGDB)との通信インターフェースを提供します。GDBサーバーはGDBリモートデバッグプロトコルを実装し、開発用PC上のGDBクライアントからの要求を受け付け、Target Layerなどに処理を委譲します。Telnetサーバーは、OpenOCD独自のコマンドを受け付けるためのインターフェースで、スクリプト実行や状態確認などに利用されます。
- 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 - その他: 各ディストリビューションのパッケージマネージャーを確認してください。
パッケージが古い場合は、ソースコードからビルドすることも可能です。ソースビルドは最新機能を利用したい場合や、特定のオプションを有効にしたい場合に必要となります。
- 依存関係のインストール(例: 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など)が必要です。 - ソースコードの取得:
bash
git clone git://git.code.sf.net/p/openocd/code openocd
cd openocd
./bootstrap # Autotools関連ファイルの生成 - ビルドとインストール:
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からダウンロードできます。
- SourceForgeのOpenOCDプロジェクトページ (
https://sourceforge.net/projects/openocd/files/
) から、最新版のWindows用バイナリ(通常はopenocd-*-x64.zip
のようなファイル名)をダウンロードします。 - ダウンロードしたZIPファイルを任意の場所に解凍します(例:
C:\openocd
)。 - OpenOCDを実行するために、解凍したディレクトリ内の
bin
フォルダにパスを通しておくと便利です。または、コマンドプロンプトやPowerShellでbin
フォルダに移動して実行します。
USBドライバのインストール: WindowsでUSB接続のデバッグアダプターを使用する場合、適切なドライバが必要になります。多くの汎用アダプターや、独自のドライバを提供しないアダプター(特にFTDIチップベースのものやCMSIS-DAP)では、Zadigというツールを使ってWinUSBやlibusbなどの汎用ドライバをインストールする必要がある場合があります。
- Zadigをダウンロード (
https://zadig.akeo.ie/
) して実行します。 - Optionsメニューから「List All Devices」を選択します。
- プルダウンメニューから、接続したデバッグアダプターに対応するUSBデバイスを選択します。デバイス名はアダプターによって異なります(例: ST-Link V2, J-Link, Dual RS232-HSなど)。
- インストールまたは置き換えるドライバとして、「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: ...V
やInfo : 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を使用します。
- GDBを起動します。
bash
arm-none-eabi-gdb - 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 ihexmonitor mdw <address> [<count>]
: 指定アドレスから指定数だけワード(32ビット)単位でメモリを読み出し、16進数で表示します。
gdb
(gdb) monitor mdw 0x20000000 16monitor 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/GDBmonitor 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の使用中に発生する可能性のある一般的な問題と、その解決策を以下に示します。
-
OpenOCDがデバッグアダプターを認識しない:
- 確認事項:
- デバッグアダプターがPCに物理的に接続されているか?
- アダプターに電源が入っているか?
- Windowsの場合、USBドライバは正しくインストールされているか?(ZadigなどでWinUSBなどが割り当てられているか)
- Linuxの場合、udevルールは正しく設定されているか?(
lsusb
コマンドでデバイスが認識されているか確認) - OpenOCDのコマンドラインで指定しているインターフェース設定ファイルは、使用しているアダプターに対応しているか?
- アダプターが故障していないか?(別のツールで認識されるか確認)
- 解決策: ドライバ/udevルールの再設定、OpenOCDの再インストール、別のアダプターで試す。
- 確認事項:
-
OpenOCDがターゲットデバイスに接続できない/Target not examined yetエラー:
- 確認事項:
- ターゲットボードに電源が入っているか?(ターゲット電圧がOpenOCDログに表示されるか)
- デバッグアダプターとターゲットボード間のJTAG/SWD配線は正しいか?(結線ミス、信号線の損傷、ハンダ不良など)
- ターゲットのJTAG/SWDピンは、開発ソフトウェアによってGPIOなど別の機能に設定されてロックされていないか?(特に一部のチップでは、フラッシュ書き込み前に特定のシーケンスが必要)
- ターゲットのクロックは動作しているか?(外部クリスタルが正しく接続・発振しているか)
- ターゲットのリセット回路は正しく動作しているか?(リセット信号が張り付いていないか)
- OpenOCDコマンドラインで指定しているターゲット設定ファイルは、使用しているターゲットデバイスに正確に対応しているか?(同じシリーズでも微妙に違うことがある)
- アダプター速度(
adapter_khz
)がターゲットの最高JTAG/SWD速度を超えていないか?(速度を下げて試す) - ターゲットデバイスが物理的に損傷していないか?
- 解決策: 配線の確認・修正、アダプター速度の低下、ターゲットボードの初期化状態の確認、設定ファイルの確認・修正、ターゲットデバイスの交換。
- 確認事項:
-
フラッシュ書き込みが失敗する/検証エラー:
- 確認事項:
- OpenOCD設定ファイルで、ターゲットのフラッシュバンクが正しく定義されているか?(開始アドレス、サイズ、フラッシュドライバーなど)
- 書き込みたいバイナリファイルは正しいか?(ELF、Hex、Bin形式など)
- 書き込みアドレスは正しいか?(通常はフラッシュの開始アドレス)
- ターゲットのフラッシュメモリは書き込み可能状態か?(プロテクトがかかっていないか、消去が必要か)
- 電源供給は安定しているか?(書き込み中は消費電流が増加することがある)
- アダプター速度が速すぎて通信エラーが起きていないか?
- 解決策: 設定ファイルのフラッシュバンク定義の確認・修正、バイナリファイルの確認、書き込みアドレスの確認、フラッシュプロテクトの解除(チップベンダー提供ツールなどで)、電源の安定化、アダプター速度の低下。
- 確認事項:
-
OpenOCDが予期せず終了する/クラッシュする:
- 確認事項:
- OpenOCDのバージョンは安定版か?(開発版や古いバージョンはバグを含むことがある)
- 使用しているデバッグアダプターのファームウェアは最新か?
- PCのUSBポートやケーブルに問題はないか?
- 複雑なスクリプトを実行している場合、スクリプトにエラーはないか?
- 解決策: OpenOCDの安定版へのアップデート、アダプターファームウェアのアップデート、別のUSBポート/ケーブルで試す、スクリプトのデバッグ。
- 確認事項:
-
GDBから接続できない/認証エラー:
- 確認事項:
- OpenOCDはGDBサーバーモードで起動しているか?
- GDBクライアントから接続しようとしているIPアドレスとポート番号は、OpenOCDが待ち受けているものと一致しているか?(デフォルトはlocalhost:3333)
- ファイアウォールがポートをブロックしていないか?
- 解決策: OpenOCDの起動オプション確認、GDBの
target remote
コマンドの引数確認、ファイアウォールの設定確認。
- 確認事項:
トラブルシューティングの際は、OpenOCDのコンソールに出力されるログメッセージが非常に重要です。Debug:
レベルのログを有効にすると、さらに詳細な情報が得られる場合があります(OpenOCD起動時に-d
オプションを追加)。エラーメッセージやInfo:
メッセージを注意深く読み、何が問題なのかを特定する手がかりにしてください。OpenOCDの公式ドキュメントやメーリングリストのアーカイブも、トラブルシューティングの強力なリソースとなります。
OpenOCDのカスタマイズと拡張
OpenOCDの柔軟性は、カスタムハードウェアや特定のデバッグシナリオに合わせて設定をカスタマイズできる点にあります。
カスタム設定ファイルの作成
独自のボードや既存の設定ファイルではカバーされていないターゲットデバイスを使用する場合、カスタム設定ファイルを作成する必要があります。既存のOpenOCDインストールに含まれる.cfg
ファイルを参考にしながら作成するのが良い方法です。
基本的な手順:
- 使用するデバッグアダプターに対応するインターフェース設定ファイル(例:
interface/stlink.cfg
)を選択します。 - ターゲットデバイスのCPUアーキテクチャに対応するターゲット設定ファイル(例:
target/cortex_m.cfg
,target/riscv/riscv.cfg
など)を選択します。チップ固有のフラッシュ情報やメモリマップ、デバッグレジスタへのアクセス方法などは、特定のターゲット設定ファイル(例:target/stm32f4x.cfg
,target/esp32.cfg
)に含まれています。適切なファイルが見つからない場合は、類似のチップの設定ファイルを参考に、データシートを見ながら記述する必要があるかもしれません。 - 新しい
.cfg
ファイルを作成し、上記1と2の設定ファイルをsource
コマンドで読み込みます。
tcl
source [find interface/stlink.cfg]
source [find target/stm32f4x.cfg] - 必要に応じて、アダプター速度(
adapter_khz
)、トランスポート(transport select
)、リセット設定(reset_config
)、ターゲットの初期化(init
後に行う追加コマンドなど)を記述します。 - 特にカスタムボードの場合、ボード固有の接続ピンやリセット方法などを考慮した設定が必要になります。例えば、リセット信号の極性や使用するGPIOなどがOpenOCDコマンドで制御できる場合があります。
- 作成した設定ファイルを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 4444halt
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
``
make flash
上記はMakefileの抜粋例です。と実行すると、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入門の助けとなれば幸いです。