OS自作入門 -Advent06-
Step2 シリアル通信 後半
前回の話でシリアル通信とデータ転送に関して少し理解が進んだ。メモリ空間上にマッピングされているアドレスに対してbyteを書き込むことによってモードの調整や制御ができるようになる。ことシリアル通信に関して言えば、SSRとTDRを用いて送信完了ビットが立っている時にTDRレジスタにbyteを書き込んで、書き込んだ文字列をSSRの送信完了ビットを落とすことによって送りつける(TDRに書き込まれているbyteが相手の機器で読み取られるのだと思う)という動きになるっぽい。
前半は座学っぽかったが後半はlibを少し書き換えたり追加したりしていくみたいだ。
ライブラリ関数の追加
今回は今後必要になりそうなライブラリ群を一通り実装することを目的とする。
- lib.h
- lib.c
- main.c
あたりに手を加えるらしい。パッとみる限りメモリ操作系とstring系のメソッドのようだ。
c言語の話でプロトタイプ宣言というのが出てきた。いわゆるヘッダファイルに書いてあるシグニチャ達のこと。
※既存のライブラリとの違い。H8は16bitCPUであるため長さ指定で必要なものはint型ではなくlong型にすること。16bitで表現できる範囲だとメモリを表すには小さすぎるため。とのこと。
lib.h
上述の通りプロトタイプ宣言を追記
今回新たに8個のメソッドを追加する。
lib.c
久しぶりにcを書くなー。まともに書いたのはいつぶりだろうか。これくらい基本的な感じだとまだ全然読めるし書ける気がする。*(p++)
とか*(p--)
とかでポインタを移動しまくりながらwhileとかfor文の中で文字列を詰めていったりコピーして行ったりしているのがメモリ操作系のメソッド。int型ではなくchar型をぶん回しているのがstringの操作系のメソッドという感じの実装が多かったな。
main.c
テストとして新しく作ったputxvalという数値を16進数で表示するメソッドを埋め込んでおく。
実行
忘れずにH8の本体の方のモード切り替えを行い書き込みモードにする。
make
make image
make write
# ../../tools/h8write/kz_h8write -3069 -f20 kzload.mot /dev/tty.usbserial-FT0BTH3I
# =================================================
# H8/3069F Flash Writer for KOZOS (Version 0.2.1)
# Copyright(C) 2011-2012 Shinichiro Nakamura
# =================================================
# Bitrate sequence: Done.
# Inquiry device: Done.
# Select device: Done.
# Inquiry clock mode: Done.
# Select clock mode: Done.
# Select bitrate: Done.
# Waiting for erase done:......
# Programming:.........
# Program: Done.
# Complete.
読み込みモードにしてリセットボタンを押す。
その後にシリアル接続をする。
sudo cu -l /dev/tty.usbserial-XXXXXXX -s 9600
# Connected.
# Hello World!
# 10
# ffff
# Hello World! # リセットボタンを押すと出てくる
# 10 # リセットボタンを押すと出てくる
# ffff # リセットボタンを押すと出てくる
# ......
スタートアップ
どこから処理が始まるのかについて。
startup.sファイルの_start
から始まるとのこと。じゃどうやって_start
から始めるのか。これは割り込みベクタというものによるものらしい。
- 割り込み発生時に特定のアドレスから実行する
- 割り込み発生時にどのアドレスから実行するか特定のアドレスに設定しておく
という二つに別れており後者の「特定のアドレス」を割込みベクタと呼ぶらしい。
割り込まれたらその特定のアドレスに飛んで(GoTo文みたいだな)そこから処理を開始できる。
この割り込みというやつ。CPUは割込み線というピンを持っていてそこに電圧がかかるとCPUが割込み発生を検知するようにできているらしい。
シリアル通信時の書き込みのときも割とそんな感じで送信完了フラグを落として待っていたりしたなー。
H8はベクタ割込み方式を採用していて、0x000000-0x0000ffの範囲が割込みベクタらしい。実際にはvector.cというファイルで宣言されている配列がそれに該当していて、この配列をld.scrで0x000000を起点に配置している。これによって、電源ON => 0x000000に位置するvector[0]を参照 => _start
を実行する。という流れが出来上がる。
今日はこんな感じ。メモリマップあたりが一番頭に入ってこないなー。配列はlongだと2倍長になっているがポインタはcpu依存でintと同じ長さになる。ってやつの理由がなんとなく理解ができたが。。。難しいところだ。
今日の成果(書いたソースコード)はここ(Github)に置いておいた。
- 前の記事
英語の勉強「Why not」-Advent05- 2017.12.05
- 次の記事
英語の勉強「guess」-Advent07- 2017.12.07