(シミュレータ編第4回)OSを直接起動する

2010/09/29

あなたは 人目のお客様です.

IPAの未踏本体の公募への応募がよーやく終わってひと段落. で,シミュレータについて作業を進めよう.

前回の最後にちょろっと書いたけど, 現状ではシミュレータを利用する場合は実機のときと同様に, まずブートローダーをシミュレータで起動して, で,シリアル経由でOSをダウンロードして起動するという手順になる.

しかし前回も説明したが,この方法だとOSのデバッグをする際にOSのシンボル情報を 読み直さなければならなくて,これがけっこう面倒だ.まあなにかうまい方法は あるのかもしれないが,そもそもブートローダー経由でOSを起動するというのでは なく,シミュレータでOSを直接起動できるととってもらくちんだ.なのでそーいう 対応を今回はしてみよう.

まず,現状のOSをそのままシミュレータで起動しても,うまく動作しない. 割り込みベクタの設定が無いのと,シリアルまわりの初期化をブートローダーに まかせてしまっていてOSで初期化していないからだ.あとBSSの初期化の考慮も必要. まあシリアルに関してはやってみるとそれなりに動いてしまうかもしれないが, 割り込みベクタが無いのではまったく動かない.ということでOSに,それらの対応が 必要になる.

で,前々回のソースコードを修正したのが以下. (前回は説明だけでソースコード無しなので,前々回のソースコードを修正している)

修正の内容は以下.

まず,ブートローダー側から intr.S と vector.c をコピーしてそのまま持ってきた. さらに intr.S, vector.c をコンパイル対象にするように Makefile を修正.

diff -ruN h8_sim_02/os/Makefile h8_sim_04/os/Makefile
--- h8_sim_02/os/Makefile	Sun Sep 12 16:54:13 2010
+++ h8_sim_04/os/Makefile	Wed Sep 29 22:52:47 2010
@@ -13,7 +13,7 @@
 RANLIB  = $(BINDIR)/$(ADDNAME)ranlib
 STRIP   = $(BINDIR)/$(ADDNAME)strip
 
-OBJS  = startup.o main.o interrupt.o
+OBJS  = vector.o startup.o intr.o main.o interrupt.o
 OBJS += lib.o serial.o
 
 # sources of kozos
