NetBSDではシリアルコンソールはデフォルトのシリアルからデバイスのシリアルになります。
デフォルトのシリアルでは割り込みを使わずビジーループで出力しますが、タイマーを動かすところから割り込みが使われるようになります。
初期のデフォルトのシリアルの初期化はsys/arch/evbarm/gemini/gemini_machdep.cには下記のようにあります。
void
consinit(void)
{
static int consinit_called = 0;
if (consinit_called != 0)
return;
consinit_called = 1;
if (comcnattach(&gemini_a4x_bs_tag, consaddr, conspeed,
GEMINI_COM_FREQ, COM_TYPE_16550_NOERS, conmode))
panic("Serial console can not be initialized.");
}
comcnattach()はdev/ic/com.cにある関数です。
sys/kern/init_main.cからもよばれるので、一度しか処理しないようにしています。
第三引数のTYPEはいのように定義があります。
/*
* There are a great many almost-ns16550-compatible UARTs out
* there, which have minor differences. The type field here
* lets us distinguish between them.
*/
int sc_type;
#define COM_TYPE_NORMAL 0 /* normal 16x50 */
#define COM_TYPE_HAYESP 1 /* Hayes ESP modem */
#define COM_TYPE_PXA2x0 2 /* Intel PXA2x0 processor built-in */
#define COM_TYPE_AU1x00 3 /* AMD/Alchemy Au1x000 proc. built-in */
#define COM_TYPE_OMAP 4 /* TI OMAP processor built-in */
#define COM_TYPE_16550_NOERS 5 /* like a 16550, no ERS */
#define COM_TYPE_INGENIC 6 /* JZ4780 built-in */
#define COM_TYPE_TEGRA 7 /* NVIDIA Tegra built-in */
#define COM_TYPE_BCMAUXUART 8 /* BCM2835 AUX UART */
#define COM_TYPE_16650 9
#define COM_TYPE_16750 10
#define COM_TYPE_DW_APB 11 /* DesignWare APB UART */
この関数はレジスタが1バイト毎に並んでる場合に使います。SOCによっては4バイト毎になっていて、その場合はcomcnattach()の中身をいじる必要があるので、自前で用意します。4バイトすなわち2ビットシフトでcom_init_regs_stride()関数を呼びます。
int
m83comcnattach(bus_space_tag_t iot, bus_addr_t iobase, int rate,
int frequency, int type, tcflag_t cflag)
{
struct com_regs regs;
/*XXX*/
bus_space_handle_t dummy_bsh;
memset(&dummy_bsh, 0, sizeof(dummy_bsh));
/*
* dummy_bsh required because com_init_regs() wants it. A
* real bus_space_handle will be filled in by cominit() later.
* XXXJRT Detangle this mess eventually, plz.
*/
com_init_regs_stride(®s, iot, dummy_bsh/*XXX*/, iobase,
2);
return comcnattach1(®s, rate, frequency, type, cflag);
}
これでデバイスになるまではOKです。
あとはcomデバイスのattach()でもcom_init_regs_strideを呼びます。
comにも上記のようにいくつかのタイプの処理がはいっていますが、大幅に違う場合は独自に実装しているケースもあるようです。
comの実装は分かりにくくて、よくありません。
sys/arch/evbarm/devにもcomのコードがあるようです。
RT1310でuartが暴走するので調べてみたら受信をsoftintしているところで、暴走してました。とりあえず、rxはsoftintしないで直に実行するようにしたらうごきました。なんか動きが変です。