From 616f70bfa48619b75995714ff454d962ab57ea41 Mon Sep 17 00:00:00 2001 From: Konstantin Nazarov Date: Sun, 22 Dec 2024 14:07:57 +0000 Subject: [PATCH] Implement UART closer to how it's done on the sifive board --- src/vm.cpp | 20 ++++++++++++++++---- src/vm.hpp | 6 +++--- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/vm.cpp b/src/vm.cpp index 5644d1d..78c8e44 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -37,9 +37,13 @@ void UART::read_mem_u8(uint8_t* dst, size_t addr) { } addr -= UART_ADDR; switch (addr) { - case UART_LSR: - // Always ready to transmit - *dst = LSR_TRANSMITTER_EMPTY; + case UART_RXDATA: + *dst = 0x0; + break; + case UART_RXDATA + 3: + // receiver is always empty for now + *dst = 0x80; + break; default: *dst = 0; } @@ -52,7 +56,7 @@ void UART::write_mem_u8(uint8_t* src, size_t addr) { } addr -= UART_ADDR; switch (addr) { - case UART_THR: + case UART_TXDATA: std::cout.put(static_cast(*src)); break; } @@ -66,6 +70,14 @@ void UART::write_mem_u32(uint32_t* src, size_t addr) { } } +void UART::read_mem_u32(uint32_t* dst, size_t addr) { + uint8_t* d = (uint8_t*)dst; + + for (size_t i = 0; i < 4; i++) { + read_mem_u8(d + i, addr + i); + } +} + void Timer::update() { using Clock = std::chrono::high_resolution_clock; constexpr auto den = Clock::period::den; diff --git a/src/vm.hpp b/src/vm.hpp index a9c3458..824c99f 100644 --- a/src/vm.hpp +++ b/src/vm.hpp @@ -78,12 +78,12 @@ class UART final : public Device { virtual void write_mem_u32(uint32_t *src, size_t addr); virtual void read_mem_u8(uint8_t *dst, size_t addr); + virtual void read_mem_u32(uint32_t *dst, size_t addr); private: enum Registers { - UART_RBR = 0x00, // Receiver Buffer Register - UART_THR = 0x00, // Transmitter Holding Register - UART_LSR = 0x05 // Line Status Register + UART_TXDATA = 0x00, + UART_RXDATA = 0x04, }; // Line Status Register bits