ベアメタルRaspberryPiでのOpenOCDとGDBによるJTAGデバッグ

この記事はkstmアドベントカレンダー2018 23日目の記事として書かれました.

qiita.com

はじめに

お久しぶりです.昨年のアドベントカレンダーの記事(URL)を見返したところ.

なにこれ...意味わからん...となってしまったので,今年は昨年の内容を補足・修正した上で, 今回は実際にOpenOCDによるJTAGデバッグを行っみたいと思います.

ベアメタルって何

この本を買って読みましょう.

tatsu-zine.com

要するにRaspberryPiなどのマイコンシングルボードコンピュータにて,あえてOSを用いずに直接CPUを動作させることです. そんなベアメタルのメリットですが,私は普段OSによって抽象化されているハードウェアがどのように制御されているのか, 実際に手を動かしながら学べるところにあると考えています. また,ベアメタルガチ勢の方々はCPUの性能を限界まで引き出せるような使い方をしているようです.かっこいい.

今回の記事は,すでにARMクロスコンパイル環境が完成している前提で進めていきます.クロスコンパイル環境の構築やベアメタルでのLチカ等は, 上記の本やインターネット上の記事を参考にしてください.

JTAGとは

https://ja.wikipedia.org/wiki/JTAG

マイコン等の検査やデバッグに用いられるアクセスポートの規格のようです. 今回はICE(In-Cercuit Emulator)の一種として,マイコンを動作させながら デバッグを行います.

OpenOCDとは

申し訳ないのですが,正直ここへの理解は曖昧です.FT232HL等のJTAGデバッガとGDBを接続しているモノと理解しています.

JTAG環境の構築

使用機材

akizukidenshi.com

環境

ハードウェアの接続

RPi ft232HL
GPIO25 AD0
GPIO4 AD1
GPIO24 AD2
GPIO27 AD3
GPIO22 AD4
GND GND

OpenOCDの導入

sudo apt install openocd

cfgファイルのダウンロード

OpenOCDを起動する際に,JTAGデバッガとターゲットマイコンの情報を記したcfgファイルが必要になります.

Raspberry Piのcfgファイルは,下記ページからお借りしました.ありがとうございました.

github.com

OpenOCDの起動

下記コマンドでOpenOCDを起動します.

sudo openocd -f /usr/share/openocd/scripts/interface/ftdi/um232h.cfg -f ~/work/rpi_bmetal/raspberrypi/armjtag/raspi.cfg 

JTAGデバッガのcfgファイルとして,/usr/share/openocd/script/ftdi/にある um232h.cfgを使用しました.今回使用するFT232HLとは異なる気もするのですが ほぼ同じ仕様のICらしくとりあえず動いているので良しとします. Raspberry Pi用のものは先程ダウンロードしたものです. 成功時にはこのようなメッセージが表示されました.

Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
adapter speed: 1000 kHz
none separate
Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'.
raspi.arm
Info : clock speed 1000 kHz
Info : JTAG tap: raspi.arm tap/device found: 0x07b7617f (mfg: 0x0bf (Broadcom), part: 0x7b76, ver: 0x0)
Info : found ARM1176
Info : raspi.arm: hardware has 6 breakpoints, 2 watchpoints

GDBの起動

arm-unknown-eabi-gdb "デバッグ対象のelfファイル"

プログラムの実行や停止はホストとなるPCから行います. OpenOCDは起動したまま,別のタブかターミナルを開きGDBを起動します. OpenOCDはサーバとして待機しているのでそこへGDBを接続します. target remote 3333で 接続します.

(gdb) target remote localhost:3333

openOCD側ではこんなメッセージが

Info : accepting 'gdb' connection on tcp/3333

デバッグ環境が完成しました.

GDB便利!面白い!

GDBの勉強ついでにLチカ(LED点滅回路)で遊んでみました.

LEDの点滅部分だけ抜粋するとこんなコードです.

16  //RaspberryPi A+のactLEDに接続されているGPIO47を操作する
17 // GPIO47をOutputに
18 *(volatile unsigned int *)GPFSEL4 |= 0x01 << (3*7);
19 //変数観察用
20 volatile unsigned char  LED_state = 'L';
21 //mainループ
22 while(1){
23     // GPIO47をLに
24     *(volatile unsigned int *)GPCLR1 |= 0x01 << 15;
25     LED_state = 'L';
26
27     // GPIO47をHに
28     *(volatile unsigned int *)GPSET1 |= 0x01 << 15;
29     LED_state = 'H';
30 }

JTAGデバッグを行うプログラムをコンパイルする際には,コンパイラの最適化をOFFにし デバッグオプションをつけるようにしてください.

(gdb) load

これで実行の準備ができました.

(gdb) continue

で普通にプログラムが動作します.(フリー実行)

接続して一回目はうまく動かないことがありますが,loadとcontinueをもう一度繰り返すと動きました.

step実行

(gdb) step

stepで1ステップずつプログラムを進められます. 繰り返しstepコマンドを入力するとwhileループ中の処理ごとに停止している様子が確認できます.

(gdb) step
25          LED_state = 'L';
(gdb) step
28          *(volatile unsigned int *)GPSET1 |= 0x01 << 15;
(gdb) step
29          LED_state = 'H';
(gdb) step
30      }
(gdb) step
24          *(volatile unsigned int *)GPCLR1 |= 0x01 << 15;

bleakポイント

(gdb)break main.c:"行番号"

指定した行でプログラムを停止できます.

(gdb) break main.c:24
Breakpoint 1 at 0x807c: file main.c, line 24.
(gdb) break main.c:28
Breakpoint 2 at 0x8098: file main.c, line 28.

watchポイント

(gdb) watch "変数名"

指定した変数に代入が行われたら停止します.

