uart.c void uartputc(int c)
トップページ
jupiteroak.hatenablog.com
uart.c
https://github.com/mit-pdos/xv6-public/blob/master/uart.c#L51
void uartputc(int c) { int i; if(!uart) return; for(i = 0; i < 128 && !(inb(COM1+5) & 0x20); i++) microdelay(10); outb(COM1+0, c); }
uartputc関数は、引数cで指定された1文字分のデータ(8bit)をシリアル通信で送信する処理を行います。
引数 int c
シリアル通信で送信したい1文字分のデータ(8bit)です。
処理の内容
- シリアルポートがシステム上に存在することを確認する
- THR(Transmitter Holding Register)が利用できることを確認する
- THR(Transmitter Holding Register)への書き込みを行う
シリアルポートがシステム上に存在することを確認する
if(!uart) return;
!uartが真となる場合→uartに1が代入されていない場合→uartinit関数でシリアルポートの存在が確認できなかった場合は、ここで処理を終了します。
THR(Transmitter Holding Register)が利用できることを確認する
for(i = 0; i < 128 && !(inb(COM1+5) & 0x20); i++) microdelay(10);
in命令(ポート入力命令)でポートアドレス COM1(#define COM1 0x3f8)+5を指定することにより、UARTが持つLine Status Registerの読み取りを行なっています。
Line Status Registerは、シリアル通信の現在の状態やUART内で生じたエラー情報を示すために使用されているレジスタです。読み取ったレジスタの値を0x20でマスク処理することで、Line Status Registerのbit5の値を取得しています。Line Status Registerのbit5の値はTHR(Transmitter Holding Register)が空になっている(利用可能な)時に1となります。
THR(Transmitter Holding Register)が利用できる場合
!(inb(COM1+5) & 0x20)が偽となる場合→(inb(COM1+5) & 0x20)が1となる場合→THR(Transmitter Holding Register)が利用できる場合は、ループに入らず、次の処理へ進みます。
THR(Transmitter Holding Register)が利用できない場合
!(inb(COM1+5) & 0x20)が真となる場合→(inb(COM1+5) & 0x20)が0となる場合→THR(Transmitter Holding Register)が利用できない場合は、for分内の処理に入り、microdelay関数を呼び出します。その後、THR(Transmitter Holding Register)が利用できるまで、または、iの値が129になるまで、ループします。
THR(Transmitter Holding Register)への書き込みを行う
outb(COM1+0, c);
out命令(ポート出力命令)でポートアドレスCOM1(#define COM1 0x3f8)+0を指定することにより、UART が持つ THR(Transmitter Holding Register)への書き込みを行なっています。THR(Transmitter Holding Register)は送信用のバッファとして使用されます。1つの文字データだけをこのレジスタに保存すると、保存された文字データが送信用のシフトレジスタに転送され、シフトレジスタからシリアル線へと送信されます。