Skip to content

Commit 67b6d9d

Browse files
Daniel Thompsonpfalcon
authored andcommitted
zephyr: Initial implementation of machine.Pin.
The integration with Zephyr is fairly clean but as MicroPython Hardware API requires pin ID to be a single value, but Zephyr operates GPIO in terms of ports and pins, not just pins, a "hierarchical" ID is required, using tuple of (port, pin). Port is a string, effectively a device name of a GPIO port, per Zephyr conventions these are "GPIO_0", "GPIO_1", etc.; pin is integer number of pin with the port (supposed to be in range 0-31). Example of pin initialization: pin = Pin(("GPIO_1", 21), Pin.OUT) (an LED on FRDM-K64F's Port B, Pin 21). There is support for in/out pins and pull up/pull down but currently there is no interrupt support. Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Signed-off-by: Vincenzo Frascino <vincenzo.frascino@linaro.org> Signed-off-by: Paul Sokolovsky <paul.sokolovsky@linaro.org>
1 parent a351933 commit 67b6d9d

File tree

5 files changed

+272
-0
lines changed

5 files changed

+272
-0
lines changed

zephyr/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ INC += -I$(ZEPHYR_BASE)/net/ip/contiki/os
3535
SRC_C = main.c \
3636
help.c \
3737
modutime.c \
38+
modmachine.c \
39+
machine_pin.c \
3840
uart_core.c \
3941
lib/utils/stdout_helpers.c \
4042
lib/utils/printf.c \

zephyr/machine_pin.c

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
/*
2+
* This file is part of the Micro Python project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2013, 2014, 2015 Damien P. George
7+
* Copyright (c) 2016 Linaro Limited
8+
*
9+
* Permission is hereby granted, free of charge, to any person obtaining a copy
10+
* of this software and associated documentation files (the "Software"), to deal
11+
* in the Software without restriction, including without limitation the rights
12+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
* copies of the Software, and to permit persons to whom the Software is
14+
* furnished to do so, subject to the following conditions:
15+
*
16+
* The above copyright notice and this permission notice shall be included in
17+
* all copies or substantial portions of the Software.
18+
*
19+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
* THE SOFTWARE.
26+
*/
27+
28+
#include <stdio.h>
29+
#include <stdint.h>
30+
#include <string.h>
31+
32+
#include <zephyr.h>
33+
#include <gpio.h>
34+
35+
#include "py/nlr.h"
36+
#include "py/runtime.h"
37+
#include "py/gc.h"
38+
#include "py/mphal.h"
39+
#include "modmachine.h"
40+
41+
const mp_obj_base_t machine_pin_obj_template = {&machine_pin_type};
42+
43+
STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
44+
machine_pin_obj_t *self = self_in;
45+
mp_printf(print, "<Pin %p %d>", self->port, self->pin);
46+
}
47+
48+
// pin.init(mode, pull=None, *, value)
49+
STATIC mp_obj_t machine_pin_obj_init_helper(machine_pin_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
50+
enum { ARG_mode, ARG_pull, ARG_value };
51+
static const mp_arg_t allowed_args[] = {
52+
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT },
53+
{ MP_QSTR_pull, MP_ARG_OBJ, {.u_obj = mp_const_none}},
54+
{ MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}},
55+
};
56+
57+
// parse args
58+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
59+
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
60+
61+
// get io mode
62+
uint mode = args[ARG_mode].u_int;
63+
64+
// get pull mode
65+
uint pull = GPIO_PUD_NORMAL;
66+
if (args[ARG_pull].u_obj != mp_const_none) {
67+
pull = mp_obj_get_int(args[ARG_pull].u_obj);
68+
}
69+
70+
int ret = gpio_pin_configure(self->port, self->pin, mode | pull);
71+
if (ret) {
72+
mp_raise_ValueError("invalid pin");
73+
}
74+
75+
// get initial value
76+
if (args[ARG_value].u_obj != MP_OBJ_NULL) {
77+
(void)gpio_pin_write(self->port, self->pin, mp_obj_is_true(args[ARG_value].u_obj));
78+
}
79+
80+
return mp_const_none;
81+
}
82+
83+
// constructor(drv_name, pin, ...)
84+
STATIC mp_obj_t machine_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
85+
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
86+
87+
// get the wanted port
88+
if (!MP_OBJ_IS_TYPE(args[0], &mp_type_tuple)) {
89+
mp_raise_ValueError("Pin id must be tuple of (\"GPIO_x\", pin#)");
90+
}
91+
mp_obj_t *items;
92+
mp_obj_get_array_fixed_n(args[0], 2, &items);
93+
const char *drv_name = mp_obj_str_get_str(items[0]);
94+
int wanted_pin = mp_obj_get_int(items[1]);
95+
struct device *wanted_port = device_get_binding(drv_name);
96+
if (!wanted_port) {
97+
mp_raise_ValueError("invalid port");
98+
}
99+
100+
machine_pin_obj_t *pin = m_new_obj(machine_pin_obj_t);
101+
pin->base = machine_pin_obj_template;
102+
pin->port = wanted_port;
103+
pin->pin = wanted_pin;
104+
105+
if (n_args > 1 || n_kw > 0) {
106+
// pin mode given, so configure this GPIO
107+
mp_map_t kw_args;
108+
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
109+
machine_pin_obj_init_helper(pin, n_args - 1, args + 1, &kw_args);
110+
}
111+
112+
return (mp_obj_t)pin;
113+
}
114+
115+
// fast method for getting/setting pin value
116+
STATIC mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
117+
mp_arg_check_num(n_args, n_kw, 0, 1, false);
118+
machine_pin_obj_t *self = self_in;
119+
if (n_args == 0) {
120+
uint32_t pin_val;
121+
(void)gpio_pin_read(self->port, self->pin, &pin_val);
122+
return MP_OBJ_NEW_SMALL_INT(pin_val);
123+
} else {
124+
(void)gpio_pin_write(self->port, self->pin, mp_obj_is_true(args[0]));
125+
return mp_const_none;
126+
}
127+
}
128+
129+
// pin.init(mode, pull)
130+
STATIC mp_obj_t machine_pin_obj_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
131+
return machine_pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args);
132+
}
133+
MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_init_obj, 1, machine_pin_obj_init);
134+
135+
// pin.value([value])
136+
STATIC mp_obj_t machine_pin_value(size_t n_args, const mp_obj_t *args) {
137+
return machine_pin_call(args[0], n_args - 1, 0, args + 1);
138+
}
139+
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_value_obj, 1, 2, machine_pin_value);
140+
141+
// pin.low()
142+
STATIC mp_obj_t machine_pin_low(mp_obj_t self_in) {
143+
machine_pin_obj_t *self = self_in;
144+
(void)gpio_pin_write(self->port, self->pin, 0);
145+
return mp_const_none;
146+
}
147+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_low_obj, machine_pin_low);
148+
149+
// pin.high()
150+
STATIC mp_obj_t machine_pin_high(mp_obj_t self_in) {
151+
machine_pin_obj_t *self = self_in;
152+
(void)gpio_pin_write(self->port, self->pin, 1);
153+
return mp_const_none;
154+
}
155+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_high_obj, machine_pin_high);
156+
157+
STATIC const mp_map_elem_t machine_pin_locals_dict_table[] = {
158+
// instance methods
159+
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&machine_pin_init_obj },
160+
{ MP_OBJ_NEW_QSTR(MP_QSTR_value), (mp_obj_t)&machine_pin_value_obj },
161+
{ MP_OBJ_NEW_QSTR(MP_QSTR_low), (mp_obj_t)&machine_pin_low_obj },
162+
{ MP_OBJ_NEW_QSTR(MP_QSTR_high), (mp_obj_t)&machine_pin_high_obj },
163+
164+
// class constants
165+
{ MP_OBJ_NEW_QSTR(MP_QSTR_IN), MP_OBJ_NEW_SMALL_INT(GPIO_DIR_IN) },
166+
{ MP_OBJ_NEW_QSTR(MP_QSTR_OUT), MP_OBJ_NEW_SMALL_INT(GPIO_DIR_OUT) },
167+
{ MP_OBJ_NEW_QSTR(MP_QSTR_PULL_UP), MP_OBJ_NEW_SMALL_INT(GPIO_PUD_PULL_UP) },
168+
{ MP_OBJ_NEW_QSTR(MP_QSTR_PULL_DOWN), MP_OBJ_NEW_SMALL_INT(GPIO_PUD_PULL_DOWN) },
169+
};
170+
171+
STATIC MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table);
172+
173+
const mp_obj_type_t machine_pin_type = {
174+
{ &mp_type_type },
175+
.name = MP_QSTR_Pin,
176+
.print = machine_pin_print,
177+
.make_new = machine_pin_make_new,
178+
.call = machine_pin_call,
179+
.locals_dict = (mp_obj_t)&machine_pin_locals_dict,
180+
};

