mit-pdos / xv6-riscv

Xv6 for RISC-V
Other
6.58k stars 2.38k forks source link

Update uart.c #167

Open x653 opened 1 year ago

x653 commented 1 year ago

Hi there, many thanks for the xv6-riscv project. I learned a lot about operating systems.

I managed to implement a riscv32 CPU with virtual memory management on a fpga board ice40HX8K and run xv6-riscv on it. I noticed that on my real hardware the interrupts got stuck, because the UART continuosly fires THR interrupts when the transit queue is empty. In the interrupt trap routine, when we see the UART interrupt according to specification of the UART controller 16550 we can clear the interrupt source in one of the two ways:

  1. send a byte to UART (clearly this clears the interrupt source, because THR register is not empty any more).
  2. what should we do, if we have no bytes to send, because our send queue is empty? We have to read the UART register ISR. This will clear the interrupt source and our CPU can run without interruption.

so I added the instruction to read the register ISR of UART.

With the added ReadReg(ISR); command xv6 nicely runs on my fpga. If you are interested have a look at my repo: https://gitlab.com/x653/xv6-riscv-fpga

I was wondering, why your code runs on qemu without the ReadReg(ISR) instruction. I did some investigation by adding a counter to count how many times we enter the trap routine due to THR interrupts. With the help of a systemcall to read the counter I found, that qemu does not generate endless many interrupts. It just produces about 50 or so interrupts. This seems to fill some internal interrupt queue. So it seems that the code runs on qemu because qemu does not (like real hardware) generate endlessly interrupts...

Best Micha