RaspberryPi3 64bitモード ベアメタルをJTAGデバッグする

# 今回目指す環境

[Raspberry Pi 3] ⇔ [JTAGデバッガ] ⇔ [WindowsPC]

Raspberry Pi上ではベアメタルプログラムを動作させる。
OpneOCD + GDBを用いたフリーな環境を構築する。
WindowsでOpenOCD + GDBを動作させてデバッグを行う。

# 必要なもの

- Raspberry Pi 3 一式
- JTAGデバッガ  
JTAGデバッガとしてARM-USB-TINY-Hを用いる。5000円程度で購入可能なもの。  
https://www.olimex.com/Products/ARM/JTAG/ARM-USB-TINY-H/  
- JTAG - Rpi3接続用の線材
- Windowsマシン  
実際のJTAGデバッグはWindows PCで行う。  
- Linuxマシン  
OpenOCDのビルドにUbuntu1４.04を用いた。  
Windows上のMinGWやCygwinでもビルドできそうだが未確認。

# ハードの接続

## Raspberry Piのピン配置

### 基板のGPIOピンの位置
Raspberry Pi 2用の情報だが、Raspberry Pi 3と同じらしい。
https://www.raspberrypi.org/documentation/usage/gpio-plus-and-raspi2/README.md

### GPIOピンのファンクション切り替え

Raspberry Piでは、レジスタ設定することで、それぞれのGPIOピンの機能を個別に切り替えることができる。
以下はRaspberry Pi 1用の情報だが参考になる。
GPIO22～27をALT4に切り替えてJTAGを接続する。
https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2835/BCM2835-ARM-Peripherals.pdf

## ARM-USB-TINY-Hのピン配置

https://www.olimex.com/Products/ARM/JTAG/_resources/ARM-USB-TINY_and_TINY_H_manual.pdf
ARM-USB-TINY-H本体のコネクタ面にLEDが付いている
コネクタ面のLEDが下になるように以下のピン配置を見る

| pin | signal name | pin | signal name |
|---|---|---|---|
| 1 | VREF | 2 | VREF |
| 3 | TTRST_N | 4 | GND |
| 5 | TTDI | 6 | GND |
| 7 | TTMS | 8 | GND |
| 9 | TTCK | 10 | GND |
| 11 | TRTCK | 12 | GND |
| 13 | TTDO | 14 | GND |
| 15 | TSRST_N | 16 | GND |
| 17 | NOT CONNECTED | 18 | GND |
| 19 | TARGET SUPPLY | 20 | GND |

　　　　　　　　 ○ LED側

## Raspberry Pi 3 と ARM-USB-TINY-H の接続

接続はしっかり確認すること。間違えると壊れる可能性大。

| RPi3信号名 | 結線 | ARM-USB-TINY-H信号名 |
|---|---|---|
| 3.3v | <-> | VREF |
| Ground | <-> | GND |
| GPIO22 | <-> | TSRTS_N |
| GPIO26 | <-> | TTDI |
| GPIO27 | <-> | TTMS |
| GPIO25 | <-> | TTCK |
| GPIO23 | <-> | TRTCK |
| GPIO24 | <-> | TTDO |

