GDBをつかって、microbitのレジスタへ値を書き込む
はじめに
GDBを使ってレジスタの読み書きを行い、microbitのLEDの点灯をしてみます。
使用するmicrobitはV1.5です。
利用するコード
いきなりすべてのレジスタをgdbを使って設定するのはさすがに面倒なので
1個のレジスタの読み書きだけをしてみます。
丁度いいコードがどこかないか探してみたところ、
以下のようなものがありましたので、こちらを利用します。
上記の
https://github.com/dwelch67/microbit/tree/master/blinker01
を利用します。これはLEDのひとつを点滅させるだけの単純なものです。
Debug用に修正
Makefileを以下のように修正します。
-g -O0
を付け、makeを実行します。そうすると
notmain.elf
が作成されます。
diff --git a/blinker01/Makefile b/blinker01/Makefile
index 404cb37..26611c6 100644
--- a/blinker01/Makefile
+++ b/blinker01/Makefile
@@ -2,8 +2,8 @@
ARMGNU = arm-none-eabi
#ARMGNU = arm-linux-gnueabi
-AOPS = --warn --fatal-warnings -mcpu=cortex-m0
-COPS = -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding -mcpu=cortex-m0
+AOPS = -g --warn --fatal-warnings -mcpu=cortex-m0
+COPS = -Wall -Werror -g -O0 -nostdlib -nostartfiles -ffreestanding -mcpu=cortex-m0
pyocd-gdbserverの起動
microbitをPCに接続し pyocd-gdbserverを起動します。
$ pyocd-gdbserver -t nrf51 -bh -r
0000988:WARNING:gdb_server:pyocd-gdbserver is deprecated; please use the new combined pyocd tool.
0001102:INFO:board:Target type is nrf51
0001356:INFO:dap:DP IDR = 0x0bb11477 (v1 MINDP rev0)
0001906:INFO:ap:AHB-AP#0 IDR = 0x04770021 (AHB-AP var2 rev0)
0002092:INFO:rom_table:AHB-AP#0 Class 0x1 ROM table #0 @ 0xf0000000 (designer=244 part=001)
0002110:INFO:rom_table:[0]<e00ff000:ROM class=1 designer=43b part=471>
0002111:INFO:rom_table: AHB-AP#0 Class 0x1 ROM table #1 @ 0xe00ff000 (designer=43b part=471)
0002142:INFO:rom_table: [0]<e000e000:SCS-M0+ class=14 designer=43b part=008>
0002159:INFO:rom_table: [1]<e0001000:DWT-M0+ class=14 designer=43b part=00a>
0002170:INFO:rom_table: [2]<e0002000:BPU class=14 designer=43b part=00b>
0002180:INFO:rom_table:[1]<f0002000:MTB-M0 class=9 designer=43b part=9a3 devtype=13 archid=0000 devid=0:0:0>
0002186:INFO:cortex_m:CPU core #0 is Cortex-M0 r0p0
0002196:INFO:dwt:2 hardware watchpoints
0002201:INFO:fpb:4 hardware breakpoints, 0 literal comparators
0002225:INFO:server:Semihost server started on port 4444 (core 0)
0002241:INFO:gdbserver:GDB server started on port 3333 (core 0)
gdbの起動
pyocd-gdbserverを起動した terminal画面とは別の画面を起動し、そこから
arm-none-eabi-gdbを起動します。
$ arm-none-eabi-gdb
GNU gdb (GNU Arm Embedded Toolchain 10-2020-q4-major) 10.1.90.20201028-git
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
<省略>
(gdb)
起動後、gdb serverに接続しnomain.elf
をloadします。
(gdb) target remote localhost:3333
Remote debugging using localhost:3333
warning: No executable has been specified and target does not support
determining executable automatically. Try using the "file" command.
0x000000b6 in ?? ()
(gdb) file notmain.elf
A program is being debugged already.
Are you sure you want to change the file? (y or n) y
Reading symbols from notmain.elf...
(gdb) load notmain.elf
Loading section .text, size 0xdc lma 0x0
Start address 0x00000000, load size 220
Transfer rate: 450 bytes/sec, 220 bytes/write.
(gdb)
tuiを使用
必須では無いですが、TUI(Text User Interface)モードというものがあるので(最近知った)、
こちらを利用して、コード、レジスタ情報を1画面に表示します。
(gdb) tui enable
(gdb) tui new-layout example {-horizontal src 1 asm 1 regs 1} 2 status 0 cmd 1
(gdb) layout example
(gdb) focus cmd
上記コマンドで、以下のように表示されます。
詳しくは以下。
LED点灯直前の処理まで処理をすすめる。
以下のようにして、
LED点灯直前まで処理を進めます。
(gdb) b notmain.c:33
Breakpoint 1 at 0xa0: file notmain.c, line 33.
Note: automatically using hardware breakpoints for read-only addresses.
(gdb) c
Continuing.
Breakpoint 1, notmain () at notmain.c:33
(gdb) s
PUT32 () at flash.s:38
画面は以下のようになります。
現在、以下の命令のところで停止しています。
str r1,[r0]
レジスタR0とR1の値はそれぞれ以下のようになっています
r0 0x50000508
r1 0x2000
アドレス、0x50000508に0x2000を書いているようです。
gdbのsetコマンドで設定をしてみます。
(gdb) set *((int *) 0x50000508) = 0x2000
Cannot access memory at address 0x50000508
出来ないよ、とメッセージが出てしまいました。
調べると同じような症状で困っている人がいました。
gdbのドキュメントでは以下に記載がありました。
set mem inaccessible-by-default off
を入力してから
setコマンドを入力してみます。
(gdb) set mem inaccessible-by-default off
(gdb) set *((int *) 0x50000508) = 0x2000
(gdb)
先程の、Cannot access memory at ...
は表示されず
LEDが点灯しました。
参考
レジスタの情報については以下を参照
Discussion