Read and Write by Polling with UART
Last updated on February 28, 2023 pm
Read and Write by Polling with UART
In the early stages of development, the first ‘hello world’ is implemented via UART serial port since handling the screen is a more complicated task.
Developing on QEMU is just like developing on a physical machine. The kernel runs in the QEMU virtual machine, which is connected to the host machine by UART, specifically the 16550 UART.
UART, or universal asynchronous receiver/transmitter, is a serial-port communicator embedded on board. It needs some settings and initialization for data tranmission, and these tasks are done in the file uart.c
.
Basically, everything inside 16550 UART is mapped to the memory location UART0
. One register may have one or more functionalities, and is always distinguished by the read mode and write mode.
Initialize UART
This is done in 3 steps:
- Disable interrupts (which will be discussed in the future).
- Set the baud rate.
- Set the data communication format.
More information can be found in the source code.
UART initialization should only be done once after booting.
Setting the Baud Rate
The baud rate is the frequency of data transmission and should be set to the same value for both the transmitter and receiver.
But note that the divisor latch is seprated into 2 parts, DLL
and DLM
, which stand for the least and most significant bits of the divisor latch, respectively.
Polling and UART I/O
To write things through UART, we just need to put the data into THR
(the transmit holding register in write mode). However, as data transmission takes time, we need to check whether the data in THR
was sent before new data was put into it.
The line status register‘s bit 5 (6th bit) is designed for this purpose. This bit will be set to 0 to indicate that transmission is complete.
Therefore, when we want to write through UART, we keep checking this bit. When we get a zero, we know that we can put our data. This procedure of continuously asking a register is also known as polling.
Printing a string could be seen as printing chars iteratively.
Reading data from console is technically the same thing, except that we check and read data from different registers.
Other Notes
Remember to add --nographic
flag when running QEMU. This flag means to disable the QEMU graphic monitor and use UART as the I/O device, so all output and input will be displayed on the current terminal.
To quit QEMU emulator, just press Ctrl + A
then press X
. Or press Ctrl + A
followed by C
, and then type quit
.
References
- ByteRunner.com | TECHNICAL DATA ON 16550
- [完结] 循序渐进,学习开发一个RISC-V上的操作系统 - 汪辰 - 第7章(下)-Hello RVOS_哔哩哔哩_bilibili
- riscv-operating-system-mooc/uart.c at main · plctlab/riscv-operating-system-mooc
- xv6: a simple, Unix-like teaching operating system, Russ Cox, Frans Kaashoek, Robert Morris, MIT, 5 September 2022, 5.1 Code: Console input (P53 - 55)
- xv6-riscv/uart.c at riscv · mit-pdos/xv6-riscv
- 16550 UART - Wikipedia
- qemu/virt.c at master · qemu/qemu
- QEMU documentation –nographic
- XV6学习(8)中断和设备驱动 - 星見遥 - 博客园
- Cross compiler - Wikipedia