What is UART Link to heading

UART is a way to asynchronously transmit serial data between 2 devices.

serial means data gets sent 1 bit at a time

UART connection
1. UART serial communication

Each device has a Transmitter(Tx) and a Receiver(Rx) and are connected in a cross so each Tx is connected to the Rx of the other device.

Recourses Link to heading

So far we didn’t require information about the specifics of the on board chip. This chapter we will be talking a lot about register addresses and for this we need a details about the peripherals of the PI.

Gladly Raspberry Pi has documented this on their website with all relevant links to the PDFs.

Raspberry PI Processors

The raspberry pi 3 B+ uses the BCM2837B0 Broadcom chip. The documentation says here that we can refer to the BCM2837.

The BCM2837 mentions: “The underlying architecture of the BCM2837 is identical to the BCM2836

Okay so lets check BCM2836: “The underlying architecture in BCM2836 is identical to BCM2835

Finally we reached the end of this chain and the BCM2835 has the peripheral specification.

Download this file and keep it somewhere safe, because we’ll need it.

UART PL011 vs Mini UART Link to heading

The Broadcom chip comes with two UARTS.

They differ in a few areas but the most important part is that PL011 is tied to its own clock, while Mini UART uses the system clock. This means that Mini UART is more prone to data loss making it less reliable so we’ll focus on PL011 first.

Configuring UART Link to heading

Baud rate Link to heading

The baud rate is a measurement of how many symbols changes can occur per second. It’s important that both devices use the same rate or else the data can become scrambled.

The Baud rate is usually just referred as single number and can range from 110 bps to 1_000_000 bps but the most common one is 115_200 that gives use 115 kbps of data transfer, which should be enough for our use case.

To configure the baud rate we need to set the Integer Baud rate divisor (IBRD) and the Fractional Baud rate divisor (FBRD).

In the peripherals PDF(page 177) we can find the UART Address Map that tells us the base address and the offset.

The base Address is 0x7E20100 according to the documentation BUT thats NOT correct in our environment. The 0x7E... address is for peripherals. We are developing for the CPU so we have to use the physical address that start at 0x3F...

Our base address for the UART registers is 0x3E20100.

Lets calculate IBRD/FBRD Link to heading

Yes Yes you are seeing math in this section, ill try to be quick and get back to coding.

Note: The Broadcom Peripherals contains a formula for the BAUDDIV: BAUDDIV = (FUARTCLK/(16 Baud rate)). The integer divisor (floor(BAUDDIV)) would be the IBRD and the fractional devisor (round((BAUDDIV - IBRD) × 64)) would be the FBRD.

For this guide we’ll use a different formula:

\[ \text{Baud Rate} = \frac{FUARTCLK}{16 \times \left(\text{IBRD} + \frac{\text{FBRD}}{64} \right)} \]

Because our goal is to get the IBRD and FBRD we can do a switcheroo and get:

\[ 16 \times \left(\text{IBRD} + \frac{\text{FBRD}}{64} \right) = \frac{FUARTCLK}{ \text{Baud Rate}} \]

Now times both sides by 4:

\[ \text{ScaledBaudDivisor} = \\ 64 \times \text{IBRD} + \text{FBRD} = \frac{FUARTCLK \times 4}{\text{Baud Rate}} \]

And at last:

\[ IBRD = ScaledBaudDivisor/64; \]

\[ FBRD = ScaledBaudDivisor\%64; \]

Why do all this math though? Cant we just use the one mentioned by Broadcom. And yes we can but with this version we can save us some floating point math. The .floor() function is also from the std library so we’d have to implement it ourself.

Now in code Link to heading

const BAUD: u32 = 115200;
const UART_CLK: u32 = 48_000_000;

pub fn configure_uart() {
    let scaled_baud_rate = (UART_CLK * 4) / BAUD;

    let ibrd = scaled_baud_rate / 64;
    let fbrd = scaled_baud_rate % 64;
    //...

For now we’ll use a constant for UART_CLK but in the future we can read it from a register.

Summary Link to heading

In this chapter we mainly focused on the functionality of UART and how we can calculate the baud rate. Next chapter we will configure everything and hopefully have our first REAL “Hello World!”.

Git Repository Link to heading