zephyr/modmachine.c

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2013-2015 Damien P. George
7+
* Copyright (c) 2016 Paul Sokolovsky
8+
* Copyright (c) 2016 Linaro Limited
9+
*
10+
* Permission is hereby granted, free of charge, to any person obtaining a copy
11+
* of this software and associated documentation files (the "Software"), to deal
12+
* in the Software without restriction, including without limitation the rights
13+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14+
* copies of the Software, and to permit persons to whom the Software is
15+
* furnished to do so, subject to the following conditions:
16+
*
17+
* The above copyright notice and this permission notice shall be included in
18+
* all copies or substantial portions of the Software.
19+
*
20+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26+
* THE SOFTWARE.
27+
*/
28+
29+
#include <stdint.h>
30+
#include <stdio.h>
31+
32+
#include "py/obj.h"
33+
#include "py/runtime.h"
34+
#include "extmod/machine_mem.h"
35+
#include "extmod/machine_pulse.h"
36+
#include "extmod/machine_i2c.h"
37+
#include "modmachine.h"
38+
39+
#if MICROPY_PY_MACHINE
40+
41+
STATIC mp_obj_t machine_reset(void) {
42+
printf("Warning: %s is not implemented\n", __func__);
43+
return mp_const_none;
44+
}
45+
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset);
46+
47+
STATIC mp_obj_t machine_reset_cause(void) {
48+
printf("Warning: %s is not implemented\n", __func__);
49+
return MP_OBJ_NEW_SMALL_INT(42);
50+
}
51+
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause);
52+
53+
STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
54+
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) },
55+
{ MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) },
56+
{ MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) },
57+
58+
{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) },
59+
60+
// reset causes
61+
/*{ MP_ROM_QSTR(MP_QSTR_PWRON_RESET), MP_ROM_INT(REASON_DEFAULT_RST) },*/
62+
};
63+
64+
STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table);
65+
66+
const mp_obj_module_t mp_module_machine = {
67+
.base = { &mp_type_module },
68+
.globals = (mp_obj_dict_t*)&machine_module_globals,
69+
};
70+
71+
#endif // MICROPY_PY_MACHINE

