Skip to content

Commit 07d9efc

Browse files
committed
ports/cheriot-rots: Initial (blocking) UART implementation.
Signed-off-by: Jacob Trevor <[email protected]>
1 parent 796f501 commit 07d9efc

File tree

2 files changed

+226
-0
lines changed

2 files changed

+226
-0
lines changed

ports/cheriot-rtos/hal/uart.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#include <platform-uart.hh>
2+
3+
#define UART_TX_FIFO_SIZE (32)
4+
5+
extern "C" uint8_t uart_get_rx_level(volatile OpenTitanUart<115'200> *block) {
6+
return (block->fifoStatus >> 16) & 0xff;
7+
}
8+
9+
extern "C" uint8_t uart_get_tx_level(volatile OpenTitanUart<115'200> *block) {
10+
return block->fifoStatus & 0xff;
11+
}
12+
13+
extern "C" bool uart_is_readable(volatile OpenTitanUart<115'200> *block) {
14+
return block->can_read();
15+
}
16+
17+
extern "C" bool uart_is_writable(volatile OpenTitanUart<115'200> *block) {
18+
return block->can_write();
19+
}
20+
21+
extern "C" uint8_t uart_read(volatile OpenTitanUart<115'200> *block) {
22+
return block->blocking_read();
23+
}
24+
25+
extern "C" void uart_write(volatile OpenTitanUart<115'200> *block, uint8_t data) {
26+
block->blocking_write(data);
27+
}
28+
29+
extern "C" void uart_init(volatile OpenTitanUart<115'200> *block, uint32_t baudrate) {
30+
block->init(baudrate);
31+
}