以下の写真のようにピン同士を直接つないだ。
本当は、専用コネクタ＆ケーブルを用意しておくほうが便利かつ安全。
なお、テスト用にGPIO16にLEDをつないでいる。
![rp3_jtag.jpg](https://qiita-image-store.s3.amazonaws.com/0/176334/99c87edf-57e8-f58f-1b0f-cc4d7ce8b95b.jpeg)




# ソフトの用意

## OpenOCD

Ubuntu上でWindows用のOpenOCDをビルドする。
MinGWやCygwinでもビルドできそうだが未確認。

以下をインストールしておく
sudo apt-get install mingw-w64 automake libtool libudev-dev

openocdをビルドするにはlibusbライブラリが必要となる。
libusbをビルド＆インストールしておく。
~~git clone git://git.libusb.org/libusb.git~~ (2017/10/7 アクセスできなくなったため修正)
git clone https://github.com/libusb/libusb.git
cd ./libusb/
./autogen.sh
./configure --host=i686-w64-mingw32
make
sudo make install

raspberry pi 3 AArch64用のOpneOCDを作ってくれている方がいるので、それを利用させてもらった。
(2017/10/7 複数コアを停止した際に再開できなくなる問題あり)
git clone https://github.com/daniel-k/openocd.git openocd-armv8
cd openocd-armv8
git checkout armv8
./bootstrap
./configure --host=i686-w64-mingw32 --enable-ftdi
make

以下をWindows側に持ってくる
 - openocd-armv8/src/openocd.exe
 - openocd-armv8/tcl以下一式
試しにWindowsのコマンドプロンプト（or cygwin）でopenocd.exeを実行してみる。
libusbxxx.dllがないというようなエラーが出たら、別途入手してpathを通しておく。

## GDB
LinaroのWindows用のGCCを用いる。
AArch64ベアメタル向けtoolchainにGDBが含まれている。
https://www.linaro.org/downloads/

## Raspberry Piで動かすプログラム

Raspberry Piは電源ON直後は、全ピンの機能がGPIOになっている。
JTAGを使用するには、ピンの機能をJTAGに切り替えなければならない。
GPIO22～27をALT4に切り替える。

サンプルプログラムを以下に置いた。(2017/10/7)
https://github.com/YujiToshinaga/RPi64BareMetal/tree/master/JtagCon

## ドライバインストール

http://zadig.akeo.ie/
Zadigを使用して"ARM-USB-OCD-H (Interface 0)"のデバイスにWinUSBを適用する。
"Interface 1"には適用してはいけない。
とりあえず、"Interface 1"のドライバはインストールしなくて良い。

# JTAGデバッグ動作
## OpenOCDによるデバッグ
### OpenOCDの起動
Windows側でターミナル等で以下を実行する
openocd.exe -f tcl/interface/ftdi/olimex-arm-usb-tiny-h.cfg -f tcl/target/rpi3.cfg
大量にエラーが出力されるが特に問題なくJTAGデバッグできる。
あらかじめRPi側のキャッシュ、MMU等の設定を正しくしておけばエラーなく接続できた。

### telnetでOpenOCDの設定
別のターミナルを開きtelnetでOpenOCDに接続
% telnet localhost 4444
以下コマンドでコア一覧（4コアの状態）が表示される
\> targets
おそらく最初はコア3に接続中なので、以下コマンドでコア0に切り替える
\> targets rpi3.cpu
GDBに接続するために、コア0を止めておく
\> halt

よく使うコマンド例

| コマンド例 | 説明 |
| --- | --- |
| targets | 全コアの状態を表示する |
| targets rpi3.cpu1 | コア1に切り替える |
| halt | コアを動作を停止する |
| resume | コアの動作を開始する |
| reg | レジスタの内容を表示する |
| reg x1 0x5f5f | x1レジスタに0x5f5fを書き込む |
| reg pc 0x200 | 0x200番地にジャンプする |
| bp 0x1000 4 hw | 0x1000番地にブレークポイントを設定する |
| rbp 0x1000 | 0x1000番地のブレークポイントを削除する |
| mdw 0x400 | 0x400番地をワードサイズ分表示する |
| mww 0x400 0x5f5f | 0x400番地にワードサイズ分0x5f5fを書き込む |
| load_image test.bin 0x0 | 0x0番地にtest.binを展開する（test.binのパスはopenocd.exeの場所が基準となる） |


## GDBによるデバッグ
aarch64-elf-gdb.exe xxx.axf
\> target remote localhost 3333
あとはGDBコマンドでデバッグ可能になるはず

↓コアのレジスタを表示した様子
![telnet.jpg](https://qiita-image-store.s3.amazonaws.com/0/176334/1b0fd438-8819-5906-07f2-008f977eecee.jpeg)

↓gdbでデバッグする様子
![gdb.jpg](https://qiita-image-store.s3.amazonaws.com/0/176334/f04310c5-30de-54f1-26b4-63afa02b4d37.jpeg)