いろんなものはつながっている

組み込みOS自作入門(2)シリアル通信

周辺ハードウェアとのデータのやりとりは、周辺ハードウェアのコントローラのレジスタを経由して行う。例えば、シリアルコントローラならコントローラのある特定のレジスタに1ビット書き込むとその1バイトを送信するという具合。

では、そのレジスタにどのように書き込むのか?それはレジスタをアドレス空間上にマッピングすることで、CPUからレジスタがアドレス上に見えるようにして書き込む。

実際にどのようにレジスタに書き込むか?レジスタの構造体を定義し、マップしたアドレスにその構造体をわりあてる。こういった操作方法をメモリマップドI/Oという。

#define SERIAL_REGADDR 0x10000000 /*コントローラのレジスタのアドレス*/

struct serial_regs {
    volatile char reg1;
    volatile char reg2;
    ....
    volatile char reg16;
};

volatile struct serial_regs *serreg;
serreg = (struct serial_regs*)SERIAL_REGADDR;

char c = serreg->reg1;  /*レジスタ1からの呼び出し*/
serreg->reg1 = 0x01;    /*レジスタ1への書き込み*/

各レジスタは各ビットごとに意味を持つことが多い。例えば1ビット目はモード規定、2ビット目は受信の可否等々。この各レジスタの設定は各ビットのORで設定。

#define MODE (1<<0)  /* モード */
#define RECV (1<<1)  /* 受信 */
#define SEND (1<<2) /* 送信 */
...

/*レジスタに設定*/
serreg->reg1 = MODE | SEND;

例えば送信の手順が
①送信完了ビットが落ちていないことを確認する
②送信したい文字列を所定のレジスタに書き込む
③送信完了ビットをおとす
④送信が完了するとコントローラが送信完了ビットをたてる
である場合

int serial_is_send_enable()
{
    return (
}

int serial_send_byte(unsigned char c) /* 送信する1文字 */
{
    volatile struct serial_regs *serreg = (struct serial_regs*)SERIAL_REGADDR;
    
    /* 送信可能になるまで待つ */
    while(!(serreg->reg1 & MODE))/* 送信完了ビットを落ちているか? */
    ;
    /* 送信する文字を設定 */
    serial_regs->reg2 = c;
    /* 送信開始 */
    serial_regs->reg1 &= ~RECV;  /* 送信完了ビットを落としている */
}

多くのコントローラにはモード設定、制御、状態取得の3つのレジスタがあり、例えば初期化を行うには①コントロールレジスタで動作を停止し、②モードレジスタを設定し、③ステータスレジスタで動作を開始するという枠組み。いまいち具体的にしっくりこないがおいおい理解できるだろう。

関連記事

コメント

  1. この記事へのコメントはありません。

  1. この記事へのトラックバックはありません。

スポンサード リンク

カテゴリー

スポンサード リンク