Permalink
Browse files

[WIP] Implement a minimal MMIO 8250 UART

  • Loading branch information...
neuschaefer committed Jun 4, 2016
1 parent 68d0fca commit 33e5b6f446cb21f54a04f6b7aec3cd2d81ab114f
Showing with 69 additions and 1 deletion.
  1. +7 −0 riscv/devices.h
  2. +1 −0 riscv/riscv.mk.in
  3. +8 −1 riscv/sim.cc
  4. +1 −0 riscv/sim.h
  5. +52 −0 riscv/uart.cc
@@ -47,4 +47,11 @@ class rtc_t : public abstract_device_t {
uint64_t time() { return regs[0]; }
};

class uart_t : public abstract_device_t {
public:
bool load(reg_t addr, size_t len, uint8_t* bytes);
bool store(reg_t addr, size_t len, const uint8_t* bytes);
size_t size() { return 8; }
};

#endif
@@ -47,6 +47,7 @@ riscv_srcs = \
devices.cc \
rom.cc \
rtc.cc \
uart.cc \
gdbserver.cc \
debug_module.cc \
$(riscv_gen_srcs) \
@@ -51,6 +51,7 @@ sim_t::sim_t(const char* isa, size_t nprocs, size_t mem_mb, bool halted,
}

rtc.reset(new rtc_t(procs));
uart.reset(new uart_t());
make_config_string();
}

@@ -149,8 +150,11 @@ bool sim_t::mmio_store(reg_t addr, size_t len, const uint8_t* bytes)

void sim_t::make_config_string()
{
reg_t rtc_addr = EXT_IO_BASE;
reg_t rtc_addr = EXT_IO_BASE;
reg_t uart_addr = 0x30000000 + 0x1000;// TODO: move EXT_IO_BASE + 0x1000

bus.add_device(rtc_addr, rtc.get());
bus.add_device(uart_addr, uart.get());

const int align = 0x1000;
reg_t cpu_addr = rtc_addr + ((rtc->size() - 1) / align + 1) * align;
@@ -176,6 +180,9 @@ void sim_t::make_config_string()
"rtc {\n"
" addr 0x" << rtc_addr << ";\n"
"};\n"
"uart {\n"
" addr 0x" << uart_addr << ";\n"
"};\n"
"ram {\n"
" 0 {\n"
" addr 0x" << DRAM_BASE << ";\n"
@@ -46,6 +46,7 @@ class sim_t
std::string config_string;
std::unique_ptr<rom_device_t> boot_rom;
std::unique_ptr<rtc_t> rtc;
std::unique_ptr<uart_t> uart;
bus_t bus;
debug_module_t debug_module;

@@ -0,0 +1,52 @@
/* This file implements a minimal 8250 UART block. */
#include "devices.h"
#include "processor.h"
#include <unistd.h>

enum {
UART_DATA = 0, /* Data RX/TX */
UART_INTR_EN, /* Interrupt enable */
UART_INTR_ID, /* Interrupt identification */
UART_LINE_CTL, /* Line control */
UART_MODEM_CTL, /* Modem control */
UART_LINE_STAT, /* Line status */
UART_MODEM_STAT, /* Modem status */
UART_SCRATCH /* Scratch register */
};

enum {
UART_LINE_STAT_TEMT = (1 << 6) /* Transmitter empty */
};

bool uart_t::load(reg_t addr, size_t len, uint8_t* bytes)
{
/* For simplicity on our side, only support byte-sized accesses for now. */
if (len > 1)
return false;

switch (addr)
{
case UART_LINE_STAT:
*bytes = UART_LINE_STAT_TEMT;
default:
*bytes = 0;
}

return true;
}

bool uart_t::store(reg_t addr, size_t len, const uint8_t* bytes)
{
if (len > 1)
return false;

switch (addr)
{
case UART_DATA:
putchar(*bytes);
fflush(stdout);
break;
}

return true;
}

0 comments on commit 33e5b6f

Please sign in to comment.