zephyr/modmachine.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#ifndef __MICROPY_INCLUDED_ZEPHYR_MODMACHINE_H__
2+
#define __MICROPY_INCLUDED_ZEPHYR_MODMACHINE_H__
3+
4+
#include "py/obj.h"
5+
6+
extern const mp_obj_type_t machine_pin_type;
7+
8+
MP_DECLARE_CONST_FUN_OBJ_0(machine_info_obj);
9+
10+
typedef struct _machine_pin_obj_t {
11+
mp_obj_base_t base;
12+
struct device *port;
13+
uint32_t pin;
14+
} machine_pin_obj_t;
15+
16+
#endif // __MICROPY_INCLUDED_ZEPHYR_MODMACHINE_H__

zephyr/mpconfigport.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
#define MICROPY_PY_CMATH (0)
5454
#define MICROPY_PY_IO (0)
5555
#define MICROPY_PY_MICROPYTHON_MEM_INFO (1)
56+
#define MICROPY_PY_MACHINE (1)
5657
#define MICROPY_PY_STRUCT (0)
5758
#define MICROPY_PY_UTIME (1)
5859
#define MICROPY_PY_UTIME_MP_HAL (1)
@@ -90,6 +91,7 @@ typedef long mp_off_t;
9091
mp_obj_t mp_kbd_exception; \
9192
const char *readline_hist[8];
9293

94+
extern const struct _mp_obj_module_t mp_module_machine;
9395
extern const struct _mp_obj_module_t mp_module_time;
9496

9597
#if MICROPY_PY_UTIME
@@ -99,6 +101,7 @@ extern const struct _mp_obj_module_t mp_module_time;
99101
#endif
100102

101103
#define MICROPY_PORT_BUILTIN_MODULES \
104+
{ MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&mp_module_machine }, \
102105
MICROPY_PY_UTIME_DEF \
103106

104107
// extra built in names to add to the global namespace

0 commit comments

Comments
 (0)