ports/cheriot-rtos/machine_uart.c

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
#include "py/stream.h"
2+
#include "py/runtime.h"
3+
#include "py/obj.h"
4+
5+
6+
typedef struct OpenTitanUart open_titan_uart_t;
7+
8+
typedef struct _machine_uart_obj_t {
9+
mp_obj_base_t base;
10+
volatile open_titan_uart_t *uart_block;
11+
} machine_uart_obj_t;
12+
13+
14+
extern uint8_t uart_get_rx_level(volatile open_titan_uart_t *block);
15+
extern uint8_t uart_get_tx_level(volatile open_titan_uart_t *block);
16+
extern bool uart_is_readable(volatile open_titan_uart_t *block);
17+
extern bool uart_is_writable(volatile open_titan_uart_t *block);
18+
extern uint8_t uart_read(volatile open_titan_uart_t *block);
19+
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);
21+
22+
volatile open_titan_uart_t *get_uart_block(uint32_t id) {
23+
switch (id)
24+
{
25+
case 1:
26+
return MMIO_CAPABILITY(open_titan_uart_t, uart1);
27+
case 2:
28+
return MMIO_CAPABILITY(open_titan_uart_t, uart2);
29+
default:
30+
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("Unknown UART device \"%d\""), id);
31+
}
32+
}
33+
34+
static void mp_machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
35+
// machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
36+
mp_printf(print, "UART");
37+
}
38+
39+
40+
static void mp_machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
41+
enum { ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_tx, ARG_rx, ARG_cts, ARG_rts,
42+
ARG_timeout, ARG_timeout_char, ARG_invert, ARG_flow, ARG_txbuf, ARG_rxbuf};
43+
static const mp_arg_t allowed_args[] = {
44+
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 9600} },
45+
{ MP_QSTR_bits, MP_ARG_INT, {.u_int = 8} },
46+
{ MP_QSTR_parity, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
47+
{ MP_QSTR_stop, MP_ARG_INT, {.u_int = 1} },
48+
{ MP_QSTR_tx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
49+
{ MP_QSTR_rx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
50+
{ MP_QSTR_cts, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
51+
{ 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_invert, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
55+
{ MP_QSTR_flow, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
56+
{ MP_QSTR_txbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 32} },
57+
{ MP_QSTR_rxbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 64} },
58+
};
59+
// Parse args.
60+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
61+
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
62+
63+
if (args[ARG_bits].u_int != 8) {
64+
mp_raise_ValueError("Bit hard coded to 8");
65+
}
66+
67+
if (args[ARG_stop].u_int != 1) {
68+
mp_raise_ValueError("Stop bits hard coded to 1");
69+
}
70+
71+
if ((args[ARG_tx].u_obj != MP_OBJ_NULL) ||
72+
(args[ARG_rx].u_obj != MP_OBJ_NULL) ||
73+
(args[ARG_cts].u_obj != MP_OBJ_NULL) ||
74+
(args[ARG_rts].u_obj != MP_OBJ_NULL)) {
75+
mp_raise_NotImplementedError(
76+
MP_ERROR_TEXT("explicit choice of tx/rx/rts/cts pins is not implemented"));
77+
}
78+
79+
if (args[ARG_txbuf].u_int != 32) {
80+
mp_raise_ValueError("tx buffer is 32 bytes long");
81+
}
82+
83+
if (args[ARG_rxbuf].u_int != 64) {
84+
mp_raise_ValueError("rx buffer is 64 bytes long");
85+
}
86+
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+
92+
if (args[ARG_invert].u_int != -1) {
93+
mp_raise_NotImplementedError("UART invert not implemented");
94+
}
95+
96+
if (args[ARG_flow].u_int != -1) {
97+
mp_raise_NotImplementedError("UART flow not implemented");
98+
}
99+
100+
// uint32_t parity = 0;
101+
if (args[ARG_parity].u_obj != MP_OBJ_NULL) {
102+
mp_raise_NotImplementedError("UART parity not implemented");
103+
// parity = mp_obj_get_int(args[ARG_parity].u_obj);
104+
}
105+
106+
uint32_t baudrate = args[ARG_baudrate].u_int;
107+
uart_init(self->uart_block, baudrate);
108+
}
109+
110+
111+
static mp_obj_t mp_machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
112+
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
113+
114+
int id = mp_obj_get_int(args[0]);
115+
volatile open_titan_uart_t *block = get_uart_block(id);
116+
117+
machine_uart_obj_t *self = m_new_obj(machine_uart_obj_t);
118+
self->base.type = &machine_uart_type;
119+
self->uart_block = block;
120+
121+
mp_map_t kw_args;
122+
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
123+
mp_machine_uart_init_helper(self, n_args - 1, args + 1, &kw_args);
124+
125+
return MP_OBJ_FROM_PTR(self);
126+
}
127+
128+
129+
// TODO this one too
130+
static void mp_machine_uart_deinit(machine_uart_obj_t *self) {
131+
132+
}
133+
134+
static mp_int_t mp_machine_uart_any(machine_uart_obj_t *self) {
135+
return uart_get_rx_level(self->uart_block);
136+
}
137+
138+
static bool mp_machine_uart_txdone(machine_uart_obj_t *self) {
139+
return uart_get_tx_level(self->uart_block) == 0;
140+
}
141+
142+
static mp_uint_t mp_machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
143+
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
144+
145+
uint8_t *dest = buf_in;
146+
147+
for (size_t i = 0; i < size; i++) {
148+
dest[i] = uart_read(self->uart_block);
149+
}
150+
return size;
151+
}
152+
153+
154+
static mp_uint_t mp_machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) {
155+
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
156+
157+
uint8_t *data = (uint8_t *)buf_in;
158+
159+
for (size_t i = 0; i < size; i++) {
160+
uart_write(self->uart_block, data[i]);
161+
}
162+
return size;
163+
}
164+
165+
166+
static mp_uint_t mp_machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
167+
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
168+
mp_uint_t ret;
169+
170+
switch (request) {
171+
case MP_STREAM_POLL: {
172+
uintptr_t flags = arg;
173+
ret = 0;
174+
if ((flags & MP_STREAM_POLL_RD) && uart_is_readable(self->uart_block)) {
175+
ret |= MP_STREAM_POLL_RD;
176+
}
177+
if ((flags & MP_STREAM_POLL_WR) && uart_is_writable(self->uart_block)) {
178+
ret |= MP_STREAM_POLL_WR;
179+
}
180+
break;
181+
}
182+
// case MP_STREAM_FLUSH:
183+
// break;
184+
185+
default: {
186+
*errcode = MP_EINVAL;
187+
ret = MP_STREAM_ERROR;
188+
break;
189+
}
190+
}
191+
return ret;
192+
}
193+
194+
195+
#define MICROPY_PY_MACHINE_UART_CLASS_CONSTANTS

0 commit comments

Comments
 (0)