Devlog 15 Initializing Uart Pt2
December 7, 2022
Log 15
The goal today is to continue with the UART initialization and validate the register values in GDB
.
Initializing UART pt2
After enabling the clocks, the next step is to set the baud rate for USART0
. From the GD32VF103 manual, we can find the base address of USART0
to be 0x4001 3800
, and the Baud rate register is at offset 0x08
, let’s remember that for later.
Since we haven’t configured the device other than enabling some clocks, it’s a good idea to confirm the current clock speed by reading the RCU Control register at address 0x4002 1000
with offset 0x00
:
(gdb) x/t 0x40021000+0x00
0x40021000: 00000000000000000110001010000011
Let’s clear up that formatting:
00000000 00000000 01100010 10000011
According to the above user manual:
- bit 0 means the internal 8MHz oscillator (IRC8M) is enabled
- bit 1 means it’s stable
- bit 16 means the external high speed oscillator (HXTAL) is disabled
Let’s also read the Clock register 0 at offset 0x04
:
(gdb) x/t 0x40021000+0x04
0x40021004: 00000000000000000000000000000000
All zeroes! What this means is all the clocks are running at 8MHz with the internal oscillator, so we’ll use that to calculate the baud rate divider for our 115200 bauds (symbols per seconds) setting. In the future we might want to bump that to the max 108MHz using the external oscillator. Let’s continue with uart_init:
# set the baud rate: USARTDIV = frequency (8 MHz) / baud rate (115200 bps)
li t0, 0x40013800 # load USART0 base address
li t1, ((8000000/115200) & 0x0000fff0) | ((8000000/115200) & 0x0000000f) # load baud rate divider
sw t1, 0x08(t0) # store the value in the Baud rate register (USART_BAUD)
And when we inspect with GDB
:
(gdb) x/th 0x40013800+0x08
0x40013808: 0000000001000101
(gdb) x/x 0x40013800+0x08
0x40013808: 0x0045
Now let’s explain what just happened there. Once again, according to the above user manual, there is a way to calculate the USARTDIV
in order for the MCU to generate the baud rate we want. The method is somewhat complex and is usually satisfied by a simpler frequency / baud rate
. However I wanted to do it “correctly” so I used the above formula, which isolates the first 4 bits (0:3
) as the fractional part using the mask 0x0000000f
, and the next 12 bits (4:15
) using the mask 0x0000fff0
. Finally it performs a bitwise OR
of the integer and fraction in order to give us the exact value to be stored in the Baud rate register.
When we examine the memory address 0x40013800
at the offset 0x08
, we can see the result is exactly 0x0045
. I know, I could have just hardcoded 0x0045
but that would make it much more difficult to change the frequency/baud rate in the future.
Closing thoughts
I’ll end this session here. Next time I’ll setup the data/stop/parity/mode/flowctrl
bits in the USART Control register and maybe finally configure the GPIOs.