Skip to content

Commit 14251ff

Browse files
authored
ports/cheriot-rtos: Merge pull request #1 from JakeTrevor/cheriot-dev.
Added mod machine Pin & SPI
2 parents 13f43dc + 8d5937a commit 14251ff

File tree

6 files changed

+615
-26
lines changed

6 files changed

+615
-26
lines changed

ports/cheriot-rtos/Makefile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ MICROPY_ROM_TEXT_COMPRESSION ?= 0
88

99
# include py core make definitions
1010
include $(TOP)/py/py.mk
11+
include $(TOP)/extmod/extmod.mk
1112

1213
CLLVM_DIR ?= ~/cheriot-llvm/
1314
CRTOS_DIR ?= ../../../cheriot-rtos
@@ -49,10 +50,12 @@ SRC_C = mp_entry.c \
4950
shared/readline/readline.c \
5051
shared/runtime/pyexec.c \
5152
$(BUILD)/_frozen_mpy.c \
53+
machine_pin.c \
54+
machine_spi.c
5255

5356
SRC_CXX =
5457

55-
SRC_QSTR += shared/readline/readline.c shared/runtime/pyexec.c mp_entry.c
58+
SRC_QSTR += shared/readline/readline.c shared/runtime/pyexec.c mp_entry.c machine_pin.c machine_spi.c
5659

5760
SRC_HAL_C = shared/runtime/stdout_helpers.c
5861
SRC_HAL_CXX = uart_core.cpp
@@ -62,7 +65,7 @@ SRC_MAIN_CXX = main.cpp
6265

6366
OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
6467
OBJ += $(addprefix $(BUILD)/, $(SRC_CXX:.cpp=.o))
65-
OBJ += $(PY_CORE_O)
68+
OBJ += $(PY_O)
6669

6770
OBJ_HAL += $(addprefix $(BUILD)/, $(SRC_HAL_C:.c=.o))
6871
OBJ_HAL += $(addprefix $(BUILD)/, $(SRC_HAL_CXX:.cpp=.o))

