前回の課題というか今までの課題として, 第4回でちょろっと書いたのだけど, ブートローダーをモトローラSレコードフォーマットに対応させよう.理由は以下.
で,以下の方針で実装してみた.
修正内容について,以下に説明しよう.まずはブートローダーの修正箇所.
diff -ruN h8_08/kzload/ld.scr h8_10/kzload/ld.scr --- h8_08/kzload/ld.scr Sun Sep 20 00:33:51 2009 +++ h8_10/kzload/ld.scr Sun Sep 20 13:39:14 2009 @@ -8,6 +8,7 @@ rom(rx) : o = 0x000100, l = 0x07ff00 /* 512kb */ ram(rwx) : o = 0xffbf20, l = 0x004000 /* 16kb */ buffer(rwx) : o = 0xffdf20, l = 0x002000 /* 8kb */ + data(rwx) : o = 0xffdf20+7400, l = 0x002000-7400 /* -BUFSIZE */ stack(rw) : o = 0xffff00, l = 0x000010 /* end of RAM */ } @@ -30,18 +31,22 @@ _erodata = . ; } > rom + .buffer : { + _buffer_start = . ; + } > buffer + .data : AT(_erodata) { _data_start = . ; *(.data) _edata = . ; - } > buffer + } > data .bss : { _bss_start = . ; *(.bss) *(COMMON) _ebss = . ; - } > buffer + } > data _end = . ;まずリンカスクリプトなのだけど,従来はグローバル変数も loadbuf[] も 両方ともバッファ領域に配置されていて,BSSの展開時にグローバル変数も 破壊される恐れがあった(ていうか,破壊されていた).
対策として,ロード用のバッファ領域とデータ領域を別セクションとして, データ領域はバッファ領域の後ろのほうに配置してグローバル変数などのデータは そっちに持っていくように修正した.
同様に,main.c の修正が以下.
diff -ruN h8_08/kzload/main.c h8_10/kzload/main.c --- h8_08/kzload/main.c Sun Sep 20 00:33:51 2009 +++ h8_10/kzload/main.c Sun Sep 20 13:39:14 2009 @@ -1,12 +1,10 @@ #include "lib.h" #include "serial.h" #include "xmodem.h" +#include "srec.h" #include "elf.h" #include "interrupt.h" -#define BUFSIZE 7400 -static unsigned char loadbuf[BUFSIZE]; - static int init() { extern int erodata, data_start, edata, bss_start, ebss; @@ -33,7 +31,8 @@ return 0; } -static int putval(unsigned int value, int column) +#if 0 +static int putval(unsigned long value, int column) { char buf[12]; char *p; @@ -54,8 +53,9 @@ return 0; } +#endif -static int putxval(unsigned int value, int column) +static int putxval(unsigned long value, int column) { char buf[9]; char *p; @@ -118,6 +118,8 @@ int size = -1; char *entry_point; void (*f)(); + unsigned char *loadbuf; + extern int buffer_start; init(); @@ -127,7 +129,11 @@ puts("kzboot> "); gets(buf); - if (!strcmp(buf, "load")) { + if (!strcmp(buf, "load") || !strcmp(buf, "loadelf")) { + if (!strcmp(buf, "load")) + loadbuf = NULL; + else + loadbuf = (char *)(&buffer_start); size = xmodem_recv(loadbuf); if (size < 0) { puts("XMODEM receive error!\n"); @@ -136,15 +142,20 @@ } } else if (!strcmp(buf, "dump")) { puts("size: "); - putval(size, 0); + putxval(size, 0); puts("\n"); dump(loadbuf, size); - } else if (!strcmp(buf, "run")) { - entry_point = elf_load(loadbuf); + } else if (!strcmp(buf, "run") || !strcmp(buf, "runelf")) { + if (!strcmp(buf, "run")) + entry_point = srec_startaddr(); + else + entry_point = elf_load(loadbuf); if (!entry_point) { puts("run error!\n"); } else { - puts("starting from entry point.\n"); + puts("starting from entry point: "); + putxval((unsigned long)entry_point, 0); + puts("\n"); f = (void (*)())entry_point; f(); }従来はロード用のバッファ領域を loadbuf[] として静的に獲得していたが, リンカスクリプト内で定義されている &buffer_start を見て, バッファ領域を利用するように修正.
あと loadelf とか runelf とかのコマンド対応がされている. load が実行されたときにはバッファ領域は必要無いのでバッファ未指定で xmodem_recv()が呼ばれ,この場合にはモトローラSフォーマットを受信して 直接展開する,という動作になる.
次に xmodem.c の修正.
diff -ruN h8_08/kzload/xmodem.c h8_10/kzload/xmodem.c --- h8_08/kzload/xmodem.c Sun Sep 20 00:33:51 2009 +++ h8_10/kzload/xmodem.c Sun Sep 20 13:39:14 2009 @@ -1,5 +1,6 @@ #include "lib.h" #include "serial.h" +#include "srec.h" #include "uudecode.h" #include "xmodem.h" @@ -46,11 +47,16 @@ check_sum = 0; for (i = 0; i < XMODEM_BLOCK_SIZE; i++) { c = serial_getb(); + if (!buf) { + if (srec_decode(c) < 0) + return NULL; + } else { #ifdef USE_UUENCODE - buf = uu_decode(buf, c); + buf = uu_decode(buf, c); #else - *(buf++) = c; + *(buf++) = c; #endif + } check_sum += c; } @@ -67,6 +73,8 @@ unsigned char c; unsigned char *p; + srec_init(); + while (1) { if (!receiving) xmodem_wait(); @@ -79,10 +87,11 @@ } else if (c == XMODEM_SOH) { receiving++; p = xmodem_read_block(buf); - if (!p) { + if (buf && !p) { serial_putc(XMODEM_NAK); } else { - buf = p; + if (p) + buf = p; size += XMODEM_BLOCK_SIZE; serial_putc(XMODEM_ACK); }バッファ未指定の場合の対処が追加されている.
ブートローダーの修正のおおまかな内容は以上.次にOS側の修正点.
まず make image でモトローラSフォーマットのファイル「kozos.mot」を 作成するように Makefile にターゲットを追加.
diff -ruN h8_08/os/Makefile h8_10/os/Makefile --- h8_08/os/Makefile Sun Sep 20 00:34:04 2009 +++ h8_10/os/Makefile Sun Sep 20 13:39:30 2009 @@ -42,11 +42,14 @@ #$(LIB) : $(LIBOBJS) # $(AR) ruc $(LIB) $(LIBOBJS) -$(TARGET).uu : $(TARGET) +$(TARGET).mot : $(TARGET) + $(OBJCOPY) -O srec $(TARGET) $(TARGET).mot + +$(TARGET).uu : $(TARGET) uuencode -o $(TARGET).uu $(TARGET) $(TARGET) -image : $(TARGET).uu +image : $(TARGET).mot $(TARGET).uu clean : rm -f $(OBJS) $(LIBOBJS) $(LIB) \ - $(TARGET) $(TARGET).elf $(TARGET).uu + $(TARGET) $(TARGET).elf $(TARGET).mot $(TARGET).uu次に,BSSの初期化処理を追加する.モトローラSフォーマットだとBSSの情報が 来ないみたいなので,OS側でゼロクリアする必要がある.これをやらないと なんかうまく動かなかった.
diff -ruN h8_08/os/main.c h8_10/os/main.c --- h8_08/os/main.c Sun Sep 20 00:34:04 2009 +++ h8_10/os/main.c Sun Sep 20 13:39:30 2009 @@ -9,6 +9,12 @@ static int init() { + extern int bss_start; + extern int ebss; + + /* clear BSS */ + memset(&bss_start, 0, (uint32)&ebss - (uint32)bss_start); + serial_initialize(0, 0); return 0; }OS側の修正はこれだけ.
では実際に試してみよう.ブートローダーをビルドしてフラッシュROMに書き込んで 起動し,従来通りの動作として,loadelf; runelf でELFフォーマットをダウンロード させてOS起動してみる.
kzboot> loadelf ~CLocal command? lsx kozos Sending kozos, 56 blocks: Give your local XMODEM receive command now. Bytes Sent: 7296 BPS:777 Transfer complete eceive succeeded. kzboot> runelf starting from entry point: ffc120 kozos boot succeed! command> echo aaa aaa OK command> threads extintr idle command1 OK command>とりあえず問題なさそう.
次に,リセットボタンを押してブートローダーを起動しなおして, load; run でモトローラSフォーマットでダウンロードしてOS起動してみる.
kzboot> load ~CLocal command? lsx kozos.mot Sending kozos.mot, 153 blocks: Give your local XMODEM receive command now. Bytes Sent: 19712 BPS:827 Transfer complete eceive succeeded. kzboot> run starting from entry point: ffc120 kozos boot succeed! command> echo aaaa aaaa OK command> threads extintr idle command1 OK command>おー問題無さそうだ.ちゃんと動いている.
ただ,当り前だけどモトローラSフォーマットはテキスト形式なので, ダウンロード時間がやたら長くなる.修正しては試してまた修正してを ガンガン繰り返すような感じでやりたいときにはちょっとうっとうしいかも. まあシリアルの速度が9600bpsなので,115200bpsとかにすれば解決できるとは思うが. これはそのうち考えよう.