Skip to content

Commit 1889bd9

Browse files
committed
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 <[email protected]>
1 parent ca242e3 commit 1889bd9

File tree

7 files changed

+130
-4
lines changed

7 files changed

+130
-4
lines changed

qtmips_gui/mainwindow.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ void MainWindow::create_core(const machine::MachineConfig &config) {
154154
osemu::OsSyscallExceptionHandler *osemu_handler = new osemu::OsSyscallExceptionHandler;
155155
machine->register_exception_handler(machine::EXCAUSE_SYSCALL, osemu_handler);
156156
connect(osemu_handler, SIGNAL(char_written(int,uint)), terminal, SLOT(tx_byte(int,uint)));
157+
connect(osemu_handler, SIGNAL(rx_byte_pool(int,uint&,bool&)),
158+
terminal, SLOT(rx_byte_pool(int,uint&,bool&)));
157159
#endif
158160

159161
// Connect machine signals and slots

qtmips_gui/terminaldock.cpp

+17
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ TerminalDock::TerminalDock(QWidget *parent, QSettings *settings) : QDockWidget(p
4949
terminal_text->setMinimumSize(30, 30);
5050
layout_box->addWidget(terminal_text);
5151
append_cursor = new QTextCursor(terminal_text->document());
52+
layout_bottom_box = new QHBoxLayout();
53+
layout_bottom_box->addWidget(new QLabel("Input:"));
54+
input_edit = new QLineEdit();
55+
layout_bottom_box->addWidget(input_edit);
56+
layout_box->addLayout(layout_bottom_box);
5257

5358
setObjectName("Terminal");
5459
setWindowTitle("Terminal");
@@ -62,6 +67,8 @@ void TerminalDock::setup(const machine::SerialPort *ser_port) {
6267
if (ser_port == nullptr)
6368
return;
6469
connect(ser_port, SIGNAL(tx_byte(uint)), this, SLOT(tx_byte(uint)));
70+
connect(ser_port, SIGNAL(rx_byte_pool(int,uint&,bool&)),
71+
this, SLOT(rx_byte_pool(int,uint&,bool&)));
6572
}
6673

6774
void TerminalDock::tx_byte(unsigned int data) {
@@ -76,3 +83,13 @@ void TerminalDock::tx_byte(int fd, unsigned int data)
7683
(void)fd;
7784
tx_byte(data);
7885
}
86+
87+
void TerminalDock::rx_byte_pool(int fd, unsigned int &data, bool &available) {
88+
QString str = input_edit->text();
89+
available = false;
90+
if (str.count() > 0) {
91+
data = str[0].toLatin1();
92+
input_edit->setText(str.remove(0, 1));
93+
available = true;
94+
}
95+
}

qtmips_gui/terminaldock.h

+4
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include <QDockWidget>
4040
#include <QLabel>
4141
#include <QFormLayout>
42+
#include <QLineEdit>
4243
#include <QTextEdit>
4344
#include <QTextCursor>
4445
#include "qtmipsmachine.h"
@@ -54,13 +55,16 @@ class TerminalDock : public QDockWidget {
5455
public slots:
5556
void tx_byte(unsigned int data);
5657
void tx_byte(int fd, unsigned int data);
58+
void rx_byte_pool(int fd, unsigned int &data, bool &available);
5759

5860
private:
5961
QVBoxLayout *layout_box;
62+
QHBoxLayout *layout_bottom_box;
6063
QWidget *top_widget, *top_form;
6164
QFormLayout *layout_top_form;
6265
QTextEdit *terminal_text;
6366
QTextCursor *append_cursor;
67+
QLineEdit *input_edit;
6468
};
6569

6670
#endif // TERMINALDOCK_H

qtmips_machine/serialport.cpp

+21-1
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,26 @@ using namespace machine;
5151

5252
SerialPort::SerialPort() {
5353
rx_st_reg = 0;
54+
rx_data_reg = 0;
5455
tx_st_reg = 0;
5556
}
5657

5758
SerialPort::~SerialPort() {
5859

5960
}
6061

62+
void SerialPort::pool_rx_byte() const {
63+
unsigned int byte = 0;
64+
bool available = false;
65+
if (!(rx_st_reg & SERP_RX_ST_REG_READY_m)) {
66+
emit rx_byte_pool(0, byte, available);
67+
if (available) {
68+
rx_data_reg = byte;
69+
rx_st_reg |= SERP_RX_ST_REG_READY_m;
70+
}
71+
}
72+
}
73+
6174
bool SerialPort::wword(std::uint32_t address, std::uint32_t value) {
6275
#if 0
6376
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
90103
#endif
91104
switch (address) {
92105
case SERP_RX_ST_REG_o:
106+
pool_rx_byte();
93107
value = rx_st_reg;
94108
break;
95109
case SERP_RX_DATA_REG_o:
96-
value = 0;
110+
pool_rx_byte();
111+
if (rx_st_reg & SERP_RX_ST_REG_READY_m) {
112+
value = rx_data_reg;
113+
rx_st_reg &= ~SERP_RX_ST_REG_READY_m;
114+
} else {
115+
value = 0;
116+
}
97117
break;
98118
case SERP_TX_ST_REG_o:
99119
value = tx_st_reg | SERP_TX_ST_REG_READY_m;

qtmips_machine/serialport.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,17 @@ class SerialPort : public MemoryAccess {
5252

5353
signals:
5454
void tx_byte(unsigned int data);
55+
void rx_byte_pool(int fd, unsigned int &data, bool &available) const;
5556
void write_notification(std::uint32_t address, std::uint32_t value);
5657
void read_notification(std::uint32_t address, std::uint32_t *value) const;
5758

5859
public:
5960
bool wword(std::uint32_t address, std::uint32_t value);
6061
std::uint32_t rword(std::uint32_t address, bool debug_access = false) const;
6162
private:
62-
std::uint32_t rx_st_reg;
63+
void pool_rx_byte() const;
64+
mutable std::uint32_t rx_st_reg;
65+
mutable std::uint32_t rx_data_reg;
6366
std::uint32_t tx_st_reg;
6467
};
6568

qtmips_osemu/ossyscall.cpp

+79-2
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ static const mips_syscall_desc_t mips_syscall_args[] = {
6262
MIPS_SYS(sys_syscall , 8, syscall_default_handler) /* 4000 */
6363
MIPS_SYS(sys_exit , 1, syscall_default_handler)
6464
MIPS_SYS(sys_fork , 0, syscall_default_handler)
65-
MIPS_SYS(sys_read , 3, syscall_default_handler)
65+
MIPS_SYS(sys_read , 3, do_sys_read)
6666
MIPS_SYS(sys_write , 3, do_sys_write)
6767
MIPS_SYS(sys_open , 3, syscall_default_handler) /* 4005 */
6868
MIPS_SYS(sys_close , 1, syscall_default_handler)
@@ -204,7 +204,7 @@ static const mips_syscall_desc_t mips_syscall_args[] = {
204204
MIPS_SYS(sys_select , 5, syscall_default_handler)
205205
MIPS_SYS(sys_flock , 2, syscall_default_handler)
206206
MIPS_SYS(sys_msync , 3, syscall_default_handler)
207-
MIPS_SYS(sys_readv , 3, syscall_default_handler) /* 4145 */
207+
MIPS_SYS(sys_readv , 3, do_sys_readv) /* 4145 */
208208
MIPS_SYS(sys_writev , 3, do_sys_writev)
209209
MIPS_SYS(sys_cacheflush , 3, syscall_default_handler)
210210
MIPS_SYS(sys_cachectl , 3, syscall_default_handler)
@@ -598,6 +598,83 @@ int OsSyscallExceptionHandler::do_sys_write(std::uint32_t &result, Core *core,
598598
return 0;
599599
}
600600

601+
// ssize_t readv(int fd, const struct iovec *iov, int iovcnt);
602+
int OsSyscallExceptionHandler::do_sys_readv(std::uint32_t &result, Core *core,
603+
std::uint32_t syscall_num,
604+
std::uint32_t a1, std::uint32_t a2, std::uint32_t a3,
605+
std::uint32_t a4, std::uint32_t a5, std::uint32_t a6,
606+
std::uint32_t a7, std::uint32_t a8) {
607+
(void)core; (void)syscall_num;
608+
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5; (void)a6; (void)a7; (void)a8;
609+
610+
result = 0;
611+
int fd = a1;
612+
std::uint32_t iov = a2;
613+
int iovcnt = a3;
614+
MemoryAccess *mem = core->get_mem_data();
615+
bool available;
616+
unsigned int byte;
617+
618+
printf("sys_readv to fd %d\n", fd);
619+
620+
while (iovcnt-- > 0) {
621+
std::uint32_t iov_base = mem->read_word(iov);
622+
std::uint32_t iov_len = mem->read_word(iov + 4);
623+
iov += 8;
624+
available = true;
625+
for (std::uint32_t i = 0; i < iov_len; i++) {
626+
emit rx_byte_pool(fd, byte, available);
627+
if (!available) {
628+
// add final newline if there are no more data
629+
mem->write_byte(iov_base++, '\n');
630+
result += 1;
631+
break;
632+
}
633+
mem->write_byte(iov_base++, byte);
634+
result += 1;
635+
}
636+
if (!available)
637+
break;
638+
}
639+
640+
return 0;
641+
}
642+
643+
// ssize_t read(int fd, void *buf, size_t count);
644+
int OsSyscallExceptionHandler::do_sys_read(std::uint32_t &result, Core *core,
645+
std::uint32_t syscall_num,
646+
std::uint32_t a1, std::uint32_t a2, std::uint32_t a3,
647+
std::uint32_t a4, std::uint32_t a5, std::uint32_t a6,
648+
std::uint32_t a7, std::uint32_t a8) {
649+
(void)core; (void)syscall_num;
650+
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5; (void)a6; (void)a7; (void)a8;
651+
652+
result = 0;
653+
int fd = a1;
654+
std::uint32_t buf = a2;
655+
int size = a3;
656+
MemoryAccess *mem = core->get_mem_data();
657+
bool available;
658+
unsigned int byte;
659+
660+
printf("sys_read to fd %d\n", fd);
661+
662+
result = 0;
663+
while (size-- > 0) {
664+
emit rx_byte_pool(fd, byte, available);
665+
if (!available) {
666+
// add final newline if there are no more data
667+
mem->write_byte(buf++, '\n');
668+
result += 1;
669+
break;
670+
}
671+
mem->write_byte(buf++, byte);
672+
result += 1;
673+
}
674+
675+
return 0;
676+
}
677+
601678
// int or void * brk(void *addr);
602679
int OsSyscallExceptionHandler::do_sys_brk(std::uint32_t &result, Core *core,
603680
std::uint32_t syscall_num,

qtmips_osemu/ossyscall.h

+3
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,13 @@ class OsSyscallExceptionHandler : public machine::ExceptionHandler {
6666
OSSYCALL_HANDLER_DECLARE(do_sys_set_thread_area);
6767
OSSYCALL_HANDLER_DECLARE(do_sys_writev);
6868
OSSYCALL_HANDLER_DECLARE(do_sys_write);
69+
OSSYCALL_HANDLER_DECLARE(do_sys_readv);
70+
OSSYCALL_HANDLER_DECLARE(do_sys_read);
6971
OSSYCALL_HANDLER_DECLARE(do_sys_brk);
7072
OSSYCALL_HANDLER_DECLARE(do_sys_mmap2);
7173
signals:
7274
void char_written(int fd, unsigned int val);
75+
void rx_byte_pool(int fd, unsigned int &data, bool &available);
7376
private:
7477
std::uint32_t brk_limit;
7578
std::uint32_t anonymous_base;

0 commit comments

Comments
 (0)