uartxv6baud-rate

xv6 uartinit: set baud rate


I'm confused about how the baud rate 38.4K is calculated in xv6.

Here is the UART documentation.

void
uartinit(void)
{
  // disable interrupts.
  WriteReg(IER, 0x00);

  // special mode to set baud rate.
  WriteReg(LCR, LCR_BAUD_LATCH);

  // LSB for baud rate of 38.4K.
  WriteReg(0, 0x03);

  // MSB for baud rate of 38.4K.
  WriteReg(1, 0x00);

  // leave set-baud mode,
  // and set word length to 8 bits, no parity.
  WriteReg(LCR, LCR_EIGHT_BITS);

  // reset and enable FIFOs.
  WriteReg(FCR, FCR_FIFO_ENABLE | FCR_FIFO_CLEAR);

  // enable transmit and receive interrupts.
  WriteReg(IER, IER_TX_ENABLE | IER_RX_ENABLE);

  initlock(&uart_tx_lock, "uart");
}

I think these lines in the above documentation may illustrate baud rate settings:

PROGRAMMABLE BAUD RATE GENERATOR: The 16550 contains a programmable Baud Rate Generator that is capable of tracking any clock input from DC-8 MHz and dividing it by any divisor from 1 to 2^16-1. The output frequency of the Baudout is equal to the 16X of transmission baud rate (Baudout=16 X Baud Rate). Customize Baud Rates can be achieved by selecting proper divisor values for MSB and LSB of baud rate generator.


Solution

  • xv6 targets standard x86 PC hardware, and on a PC, the 16550 UART is connected to a clock source with frequency 1.8432 MHz. This has been true ever since the original IBM PC released in 1981 (with an 8250 UART); see page 2-135 of its Technical Reference Manual.

    The divisor in that code is set to 3, so the output frequency is 1.8432 / 3 = 0.6144 MHz, or 614.4 KHz. The baud rate is 1/16 of that, which is indeed 38.4K.