Skip to content

Commit 1c48699

Browse files
committed
ports/cheriot-rtos: Added timeout functionality to UART peripheral.
Signed-off-by: Jacob Trevor <[email protected]>
1 parent 07d9efc commit 1c48699

File tree

5 files changed

+53
-20
lines changed

5 files changed

+53
-20
lines changed

ports/cheriot-rtos/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ SRC_C = mp_entry.c \
5454
machine_spi.c \
5555
machine_i2c.c
5656

57-
SRC_CXX = hal/i2c.cpp
57+
SRC_CXX = hal/i2c.cpp hal/uart.cpp hal/timer.cpp
5858

5959
SRC_QSTR += shared/readline/readline.c shared/runtime/pyexec.c mp_entry.c machine_pin.c machine_spi.c machine_i2c.c
6060

ports/cheriot-rtos/hal/timer.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include <platform-timer.hh>
2+
3+
uint64_t get_time() {
4+
StandardClint::init();
5+
return StandardClint::time();
6+
}

ports/cheriot-rtos/hal/uart.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#include <platform-uart.hh>
22

3-
#define UART_TX_FIFO_SIZE (32)
3+
extern uint64_t get_time();
4+
5+
#define CLOCK_FREQ_KHZ (50000)
6+
#define MS_TO_CLOCK_CYCLES(x) (x * CLOCK_FREQ_KHZ) // clock 50mHz
47

