为什么向串口发送字符需要延时?

Why do we need to delay when sending char to serial port?

考虑这段代码 here:

// Stupid I/O delay routine necessitated by historical PC design flaws
static void
delay(void)
{
    inb(0x84);
    inb(0x84);
    inb(0x84);
    inb(0x84);
}

什么是端口 0x84?为什么是设计缺陷? delay() 用于 serial_putc() 函数:

static void
serial_putc(int c)
{
    int i;

    for (i = 0;
         !(inb(COM1 + COM_LSR) & COM_LSR_TXRDY) && i < 12800;
         i++)
        delay();

    outb(COM1 + COM_TX, c);
}

文件来自lab1 of the course Operating System Engineering from OCW.

串行端口是一种硬件,具有您必须接受的某些语义。它通常有一个移位寄存器,用于将并行数据转换为串行数据。它可以有一个用于下一个要发送的字节的保持寄存器,甚至可以有一个用于多个字节的 FIFO。这就是为什么您必须轮询线路状态寄存器 (LSR) 的原因。

有些硬件修订版无法正常运行。您的代码看起来像是旧硬件中错误的解决方法。这里应该不需要读取端口0x84。

但是当您提高编译器优化级别时,无法优化延迟实现,因为它正在访问 I/O 范围。 运行 如果 运行 时间性能提供的延迟太少,则此代码在最新硬件中可能会出现问题。您必须验证循环中可以等待的最长时间是否足以通过 UART 移出一个字节。请记住,这是波特率相关的,而您的代码示例则不是。

端口 0x84 用于访问 "extra page register" (Overview)。但是读取这个寄存器应该是一个空洞。只有读取操作本身对消耗 CPU 个周期很重要。