aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Pisa <pisa@cmp.felk.cvut.cz>2019-02-25 14:57:00 +0100
committerPavel Pisa <pisa@cmp.felk.cvut.cz>2019-02-25 14:57:00 +0100
commit1889bd9353b309ea54f3543f5d609015fec5b73c (patch)
treef203dac446435aa395cadbd34ea4d347efdaacd6
parentca242e325d823bc627ca4e6ff8eca24b888a6113 (diff)
downloadqtmips-1889bd9353b309ea54f3543f5d609015fec5b73c.tar.gz
qtmips-1889bd9353b309ea54f3543f5d609015fec5b73c.tar.bz2
qtmips-1889bd9353b309ea54f3543f5d609015fec5b73c.zip
Simple serial port receive implementation.
Simple polled mode serial port input implemented for serial port peripheral and for read and readv system calls. When end of input character reserve is reached for read/readv, newline is automatically appended. Signed-off-by: Pavel Pisa <pisa@cmp.felk.cvut.cz>
-rw-r--r--qtmips_gui/mainwindow.cpp2
-rw-r--r--qtmips_gui/terminaldock.cpp17
-rw-r--r--qtmips_gui/terminaldock.h4
-rw-r--r--qtmips_machine/serialport.cpp22
-rw-r--r--qtmips_machine/serialport.h5
-rw-r--r--qtmips_osemu/ossyscall.cpp81
-rw-r--r--qtmips_osemu/ossyscall.h3
7 files changed, 130 insertions, 4 deletions
diff --git a/qtmips_gui/mainwindow.cpp b/qtmips_gui/mainwindow.cpp
index 253ab03..01321cf 100644
--- a/qtmips_gui/mainwindow.cpp
+++ b/qtmips_gui/mainwindow.cpp
@@ -154,6 +154,8 @@ void MainWindow::create_core(const machine::MachineConfig &config) {
osemu::OsSyscallExceptionHandler *osemu_handler = new osemu::OsSyscallExceptionHandler;
machine->register_exception_handler(machine::EXCAUSE_SYSCALL, osemu_handler);
connect(osemu_handler, SIGNAL(char_written(int,uint)), terminal, SLOT(tx_byte(int,uint)));
+ connect(osemu_handler, SIGNAL(rx_byte_pool(int,uint&,bool&)),
+ terminal, SLOT(rx_byte_pool(int,uint&,bool&)));
#endif
// Connect machine signals and slots
diff --git a/qtmips_gui/terminaldock.cpp b/qtmips_gui/terminaldock.cpp
index 4b394a6..bb26952 100644
--- a/qtmips_gui/terminaldock.cpp
+++ b/qtmips_gui/terminaldock.cpp
@@ -49,6 +49,11 @@ TerminalDock::TerminalDock(QWidget *parent, QSettings *settings) : QDockWidget(p
terminal_text->setMinimumSize(30, 30);
layout_box->addWidget(terminal_text);
append_cursor = new QTextCursor(terminal_text->document());
+ layout_bottom_box = new QHBoxLayout();
+ layout_bottom_box->addWidget(new QLabel("Input:"));
+ input_edit = new QLineEdit();
+ layout_bottom_box->addWidget(input_edit);
+ layout_box->addLayout(layout_bottom_box);
setObjectName("Terminal");
setWindowTitle("Terminal");
@@ -62,6 +67,8 @@ void TerminalDock::setup(const machine::SerialPort *ser_port) {
if (ser_port == nullptr)
return;
connect(ser_port, SIGNAL(tx_byte(uint)), this, SLOT(tx_byte(uint)));
+ connect(ser_port, SIGNAL(rx_byte_pool(int,uint&,bool&)),
+ this, SLOT(rx_byte_pool(int,uint&,bool&)));
}
void TerminalDock::tx_byte(unsigned int data) {
@@ -76,3 +83,13 @@ void TerminalDock::tx_byte(int fd, unsigned int data)
(void)fd;
tx_byte(data);
}
+
+void TerminalDock::rx_byte_pool(int fd, unsigned int &data, bool &available) {
+ QString str = input_edit->text();
+ available = false;
+ if (str.count() > 0) {
+ data = str[0].toLatin1();
+ input_edit->setText(str.remove(0, 1));
+ available = true;
+ }
+}
diff --git a/qtmips_gui/terminaldock.h b/qtmips_gui/terminaldock.h
index 7154e81..27dc617 100644
--- a/qtmips_gui/terminaldock.h
+++ b/qtmips_gui/terminaldock.h
@@ -39,6 +39,7 @@
#include <QDockWidget>
#include <QLabel>
#include <QFormLayout>
+#include <QLineEdit>
#include <QTextEdit>
#include <QTextCursor>
#include "qtmipsmachine.h"
@@ -54,13 +55,16 @@ public:
public slots:
void tx_byte(unsigned int data);
void tx_byte(int fd, unsigned int data);
+ void rx_byte_pool(int fd, unsigned int &data, bool &available);
private:
QVBoxLayout *layout_box;
+ QHBoxLayout *layout_bottom_box;
QWidget *top_widget, *top_form;
QFormLayout *layout_top_form;
QTextEdit *terminal_text;
QTextCursor *append_cursor;
+ QLineEdit *input_edit;
};
#endif // TERMINALDOCK_H
diff --git a/qtmips_machine/serialport.cpp b/qtmips_machine/serialport.cpp
index 9e4177b..c636d38 100644
--- a/qtmips_machine/serialport.cpp
+++ b/qtmips_machine/serialport.cpp
@@ -51,6 +51,7 @@ using namespace machine;
SerialPort::SerialPort() {
rx_st_reg = 0;
+ rx_data_reg = 0;
tx_st_reg = 0;
}
@@ -58,6 +59,18 @@ SerialPort::~SerialPort() {
}
+void SerialPort::pool_rx_byte() const {
+ unsigned int byte = 0;
+ bool available = false;
+ if (!(rx_st_reg & SERP_RX_ST_REG_READY_m)) {
+ emit rx_byte_pool(0, byte, available);
+ if (available) {
+ rx_data_reg = byte;
+ rx_st_reg |= SERP_RX_ST_REG_READY_m;
+ }
+ }
+}
+
bool SerialPort::wword(std::uint32_t address, std::uint32_t value) {
#if 0
printf("SerialPort::wword address 0x%08lx data 0x%08lx\n",
@@ -90,10 +103,17 @@ std::uint32_t SerialPort::rword(std::uint32_t address, bool debug_access) const
#endif
switch (address) {
case SERP_RX_ST_REG_o:
+ pool_rx_byte();
value = rx_st_reg;
break;
case SERP_RX_DATA_REG_o:
- value = 0;
+ pool_rx_byte();
+ if (rx_st_reg & SERP_RX_ST_REG_READY_m) {
+ value = rx_data_reg;
+ rx_st_reg &= ~SERP_RX_ST_REG_READY_m;
+ } else {
+ value = 0;
+ }
break;
case SERP_TX_ST_REG_o:
value = tx_st_reg | SERP_TX_ST_REG_READY_m;
diff --git a/qtmips_machine/serialport.h b/qtmips_machine/serialport.h
index add1fe6..5262720 100644
--- a/qtmips_machine/serialport.h
+++ b/qtmips_machine/serialport.h
@@ -52,6 +52,7 @@ public:
signals:
void tx_byte(unsigned int data);
+ void rx_byte_pool(int fd, unsigned int &data, bool &available) const;
void write_notification(std::uint32_t address, std::uint32_t value);
void read_notification(std::uint32_t address, std::uint32_t *value) const;
@@ -59,7 +60,9 @@ public:
bool wword(std::uint32_t address, std::uint32_t value);
std::uint32_t rword(std::uint32_t address, bool debug_access = false) const;
private:
- std::uint32_t rx_st_reg;
+ void pool_rx_byte() const;
+ mutable std::uint32_t rx_st_reg;
+ mutable std::uint32_t rx_data_reg;
std::uint32_t tx_st_reg;
};
diff --git a/qtmips_osemu/ossyscall.cpp b/qtmips_osemu/ossyscall.cpp
index a5748f1..aeee079 100644
--- a/qtmips_osemu/ossyscall.cpp
+++ b/qtmips_osemu/ossyscall.cpp
@@ -62,7 +62,7 @@ static const mips_syscall_desc_t mips_syscall_args[] = {
MIPS_SYS(sys_syscall , 8, syscall_default_handler) /* 4000 */
MIPS_SYS(sys_exit , 1, syscall_default_handler)
MIPS_SYS(sys_fork , 0, syscall_default_handler)
- MIPS_SYS(sys_read , 3, syscall_default_handler)
+ MIPS_SYS(sys_read , 3, do_sys_read)
MIPS_SYS(sys_write , 3, do_sys_write)
MIPS_SYS(sys_open , 3, syscall_default_handler) /* 4005 */
MIPS_SYS(sys_close , 1, syscall_default_handler)
@@ -204,7 +204,7 @@ static const mips_syscall_desc_t mips_syscall_args[] = {
MIPS_SYS(sys_select , 5, syscall_default_handler)
MIPS_SYS(sys_flock , 2, syscall_default_handler)
MIPS_SYS(sys_msync , 3, syscall_default_handler)
- MIPS_SYS(sys_readv , 3, syscall_default_handler) /* 4145 */
+ MIPS_SYS(sys_readv , 3, do_sys_readv) /* 4145 */
MIPS_SYS(sys_writev , 3, do_sys_writev)
MIPS_SYS(sys_cacheflush , 3, syscall_default_handler)
MIPS_SYS(sys_cachectl , 3, syscall_default_handler)
@@ -598,6 +598,83 @@ int OsSyscallExceptionHandler::do_sys_write(std::uint32_t &result, Core *core,
return 0;
}
+// ssize_t readv(int fd, const struct iovec *iov, int iovcnt);
+int OsSyscallExceptionHandler::do_sys_readv(std::uint32_t &result, Core *core,
+ std::uint32_t syscall_num,
+ std::uint32_t a1, std::uint32_t a2, std::uint32_t a3,
+ std::uint32_t a4, std::uint32_t a5, std::uint32_t a6,
+ std::uint32_t a7, std::uint32_t a8) {
+ (void)core; (void)syscall_num;
+ (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; (void)a6; (void)a7; (void)a8;
+
+ result = 0;
+ int fd = a1;
+ std::uint32_t iov = a2;
+ int iovcnt = a3;
+ MemoryAccess *mem = core->get_mem_data();
+ bool available;
+ unsigned int byte;
+
+ printf("sys_readv to fd %d\n", fd);
+
+ while (iovcnt-- > 0) {
+ std::uint32_t iov_base = mem->read_word(iov);
+ std::uint32_t iov_len = mem->read_word(iov + 4);
+ iov += 8;
+ available = true;
+ for (std::uint32_t i = 0; i < iov_len; i++) {
+ emit rx_byte_pool(fd, byte, available);
+ if (!available) {
+ // add final newline if there are no more data
+ mem->write_byte(iov_base++, '\n');
+ result += 1;
+ break;
+ }
+ mem->write_byte(iov_base++, byte);
+ result += 1;
+ }
+ if (!available)
+ break;
+ }
+
+ return 0;
+}
+
+// ssize_t read(int fd, void *buf, size_t count);
+int OsSyscallExceptionHandler::do_sys_read(std::uint32_t &result, Core *core,
+ std::uint32_t syscall_num,
+ std::uint32_t a1, std::uint32_t a2, std::uint32_t a3,
+ std::uint32_t a4, std::uint32_t a5, std::uint32_t a6,
+ std::uint32_t a7, std::uint32_t a8) {
+ (void)core; (void)syscall_num;
+ (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; (void)a6; (void)a7; (void)a8;
+
+ result = 0;
+ int fd = a1;
+ std::uint32_t buf = a2;
+ int size = a3;
+ MemoryAccess *mem = core->get_mem_data();
+ bool available;
+ unsigned int byte;
+
+ printf("sys_read to fd %d\n", fd);
+
+ result = 0;
+ while (size-- > 0) {
+ emit rx_byte_pool(fd, byte, available);
+ if (!available) {
+ // add final newline if there are no more data
+ mem->write_byte(buf++, '\n');
+ result += 1;
+ break;
+ }
+ mem->write_byte(buf++, byte);
+ result += 1;
+ }
+
+ return 0;
+}
+
// int or void * brk(void *addr);
int OsSyscallExceptionHandler::do_sys_brk(std::uint32_t &result, Core *core,
std::uint32_t syscall_num,
diff --git a/qtmips_osemu/ossyscall.h b/qtmips_osemu/ossyscall.h
index 00b6575..0c02699 100644
--- a/qtmips_osemu/ossyscall.h
+++ b/qtmips_osemu/ossyscall.h
@@ -66,10 +66,13 @@ public:
OSSYCALL_HANDLER_DECLARE(do_sys_set_thread_area);
OSSYCALL_HANDLER_DECLARE(do_sys_writev);
OSSYCALL_HANDLER_DECLARE(do_sys_write);
+ OSSYCALL_HANDLER_DECLARE(do_sys_readv);
+ OSSYCALL_HANDLER_DECLARE(do_sys_read);
OSSYCALL_HANDLER_DECLARE(do_sys_brk);
OSSYCALL_HANDLER_DECLARE(do_sys_mmap2);
signals:
void char_written(int fd, unsigned int val);
+ void rx_byte_pool(int fd, unsigned int &data, bool &available);
private:
std::uint32_t brk_limit;
std::uint32_t anonymous_base;