diff --git a/kernel/include/serial.h b/kernel/include/serial.h index 4883038..64bf817 100644 --- a/kernel/include/serial.h +++ b/kernel/include/serial.h @@ -1,43 +1,50 @@ -/* Serial constants */ +// 串口相关的常量 -// For QEMU, use 0x10000000 -// For AXI Uart16550, use base+0x1000 -#define COM1 0x10000000 +// QEMU 虚拟的 RISC-V 机器的串口基地址在 0x10000000 +// 如果使用了 AXI Uart16550,请设置为它的基地址 + 0x10000 +#define COM1 0x10000000 -// For AXI Uart16550, use 4 -// For QEMU, use 1 -#define COM_MULTIPLY 1 +// QEMU 虚拟的串口的寄存器地址间隔为 1 字节 +// AXI Uart16550 的寄存器地址间隔为 4 字节 +#define COM_MULTIPLY 1 +// 各个寄存器地址相对于基地址的偏移 // ref: https://www.lammertbies.nl/comm/info/serial-uart -#define COM_RBR_OFFSET (0 * COM_MULTIPLY) /* In: Recieve Buffer Register */ -#define COM_THR_OFFSET (0 * COM_MULTIPLY) /* Out: Transmitter Holding Register */ -#define COM_DLL_OFFSET (0 * COM_MULTIPLY) /* Out: Divisor Latch Low */ -#define COM_IER_OFFSET (1 * COM_MULTIPLY) /* I/O: Interrupt Enable Register */ -#define COM_DLM_OFFSET (1 * COM_MULTIPLY) /* Out: Divisor Latch High */ -#define COM_FCR_OFFSET (2 * COM_MULTIPLY) /* Out: FIFO Control Register */ -#define COM_IIR_OFFSET (2 * COM_MULTIPLY) /* I/O: Interrupt Identification Register */ -#define COM_LCR_OFFSET (3 * COM_MULTIPLY) /* Out: Line Control Register */ -#define COM_MCR_OFFSET (4 * COM_MULTIPLY) /* Out: Modem Control Register */ -#define COM_LSR_OFFSET (5 * COM_MULTIPLY) /* In: Line Status Register */ -#define COM_MSR_OFFSET (6 * COM_MULTIPLY) /* In: Modem Status Register */ -#define COM_SCR_OFFSET (7 * COM_MULTIPLY) /* I/O: Scratch Register */ -#define COM_MDR1_OFFSET (8 * COM_MULTIPLY) /* I/O: Mode Register */ - -#define COM_LSR_FIFOE 0x80 /* Fifo error */ -#define COM_LSR_TEMT 0x40 /* Transmitter empty */ -#define COM_LSR_THRE 0x20 /* Transmit-hold-register empty */ -#define COM_LSR_BI 0x10 /* Break interrupt indicator */ -#define COM_LSR_FE 0x08 /* Frame error indicator */ -#define COM_LSR_PE 0x04 /* Parity error indicator */ -#define COM_LSR_OE 0x02 /* Overrun error indicator */ -#define COM_LSR_DR 0x01 /* Receiver data ready */ -#define COM_LSR_BRK_ERROR_BITS 0x1E /* BI, FE, PE, OE bits */ - -#define COM_FCR_CONFIG 0x7 /* FIFO Enable and FIFO Reset */ -#define COM_LCR_DLAB 0x80 -// For AXI Uart16550, use clk_freq / 16 / baudrate -// For QEMU, use 115200 / 9600 -#define COM_DLL_VAL (115200 / 9600) -#define COM_LCR_WLEN8 0x03 -#define COM_LCR_CONFIG (COM_LCR_WLEN8 & ~(COM_LCR_DLAB)) -#define COM_IER_RDI 0x01 +#define COM_RBR_OFFSET (0 * COM_MULTIPLY) /* In: Recieve Buffer Register */ +#define COM_THR_OFFSET \ + (0 * COM_MULTIPLY) /* Out: Transmitter Holding Register */ +#define COM_DLL_OFFSET (0 * COM_MULTIPLY) /* Out: Divisor Latch Low */ +#define COM_IER_OFFSET (1 * COM_MULTIPLY) /* I/O: Interrupt Enable Register */ +#define COM_DLM_OFFSET (1 * COM_MULTIPLY) /* Out: Divisor Latch High */ +#define COM_FCR_OFFSET (2 * COM_MULTIPLY) /* Out: FIFO Control Register */ +#define COM_IIR_OFFSET \ + (2 * COM_MULTIPLY) /* I/O: Interrupt Identification Register */ +#define COM_LCR_OFFSET (3 * COM_MULTIPLY) /* Out: Line Control Register */ +#define COM_MCR_OFFSET (4 * COM_MULTIPLY) /* Out: Modem Control Register */ +#define COM_LSR_OFFSET (5 * COM_MULTIPLY) /* In: Line Status Register */ +#define COM_MSR_OFFSET (6 * COM_MULTIPLY) /* In: Modem Status Register */ +#define COM_SCR_OFFSET (7 * COM_MULTIPLY) /* I/O: Scratch Register */ +#define COM_MDR1_OFFSET (8 * COM_MULTIPLY) /* I/O: Mode Register */ + +// LSR 寄存器的定义 +#define COM_LSR_FIFOE 0x80 /* Fifo error */ +#define COM_LSR_TEMT 0x40 /* Transmitter empty */ +#define COM_LSR_THRE 0x20 /* Transmit-hold-register empty */ +#define COM_LSR_BI 0x10 /* Break interrupt indicator */ +#define COM_LSR_FE 0x08 /* Frame error indicator */ +#define COM_LSR_PE 0x04 /* Parity error indicator */ +#define COM_LSR_OE 0x02 /* Overrun error indicator */ +#define COM_LSR_DR 0x01 /* Receiver data ready */ +#define COM_LSR_BRK_ERROR_BITS 0x1E /* BI, FE, PE, OE bits */ + +#define COM_FCR_CONFIG 0x7 /* FIFO Enable and FIFO Reset */ + +#define COM_LCR_DLAB 0x80 +#define COM_LCR_WLEN8 0x03 +#define COM_LCR_CONFIG (COM_LCR_WLEN8 & ~(COM_LCR_DLAB)) + +// QEMU 中,DLL 的值应该是 baudrate / 9600 +// AXI Uart16550 中,DLL 的值应该是 clk_freq / 16 / baudrate +#define COM_DLL_VAL (115200 / 9600) + +#define COM_IER_RDI 0x01 diff --git a/kernel/kern/evec.S b/kernel/kern/evec.S index e808583..1de8d38 100755 --- a/kernel/kern/evec.S +++ b/kernel/kern/evec.S @@ -1,5 +1,4 @@ -// You don't have to care about this file if you don't enable interrupt and paging. - +// 监控程序的入口点,.text.init 段放在内存的 0x80000000 位置,是最先执行的代码。 .p2align 2 .section .text.init INITLOCATE: // 定位启动程序 diff --git a/kernel/kern/init.S b/kernel/kern/init.S index 8a942f7..ffe8ebb 100755 --- a/kernel/kern/init.S +++ b/kernel/kern/init.S @@ -114,20 +114,24 @@ mtvec_done: #ifdef ENABLE_UART16550 // 配置串口,见 serial.h 中的叙述进行配置 - // 参考 ucore/kern/driver/console.c li t0, COM1 - li t1, COM_FCR_CONFIG // console.c:54 - sb t1, %lo(COM_FCR_OFFSET)(t0) // :57 + // 打开 FIFO,并且清空 FIFO + li t1, COM_FCR_CONFIG + sb t1, %lo(COM_FCR_OFFSET)(t0) + // 打开 DLAB li t1, COM_LCR_DLAB - sb t1, %lo(COM_LCR_OFFSET)(t0) // :57 + sb t1, %lo(COM_LCR_OFFSET)(t0) + // 设置 Baudrate li t1, COM_DLL_VAL - sb t1, %lo(COM_DLL_OFFSET)(t0) // :58 - sb x0, %lo(COM_DLM_OFFSET)(t0) // :59 + sb t1, %lo(COM_DLL_OFFSET)(t0) + sb x0, %lo(COM_DLM_OFFSET)(t0) + // 关闭 DLAB,打开 WLEN8 li t1, COM_LCR_CONFIG - sb t1, %lo(COM_LCR_OFFSET)(t0) // :62 - sb x0, %lo(COM_MCR_OFFSET)(t0) // :65 + sb t1, %lo(COM_LCR_OFFSET)(t0) + sb x0, %lo(COM_MCR_OFFSET)(t0) + // 开串口中断 li t1, COM_IER_RDI - sb t1, %lo(COM_IER_OFFSET)(t0) // :67 + sb t1, %lo(COM_IER_OFFSET)(t0) #endif // 清空并留出空间用于存储中断帧