2ndステップの内容としては
- シリアル通信
- ライブラリ関数の追加
となります。
■シリアル通信は難しくはないが実装は大変
シリアル通信自体は、1stステップでターミナルでHello Worldを表示する際にシリアル通信を経由していて既に実装済みです。
2ndステップで改めて、そのソースコードの内容を説明してます。内容的にはハードウェアの初期化のルールに従って、ひたすらレジスタを操作するだけなので難しいものではないです。
#define H8_3069F_SCI0 ((volatile struct h8_3069f_sci *)0xffffb0)
#define H8_3069F_SCI1 ((volatile struct h8_3069f_sci *)0xffffb8)
#define H8_3069F_SCI2 ((volatile struct h8_3069f_sci *)0xffffc0)
struct h8_3069f_sci {
volatile uint8 smr;
volatile uint8 brr;
volatile uint8 scr;
volatile uint8 tdr;
volatile uint8 ssr;
volatile uint8 rdr;
volatile uint8 scmr;
};
のようにシリアル通信を制御するためのレジスタにマップされたメモリのアドレスを構造体等でキャストして、あとは手順通りに操作していくようなコーディング方法になります。
こうやって実装後のソースコードを見てしまうと難しくはないのですが、ハードウェアの仕様のみで1から実装するのは面倒そうです。
■ライブラリ関数の追加
あとはライブラリ関数の追加です。
C言語の標準ライブラリに存在するmemcpyやstrcpyなどのよく使う関数ですが、当然本環境には存在しないので、改めて実装する必要があります。
あと現状数値を画面出力する関数もないので(当然printfのような便利な関数もありません)、16進で表示する関数putxval
int putxval(unsigned long value, int column);
も追加して、2ndステップは完了です。
■独自の16進ダンプ関数を作ってみた
あと少しは自分でも改造を加えようということで、先のputxval関数を利用して指定ポインタから16進ダンプする関数も作ってみました。
ソースコードは以下の通り。
/* 16進ダンプ */
void dumphex(void *b, int size)
{
int i;
char *p = b;
for(i = 0; i < size; i++){
if(i % 8 == 0){
putxval((unsigned long)(p + i), 8);
puts(":");
}
putxval(*(p + i), 2);
puts(" ");
if(i % 8 == 7){
puts("\n");
}
}
}
以下のように
char *c = "0123456789ABCDEF";
char b[] = "0123456789abcdef";
適当にポインタ変数を定義し、dumphex関数に渡すと
puts(c);puts("\n");
dumphex(c, 24);
puts("\n");
puts(b);puts("\n");
dumphex(b, 24);
puts("\n");
以下のようにポインタのアドレスとメモリ内容がダンプされます。
dumphex((char *)0, 32);
puts("\n");
のように直接アドレス指定(0番地)しても大丈夫です。
■フラッシュROMへのプログラム書き込みはh8writeがお手軽です
前回の記事では
Windows系SEの日記: 【12ステップで作る組込みOS自作入門】実践記(2)とりあえずHello World表示までできた環境を紹介
フラッシュROMへのプログラム書き込みはルネサスのFDTをとりあえず使ってたのですが、h8writeを試してみたところ、こっちのほうが簡単ですね。
Windows環境用のh8write実行ファイルを著者サイト経由でダウンロードし、Makefileの指定箇所に置いておけば、あとは
make write
だけでフラッシュROMに書き込み完了です。
WARNINGが出てるのが気になりますが、今のところ特に問題になってません。
当面はh8writeで行こうと思います。