次に,vector.c で定義してある割り込みベクタがROMのアドレスの先頭 (つまり,ゼロ番地)に配置されるようにリンカスクリプトにルールを追加する (シミュレータなのでROM領域はリードオンリーではなく,通常のメモリとして扱える). これもブートローダー側のリンカスクリプト内の記述をそのまま持ってきただけ.
diff -ruN h8_sim_02/os/ld.scr h8_sim_04/os/ld.scr
--- h8_sim_02/os/ld.scr	Sun Sep 12 16:54:13 2010
+++ h8_sim_04/os/ld.scr	Wed Sep 29 22:53:47 2010
@@ -4,6 +4,10 @@
 
 MEMORY
 {
+	romall(rx)	: o = 0x000000, l = 0x080000 /* 512KB */
+	vectors(r)	: o = 0x000000, l = 0x000100 /* top of ROM */
+	rom(rx)		: o = 0x000100, l = 0x07ff00
+
 	ramall(rwx)	: o = 0xffbf20, l = 0x004000 /* 16KB */
 	softvec(rw)	: o = 0xffbf20, l = 0x000040 /* top of RAM */
 	ram(rwx)	: o = 0xffc020, l = 0x003f00
@@ -14,6 +18,10 @@
 
 SECTIONS
 {
+	.vectors : {
+		vector.o(.data)
+	} > vectors
+
 	.softvec : {
 		_softvec = .;
 	} > softvec
さらにブートローダー側で行っている初期化処理(具体的には,BSSと割り込みベクタと シリアルの初期化)を main.c の初期化部分に追加する.
diff -ruN h8_sim_02/os/main.c h8_sim_04/os/main.c
--- h8_sim_02/os/main.c	Thu Sep  9 21:52:41 2010
+++ h8_sim_04/os/main.c	Thu Sep 30 02:39:01 2010
@@ -1,6 +1,9 @@
 #include "defines.h"
 #include "kozos.h"
 #include "interrupt.h"
+#ifdef SIMULATOR
+#include "serial.h"
+#endif
 #include "lib.h"
 
 /* システム・タスクとユーザ・タスクの起動 */
@@ -23,6 +26,19 @@
 int main(void)
 {
   INTR_DISABLE; /* 割込み無効にする */
+
+#ifdef SIMULATOR
+  {
+    extern int bss_start, ebss;
+    memset(&bss_start, 0, (long)&ebss - (long)&bss_start);
+  }
+
+  /* ソフトウエア・割り込みベクタを初期化する */
+  softvec_init();
+
+  /* シリアルの初期化 */
+  serial_init(SERIAL_DEFAULT_DEVICE);
+#endif
 
   puts("kozos boot succeed!\n");
 
まあ結論をいっちゃうと,ブートローダー側で行っている初期化処理をOS側に そのまま持ってきただけだ.

では試してみよう.まずOSをビルドして,OSのELFファイルを指定してGDBを起動する.

hiroaki@teapot:~/h8>% ./gcc/gdb-7.2/gdb/gdb sim/h8_sim_04/os/kozos.elf
GNU gdb (GDB) 7.2
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=i386-unknown-freebsd6.2 --target=h8300-elf".
For bug reporting instructions, please see:
...
Reading symbols from /home/hiroaki/h8/sim/h8_sim_04/os/kozos.elf...done.
(gdb) 
target sim, load を実行する.
(gdb) target sim
Connected to the simulator.
(gdb) load
connect to /dev/ttyp9
Loading section .vectors, size 0x100 vma 0x0
Loading section .text, size 0x16b6 vma 0xffc020
Loading section .rodata, size 0xa3 vma 0xffd6d8
Loading section .data, size 0x2c vma 0xffd77c
Start address 0xffc020
Transfer rate: 50216 bits in <1 sec.
(gdb) 
loadを実行すると,利用すべきTTYデバイスが表示される(この場合は/dev/ttyp9) ので,別の kterm で cu を起動して,そのデバイスに接続する.まあこのへんの やりかたは,前回と同じだ.
teapot# cu -l /dev/ttyp9
Connected

GDBでrunを実行する.
(gdb) run
Starting program: /home/hiroaki/h8/sim/h8_sim_04/os/kozos.elf 

すると,cu側にブートメッセージが出力される.
teapot# cu -l /dev/ttyp9
Connected
kozos boot succeed!

command> 
コマンド入力してみよう.
teapot# cu -l /dev/ttyp9
Connected
kozos boot succeed!

command> echo sample
 sample
command> 
ちゃんと応答している.割り込みまわりも大丈夫そうだ.

これでOSが直接起動できたので,前回のようなシンボル情報読み直しとかを しなくても,OSを直接シンボルデバッグできることになる.

さて,今回のOSの修正だが,OSのモジュールが割り込みベクタを持つように 修正されている.このOSモジュールはシミュレータから直接起動することを 想定したものだが,シミュレータ上でブートローダーから起動することも,できる. シミュレータではROM領域がリードオンリーとして扱われるわけではないので, ブートローダーがOSのELF形式を読んで,割り込みベクタをゼロ番地に書き込もうと しても正常に書き込めるからだ.

また,実機でブートローダーから起動しようとしても,たぶん起動できるように思う. ブートローダーはOSが持つ割り込みベクタをゼロ番地に書き込もうとするが実機だと ROMなので書き込めず,もともとブートローダーが持っている割り込みベクタが そのまま残るはず.で,それはそもそも元の動作なので問題ないからだ.

以下はシミュレータでブートローダーを起動して,今回修正版のOSを起動したところ. まずGDBの出力.

hiroaki@teapot:~/h8>% ./gcc/gdb-7.2/gdb/gdb sim/h8_sim_04/bootload/kzload.elf
GNU gdb (GDB) 7.2
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=i386-unknown-freebsd6.2 --target=h8300-elf".
For bug reporting instructions, please see:
...
Reading symbols from /home/hiroaki/h8/sim/h8_sim_04/bootload/kzload.elf...done.
(gdb) target sim
Connected to the simulator.
(gdb) load
connect to /dev/ttyp9
Loading section .vectors, size 0x100 vma 0x0
Loading section .text, size 0x1142 vma 0x100
Loading section .rodata, size 0xcd vma 0x1242
Loading section .data, size 0x10 vma 0xfffc20
Start address 0x100
Transfer rate: 39160 bits in <1 sec.
(gdb) run
Starting program: /home/hiroaki/h8/sim/h8_sim_04/bootload/kzload.elf 

以下はcu側の出力.転送するのは「kozos.elf」でなく「kozos」なことに注意.
teapot# cu -l /dev/ttyp9
Connected
kzload (kozos boot loader) started.
kzload> load
~CLocal command? lsx h8/sim/h8_sim_04/os/kozos
Sending h8/sim/h8_sim_04/os/kozos, 53 blocks: Give your local XMODEM receive command now.
Bytes Sent:   6784   BPS:1874                            

Transfer complete

XMODEM receive succeeded.
kzload> run
starting from entry point: ffc020

kozos boot succeed!

command> echo sample
 sample
command> 
無事に起動できている.ということで,今回修正したOSは,シミュレータで ブートローダーからも起動できるが,シミュレータで直接起動することも できるということだ.

ブートローダーのデバッグ(ブートローダーからのOSの起動も含む)をしたいときは ブートローダーから起動して,OSのデバッグをしたいときはOSを直接起動, というように使い分けるといいだろう.


メールは kozos(アットマーク)kozos.jp まで