(シミュレータ編第6回)ネットワーク対応だ!

2010/10/04

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

ここんとこずっとやってきたシミュレータ対応だけど,シリアル,タイマと実装した. 今回はネットワーク対応だ.ネットワーク対応ができれば,シミュレータ上で TCP/IPの実装をできるようになるので開発がとっても楽ちんになる.なので, ぜひやっておきたいところだ.ていうかそもそもTCP/IPの実装のために シミュレータ環境を整備しているので,ネットワーク対応させなければ そもそもの意味が無い.

というわけでネットワーク対応なのだけど,H8/3069Fボードに載っている RTL8019の動作に合わせて同様の動きをするようにシミュレータ側に機能追加する ことになる.

で,RTL8019の動きなのだけど,本来ならばチップのデータシートとかちゃんと読んで 実装すべきだろう.しかしRTL8019については (H8移植編その2第4回)ネットワークに接続しよう でデバイスドライバをすでに実装しているので,このデバイスドライバのコードを 読めば,デバイスの動きはだいたい想像できることになる.

で,デバイスドライバのコードを見てみると,RTL8019はどうもリングバッファを 持っていて,データは順に書き込まれるようだ.で,そのリングバッファは256バイト 単位でブロック化されているみたい.あとバッファは送信用と受信用に分かれて いるみたいだ.

あとRTL8019ではレジスタはページ形式になっていて,ページ指定すると レジスタマッピングががっさり変わるようだ.

次に,パケットの送受信をシミュレータ上で実際にどのように行うかだ. 実はFreeBSDはtapデバイスというのを持っていて,ネットワークインタフェースの 送受信を自身のプロセスに折り返すことができる.似たものでトンネルデバイス (tunデバイス)というのもあるが,tunデバイスはIP層のレベルで折り返すのに対して, tapデバイスはethernetの層で折り返してくれるので,ethernetデバイスのように 用いることができる.ということで今回は,tapデバイスを利用して通信を行う. ちなみにここで紹介するのはFreeBSD用の方法になるが,tapもtunもLinuxでも 存在する?らしいので,GNU/Linuxへの移植も簡単にできるかもしれない.

ここまではGDB側,つまりシミュレータ側での対応の話. で,さらに実際に動作させるファームウエア側だけど,今回はネットワーク通信を 行うということで, (H8移植編その2第4回)ネットワークに接続しよう で紹介したOSのソースコードをベースにして今までのシミュレータ対応を入れて, 動作させてみる.毎回動作させるものがコロコロ変わってしまってややこしくて ゴメン.

で,作成したのが以下.

まずGDBに対する修正だが,上記ソースコードのgdbというフォルダに device.cに対する修正 (device.c本体と,前回からの差分パッチ) が置いてあるので,これらを利用してGDBをビルドしなおしてほしい. GDBの再ビルド方法は前回に説明したのと同様.

なおdevice.cのパッチは前回のソースコードに 対する差分なので,オリジナルのdevice.cからパッチを当てるには, 前回のパッチ→今回のパッチというように, 2回ぶんのパッチを当てる必要がある.まあ面倒ならdevice.c本体をそのままコピー してしまえばいいだろう.

device.cへの修正の内容だが,RTL8019のレジスタを参照して互換の動作をするように 機能追加しただけだ.デバドラのコードからチップの動作を推測して書いたので ほんとにこれで正しいかどうか確実というわけではないが,まあいいとしよう. レジスタのページ処理のために,RTL8019の実際の動作の処理(ether_run())の 先頭でレジスタ内容を退避して,終端で書き戻しているところがポイントだ (ether_run()の先頭と終端のmemcpy()の処理).

あとtapデバイスをオープンしてパケット通信ができるようにしてある. 方法としては,/dev/tap0から順にopen()してみることで空いてるデバイスを探して, あとは select() で見張って read()/write() するだけだ. まあ具体的な方法は,device.c の修正を参考にしてほしい.