58
extern "C" uint8_t uart_get_rx_level(volatile OpenTitanUart<115'200> *block) {
69
return (block->fifoStatus >> 16) & 0xff;
@@ -18,12 +21,23 @@ extern "C" bool uart_is_writable(volatile OpenTitanUart<115'200> *block) {
1821
return block->can_write();
1922
}
2023

21-
extern "C" uint8_t uart_read(volatile OpenTitanUart<115'200> *block) {
22-
return block->blocking_read();
24+
extern "C" bool uart_read(volatile OpenTitanUart<115'200> *block, uint8_t *out, uint32_t timeout_ms) {
25+
uint32_t t_end = get_time() + MS_TO_CLOCK_CYCLES(timeout_ms);
26+
27+
while (!block->can_read()) {
28+
if (get_time() > t_end) {
29+
return false;
30+
}
31+
}
32+
33+
*out = block->rData;
34+
return true;
2335
}
2436

2537
extern "C" void uart_write(volatile OpenTitanUart<115'200> *block, uint8_t data) {
26-
block->blocking_write(data);
38+
while (!block->can_write()) {
39+
}
40+
block->wData = data;
2741
}
2842

2943
extern "C" void uart_init(volatile OpenTitanUart<115'200> *block, uint32_t baudrate) {

ports/cheriot-rtos/machine_uart.c

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,18 @@ typedef struct OpenTitanUart open_titan_uart_t;
88
typedef struct _machine_uart_obj_t {
99
mp_obj_base_t base;
1010
volatile open_titan_uart_t *uart_block;
11+
uint32_t timeout_ms;
12+
uint32_t char_timeout_ms;
1113
} machine_uart_obj_t;
1214

1315

16+
extern void uart_init(volatile open_titan_uart_t *block, uint32_t baudrate);
1417
extern uint8_t uart_get_rx_level(volatile open_titan_uart_t *block);
1518
extern uint8_t uart_get_tx_level(volatile open_titan_uart_t *block);
1619
extern bool uart_is_readable(volatile open_titan_uart_t *block);
1720
extern bool uart_is_writable(volatile open_titan_uart_t *block);
18-
extern uint8_t uart_read(volatile open_titan_uart_t *block);
21+
extern bool uart_read(volatile open_titan_uart_t *block, uint8_t *out, uint32_t timeout_ms);
1922
extern void uart_write(volatile open_titan_uart_t *block, uint8_t data);
20-
extern void uart_init(volatile open_titan_uart_t *block, uint32_t baudrate);
2123

2224
volatile open_titan_uart_t *get_uart_block(uint32_t id) {
2325
switch (id)
@@ -49,8 +51,8 @@ static void mp_machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args,
4951
{ MP_QSTR_rx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
5052
{ MP_QSTR_cts, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
5153
{ MP_QSTR_rts, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
52-
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
53-
{ MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
54+
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 100} },
55+
{ MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 100} },
5456
{ MP_QSTR_invert, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
5557
{ MP_QSTR_flow, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
5658
{ MP_QSTR_txbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 32} },
@@ -84,11 +86,6 @@ static void mp_machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args,
8486
mp_raise_ValueError("rx buffer is 64 bytes long");
8587
}
8688

87-
if (args[ARG_timeout].u_int != -1 ||
88-
args[ARG_timeout_char].u_int != -1) {
89-
mp_raise_NotImplementedError("UART Timeouts not implemented");
90-
}
91-
9289
if (args[ARG_invert].u_int != -1) {
9390
mp_raise_NotImplementedError("UART invert not implemented");
9491
}
@@ -103,6 +100,9 @@ static void mp_machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args,
103100
// parity = mp_obj_get_int(args[ARG_parity].u_obj);
104101
}
105102

103+
self->timeout_ms = args[ARG_timeout].u_int;
104+
self->char_timeout_ms = args[ARG_timeout_char].u_int;
105+
106106
uint32_t baudrate = args[ARG_baudrate].u_int;
107107
uart_init(self->uart_block, baudrate);
108108
}
@@ -141,24 +141,34 @@ static bool mp_machine_uart_txdone(machine_uart_obj_t *self) {
141141

142142
static mp_uint_t mp_machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
143143
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
144-
145-
uint8_t *dest = buf_in;
144+
uint8_t *dest = (uint8_t *)buf_in;
146145

147146
for (size_t i = 0; i < size; i++) {
148-
dest[i] = uart_read(self->uart_block);
147+
uint32_t timeout = (i == 0? self->timeout_ms:self->char_timeout_ms);
148+
if (!uart_read(self->uart_block, &dest[i], timeout)) {
149+
for (size_t x = 0; x < size; x++) {
150+
}
151+
if (i <= 0) {
152+
*errcode = MP_EAGAIN;
153+
return MP_STREAM_ERROR;
154+
} else {
155+
return i;
156+
}
157+
}
158+
149159
}
150160
return size;
151161
}
152162

153163

154164
static mp_uint_t mp_machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) {
155165
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
156-
157166
uint8_t *data = (uint8_t *)buf_in;
158167

159168
for (size_t i = 0; i < size; i++) {
160169
uart_write(self->uart_block, data[i]);
161170
}
171+
162172
return size;
163173
}
164174

ports/cheriot-rtos/mpconfigport.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ enum { SPI_MSB_FIRST, SPI_LSB_FIRST };
1111

1212
// Use the minimal starting configuration (disables all optional features).
1313
#define MICROPY_CONFIG_ROM_LEVEL \
14-
(MICROPY_CONFIG_ROM_LEVEL_CORE_FEATURES) // MINIMUM)
14+
(MICROPY_CONFIG_ROM_LEVEL_CORE_FEATURES) // MINIMUM)
1515

1616
// You can disable the built-in MicroPython compiler by setting the following
1717
// config option to 0. If you do this then you won't get a REPL prompt, but you
@@ -31,6 +31,8 @@ enum { SPI_MSB_FIRST, SPI_LSB_FIRST };
3131
#define MICROPY_PY_IO (0)
3232
#define MICROPY_PY_BUILTINS_MEMORYVIEW (1)
3333

34+
#define MICROPY_STREAMS_NON_BLOCK (1)
35+
3436
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
3537

3638
#define MICROPY_ALLOC_PATH_MAX (256)
@@ -42,7 +44,8 @@ enum { SPI_MSB_FIRST, SPI_LSB_FIRST };
4244
#define MICROPY_PY_MACHINE_SPI_MSB (SPI_MSB_FIRST)
4345
#define MICROPY_PY_MACHINE_SPI_LSB (SPI_LSB_FIRST)
4446
#define MICROPY_PY_MACHINE_I2C (1)
45-
47+
#define MICROPY_PY_MACHINE_UART (1)
48+
#define MICROPY_PY_MACHINE_UART_INCLUDEFILE "ports/cheriot-rtos/machine_uart.c"
4649
// Use the minimum headroom in the chunk allocator for parse nodes.
4750
#define MICROPY_ALLOC_PARSE_CHUNK_INIT (16)
4851

0 commit comments

Comments
 (0)