ports/cheriot-rtos/machine_pin.c

Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
#include <string.h>
2+
3+
#include "extmod/modmachine.h"
4+
#include "py/obj.h"
5+
#include "py/runtime.h"
6+
7+
typedef struct {
8+
uint32_t output;
9+
uint32_t input;
10+
uint32_t debounced_input;
11+
uint32_t debounce_threshold;
12+
} gpio_block_t;
13+
14+
typedef struct _machine_pin_obj_t {
15+
mp_obj_base_t base;
16+
volatile gpio_block_t *port;
17+
uint32_t pin;
18+
uint32_t mode;
19+
} machine_pin_obj_t;
20+
21+
enum {
22+
MACHINE_PIN_MODE_IN = 0,
23+
MACHINE_PIN_MODE_OUT = 1,
24+
MACHINE_PIN_MODE_OPEN_DRAIN = 2,
25+
// MACHINE_PIN_MODE_ANALOG = 3
26+
};
27+
28+
#define GET_BUFFER(self) ((self->port->output >> self->pin) & 1)
29+
30+
static uint32_t set_pin_value(uint32_t block, uint32_t pin, bool value) {
31+
if (value) {
32+
return block | (1 << pin);
33+
} else {
34+
return block & ~(1 << pin);
35+
}
36+
}
37+
38+
static uint32_t set_pin_enable(uint32_t block, uint32_t pin, bool value) {
39+
if (value) {
40+
return block | (1 << (pin + 16));
41+
} else {
42+
return block & ~(1 << (pin + 16));
43+
}
44+
}
45+
46+
volatile gpio_block_t *get_port(const char *drv_name) {
47+
// !! MMIO_CAPABILITY names were custom hard-coded into the boards/sonata.json
48+
// !! file since the headers are currently out of date.
49+
switch (drv_name[0]) {
50+
case 'g':
51+
if (strcmp(drv_name, "gpio") == 0) {
52+
return MMIO_CAPABILITY(gpio_block_t, gpio);
53+
}
54+
#if 0
55+
case 'r':
56+
if (strcmp(drv_name, "rpi") == 0) {
57+
return MMIO_CAPABILITY(gpio_block_t, rpi);
58+
}
59+
case 'a':
60+
if (strcmp(drv_name, "arduino") == 0) {
61+
return MMIO_CAPABILITY(gpio_block_t, arduino);
62+
}
63+
case 'p':
64+
if (strcmp(drv_name, "pmod") == 0) {
65+
return MMIO_CAPABILITY(gpio_block_t, pmod);
66+
}
67+
#endif
68+
default:
69+
mp_raise_msg_varg(&mp_type_ValueError,
70+
MP_ERROR_TEXT("Unknown port \"%s\""), drv_name);
71+
}
72+
}
73+
74+
static void machine_pin_obj_init_helper(machine_pin_obj_t *self, size_t n_args,
75+
const mp_obj_t *pos_args,
76+
mp_map_t *kw_args) {
77+
enum { ARG_mode, ARG_value };
78+
79+
static const mp_arg_t allowed_args[] = {
80+
{MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT},
81+
{MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}
82+
};
83+
84+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
85+
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args),
86+
allowed_args, args);
87+
88+
self->mode = args[ARG_mode].u_int;
89+
90+
uint32_t init = GET_BUFFER(self);
91+
if (args[ARG_value].u_obj != MP_OBJ_NULL) {
92+
init = mp_obj_is_true(args[ARG_value].u_obj);
93+
}
94+
95+
bool enabled = (self->mode == MACHINE_PIN_MODE_OUT) ||
96+
(self->mode == MACHINE_PIN_MODE_OPEN_DRAIN && !init);
97+
98+
uint32_t block = self->port->output;
99+
block = set_pin_enable(block, self->pin, enabled);
100+
block = set_pin_value(block, self->pin, init);
101+
self->port->output = block;
102+
}
103+
104+
// constructor Pin(id, mode, *, value)
105+
mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw,
106+
const mp_obj_t *args) {
107+
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
108+
109+
if (!mp_obj_is_type(args[0], &mp_type_tuple)) {
110+
mp_raise_ValueError(
111+
MP_ERROR_TEXT("Pin id must be a tuple of (\"name\", pin#)"));
112+
}
113+
114+
mp_obj_t *pin_id;
115+
mp_obj_get_array_fixed_n(args[0], 2, &pin_id);
116+
117+
const char *drv_name = mp_obj_str_get_str(pin_id[0]);
118+
int wanted_pin = mp_obj_get_int(pin_id[1]);
119+
120+
volatile gpio_block_t *wanted_port = get_port(drv_name);
121+
122+
machine_pin_obj_t *pin = m_new_obj(machine_pin_obj_t);
123+
pin->base.type = &machine_pin_type;
124+
pin->port = wanted_port;
125+
pin->pin = wanted_pin;
126+
127+
if (n_args > 1 || n_kw > 0) {
128+
mp_map_t kw_args;
129+
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
130+
machine_pin_obj_init_helper(pin, n_args - 1, args + 1, &kw_args);
131+
}
132+
133+
return MP_OBJ_FROM_PTR(pin);
134+
}
135+
136+
// Pin.init(mode, *, value)
137+
static mp_obj_t machine_pin_obj_init(size_t n_args, const mp_obj_t *args,
138+
mp_map_t *kw_args) {
139+
if (mp_obj_is_type(args[0], &machine_pin_type)) {
140+
machine_pin_obj_init_helper(MP_OBJ_TO_PTR(args[0]), n_args - 1, args + 1,
141+
kw_args);
142+
return args[0];
143+
} else {
144+
mp_raise_TypeError(
145+
MP_ERROR_TEXT("Cannot call Pin.init on object that is not Pin"));
146+
}
147+
}
148+
MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_init_obj, 1, machine_pin_obj_init);
149+
150+
static mp_uint_t pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg,
151+
int *errcode) {
152+
(void)errcode;
153+
machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in);
154+
155+
switch (request) {
156+
case MP_PIN_READ: {
157+
if (self->mode == MACHINE_PIN_MODE_IN) {
158+
return (self->port->input >> self->pin) & 1;
159+
} else {
160+
return GET_BUFFER(self);
161+
}
162+
}
163+
case MP_PIN_WRITE: {
164+
uint32_t block = set_pin_value(self->port->output, self->pin, (bool)arg);
165+
166+
if (self->mode == MACHINE_PIN_MODE_OPEN_DRAIN) {
167+
block = set_pin_enable(block, self->pin, !(bool)arg);
168+
}
169+
170+
self->port->output = block;
171+
return 0;
172+
}
173+
}
174+
return -1;
175+
}
176+
177+
static mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw,
178+
const mp_obj_t *args) {
179+
mp_arg_check_num(n_args, n_kw, 0, 1, false);
180+
181+
if (n_args == 0) {
182+
return MP_OBJ_NEW_SMALL_INT(mp_virtual_pin_read(self_in));
183+
} else {
184+
mp_virtual_pin_write(self_in, mp_obj_is_true(args[0]));
185+
return mp_const_none;
186+
}
187+
}
188+
189+
// Pin.value([value])
190+
static mp_obj_t machine_pin_value(size_t n_args, const mp_obj_t *args) {
191+
return machine_pin_call(args[0], n_args - 1, 0, args + 1);
192+
}
193+
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_value_obj, 1, 2,
194+
machine_pin_value);
195+
196+
static mp_obj_t machine_pin_off(mp_obj_t self_in) {
197+
mp_virtual_pin_write(self_in, 0);
198+
return mp_const_none;
199+
}
200+
static MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_off_obj, machine_pin_off);
201+
202+
static mp_obj_t machine_pin_on(mp_obj_t self_in) {
203+
mp_virtual_pin_write(self_in, 1);
204+
return mp_const_none;
205+
}
206+
static MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_on_obj, machine_pin_on);
207+
208+
// print(pin)
209+
static void machine_pin_print(const mp_print_t *print, mp_obj_t self_in,
210+
mp_print_kind_t kind) {
211+
machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in);
212+
const char *mode_str;
213+
214+
switch (self->mode) {
215+
case MACHINE_PIN_MODE_IN:
216+
mode_str = "IN";
217+
break;
218+
case MACHINE_PIN_MODE_OUT:
219+
mode_str = "OUT";
220+
break;
221+
case MACHINE_PIN_MODE_OPEN_DRAIN:
222+
mode_str = "OPEN DRAIN";
223+
break;
224+
default:
225+
mode_str = "unknown mode";
226+
}
227+
228+
const char *name_str;
229+
230+
switch ((ptraddr_t)self->port) {
231+
case 0x80000000:
232+
name_str = "gpio";
233+
case 0x80006000:
234+
name_str = "rpi";
235+
case 0x80007000:
236+
name_str = "arduino";
237+
case 0x80008000:
238+
name_str = "pmod";
239+
default:
240+
name_str = "unknown port";
241+
}
242+
243+
mp_printf(print, "Pin(%s(%d) mode=%s)", name_str, self->pin, mode_str);
244+
}
245+
246+
static const mp_rom_map_elem_t machine_pin_locals_dict_table[] = {
247+
// instance methods
248+
{MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_pin_init_obj)},
249+
{MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&machine_pin_value_obj)},
250+
{MP_ROM_QSTR(MP_QSTR_low), MP_ROM_PTR(&machine_pin_off_obj)},
251+
{MP_ROM_QSTR(MP_QSTR_high), MP_ROM_PTR(&machine_pin_on_obj)},
252+
{MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&machine_pin_off_obj)},
253+
{MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&machine_pin_on_obj)},
254+
255+
// class constants
256+
{MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(MACHINE_PIN_MODE_IN)},
257+
{MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(MACHINE_PIN_MODE_OUT)},
258+
{MP_ROM_QSTR(MP_QSTR_OPEN_DRAIN), MP_ROM_INT(MACHINE_PIN_MODE_OPEN_DRAIN)},
259+
};
260+
static MP_DEFINE_CONST_DICT(machine_pin_locals_dict,
261+
machine_pin_locals_dict_table);
262+
263+
static const mp_pin_p_t pin_pin_p = {
264+
.ioctl = pin_ioctl,
265+
};
266+
267+
/**
268+
* TODO:
269+
* pin.mode()
270+
*/
271+
272+
MP_DEFINE_CONST_OBJ_TYPE(machine_pin_type, MP_QSTR_Pin, MP_TYPE_FLAG_NONE,
273+
make_new, mp_pin_make_new, print, machine_pin_print,
274+
call, machine_pin_call, protocol, &pin_pin_p,
275+
locals_dict, &machine_pin_locals_dict);

0 commit comments

Comments
 (0)