一点,注意点として,シミュレータ用の特殊レジスタとして RTL8019_SIM_SR という仮想的なレジスタが追加されていて, RTL8019_SIM_SR_NRDY というビットを見て動作するように実装してある.

これはなぜかというと,RTL8019のバッファのリード・ライトをする場合には, どうも RTL8019_RDMAP というレジスタをただひたすら読み書きすればいいようなのだ. たとえば今回参考にしているRTL8019のデバイスドライバには,以下のようなコードが ある.

static int read_data(int addr, int size, char *buf)
{
  ...

  for (i = 0; i < size; i++) {
    buf[i] = *RTL8019_RDMAP;
  }
  ...
つまりデータのリード時には,RTL8019_RDMAPをひたすら読めばいいようなのだ. ところがこのようだ動作は,シミュレータの実装としてはちょっと都合が悪い. RTL8019_RDMAP が読まれたことをなんらかの方法で検知しないと, RTL8019_RDMAP の内容を次のデータに更新するタイミングがとれないからだ. しかしこれはちょっとめんどくさい.

ということでシミュレータでは,RTL8019_SIM_SR という仮想レジスタを追加して, RTL8019_SIM_SR の RTL8019_SIM_SR_NRDY というビットが立ったときに RTL8019_RDMAP を更新するように実装する.つまりファームウエア側では, シミュレータで動作させる場合には RTL8019_SIM_SR を操作する特殊コードを 追加しなければならないことになる.まあちょっとなんだかなあな実装のような 気もするが,シミュレータ用にこのような仮想レジスタを実装することは 珍しいことではない気もするので,まあこれはこれでいいとしよう.

次にブートローダーとOSの修正のほう.こちらには前回までの内容を参考にして, シミュレータ用の対応を入れた.具体的には, (シミュレータ編第2回)シリアル対応をした(シミュレータ編第4回)OSを直接起動する で説明した修正を入れた. このためこのファームウエアは,ブートローダーからOSを起動して利用することも できるし,OSを直接起動して利用することもできるはずだ. まあソースコード自体は (H8移植編その2第4回)ネットワークに接続しよう からの修正なので,修正点については差分をとってもらえばわかるだろう.

注意として,シミュレータ側で行った仮想レジスタの対応を,ファームウエア側でも 行う必要がある.以下のような感じだ.

static int read_data(int addr, int size, char *buf)
{
  ...
  for (i = 0; i < size; i++) {
#ifdef SIMULATOR
    *RTL8019_SIM_SR |= RTL8019_SIM_SR_NRDY;
    while (*RTL8019_SIM_SR & RTL8019_SIM_SR_NRDY)
      ;
#endif
    buf[i] = *RTL8019_RDMAP;
  }
  ...
}

static int write_data(int addr, int size, char *buf)
{
  ...
  for (i = 0; i < size; i++) {
    *RTL8019_RDMAP = buf[i];
#ifdef SIMULATOR
    *RTL8019_SIM_SR |= RTL8019_SIM_SR_NRDY;
    while (*RTL8019_SIM_SR & RTL8019_SIM_SR_NRDY)
      ;
#endif
  }
  ...
}
RTL8019_SIM_SR_NRDY を見ることで,ファームウエアとシミュレータの間で 待ち合わせをするようになっている.

あと,修正前はIPアドレスが192.168.0.16とかになっていたけど, ぼくの環境でちょっと使ってて都合悪いので,192.168.10.16に変更.

diff -ruN h8_04/os/ip.c h8_sim_06/os/ip.c
--- h8_04/os/ip.c       Mon Oct  4 22:59:22 2010
+++ h8_sim_06/os/ip.c   Mon Oct  4 23:11:46 2010
@@ -7,7 +7,7 @@
 uint32 network_id;
 
 #define MACADDR "\x00\x11\x22\x33\x44\x55"
-#define IPADDR  0xc0a80010 /* 192.168.0.16 */
+#define IPADDR  0xc0a80a10 /* 192.168.10.16 */
 static uint32 ipaddr = IPADDR;
 
 #define MACADDR_SIZE 6
以上で修正は終了.実際に試してみよう. 今回はtapデバイスを利用するので,まずはスーパーユーザになって 以下を実行する.これでtapデバイスのモジュールがロードされ,tapデバイスが 利用可能になる.あ,いちおう繰り返しとくけど,実行環境はFreeBSDね.
# kldload if_tap
シミュレータを起動する.tapデバイスを利用するので,スーパーユーザで gdbを起動している点に注意.スーパーユーザでデバッガを起動するのって なんかちょっとこわいけど,まあいいとしよう.
teapot# ./gcc/gdb-7.2/gdb/gdb sim/h8_sim_06/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_06/os/kozos.elf...done.
(gdb) 
target sim を実行後,loadを実行する.
(gdb) target sim
Connected to the simulator.
(gdb) load
connect to /dev/ttyp7
interface: tap0
Loading section .vectors, size 0x100 vma 0x0
Loading section .text, size 0x2476 vma 0x400100
Loading section .rodata, size 0x11c vma 0x402578
Loading section .data, size 0x40 vma 0x402694
Start address 0x400100
Transfer rate: 79504 bits in <1 sec.
(gdb) 
まずシリアルが ttyp7 になっているので,cuでttyp7に接続する.このへんは 前回までと同様.
teapot# cu -l /dev/ttyp7
Connected
さらにGDBの出力をもう一度見ると,「interface: tap0」と表示されている. ifconfigでインタフェース情報を確認しよう.
teapot# ifconfig 
...(中略)...
tap0: flags=8842 mtu 1500
        ether 00:bd:22:5d:66:00
        Opened by PID 1826
tap0が利用可能になっている(このインタフェースは,GDBを起動しないと現れない).

tap0にIPアドレスを設定する.OS側は192.168.10.16なので,それと通信するための 適当なアドレスを設定する.とりあえず 192.168.10.1 にしておこう.

teapot# ifconfig tap0 192.168.10.1/24
GDBでrunを実行し,OSの動作を開始する.
(gdb) run
Starting program: /home/hiroaki/h8/sim/h8_sim_06/os/kozos.elf 

シリアルにブートメッセージが出力される.
teapot# cu -l /dev/ttyp7
Connected
kozos boot succeed!

command> MAC: 012eff334455
network ready.

unknown.
command> test
unknown.
command> 
コマンド入力もできている.大丈夫そうだ.

PC側からpingを投げてみよう.

teapot# ping 192.168.10.16
PING 192.168.10.16 (192.168.10.16): 56 data bytes
64 bytes from 192.168.10.16: icmp_seq=0 ttl=64 time=63.533 ms
64 bytes from 192.168.10.16: icmp_seq=1 ttl=64 time=18.379 ms
64 bytes from 192.168.10.16: icmp_seq=2 ttl=64 time=18.749 ms
64 bytes from 192.168.10.16: icmp_seq=3 ttl=64 time=17.373 ms
^C
--- 192.168.10.16 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max/stddev = 17.373/29.509/63.533/19.651 ms
teapot#
おー,ちゃんとpingが返ってきている.

こちらはシリアル側の出力.

command> received: 0x2abytes
replyed.
received: 0x62bytes
replyed.
received: 0x62bytes
replyed.
received: 0x62bytes
replyed.
received: 0x62bytes
replyed.
pingに正常に応答しているようだ.ばっちりだ. これでネットワーク関連の開発もできるわけだ.よかったよかった.

最後に今までのまとめとして,シミュレータ対応のための今回のソースコードの 修正の差分 ((H8移植編その2第4回)ネットワークに接続しよう に対する差分)をそのままぜんぶ掲載しておく. 今後はファームウエアをシミュレータ上で動作させたい場合には, 以下の修正を参考にしてブートローダーとOSに手を加えればいいということになる.

diff -ruN h8_04/bootload/Makefile h8_sim_06/bootload/Makefile
--- h8_04/bootload/Makefile	Mon Oct  4 22:59:22 2010
+++ h8_sim_06/bootload/Makefile	Mon Oct  4 23:01:05 2010
@@ -27,9 +27,10 @@
 CFLAGS = -Wall -mh -nostdinc -nostdlib -fno-builtin
 #CFLAGS += -mint32 # intを32ビットにすると掛算/割算ができなくなる
 CFLAGS += -I.
-#CFLAGS += -g
+CFLAGS += -g
 CFLAGS += -Os
 CFLAGS += -DKZLOAD
+CFLAGS += -DSIMULATOR
 
 LFLAGS = -static -T ld.scr -L.
 
diff -ruN h8_04/bootload/main.c h8_sim_06/bootload/main.c
--- h8_04/bootload/main.c	Mon Oct  4 22:59:22 2010
+++ h8_sim_06/bootload/main.c	Mon Oct  4 23:03:51 2010
@@ -8,6 +8,7 @@
 
 static int init(void)
 {
+#ifndef SIMULATOR /* シミュレータはVAにロードするので以下は不要 */
   /* 以下はリンカ・スクリプトで定義してあるシンボル */
   extern int erodata, data_start, edata, bss_start, ebss;
 
@@ -17,6 +18,7 @@
    */
   memcpy(&data_start, &erodata, (long)&edata - (long)&data_start);
   memset(&bss_start, 0, (long)&ebss - (long)&bss_start);
+#endif
 
   /* ソフトウエア・割り込みベクタを初期化する */
   softvec_init();
@@ -56,7 +58,11 @@
 static void wait()
 {
   volatile long i;
+#ifndef SIMULATOR
   for (i = 0; i < 300000; i++)
+#else
+  for (i = 0; i < 30000; i++)
+#endif
     ;
 }
 
diff -ruN h8_04/bootload/xmodem.c h8_sim_06/bootload/xmodem.c
--- h8_04/bootload/xmodem.c	Mon Oct  4 22:59:22 2010
+++ h8_sim_06/bootload/xmodem.c	Mon Oct  4 23:04:15 2010
@@ -19,7 +19,11 @@
   long cnt = 0;
 
   while (!serial_is_recv_enable(SERIAL_DEFAULT_DEVICE)) {
+#ifndef SIMULATOR
     if (++cnt >= 2000000) {
+#else
+    if (++cnt >= 200000) {
+#endif
       cnt = 0;
       serial_send_byte(SERIAL_DEFAULT_DEVICE, XMODEM_NAK);
     }
diff -ruN h8_04/os/Makefile h8_sim_06/os/Makefile
--- h8_04/os/Makefile	Mon Oct  4 22:59:22 2010
+++ h8_sim_06/os/Makefile	Mon Oct  4 23:06:00 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 timer.o ether.o
 
 # sources of kozos
@@ -25,9 +25,10 @@
 CFLAGS = -Wall -mh -nostdinc -nostdlib -fno-builtin
 #CFLAGS += -mint32 # intを32ビットにすると掛算/割算ができなくなる
 CFLAGS += -I.
-#CFLAGS += -g
+CFLAGS += -g
 CFLAGS += -Os
 CFLAGS += -DKOZOS
+CFLAGS += -DSIMULATOR
 
 LFLAGS = -static -T ld.scr -L.
 
diff -ruN h8_04/os/ether.c h8_sim_06/os/ether.c
--- h8_04/os/ether.c	Mon Oct  4 22:59:22 2010
+++ h8_sim_06/os/ether.c	Mon Oct  4 23:19:57 2010
@@ -68,6 +68,11 @@
 #define RTL8019_INTR    ((volatile uint8 *)(RTL8019_ADDR + 0x0b))
 #define RTL8019_CONFIG4 ((volatile uint8 *)(RTL8019_ADDR + 0x0d))
 
+#ifdef SIMULATOR
+#define RTL8019_SIM_CR  ((volatile uint8 *)(RTL8019_ADDR + 0xfe))
+#define RTL8019_SIM_SR  ((volatile uint8 *)(RTL8019_ADDR + 0xff))
+#endif
+
 #define NE2000_CR_P0       (0 << 6)
 #define NE2000_CR_P1       (1 << 6)
 #define NE2000_CR_P2       (2 << 6)
@@ -95,6 +100,10 @@
 #define NE2000_DCR_LS      (1 << 3)
 #define NE2000_DCR_BOS     (1 << 1)
 
+#ifdef SIMULATOR
+#define RTL8019_SIM_SR_NRDY (1 << 0)
+#endif
+
 #define NE2000_TP_START 0x40
 #define NE2000_RP_START 0x46
 #define NE2000_RP_STOP  0x80
@@ -125,6 +134,11 @@
   *NE2000_RSAR1 = (addr >> 8) & 0xff;
   *NE2000_CR    = NE2000_CR_P0 | NE2000_CR_RD_READ | NE2000_CR_STA;
   for (i = 0; i < size; i++) {
+#ifdef SIMULATOR
+    *RTL8019_SIM_SR |= RTL8019_SIM_SR_NRDY;
+    while (*RTL8019_SIM_SR & RTL8019_SIM_SR_NRDY)
+      ;
+#endif
     buf[i] = *RTL8019_RDMAP;
   }
   while ((*NE2000_ISR & NE2000_ISR_RDC) == 0)
@@ -145,6 +159,11 @@
   *NE2000_CR    = NE2000_CR_P0 | NE2000_CR_RD_WRITE | NE2000_CR_STA;
   for (i = 0; i < size; i++) {
     *RTL8019_RDMAP = buf[i];
+#ifdef SIMULATOR
+    *RTL8019_SIM_SR |= RTL8019_SIM_SR_NRDY;
+    while (*RTL8019_SIM_SR & RTL8019_SIM_SR_NRDY)
+      ;
+#endif
   }
   while ((*NE2000_ISR & NE2000_ISR_RDC) == 0)
     ;
diff -ruN h8_04/os/intr.S h8_sim_06/os/intr.S
--- h8_04/os/intr.S	Thu Jan  1 09:00:00 1970
+++ h8_sim_06/os/intr.S	Mon Oct  4 23:06:16 2010
@@ -0,0 +1,133 @@
+#include "intr.h"
+	.h8300h
+	.section .text
+
+	.global	_intr_softerr
+#	.type	_intr_softerr,@function
+_intr_softerr:
+	mov.l	er6,@-er7
+	mov.l	er5,@-er7
+	mov.l	er4,@-er7
+	mov.l	er3,@-er7
+	mov.l	er2,@-er7
+	mov.l	er1,@-er7
+	mov.l	er0,@-er7
+	mov.l	er7,er1
+	mov.l	#_intrstack,sp
+	mov.l	er1,@-er7
+	mov.w	#SOFTVEC_TYPE_SOFTERR,r0
+	jsr	@_interrupt
+	mov.l	@er7+,er1
+	mov.l	er1,er7
+	mov.l	@er7+,er0
+	mov.l	@er7+,er1
+	mov.l	@er7+,er2
+	mov.l	@er7+,er3
+	mov.l	@er7+,er4
+	mov.l	@er7+,er5
+	mov.l	@er7+,er6
+	rte
+
+	.global	_intr_syscall
+#	.type	_intr_syscall,@function
+_intr_syscall:
+	mov.l	er6,@-er7
+	mov.l	er5,@-er7
+	mov.l	er4,@-er7
+	mov.l	er3,@-er7
+	mov.l	er2,@-er7
+	mov.l	er1,@-er7
+	mov.l	er0,@-er7
+	mov.l	er7,er1
+	mov.l	#_intrstack,sp
+	mov.l	er1,@-er7
+	mov.w	#SOFTVEC_TYPE_SYSCALL,r0
+	jsr	@_interrupt
+	mov.l	@er7+,er1
+	mov.l	er1,er7
+	mov.l	@er7+,er0
+	mov.l	@er7+,er1
+	mov.l	@er7+,er2
+	mov.l	@er7+,er3
+	mov.l	@er7+,er4
+	mov.l	@er7+,er5
+	mov.l	@er7+,er6
+	rte
+
+	.global	_intr_serintr
+#	.type	_intr_serintr,@function
+_intr_serintr:
+	mov.l	er6,@-er7
+	mov.l	er5,@-er7
+	mov.l	er4,@-er7
+	mov.l	er3,@-er7
+	mov.l	er2,@-er7
+	mov.l	er1,@-er7
+	mov.l	er0,@-er7
+	mov.l	er7,er1
+	mov.l	#_intrstack,sp
+	mov.l	er1,@-er7
+	mov.w	#SOFTVEC_TYPE_SERINTR,r0
+	jsr	@_interrupt
+	mov.l	@er7+,er1
+	mov.l	er1,er7
+	mov.l	@er7+,er0
+	mov.l	@er7+,er1
+	mov.l	@er7+,er2
+	mov.l	@er7+,er3
+	mov.l	@er7+,er4
+	mov.l	@er7+,er5
+	mov.l	@er7+,er6
+	rte
+
+	.global	_intr_timintr
+#	.type	_intr_timintr,@function
+_intr_timintr:
+	mov.l	er6,@-er7
+	mov.l	er5,@-er7
+	mov.l	er4,@-er7
+	mov.l	er3,@-er7
+	mov.l	er2,@-er7
+	mov.l	er1,@-er7
+	mov.l	er0,@-er7
+	mov.l	er7,er1
+	mov.l	#_intrstack,sp
+	mov.l	er1,@-er7
+	mov.w	#SOFTVEC_TYPE_TIMINTR,r0
+	jsr	@_interrupt
+	mov.l	@er7+,er1
+	mov.l	er1,er7
+	mov.l	@er7+,er0
+	mov.l	@er7+,er1
+	mov.l	@er7+,er2
+	mov.l	@er7+,er3
+	mov.l	@er7+,er4
+	mov.l	@er7+,er5
+	mov.l	@er7+,er6
+	rte
+
+	.global	_intr_ethintr
+#	.type	_intr_ethintr,@function
+_intr_ethintr:
+	mov.l	er6,@-er7
+	mov.l	er5,@-er7
+	mov.l	er4,@-er7
+	mov.l	er3,@-er7
+	mov.l	er2,@-er7
+	mov.l	er1,@-er7
+	mov.l	er0,@-er7
+	mov.l	er7,er1
+	mov.l	#_intrstack,sp
+	mov.l	er1,@-er7
+	mov.w	#SOFTVEC_TYPE_ETHINTR,r0
+	jsr	@_interrupt
+	mov.l	@er7+,er1
+	mov.l	er1,er7
+	mov.l	@er7+,er0
+	mov.l	@er7+,er1
+	mov.l	@er7+,er2
+	mov.l	@er7+,er3
+	mov.l	@er7+,er4
+	mov.l	@er7+,er5
+	mov.l	@er7+,er6
+	rte
diff -ruN h8_04/os/ip.c h8_sim_06/os/ip.c
--- h8_04/os/ip.c	Mon Oct  4 22:59:22 2010
+++ h8_sim_06/os/ip.c	Mon Oct  4 23:11:46 2010
@@ -7,7 +7,7 @@
 uint32 network_id;
 
 #define MACADDR "\x00\x11\x22\x33\x44\x55"
-#define IPADDR  0xc0a80010 /* 192.168.0.16 */
+#define IPADDR  0xc0a80a10 /* 192.168.10.16 */
 static uint32 ipaddr = IPADDR;
 
 #define MACADDR_SIZE 6
diff -ruN h8_04/os/ld.scr h8_sim_06/os/ld.scr
--- h8_04/os/ld.scr	Mon Oct  4 22:59:22 2010
+++ h8_sim_06/os/ld.scr	Mon Oct  4 23:07:44 2010
@@ -4,6 +4,11 @@
 
 MEMORY
 {
+	/* internal ROM (512KB) */
+	romall(rx)	: o = 0x000000, l = 0x080000 /* 512KB */
+	vectors(r)	: o = 0x000000, l = 0x000100 /* top of ROM */
+	rom(rx)		: o = 0x000100, l = 0x07ff00
+
 	/* DRAM (2MB) */
 	dramall(rwx)	: o = 0x400000, l = 0x200000 /* 2MB */
 	ram(rwx)	: o = 0x400000 + 0x100, l = 0x200000 - 0x100
@@ -18,6 +23,10 @@
 
 SECTIONS
 {
+	.vectors : {
+		vector.o(.data)
+	} > vectors
+
 	.softvec : {
 		_softvec = .;
 	} > softvec
diff -ruN h8_04/os/main.c h8_sim_06/os/main.c
--- h8_04/os/main.c	Mon Oct  4 22:59:22 2010
+++ h8_sim_06/os/main.c	Mon Oct  4 23:08:58 2010
@@ -1,6 +1,9 @@
 #include "defines.h"
 #include "kozos.h"
 #include "interrupt.h"
+#ifdef SIMULATOR
+#include "serial.h"
+#endif
 #include "lib.h"
 
 /* システム・タスクとユーザ・タスクの起動 */
@@ -18,7 +21,9 @@
   kz_chpri(15); /* 優先順位を下げて,アイドルスレッドに移行する */
   INTR_ENABLE; /* 割込み有効にする */
   while (1) {
+#ifndef SIMULATOR /* シミュレータがsleep対応されていないので無効化する */
     asm volatile ("sleep"); /* 省電力モードに移行 */
+#endif
   }
 
   return 0;
@@ -27,6 +32,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");
 
diff -ruN h8_04/os/vector.c h8_sim_06/os/vector.c
--- h8_04/os/vector.c	Thu Jan  1 09:00:00 1970
+++ h8_sim_06/os/vector.c	Mon Oct  4 23:06:16 2010
@@ -0,0 +1,26 @@
+#include "defines.h"
+
+extern void start(void);        /* スタート・アップ */
+extern void intr_softerr(void); /* ソフトウエア・エラー */
+extern void intr_syscall(void); /* システム・コール */
+extern void intr_serintr(void); /* シリアル割込み */
+extern void intr_timintr(void); /* タイマ割込み */
+extern void intr_ethintr(void); /* イーサネット・コントローラ割込み */
+
+/*
+ * 割込みベクタの設定.
+ * リンカ・スクリプトの定義により,先頭番地に配置される.
+ */
+void (*vectors[])(void) = {
+  start, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 
+  intr_syscall, intr_softerr, intr_softerr, intr_softerr,
+  NULL, NULL, NULL, NULL, NULL, intr_ethintr /* IRQ5 */, NULL, NULL,
+  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+  intr_timintr, intr_timintr, intr_timintr, intr_timintr,
+  intr_timintr, intr_timintr, intr_timintr, intr_timintr,
+  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+  intr_serintr, intr_serintr, intr_serintr, intr_serintr,
+  intr_serintr, intr_serintr, intr_serintr, intr_serintr,
+  intr_serintr, intr_serintr, intr_serintr, intr_serintr,
+};

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