Implement UART closer to how it's done on the sifive board

This commit is contained in:
Konstantin Nazarov 2024-12-22 14:07:57 +00:00
parent 844ad3b073
commit 616f70bfa4
Signed by: knazarov
GPG key ID: 4CFE0A42FA409C22
2 changed files with 19 additions and 7 deletions

View file

@ -37,9 +37,13 @@ void UART::read_mem_u8(uint8_t* dst, size_t addr) {
} }
addr -= UART_ADDR; addr -= UART_ADDR;
switch (addr) { switch (addr) {
case UART_LSR: case UART_RXDATA:
// Always ready to transmit *dst = 0x0;
*dst = LSR_TRANSMITTER_EMPTY; break;
case UART_RXDATA + 3:
// receiver is always empty for now
*dst = 0x80;
break;
default: default:
*dst = 0; *dst = 0;
} }
@ -52,7 +56,7 @@ void UART::write_mem_u8(uint8_t* src, size_t addr) {
} }
addr -= UART_ADDR; addr -= UART_ADDR;
switch (addr) { switch (addr) {
case UART_THR: case UART_TXDATA:
std::cout.put(static_cast<char>(*src)); std::cout.put(static_cast<char>(*src));
break; 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() { void Timer::update() {
using Clock = std::chrono::high_resolution_clock; using Clock = std::chrono::high_resolution_clock;
constexpr auto den = Clock::period::den; constexpr auto den = Clock::period::den;

View file

@ -78,12 +78,12 @@ class UART final : public Device {
virtual void write_mem_u32(uint32_t *src, size_t addr); 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_u8(uint8_t *dst, size_t addr);
virtual void read_mem_u32(uint32_t *dst, size_t addr);
private: private:
enum Registers { enum Registers {
UART_RBR = 0x00, // Receiver Buffer Register UART_TXDATA = 0x00,
UART_THR = 0x00, // Transmitter Holding Register UART_RXDATA = 0x04,
UART_LSR = 0x05 // Line Status Register
}; };
// Line Status Register bits // Line Status Register bits