はじめに
以下の本で学習
12ステップで作る 組込みOS自作入門
本記事に出てくるソースコードはここ(http://kozos.jp/kozos/osbook/) の「osbook_03.zip」
組込みシステムの目的
・周辺ハードウェアを制御すること
1. データ転送の通信方法
- シリアル通信
- Ethernet など
2. 送信元と受信元の決定
(今回はH8/3069Fマイコンが送信元、PCが送信先)
用語集
インターフェース
・Input/Output間での決まりごと
(データ転送の信号の電圧、信号速度など)
プロトコル
・通信、データの転送手順
ボーレート(データ転送速度)
・単位はbps(bit per second)
・9600bpsでは、1秒間に9600回のON/OFFの信号を送る
コントローラ
・通信を制御するICチップのこと
CPUのビット数(データバス)
・CPU内部で扱うレジスタのサイズ
・int型が32bit
アドレスバス
・アドレス指定用にCPUが持つ出力ピン
・ポインタ変数のサイズと同じ
シリアル通信について
1. コントローラの操作方法
レジスタを経由
・シリアルコントローラの持つ特定のレジスタに1バイト書き込むと、
その1バイトをシリアル送信する。
2. CPUとDRAMの接続
・アドレスバスが4バイト(32bit)ある場合、0x00000000~0xffffffff
(0~4294967296:2の32乗)までアドレスを定義できる。
CPUと4GBのDRAMが接続されている場合、アクセス可能
・実際は1つの大容量のDRAMではなく少量、例えば1MBのDRAMが4個接続(DRAM1~DRAM4)などある。
その場合、1MBのアドレスに必要な信号線は20ビット(0x000fffff:2の20乗)
しかし、アドレスバスだけを利用した場合、DRAM1~DRAM4の区別ができない
3. チップセレクト信号の利用
・チップセレクトとは、DRAMが持っている信号ピンのこと。
CS = 1でチップが動作するため、このチップセレクトが1になるように
余った信号線を接続する。これで4MBを実現している。
4. シリアル・コントローラの接続
・シリアル・コントローラは16個の制御用のレジスタを持っている
レジスタの識別に必要な信号線は4本(16:2の4乗)。残りは比較器に使用する。
(アドレス:0x10000000~0x1000000f)
5. メモリマップドI/O(メモリ空間に配置されたI/O)
・こちらのサイトが分かりやすい(http://www.kumikomi.net/archives/2003/05/10kumi.php?page=27)
メモリ空間にI/Oを配置する(メモリマップドI/O)
・現在主流の方法。メモリと同じアドレス空間から、入出力装置を制御する
・I/O専用の回路や命令を持たなくてもよいため、高速化や低価格化が可能
メモリ空間とI/O空間を持つ(I/O用の命令がある)
・入出力専用の命令(I/O命令)と専用信号を使用して、メモリ空間とは別のアドレス空間から
データバスに直結されている入出力装置を制御する
5. C言語からのデバイスを操作
- レジスタのアドレスを定義
- アドレスにアクセスして読込み、書込みを行う
char c;
volatile char *reg1 = (char *)0x10000000;
c = *reg1; /* レジスタ1の値 読込み*/
*reg1 = 0x01; /* レジスタ1へ値 書込み*/
6. volatile修飾子
Cコンパイラの最適化を抑止するために必要!!
serreg->reg1 = 0x01;
serreg->reg1 = 0x02;
serreg->reg2 = 0x04;
serreg->reg3 = 0x01;
while(serreg->reg3 & 0x01){
//reg3の更新以外の処理
}
1. 値書込み定義の最適化阻止
・reg1に以下のように「0x01 → 0x02」と書き込む場合、
コンパイルの最適化で「0x01」の書き込みが省略され、以下と等価と判断される
serreg->reg1 = 0x02;
serreg->reg2 = 0x04;
2. 実行順序の最適化阻止
・reg2とreg1の変数はお互いに関係ないので、実行順序は等価と判断され
コンパイルの最適化でreg1とreg2の書き込みは、以下と等価と判断される
serreg->reg2 = 0x04;
serreg->reg1 = 0x02;
3. 実行内容の最適化阻止
・reg3の値がループ中に更新されないので、while文に入ると無限ループになる
serreg->reg3 = 0x01;
if(serreg->reg3 & 0x01){
while(1){
//reg3の更新以外の処理
}
}
7. 内臓シリアルコントローラ
1.マイクロコントローラ
・CPUにあらかじめ内蔵されているコントローラのこと
外部と接続する場合は、比較器の構成で自由なアドレスにマッピングできたが、
マイクロコントローラでは、アドレスが決められてる
2. H8/3069Fに内蔵されているシリアルコントローラ
・SCI(Serial Communication Interface)が3つ内蔵{SCI0、SCI1、SCI2}
H8/3069Fのハードウェアマニュアルの13.1.4節に記載
8. コントローラのモード設定
一旦、コントローラを無効化し、設定完了後に有効化する
・SMR(シリアルモードレジスタ)の設定
・SCR(シリアルコントロールレジスタ)の設定
9. ビットレートレジスタの設定を行う
シリアル通信のボーレートは9600bps
・周波数(20MHz)、ボーレート(9600bps)、分周(1)からビットレートレジスタ(64)を設定
10. シリアルの1文字出力
- 送信完了ビットが落ちていないことを確認する
- 送信したい文字を書き込む
- 送信完了ビットを落とす
- 送信が完了すると、送信完了ビットを立てる
11.端末変換
・C言語では、改行コードは「\n」だが、シリアル通信では「\r」
送信時「\n → \r」にコードを変換する(端末変換という)
12.ソースコードの変更
・ライブラリ関数の追加
追加した関数の仕様はこちらを参照
ソースコードの補足(serial.c)
・構造体の宣言と初期化を同時に行う
この場合、タグ名は以下出てこないため不要
http://www.kusa.ac.jp/~kajiura/c/kouzoutai/newpage1.htm
の4.構造体変数の初期化
static struct {
volatile struct h8_3069f_sci *sci;
} regs[SERIAL_SCI_NUM] = {
{ H8_3069F_SCI0 },
{ H8_3069F_SCI1 },
{ H8_3069F_SCI2 },
};