(gdb) watch LED_state

LED_stateに値が代入されるたびブレークします.

(gdb) continue
Continuing.

Program received signal SIGTRAP, Trace/breakpoint trap.
main () at main.c:30
30      }
(gdb) continue
Continuing.

Program received signal SIGTRAP, Trace/breakpoint trap.
main () at main.c:28
28          *(volatile unsigned int *)GPSET1 |= 0x01 << 15;

変数の内容を見る

(gdb) print "変数名"

変数の中身を見ます.

(gdb) print LED_state
$1 = 72 'H'
(gdb) continue
Continuing.

Program received signal SIGTRAP, Trace/breakpoint trap.
main () at main.c:28
28          *(volatile unsigned int *)GPSET1 |= 0x01 << 15;
(gdb) print LED_state
$2 = 76 'L'

メモリの値を見る

(gdb) x "番地"

指定した番地のメモリの値を見ます. Raspberry Pi A+ではメモリの0x20200038番地にGPIO32番以降のHIGH/LOW状態が格納されているようです。

(gdb) x 0x20200038
0x20200038: 0x003f5eff
(gdb) continue
Continuing.

Program received signal SIGTRAP, Trace/breakpoint trap.
main () at main.c:30
30      }
(gdb) x 0x20200038
0x20200038: 0x003fdeff

上記の値を見ると、LED消灯時は

(gdb) x 0x20200038
0x20200038: 0x003f5eff

点灯時

(gdb) x 0x20200038
0x20200038: 0x003fdeff

0x003f5eff→0x003fdeffと15番目のビットの変化が確認できます。

JTAGデバッグは組み込み開発においてかなり強力なツールだと思うので今後も使っていきたいですね. kstmのメンバーはIDEが好きではない人が多いと思いますが(勝手なイメージ),VScodeEclipseとの連携もしてみたいです.

参考文献

tatsu-zine.com

FT232HLでベアメタルな(?)Raspberry Piを JTAGデバッグする

この記事はkstmアドベントカレンダー10日目の記事として書きました。
qiita.com

 

 

 はじめに

今回の記事は,1200円(@秋月電子)で購入できるUSBシリアル変換モジュールFT232HLを使ってベアメタルなRaspberry PiJTAGデバッグ環境を構築したという内容です.

akizukidenshi.com

ベアメタルとは,Raspbian等のOSを使用せずに,直接MCUを動作させるようなプログラムを作成し動作させることを言うそうです.

ベアメタルについては,こちら↓の書籍が大変詳しく,今回の記事でもかなり参考にさせていただいているので興味がある方はぜひ読んでみてください.

tatsu-zine.com

 

Raspberry Pi(以下ラズパイと称する)におけるベアメタルプログラミングでは,ラズパイを通常のマイコンのように扱うのでJTAGデバッグが非常に有効です.

JTAGデバッグ便利そうだな〜と思っていたのですがARMのJTAGデバッガとして販売されているものは3000円位からと学生には少々お高めです.

そこで今回,秋月電子通商で1200円で購入できるUSBシリアル変換モジュールFT232HL を用いたJTAGデバッグ環境を構築しました.

僕自身まだ理解できない内容がかなり多いので,おかしな表現・内容があると思いますが,生暖かい視線で見守っていただければと思います. 

 ソフトウェアの設定

今回の開発環境は以下のようになります.

ホストPC : Linux Mint 18.2 Sonya

ターゲットボード : Raspberry Pi zero (BCM2835)

必要なパッケージ等は適宜インストールしてください.

 

まず,OpenOCDをインストールします.

Open On-Chip Debugger

(2017/12/10時点での最新版は0.10.0でした.)

下記のコマンドを入力しインストールを行いました.

./configure --enable-ftdi

make

sudo make install

 

次に,JTAG通信に使うピンを有効にするためのプログラムをラズパイのSDカードに入れますが...

コレに関しては上記の本や他のHPを参照してください(なげやりでスミマセン).

 

またOpenOCDを使うにあたりcfgファイル(ターゲットやデバッガの情報が入ったファイル)が必要となります.今回ラズパイ用のcfgファイルとして,

raspberrypi/armjtag at master · dwelch67/raspberrypi · GitHub

上記リンクのraspi.cfgを使用させていただきました.ありがとうございました.

 

 ハードウェアの設定

FT232HLとRaspberry Piを接続します.

下記のように接続しました.

ラズパイ :FT232HL

GPIO25 : AD0

GPIO4   : AD1

GPIO24 : AD3

GPIO27 : AD4

GND      : GND

 

f:id:yabashimong:20171209201524j:plain

こんな感じです.

 

動かしてみる

実際にJTAGデバッグを行ってみます.

OpenOCDは,先ほどダウンロードしたターゲット用のcfgファイルの他にJTAGデバッガ用のcfgファイルも必要です.

OpenOCDインストール時に構築されたディレクトリの中に,

/usr/local/share/openocd/scripts/interface/ftdi/um232h.cfg

FT232HLと互換性がある(らしい)um232h用のcfgファイルがにあったのでコレを使わせてもらいます.

 

下記のコマンドでOpenOCDを起動します.

OpenOCD -f /usr/local/share/openocd/scripts/interface/ftdi/um232h.cfg -f /hoge/raspi.cfg

エラーを吐かずにターゲットに関する情報が表示されれば成功です.

ここまで来たら上記の本や他のHPを参考にしてgdbを接続し作成したプログラムのデバッグを行ってください.(なげやりでスミマセン(2回目))

 

僕自身まだgdbの使い方を理解できていないのですが,ブレークポイントを貼ってステップ実行したり,メモリの中身を覗いたりと便利かつ面白い機能がたくさんありそうです.

上級ベアメタラー(?)目指してガシガシ使っていきたいです.