summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Hylands <dhylands@gmail.com>2014-07-22 07:57:36 -0700
committerDave Hylands <dhylands@gmail.com>2014-08-07 23:15:41 -0700
commit6f418fc1b068c1a41113bb2b019a5803765e1deb (patch)
tree79477835459eb424012f58d77a150bdf9a80eed5
parent3ef911345c94a6d612ab50c1e912e81cb2cc3f71 (diff)
Add support for selecting pin alternate functions from python.
Converts generted pins to use qstrs instead of string pointers. This patch also adds the following functions: pyb.Pin.names() pyb.Pin.af_list() pyb.Pin.gpio() dir(pyb.Pin.board) and dir(pyb.Pin.cpu) also produce useful results. pyb.Pin now takes kw args. pyb.Pin.__str__ now prints more useful information about the pin configuration. I found the following functions in my boot.py to be useful: ```python def pins(): for pin_name in dir(pyb.Pin.board): pin = pyb.Pin(pin_name) print('{:10s} {:s}'.format(pin_name, str(pin))) def af(): for pin_name in dir(pyb.Pin.board): pin = pyb.Pin(pin_name) print('{:10s} {:s}'.format(pin_name, str(pin.af_list()))) ```
-rw-r--r--stmhal/Makefile9
-rwxr-xr-xstmhal/boards/make-pins.py66
-rw-r--r--stmhal/boards/stm32f4xx-prefix.c3
-rw-r--r--stmhal/mphal.h1
-rw-r--r--stmhal/pin.c234
-rw-r--r--stmhal/pin.h17
-rw-r--r--stmhal/pin_defs_stmhal.c37
-rw-r--r--stmhal/pin_named_pins.c63
-rw-r--r--stmhal/qstrdefsport.h9
-rw-r--r--teensy/Makefile9
-rw-r--r--teensy/hal_gpio.c15
-rw-r--r--teensy/main.c4
-rwxr-xr-xteensy/make-pins.py67
-rw-r--r--teensy/memzip_files/boot.py10
-rw-r--r--teensy/mk20dx256-prefix.c3
-rw-r--r--teensy/pin_defs_teensy.c61
-rw-r--r--teensy/pin_defs_teensy.h1
-rw-r--r--teensy/qstrdefsport.h8
-rw-r--r--teensy/teensy_hal.h18
19 files changed, 548 insertions, 87 deletions
diff --git a/stmhal/Makefile b/stmhal/Makefile
index 4daf665fa..d56125faf 100644
--- a/stmhal/Makefile
+++ b/stmhal/Makefile
@@ -11,7 +11,7 @@ BUILD ?= build-$(BOARD)
include ../py/mkenv.mk
# qstr definitions (must come before including py.mk)
-QSTR_DEFS = qstrdefsport.h
+QSTR_DEFS = qstrdefsport.h $(BUILD)/pins_qstr.h
# include py core make definitions
include ../py/py.mk
@@ -74,6 +74,7 @@ SRC_C = \
timer.c \
led.c \
pin.c \
+ pin_defs_stmhal.c \
pin_named_pins.c \
bufhelper.c \
i2c.c \
@@ -227,6 +228,8 @@ AF_FILE = boards/stm32f4xx-af.csv
PREFIX_FILE = boards/stm32f4xx-prefix.c
GEN_PINS_SRC = $(BUILD)/pins_$(BOARD).c
GEN_PINS_HDR = $(HEADER_BUILD)/pins.h
+GEN_PINS_QSTR = $(BUILD)/pins_qstr.h
+GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins-af-const.h
INSERT_USB_IDS = ../tools/insert-usb-ids.py
FILE2H = ../tools/file2h.py
@@ -247,9 +250,9 @@ $(BUILD)/main.o: $(GEN_CDCINF_HEADER)
# Use a pattern rule here so that make will only call make-pins.py once to make
# both pins_$(BOARD).c and pins.h
-$(BUILD)/%_$(BOARD).c $(HEADER_BUILD)/%.h: boards/$(BOARD)/%.csv $(MAKE_PINS) $(AF_FILE) $(PREFIX_FILE)
+$(BUILD)/%_$(BOARD).c $(HEADER_BUILD)/%.h $(HEADER_BUILD)/%-af-const.h $(BUILD)/%_qstr.h: boards/$(BOARD)/%.csv $(MAKE_PINS) $(AF_FILE) $(PREFIX_FILE) | $(HEADER_BUILD)
$(ECHO) "Create $@"
- $(Q)$(PYTHON) $(MAKE_PINS) --board $(BOARD_PINS) --af $(AF_FILE) --prefix $(PREFIX_FILE) --hdr $(GEN_PINS_HDR) > $(GEN_PINS_SRC)
+ $(Q)$(PYTHON) $(MAKE_PINS) --board $(BOARD_PINS) --af $(AF_FILE) --prefix $(PREFIX_FILE) --hdr $(GEN_PINS_HDR) --qstr $(GEN_PINS_QSTR) --af-const $(GEN_PINS_AF_CONST) > $(GEN_PINS_SRC)
$(BUILD)/pins_$(BOARD).o: $(BUILD)/pins_$(BOARD).c
$(call compile_c)
diff --git a/stmhal/boards/make-pins.py b/stmhal/boards/make-pins.py
index e3a3f583a..f3d1dee48 100755
--- a/stmhal/boards/make-pins.py
+++ b/stmhal/boards/make-pins.py
@@ -72,6 +72,9 @@ class AlternateFunction(object):
return self.func
return '{:s}{:d}'.format(self.func, self.fn_num)
+ def mux_name(self):
+ return 'AF{:d}_{:s}'.format(self.idx, self.ptr())
+
def print(self):
"""Prints the C representation of this AF."""
if self.supported:
@@ -84,6 +87,9 @@ class AlternateFunction(object):
print('({:2d}, {:8s}, {:2d}, {:10s}, {:8s}), // {:s}'.format(self.idx,
self.func, fn_num, self.pin_type, self.ptr(), self.af_str))
+ def qstr_list(self):
+ return [self.mux_name()]
+
class Pin(object):
"""Holds the information associated with a pin."""
@@ -170,6 +176,14 @@ class Pin(object):
hdr_file.write('extern const pin_af_obj_t pin_{:s}_af[];\n'.
format(self.cpu_pin_name()))
+ def qstr_list(self):
+ result = []
+ for alt_fn in self.alt_fn:
+ if alt_fn.is_supported():
+ result += alt_fn.qstr_list()
+ return result
+
+
class NamedPin(object):
def __init__(self, name, pin):
@@ -225,13 +239,13 @@ class Pins(object):
self.board_pins.append(NamedPin(row[0], pin))
def print_named(self, label, named_pins):
- print('const pin_named_pin_t pin_{:s}_pins[] = {{'.format(label))
+ print('STATIC const mp_map_elem_t pin_{:s}_pins_locals_dict_table[] = {{'.format(label))
for named_pin in named_pins:
pin = named_pin.pin()
if pin.is_board_pin():
- print(' {{ "{:s}", &pin_{:s} }},'.format(named_pin.name(), pin.cpu_pin_name()))
- print(' { NULL, NULL }')
+ print(' {{ MP_OBJ_NEW_QSTR(MP_QSTR_{:s}), (mp_obj_t)&pin_{:s} }},'.format(named_pin.name(), pin.cpu_pin_name()))
print('};')
+ print('MP_DEFINE_CONST_DICT(pin_{:s}_pins_locals_dict, pin_{:s}_pins_locals_dict_table);'.format(label, label));
def print(self):
for named_pin in self.cpu_pins:
@@ -269,6 +283,38 @@ class Pins(object):
hdr_file.write('extern const pin_obj_t * const pin_adc2[];\n')
hdr_file.write('extern const pin_obj_t * const pin_adc3[];\n')
+ def print_qstr(self, qstr_filename):
+ with open(qstr_filename, 'wt') as qstr_file:
+ qstr_set = set([])
+ for named_pin in self.cpu_pins:
+ pin = named_pin.pin()
+ if pin.is_board_pin():
+ qstr_set |= set(pin.qstr_list())
+ qstr_set |= set([named_pin.name()])
+ for named_pin in self.board_pins:
+ qstr_set |= set([named_pin.name()])
+ for qstr in sorted(qstr_set):
+ print('Q({})'.format(qstr), file=qstr_file)
+
+ def print_af_hdr(self, af_const_filename):
+ with open(af_const_filename, 'wt') as af_const_file:
+ af_hdr_set = set([])
+ mux_name_width = 0
+ for named_pin in self.cpu_pins:
+ pin = named_pin.pin()
+ if pin.is_board_pin():
+ for af in pin.alt_fn:
+ if af.is_supported():
+ mux_name = af.mux_name()
+ af_hdr_set |= set([mux_name])
+ if len(mux_name) > mux_name_width:
+ mux_name_width = len(mux_name)
+ for mux_name in sorted(af_hdr_set):
+ key = 'MP_OBJ_NEW_QSTR(MP_QSTR_{}),'.format(mux_name)
+ val = 'MP_OBJ_NEW_SMALL_INT(GPIO_{})'.format(mux_name)
+ print(' { %-*s %s },' % (mux_name_width + 26, key, val),
+ file=af_const_file)
+
def main():
parser = argparse.ArgumentParser(
@@ -283,6 +329,12 @@ def main():
default="stm32f4xx-af.csv"
)
parser.add_argument(
+ "--af-const",
+ dest="af_const_filename",
+ help="Specifies header file for alternate function constants.",
+ default="build/pins-af-const.h"
+ )
+ parser.add_argument(
"-b", "--board",
dest="board_filename",
help="Specifies the board file",
@@ -294,6 +346,12 @@ def main():
default="stm32f4xx-prefix.c"
)
parser.add_argument(
+ "-q", "--qstr",
+ dest="qstr_filename",
+ help="Specifies name of generated qstr header file",
+ default="build/pins-qstr.h"
+ )
+ parser.add_argument(
"-r", "--hdr",
dest="hdr_filename",
help="Specifies name of generated pin header file",
@@ -323,6 +381,8 @@ def main():
pins.print_adc(2)
pins.print_adc(3)
pins.print_header(args.hdr_filename)
+ pins.print_qstr(args.qstr_filename)
+ pins.print_af_hdr(args.af_const_filename)
if __name__ == "__main__":
diff --git a/stmhal/boards/stm32f4xx-prefix.c b/stmhal/boards/stm32f4xx-prefix.c
index 3bbb6bda0..45bcc0b65 100644
--- a/stmhal/boards/stm32f4xx-prefix.c
+++ b/stmhal/boards/stm32f4xx-prefix.c
@@ -14,6 +14,7 @@
#define AF(af_idx, af_fn, af_unit, af_type, af_ptr) \
{ \
{ &pin_af_type }, \
+ .name = MP_QSTR_AF ## af_idx ## _ ## af_fn ## af_unit, \
.idx = (af_idx), \
.fn = AF_FN_ ## af_fn, \
.unit = (af_unit), \
@@ -24,7 +25,7 @@
#define PIN(p_port, p_pin, p_num_af, p_af, p_adc_num, p_adc_channel) \
{ \
{ &pin_type }, \
- .name = #p_port #p_pin, \
+ .name = MP_QSTR_ ## p_port ## p_pin, \
.port = PORT_ ## p_port, \
.pin = (p_pin), \
.num_af = (p_num_af), \
diff --git a/stmhal/mphal.h b/stmhal/mphal.h
index 4e9a8b2bb..33407622c 100644
--- a/stmhal/mphal.h
+++ b/stmhal/mphal.h
@@ -5,3 +5,4 @@
#define GPIO_read_pin(gpio, pin) (((gpio)->IDR >> (pin)) & 1)
#define GPIO_set_pin(gpio, pin_mask) (((gpio)->BSRRL) = (pin_mask))
#define GPIO_clear_pin(gpio, pin_mask) (((gpio)->BSRRH) = (pin_mask))
+#define GPIO_read_output_pin(gpio, pin) (((gpio)->ODR >> (pin)) & 1)
diff --git a/stmhal/pin.c b/stmhal/pin.c
index 0ef8b6950..5092d5e51 100644
--- a/stmhal/pin.c
+++ b/stmhal/pin.c
@@ -63,7 +63,8 @@
///
/// Users can add their own names:
///
-/// pyb.Pin.dict["LeftMotorDir"] = pyb.Pin.cpu.C12
+/// MyMapperDict = { 'LeftMotorDir' : pyb.Pin.cpu.C12 }
+/// pyb.Pin.dict(MyMapperDict)
/// g = pyb.Pin("LeftMotorDir", pyb.Pin.OUT_OD)
///
/// and can query mappings
@@ -155,8 +156,7 @@ const pin_obj_t *pin_find(mp_obj_t user_obj) {
}
// See if the pin name matches a board pin
- const char *pin_name = mp_obj_str_get_str(user_obj);
- pin_obj = pin_find_named_pin(pin_board_pins, pin_name);
+ pin_obj = pin_find_named_pin(&pin_board_pins_locals_dict, user_obj);
if (pin_obj) {
if (pin_class_debug) {
printf("Pin.board maps ");
@@ -169,7 +169,7 @@ const pin_obj_t *pin_find(mp_obj_t user_obj) {
}
// See if the pin name matches a cpu pin
- pin_obj = pin_find_named_pin(pin_cpu_pins, pin_name);
+ pin_obj = pin_find_named_pin(&pin_cpu_pins_locals_dict, user_obj);
if (pin_obj) {
if (pin_class_debug) {
printf("Pin.cpu maps ");
@@ -181,34 +181,69 @@ const pin_obj_t *pin_find(mp_obj_t user_obj) {
return pin_obj;
}
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin '%s' not a valid pin identifier", pin_name));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin '%s' not a valid pin identifier", mp_obj_str_get_str(user_obj)));
}
/// \method __str__()
/// Return a string describing the pin object.
STATIC void pin_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
pin_obj_t *self = self_in;
- print(env, "<Pin %s>", self->name);
+
+ // Need to query mode, pull, af
+
+ print(env, "Pin(Pin.cpu.%s", qstr_str(self->name));
+ uint32_t mode = pin_get_mode(self);
+ if (mode == GPIO_MODE_ANALOG) {
+ print(env, ", mode=Pin.ANALOG)", qstr_str(self->name));
+ } else {
+ const char *pull_str = "";
+ uint32_t pull = pin_get_pull(self);
+ if (pull == GPIO_PULLUP) {
+ pull_str = ", pull=Pin.PULL_UP";
+ } else if (pull == GPIO_PULLDOWN) {
+ pull_str = ", pull=Pin.PULL_DOWN";
+ }
+ if (mode == GPIO_MODE_INPUT) {
+ print(env, ", mode=Pin.IN%s)", pull_str);
+ } else if (mode == GPIO_MODE_OUTPUT_PP || mode == GPIO_MODE_OUTPUT_OD) {
+ if (mode == GPIO_MODE_OUTPUT_PP) {
+ print(env, ", mode=Pin.OUT_PP%s)", pull_str);
+ } else {
+ print(env, ", mode=Pin.OUT_OD%s)", pull_str);
+ }
+ } else {
+ if (mode == GPIO_MODE_AF_PP) {
+ print(env, ", mode=Pin.AF_PP");
+ } else {
+ print(env, ", mode=Pin.AF_OD");
+ }
+ mp_uint_t af_idx = pin_get_af(self);
+ const pin_af_obj_t *af = pin_find_af_by_index(self, af_idx);
+ if (af == NULL) {
+ print(env, ", af=%d%s)", af_idx, pull_str);
+ } else {
+ print(env, ", af=Pin.%s)", qstr_str(af->name), pull_str);
+ }
+ }
+ }
}
-STATIC mp_obj_t pin_obj_init(uint n_args, mp_obj_t *args);
+STATIC mp_obj_t pin_obj_init_helper(const pin_obj_t *pin, uint n_args, const mp_obj_t *args, mp_map_t *kw_args);
/// \classmethod \constructor(id, ...)
/// Create a new Pin object associated with the id. If additional arguments are given,
/// they are used to initialise the pin. See `init`.
STATIC mp_obj_t pin_make_new(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
- mp_arg_check_num(n_args, n_kw, 1, 3, false);
+ mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
// Run an argument through the mapper and return the result.
const pin_obj_t *pin = pin_find(args[0]);
- if (n_args >= 2) {
+ if (n_args > 1 || n_kw > 0) {
// pin mode given, so configure this GPIO
- mp_obj_t args2[3] = {(mp_obj_t)pin, args[1], MP_OBJ_NULL};
- if (n_args == 3) {
- args2[2] = args[2];
- }
- pin_obj_init(n_args, args2);
+ mp_map_t kw_args;
+ mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
+ pin_obj_init_helper(pin, n_args - 1, args + 1, &kw_args);
}
return (mp_obj_t)pin;
@@ -238,6 +273,20 @@ STATIC mp_obj_t pin_map_dict(uint n_args, mp_obj_t *args) {
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_map_dict_fun_obj, 1, 2, pin_map_dict);
STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(pin_map_dict_obj, (mp_obj_t)&pin_map_dict_fun_obj);
+/// |classmethod af_list()
+/// Returns an array of alternate functions available for this pin.
+STATIC mp_obj_t pin_af_list(mp_obj_t self_in) {
+ pin_obj_t *self = self_in;
+ mp_obj_t result = mp_obj_new_list(0, NULL);
+
+ const pin_af_obj_t *af = self->af;
+ for (mp_uint_t i = 0; i < self->num_af; i++, af++) {
+ mp_obj_list_append(result, (mp_obj_t)af);
+ }
+ return result;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_af_list_obj, pin_af_list);
+
/// \classmethod debug([state])
/// Get or set the debugging state (`True` or `False` for on or off).
STATIC mp_obj_t pin_debug(uint n_args, mp_obj_t *args) {
@@ -250,7 +299,7 @@ STATIC mp_obj_t pin_debug(uint n_args, mp_obj_t *args) {
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_debug_fun_obj, 1, 2, pin_debug);
STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(pin_debug_obj, (mp_obj_t)&pin_debug_fun_obj);
-/// \method init(mode, pull=Pin.PULL_NONE)
+/// \method init(mode, pull=Pin.PULL_NONE, af)
/// Initialise the pin:
///
/// - `mode` can be one of:
@@ -264,26 +313,53 @@ STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(pin_debug_obj, (mp_obj_t)&pin_debug_fun_o
/// - `Pin.PULL_NONE` - no pull up or down resistors;
/// - `Pin.PULL_UP` - enable the pull-up resistor;
/// - `Pin.PULL_DOWN` - enable the pull-down resistor.
+/// - when mode is Pin.AF_PP or Pin.AF_OD, then af can be the index or name
+/// of one of the alternate functions associated with a pin.
///
/// Returns: `None`.
-// TODO allow keyword args
-STATIC mp_obj_t pin_obj_init(uint n_args, mp_obj_t *args) {
- pin_obj_t *self = args[0];
+STATIC const mp_arg_t pin_init_args[] = {
+ { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT },
+ { MP_QSTR_pull, MP_ARG_INT, {.u_int = GPIO_NOPULL}},
+ { MP_QSTR_af, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none}},
+};
+#define PIN_INIT_NUM_ARGS MP_ARRAY_SIZE(pin_init_args)
+
+STATIC mp_obj_t pin_obj_init_helper(const pin_obj_t *self, uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
+ // parse args
+ mp_arg_val_t vals[PIN_INIT_NUM_ARGS];
+ mp_arg_parse_all(n_args, args, kw_args, PIN_INIT_NUM_ARGS, pin_init_args, vals);
// get io mode
- uint mode = mp_obj_get_int(args[1]);
+ uint mode = vals[0].u_int;
if (!IS_GPIO_MODE(mode)) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid pin mode: %d", mode));
}
// get pull mode
- uint pull = GPIO_NOPULL;
- if (n_args >= 3) {
- pull = mp_obj_get_int(args[2]);
- if (!IS_GPIO_PULL(pull)) {
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid pin pull: %d", pull));
+ uint pull = vals[1].u_int;
+ if (!IS_GPIO_PULL(pull)) {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid pin pull: %d", pull));
+ }
+
+ // get af (alternate function)
+ mp_int_t af_idx = -1;
+ mp_obj_t af_obj = vals[2].u_obj;
+ if (af_obj != mp_const_none) {
+ if (MP_OBJ_IS_STR(af_obj)) {
+ const pin_af_obj_t *af;
+ const char *af_str = mp_obj_str_get_str(af_obj);
+ af = pin_find_af_by_name(self, af_str);
+ if (af == NULL) {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid pin af: %s", af_str));
+ }
+ af_idx = af->idx;
+ } else {
+ af_idx = mp_obj_get_int(af_obj);
}
}
+ if ((mode == GPIO_MODE_AF_PP || mode == GPIO_MODE_AF_OD) && !IS_GPIO_AF(af_idx)) {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid pin af: %d", af_idx));
+ }
// enable the peripheral clock for the port of this pin
switch (self->port) {
@@ -325,12 +401,15 @@ STATIC mp_obj_t pin_obj_init(uint n_args, mp_obj_t *args) {
GPIO_InitStructure.Mode = mode;
GPIO_InitStructure.Pull = pull;
GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
- GPIO_InitStructure.Alternate = 0;
+ GPIO_InitStructure.Alternate = af_idx;
HAL_GPIO_Init(self->gpio, &GPIO_InitStructure);
return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_init_obj, 2, 3, pin_obj_init);
+STATIC mp_obj_t pin_obj_init(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
+ return pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pin_init_obj, 1, pin_obj_init);
/// \method value([value])
/// Get or set the digital logic level of the pin:
@@ -378,10 +457,29 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_high_obj, pin_high);
/// Get the pin name.
STATIC mp_obj_t pin_name(mp_obj_t self_in) {
pin_obj_t *self = self_in;
- return MP_OBJ_NEW_QSTR(qstr_from_str(self->name));
+ return MP_OBJ_NEW_QSTR(self->name);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_name_obj, pin_name);
+/// \method names()
+/// Returns the cpu and board names for this pin.
+STATIC mp_obj_t pin_names(mp_obj_t self_in) {
+ pin_obj_t *self = self_in;
+ mp_obj_t result = mp_obj_new_list(0, NULL);
+ mp_obj_list_append(result, MP_OBJ_NEW_QSTR(self->name));
+
+ mp_map_t *map = mp_obj_dict_get_map((mp_obj_t)&pin_board_pins_locals_dict);
+ mp_map_elem_t *elem = map->table;
+
+ for (mp_uint_t i = 0; i < map->used; i++, elem++) {
+ if (elem->value == self) {
+ mp_obj_list_append(result, elem->key);
+ }
+ }
+ return result;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_names_obj, pin_names);
+
/// \method port()
/// Get the pin port.
STATIC mp_obj_t pin_port(mp_obj_t self_in) {
@@ -398,6 +496,14 @@ STATIC mp_obj_t pin_pin(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_pin_obj, pin_pin);
+/// \method gpio()
+/// Returns the base address of the GPIO block associated with this pin.
+STATIC mp_obj_t pin_gpio(mp_obj_t self_in) {
+ pin_obj_t *self = self_in;
+ return MP_OBJ_NEW_SMALL_INT((mp_int_t)self->gpio);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_gpio_obj, pin_gpio);
+
STATIC const mp_map_elem_t pin_locals_dict_table[] = {
// instance methods
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pin_init_obj },
@@ -405,8 +511,11 @@ STATIC const mp_map_elem_t pin_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_low), (mp_obj_t)&pin_low_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_high), (mp_obj_t)&pin_high_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_name), (mp_obj_t)&pin_name_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_names), (mp_obj_t)&pin_names_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_af_list), (mp_obj_t)&pin_af_list_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_port), (mp_obj_t)&pin_port_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pin), (mp_obj_t)&pin_pin_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_gpio), (mp_obj_t)&pin_gpio_obj },
// class methods
{ MP_OBJ_NEW_QSTR(MP_QSTR_mapper), (mp_obj_t)&pin_mapper_obj },
@@ -414,8 +523,8 @@ STATIC const mp_map_elem_t pin_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_debug), (mp_obj_t)&pin_debug_obj },
// class attributes
- { MP_OBJ_NEW_QSTR(MP_QSTR_board), (mp_obj_t)&pin_board_pins_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_cpu), (mp_obj_t)&pin_cpu_pins_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_board), (mp_obj_t)&pin_board_pins_obj_type },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_cpu), (mp_obj_t)&pin_cpu_pins_obj_type },
// class constants
/// \constant IN - initialise the pin to input mode
@@ -433,6 +542,7 @@ STATIC const mp_map_elem_t pin_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_PULL_NONE), MP_OBJ_NEW_SMALL_INT(GPIO_NOPULL) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_PULL_UP), MP_OBJ_NEW_SMALL_INT(GPIO_PULLUP) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_PULL_DOWN), MP_OBJ_NEW_SMALL_INT(GPIO_PULLDOWN) },
+#include "genhdr/pins-af-const.h"
};
STATIC MP_DEFINE_CONST_DICT(pin_locals_dict, pin_locals_dict_table);
@@ -445,14 +555,76 @@ const mp_obj_type_t pin_type = {
.locals_dict = (mp_obj_t)&pin_locals_dict,
};
+/// \moduleref pyb
+/// \class PinAF - Pin Alternate Functions
+///
+/// A Pin represents a physical pin on the microcprocessor. Each pin
+/// can have a variety of functions (GPIO, I2C SDA, etc). Each PinAF
+/// object represents a particular function for a pin.
+///
+/// Usage Model:
+///
+/// x3 = pyb.Pin.board.X3
+/// x3_af = x3.af_list()
+///
+/// x3_af will now contain an array of PinAF objects which are availble on
+/// pin X3.
+///
+/// For the pyboard, x3_af would contain:
+/// [Pin.AF1_TIM2, Pin.AF2_TIM5, Pin.AF3_TIM9, Pin.AF7_USART2]
+///
+/// Normally, each peripheral would configure the af automatically, but sometimes
+/// the same function is available on multiple pins, and having more control
+/// is desired.
+///
+/// To configure X3 to expose TIM2_CH3, you could use:
+/// pin = pyb.Pin(pyb.Pin.board.X3, mode=pyb.Pin.AF_PP, af=pyb.Pin.AF1_TIM2)
+/// or:
+/// pin = pyb.Pin(pyb.Pin.board.X3, mode=pyb.Pin.AF_PP, af=1)
+
+/// \method __str__()
+/// Return a string describing the alternate function.
STATIC void pin_af_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
pin_af_obj_t *self = self_in;
- print(env, "<Pin AF %d fn:%d unit:%d typ:%d>", self->idx, self->fn,
- self->unit, self->type);
+ print(env, "Pin.%s", qstr_str(self->name));
}
+/// \method index()
+/// Return the alternate function index.
+STATIC mp_obj_t pin_af_index(mp_obj_t self_in) {
+ pin_af_obj_t *af = self_in;
+ return MP_OBJ_NEW_SMALL_INT(af->idx);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_af_index_obj, pin_af_index);
+
+/// \method index()
+/// Return the name of the alternate function.
+STATIC mp_obj_t pin_af_name(mp_obj_t self_in) {
+ pin_af_obj_t *af = self_in;
+ return MP_OBJ_NEW_QSTR(af->name);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_af_name_obj, pin_af_name);
+
+/// \method index()
+/// Return the base register associated with the peripheral assigned to this
+/// alternate function. For example, if the alternate function were TIM2_CH3
+/// this would return stm.TIM2
+STATIC mp_obj_t pin_af_reg(mp_obj_t self_in) {
+ pin_af_obj_t *af = self_in;
+ return MP_OBJ_NEW_SMALL_INT((mp_uint_t)af->reg);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_af_reg_obj, pin_af_reg);
+
+STATIC const mp_map_elem_t pin_af_locals_dict_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR_index), (mp_obj_t)&pin_af_index_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_name), (mp_obj_t)&pin_af_name_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_reg), (mp_obj_t)&pin_af_reg_obj },
+};
+STATIC MP_DEFINE_CONST_DICT(pin_af_locals_dict, pin_af_locals_dict_table);
+
const mp_obj_type_t pin_af_type = {
{ &mp_type_type },
.name = MP_QSTR_PinAF,
.print = pin_af_obj_print,
+ .locals_dict = (mp_obj_t)&pin_af_locals_dict,
};
diff --git a/stmhal/pin.h b/stmhal/pin.h
index 51a434f1d..6ac73aabd 100644
--- a/stmhal/pin.h
+++ b/stmhal/pin.h
@@ -31,6 +31,7 @@
typedef struct {
mp_obj_base_t base;
+ qstr name;
uint8_t idx;
uint8_t fn;
uint8_t unit;
@@ -45,7 +46,7 @@ typedef struct {
typedef struct {
mp_obj_base_t base;
- const char *name;
+ qstr name;
uint32_t port : 4;
uint32_t pin : 5; // Some ARM processors use 32 bits/PORT
uint32_t num_af : 4;
@@ -75,10 +76,18 @@ typedef struct {
const pin_named_pin_t *named_pins;
} pin_named_pins_obj_t;
-extern const pin_named_pins_obj_t pin_board_pins_obj;
-extern const pin_named_pins_obj_t pin_cpu_pins_obj;
+extern const mp_obj_type_t pin_board_pins_obj_type;
+extern const mp_obj_type_t pin_cpu_pins_obj_type;
+
+extern const mp_obj_dict_t pin_cpu_pins_locals_dict;
+extern const mp_obj_dict_t pin_board_pins_locals_dict;
void pin_init0(void);
+uint32_t pin_get_mode(const pin_obj_t *pin);
+uint32_t pin_get_pull(const pin_obj_t *pin);
+uint32_t pin_get_af(const pin_obj_t *pin);
const pin_obj_t *pin_find(mp_obj_t user_obj);
-const pin_obj_t *pin_find_named_pin(const pin_named_pin_t *pins, const char *name);
+const pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name);
const pin_af_obj_t *pin_find_af(const pin_obj_t *pin, uint8_t fn, uint8_t unit, uint8_t pin_type);
+const pin_af_obj_t *pin_find_af_by_index(const pin_obj_t *pin, mp_uint_t af_idx);
+const pin_af_obj_t *pin_find_af_by_name(const pin_obj_t *pin, const char *name);
diff --git a/stmhal/pin_defs_stmhal.c b/stmhal/pin_defs_stmhal.c
new file mode 100644
index 000000000..c2409dc6c
--- /dev/null
+++ b/stmhal/pin_defs_stmhal.c
@@ -0,0 +1,37 @@
+#include "mpconfig.h"
+#include "nlr.h"
+#include "misc.h"
+#include "qstr.h"
+#include "obj.h"
+#include "runtime.h"
+#include MICROPY_HAL_H
+#include "pin.h"
+
+// Returns the pin mode. This value returned by this macro should be one of:
+// GPIO_MODE_INPUT, GPIO_MODE_OUTPUT_PP, GPIO_MODE_OUTPUT_OD,
+// GPIO_MODE_AF_PP, GPIO_MODE_AF_OD, or GPIO_MODE_ANALOG.
+
+uint32_t pin_get_mode(const pin_obj_t *pin) {
+ GPIO_TypeDef *gpio = pin->gpio;
+ uint32_t mode = (gpio->MODER >> (pin->pin * 2)) & 3;
+ if (mode != GPIO_MODE_ANALOG) {
+ if (gpio->OTYPER & pin->pin_mask) {
+ mode |= 1 << 4;
+ }
+ }
+ return mode;
+}
+
+// Returns the pin pullup/pulldown. The value returned by this macro should
+// be one of GPIO_NOPULL, GPIO_PULLUP, or GPIO_PULLDOWN.
+
+uint32_t pin_get_pull(const pin_obj_t *pin) {
+ return (pin->gpio->PUPDR >> (pin->pin * 2)) & 3;
+}
+
+// Returns the af (alternate function) index currently set for a pin.
+
+uint32_t pin_get_af(const pin_obj_t *pin) {
+ return (pin->gpio->AFR[pin->pin >> 3] >> ((pin->pin & 7) * 4)) & 0xf;
+}
+
diff --git a/stmhal/pin_named_pins.c b/stmhal/pin_named_pins.c
index dbf03d1a0..c1ee4b8f3 100644
--- a/stmhal/pin_named_pins.c
+++ b/stmhal/pin_named_pins.c
@@ -41,52 +41,55 @@ STATIC void pin_named_pins_obj_print(void (*print)(void *env, const char *fmt, .
print(env, "<Pin.%s>", qstr_str(self->name));
}
-STATIC void pin_named_pins_obj_load_attr(mp_obj_t self_in, qstr attr_qstr, mp_obj_t *dest) {
- pin_named_pins_obj_t *self = self_in;
- const char *attr = qstr_str(attr_qstr);
- const pin_obj_t *pin = pin_find_named_pin(self->named_pins, attr);
- if (pin) {
- dest[0] = (mp_obj_t)pin;
- dest[1] = MP_OBJ_NULL;
- }
-}
-
-static const mp_obj_type_t pin_named_pins_obj_type = {
+const mp_obj_type_t pin_cpu_pins_obj_type = {
{ &mp_type_type },
- .name = MP_QSTR_PinNamed,
+ .name = MP_QSTR_cpu,
.print = pin_named_pins_obj_print,
- .load_attr = pin_named_pins_obj_load_attr,
+ .locals_dict = (mp_obj_t)&pin_cpu_pins_locals_dict,
};
-const pin_named_pins_obj_t pin_board_pins_obj = {
- { &pin_named_pins_obj_type },
+const mp_obj_type_t pin_board_pins_obj_type = {
+ { &mp_type_type },
.name = MP_QSTR_board,
- .named_pins = pin_board_pins,
-};
-
-const pin_named_pins_obj_t pin_cpu_pins_obj = {
- { &pin_named_pins_obj_type },
- .name = MP_QSTR_cpu,
- .named_pins = pin_cpu_pins,
+ .print = pin_named_pins_obj_print,
+ .locals_dict = (mp_obj_t)&pin_board_pins_locals_dict,
};
-const pin_obj_t *pin_find_named_pin(const pin_named_pin_t *named_pins, const char *name) {
- const pin_named_pin_t *named_pin = named_pins;
- while (named_pin->name) {
- if (!strcmp(name, named_pin->name)) {
- return named_pin->pin;
- }
- named_pin++;
+const pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name) {
+ mp_map_t *named_map = mp_obj_dict_get_map((mp_obj_t)named_pins);
+ mp_map_elem_t *named_elem = mp_map_lookup(named_map, name, MP_MAP_LOOKUP);
+ if (named_elem != NULL && named_elem->value != NULL) {
+ return named_elem->value;
}
return NULL;
}
const pin_af_obj_t *pin_find_af(const pin_obj_t *pin, uint8_t fn, uint8_t unit, uint8_t type) {
const pin_af_obj_t *af = pin->af;
- for (int i = 0; i < pin->num_af; i++, af++) {
+ for (mp_uint_t i = 0; i < pin->num_af; i++, af++) {
if (af->fn == fn && af->unit == unit && af->type == type) {
return af;
}
}
return NULL;
}
+
+const pin_af_obj_t *pin_find_af_by_index(const pin_obj_t *pin, mp_uint_t af_idx) {
+ const pin_af_obj_t *af = pin->af;
+ for (mp_uint_t i = 0; i < pin->num_af; i++, af++) {
+ if (af->idx == af_idx) {
+ return af;
+ }
+ }
+ return NULL;
+}
+
+const pin_af_obj_t *pin_find_af_by_name(const pin_obj_t *pin, const char *name) {
+ const pin_af_obj_t *af = pin->af;
+ for (mp_uint_t i = 0; i < pin->num_af; i++, af++) {
+ if (strcmp(name, qstr_str(af->name)) == 0) {
+ return af;
+ }
+ }
+ return NULL;
+}
diff --git a/stmhal/qstrdefsport.h b/stmhal/qstrdefsport.h
index 719a81d12..2505ca747 100644
--- a/stmhal/qstrdefsport.h
+++ b/stmhal/qstrdefsport.h
@@ -93,13 +93,22 @@ Q(value)
Q(low)
Q(high)
Q(name)
+Q(names)
+Q(af)
+Q(af_list)
Q(port)
Q(pin)
+Q(gpio)
Q(mapper)
Q(dict)
Q(debug)
Q(board)
Q(cpu)
+Q(af)
+Q(mode)
+Q(pull)
+Q(index)
+Q(reg)
Q(IN)
Q(OUT_PP)
Q(OUT_OD)
diff --git a/teensy/Makefile b/teensy/Makefile
index 54e6ef050..5b8e26621 100644
--- a/teensy/Makefile
+++ b/teensy/Makefile
@@ -1,7 +1,7 @@
include ../py/mkenv.mk
# qstr definitions (must come before including py.mk)
-QSTR_DEFS = qstrdefsport.h
+QSTR_DEFS = qstrdefsport.h $(BUILD)/pins_qstr.h
# include py core make definitions
include ../py/py.mk
@@ -53,6 +53,7 @@ SRC_C = \
lexermemzip.c \
memzip.c \
modpyb.c \
+ pin_defs_teensy.c \
teensy_hal.c \
uart.c \
usb.c \
@@ -137,6 +138,8 @@ AF_FILE = mk20dx256-af.csv
PREFIX_FILE = mk20dx256-prefix.c
GEN_PINS_SRC = $(BUILD)/pins_gen.c
GEN_PINS_HDR = $(HEADER_BUILD)/pins.h
+GEN_PINS_QSTR = $(BUILD)/pins_qstr.h
+GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins-af-const.h
# Making OBJ use an order-only depenedency on the generated pins.h file
# has the side effect of making the pins.h file before we actually compile
@@ -147,9 +150,9 @@ $(OBJ): | $(HEADER_BUILD)/pins.h
# Use a pattern rule here so that make will only call make-pins.py once to make
# both pins_$(BOARD).c and pins.h
-$(BUILD)/%_gen.c $(HEADER_BUILD)/%.h: teensy-%.csv $(MAKE_PINS) $(AF_FILE) $(PREFIX_FILE)
+$(BUILD)/%_gen.c $(HEADER_BUILD)/%.h $(HEADER_BUILD)/%-af-const.h $(BUILD)/%_qstr.h: teensy-%.csv $(MAKE_PINS) $(AF_FILE) $(PREFIX_FILE) | $(HEADER_BUILD)
$(ECHO) "Create $@"
- $(Q)$(PYTHON) $(MAKE_PINS) --board $(BOARD_PINS) --af $(AF_FILE) --prefix $(PREFIX_FILE) --hdr $(GEN_PINS_HDR) > $(GEN_PINS_SRC)
+ $(Q)$(PYTHON) $(MAKE_PINS) --board $(BOARD_PINS) --af $(AF_FILE) --prefix $(PREFIX_FILE) --hdr $(GEN_PINS_HDR) --qstr $(GEN_PINS_QSTR) --af-const $(GEN_PINS_AF_CONST) > $(GEN_PINS_SRC)
$(BUILD)/pins_gen.o: $(BUILD)/pins_gen.c
$(call compile_c)
diff --git a/teensy/hal_gpio.c b/teensy/hal_gpio.c
index 0811f76fd..218560e29 100644
--- a/teensy/hal_gpio.c
+++ b/teensy/hal_gpio.c
@@ -25,12 +25,18 @@ void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)
if ((GPIO_Init->Mode == GPIO_MODE_AF_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_OD)) {
/* Check the Alternate function parameter */
assert_param(IS_GPIO_AF(GPIO_Init->Alternate));
- /* Configure Alternate function mapped with the current IO */
-
- *port_pcr &= ~PORT_PCR_MUX_MASK;
- *port_pcr |= PORT_PCR_MUX(GPIO_Init->Alternate);
+ }
+ else if (GPIO_Init->Mode == GPIO_MODE_ANALOG) {
+ GPIO_Init->Alternate = 0;
+ }
+ else {
+ GPIO_Init->Alternate = 1;
}
+ /* Configure Alternate function mapped with the current IO */
+ *port_pcr &= ~PORT_PCR_MUX_MASK;
+ *port_pcr |= PORT_PCR_MUX(GPIO_Init->Alternate);
+
/* Configure IO Direction mode (Input, Output, Alternate or Analog) */
if (GPIO_Init->Mode == GPIO_MODE_INPUT || GPIO_Init->Mode == GPIO_MODE_ANALOG) {
GPIOx->PDDR &= ~bitmask;
@@ -112,4 +118,3 @@ void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)
#endif
}
}
-
diff --git a/teensy/main.c b/teensy/main.c
index 53f500d57..8de26f25e 100644
--- a/teensy/main.c
+++ b/teensy/main.c
@@ -24,7 +24,7 @@
#include "usb.h"
#include "led.h"
#include "uart.h"
-//#include "pin.h"
+#include "pin.h"
#include "pybstdio.h"
@@ -272,7 +272,7 @@ soft_reset:
readline_init0();
- //pin_init();
+ pin_init0();
#if 0
// add some functions to the python namespace
diff --git a/teensy/make-pins.py b/teensy/make-pins.py
index 1fd05ec20..6df1e4162 100755
--- a/teensy/make-pins.py
+++ b/teensy/make-pins.py
@@ -71,6 +71,9 @@ class AlternateFunction(object):
return self.func
return '{:s}{:d}'.format(self.func, self.fn_num)
+ def mux_name(self):
+ return 'AF{:d}_{:s}'.format(self.idx, self.ptr())
+
def print(self):
"""Prints the C representation of this AF."""
if self.supported:
@@ -83,6 +86,9 @@ class AlternateFunction(object):
print('({:2d}, {:8s}, {:2d}, {:10s}, {:8s}), // {:s}'.format(self.idx,
self.func, fn_num, self.pin_type, self.ptr(), self.af_str))
+ def qstr_list(self):
+ return [self.mux_name()]
+
class Pin(object):
"""Holds the information associated with a pin."""
@@ -169,6 +175,14 @@ class Pin(object):
hdr_file.write('extern const pin_af_obj_t pin_{:s}_af[];\n'.
format(self.cpu_pin_name()))
+ def qstr_list(self):
+ result = []
+ for alt_fn in self.alt_fn:
+ if alt_fn.is_supported():
+ result += alt_fn.qstr_list()
+ return result
+
+
class NamedPin(object):
def __init__(self, name, pin):
@@ -222,13 +236,13 @@ class Pins(object):
self.board_pins.append(NamedPin(row[0], pin))
def print_named(self, label, named_pins):
- print('const pin_named_pin_t pin_{:s}_pins[] = {{'.format(label))
+ print('STATIC const mp_map_elem_t pin_{:s}_pins_locals_dict_table[] = {{'.format(label))
for named_pin in named_pins:
pin = named_pin.pin()
if pin.is_board_pin():
- print(' {{ "{:s}", &pin_{:s} }},'.format(named_pin.name(), pin.cpu_pin_name()))
- print(' { NULL, NULL }')
+ print(' {{ MP_OBJ_NEW_QSTR(MP_QSTR_{:s}), (mp_obj_t)&pin_{:s} }},'.format(named_pin.name(), pin.cpu_pin_name()))
print('};')
+ print('MP_DEFINE_CONST_DICT(pin_{:s}_pins_locals_dict, pin_{:s}_pins_locals_dict_table);'.format(label, label));
def print(self):
for named_pin in self.cpu_pins:
@@ -266,6 +280,39 @@ class Pins(object):
hdr_file.write('extern const pin_obj_t * const pin_adc2[];\n')
hdr_file.write('extern const pin_obj_t * const pin_adc3[];\n')
+ def print_qstr(self, qstr_filename):
+ with open(qstr_filename, 'wt') as qstr_file:
+ qstr_set = set([])
+ for named_pin in self.cpu_pins:
+ pin = named_pin.pin()
+ if pin.is_board_pin():
+ qstr_set |= set(pin.qstr_list())
+ qstr_set |= set([named_pin.name()])
+ for named_pin in self.board_pins:
+ qstr_set |= set([named_pin.name()])
+ for qstr in sorted(qstr_set):
+ print('Q({})'.format(qstr), file=qstr_file)
+
+
+ def print_af_hdr(self, af_const_filename):
+ with open(af_const_filename, 'wt') as af_const_file:
+ af_hdr_set = set([])
+ mux_name_width = 0
+ for named_pin in self.cpu_pins:
+ pin = named_pin.pin()
+ if pin.is_board_pin():
+ for af in pin.alt_fn:
+ if af.is_supported():
+ mux_name = af.mux_name()
+ af_hdr_set |= set([mux_name])
+ if len(mux_name) > mux_name_width:
+ mux_name_width = len(mux_name)
+ for mux_name in sorted(af_hdr_set):
+ key = 'MP_OBJ_NEW_QSTR(MP_QSTR_{}),'.format(mux_name)
+ val = 'MP_OBJ_NEW_SMALL_INT(GPIO_{})'.format(mux_name)
+ print(' { %-*s %s },' % (mux_name_width + 26, key, val),
+ file=af_const_file)
+
def main():
parser = argparse.ArgumentParser(
@@ -280,6 +327,12 @@ def main():
default="stm32f4xx-af.csv"
)
parser.add_argument(
+ "--af-const",
+ dest="af_const_filename",
+ help="Specifies header file for alternate function constants.",
+ default="build/pins-af-const.h"
+ )
+ parser.add_argument(
"-b", "--board",
dest="board_filename",
help="Specifies the board file",
@@ -291,6 +344,12 @@ def main():
default="stm32f4xx-prefix.c"
)
parser.add_argument(
+ "-q", "--qstr",
+ dest="qstr_filename",
+ help="Specifies name of generated qstr header file",
+ default="build/pins-qstr.h"
+ )
+ parser.add_argument(
"-r", "--hdr",
dest="hdr_filename",
help="Specifies name of generated pin header file",
@@ -320,6 +379,8 @@ def main():
pins.print_adc(2)
pins.print_adc(3)
pins.print_header(args.hdr_filename)
+ pins.print_qstr(args.qstr_filename)
+ pins.print_af_hdr(args.af_const_filename)
if __name__ == "__main__":
diff --git a/teensy/memzip_files/boot.py b/teensy/memzip_files/boot.py
index 4702d7b5d..6dd5516a9 100644
--- a/teensy/memzip_files/boot.py
+++ b/teensy/memzip_files/boot.py
@@ -1,2 +1,12 @@
import pyb
print("Executing boot.py")
+
+def pins():
+ for pin_name in dir(pyb.Pin.board):
+ pin = pyb.Pin(pin_name)
+ print('{:10s} {:s}'.format(pin_name, str(pin)))
+
+def af():
+ for pin_name in dir(pyb.Pin.board):
+ pin = pyb.Pin(pin_name)
+ print('{:10s} {:s}'.format(pin_name, str(pin.af_list())))
diff --git a/teensy/mk20dx256-prefix.c b/teensy/mk20dx256-prefix.c
index 2485dc01a..048b64316 100644
--- a/teensy/mk20dx256-prefix.c
+++ b/teensy/mk20dx256-prefix.c
@@ -15,6 +15,7 @@
#define AF(af_idx, af_fn, af_unit, af_type, af_ptr) \
{ \
{ &pin_af_type }, \
+ .name = MP_QSTR_AF ## af_idx ## _ ## af_fn ## af_unit, \
.idx = (af_idx), \
.fn = AF_FN_ ## af_fn, \
.unit = (af_unit), \
@@ -25,7 +26,7 @@
#define PIN(p_port, p_pin, p_num_af, p_af, p_adc_num, p_adc_channel) \
{ \
{ &pin_type }, \
- .name = #p_port #p_pin, \
+ .name = MP_QSTR_ ## p_port ## p_pin, \
.port = PORT_ ## p_port, \
.pin = (p_pin), \
.num_af = (p_num_af), \
diff --git a/teensy/pin_defs_teensy.c b/teensy/pin_defs_teensy.c
new file mode 100644
index 000000000..dd2f0dc21
--- /dev/null
+++ b/teensy/pin_defs_teensy.c
@@ -0,0 +1,61 @@
+#include <stdint.h>
+#include <mk20dx128.h>
+#include "mpconfig.h"
+#include "nlr.h"
+#include "misc.h"
+#include "qstr.h"
+#include "obj.h"
+#include "runtime.h"
+#include MICROPY_HAL_H
+#include "pin.h"
+
+// Returns the pin mode. This value returned by this macro should be one of:
+// GPIO_MODE_INPUT, GPIO_MODE_OUTPUT_PP, GPIO_MODE_OUTPUT_OD,
+// GPIO_MODE_AF_PP, GPIO_MODE_AF_OD, or GPIO_MODE_ANALOG.
+
+uint32_t pin_get_mode(const pin_obj_t *pin) {
+ volatile uint32_t *port_pcr = GPIO_PIN_TO_PORT_PCR(pin->gpio, pin->pin);
+ uint32_t pcr = *port_pcr;
+ uint32_t af = (*port_pcr & PORT_PCR_MUX_MASK) >> 8;;
+
+ if (af == 0) {
+ return GPIO_MODE_ANALOG;
+ }
+ if (af == 1) {
+ if (pin->gpio->PDDR & (1 << pin->pin)) {
+ if (pcr & PORT_PCR_ODE) {
+ return GPIO_MODE_OUTPUT_OD;
+ }
+ return GPIO_MODE_OUTPUT_PP;
+ }
+ return GPIO_MODE_INPUT;
+ }
+
+ if (pcr & PORT_PCR_ODE) {
+ return GPIO_MODE_AF_OD;
+ }
+ return GPIO_MODE_AF_PP;
+}
+
+// Returns the pin pullup/pulldown. The value returned by this macro should
+// be one of GPIO_NOPULL, GPIO_PULLUP, or GPIO_PULLDOWN.
+
+uint32_t pin_get_pull(const pin_obj_t *pin) {
+ volatile uint32_t *port_pcr = GPIO_PIN_TO_PORT_PCR(pin->gpio, pin->pin);
+
+ uint32_t pcr = *port_pcr;
+ if (pcr & PORT_PCR_PE) {
+ if (pcr & PORT_PCR_PS) {
+ return GPIO_PULLUP;
+ }
+ return GPIO_PULLDOWN;
+ }
+ return GPIO_NOPULL;
+}
+
+// Returns the af (alternate function) index currently set for a pin.
+
+uint32_t pin_get_af(const pin_obj_t *pin) {
+ volatile uint32_t *port_pcr = GPIO_PIN_TO_PORT_PCR(pin->gpio, pin->pin);
+ return (*port_pcr & PORT_PCR_MUX_MASK) >> 8;
+}
diff --git a/teensy/pin_defs_teensy.h b/teensy/pin_defs_teensy.h
index 66942c2ea..70fd47d8f 100644
--- a/teensy/pin_defs_teensy.h
+++ b/teensy/pin_defs_teensy.h
@@ -43,4 +43,3 @@ enum {
SPI_TypeDef *SPI;
typedef GPIO_TypeDef pin_gpio_t;
-
diff --git a/teensy/qstrdefsport.h b/teensy/qstrdefsport.h
index 2fb70af7b..bdafd1428 100644
--- a/teensy/qstrdefsport.h
+++ b/teensy/qstrdefsport.h
@@ -62,13 +62,21 @@ Q(value)
Q(low)
Q(high)
Q(name)
+Q(names)
+Q(af)
+Q(af_list)
Q(port)
Q(pin)
+Q(gpio)
Q(mapper)
Q(dict)
Q(debug)
Q(board)
Q(cpu)
+Q(mode)
+Q(pull)
+Q(index)
+Q(reg)
Q(IN)
Q(OUT_PP)
Q(OUT_OD)
diff --git a/teensy/teensy_hal.h b/teensy/teensy_hal.h
index ff16c98c5..9c9e62842 100644
--- a/teensy/teensy_hal.h
+++ b/teensy/teensy_hal.h
@@ -81,6 +81,7 @@ typedef struct {
#define GPIO_SPEED_FAST ((uint32_t)2)
#define GPIO_SPEED_HIGH ((uint32_t)3)
+#define IS_GPIO_AF(af) ((af) >= 0 && (af) <= 7)
typedef struct {
uint32_t Pin;
@@ -96,6 +97,22 @@ typedef struct {
#define GPIO_PIN_TO_PORT_PCR(GPIOx, pin) \
(&PORTA_PCR0 + GPIO_PORT_TO_PORT_NUM(GPIOx) * 32 + (pin))
+#define GPIO_AF2_I2C0 2
+#define GPIO_AF2_I2C1 2
+#define GPIO_AF2_SPI0 2
+#define GPIO_AF3_FTM0 3
+#define GPIO_AF3_FTM1 3
+#define GPIO_AF3_FTM2 3
+#define GPIO_AF3_UART0 3
+#define GPIO_AF3_UART1 3
+#define GPIO_AF3_UART2 3
+#define GPIO_AF4_FTM0 4
+#define GPIO_AF6_FTM1 6
+#define GPIO_AF6_FTM2 6
+#define GPIO_AF6_I2C1 6
+#define GPIO_AF7_FTM1 7
+
+
__attribute__(( always_inline )) static inline void __WFI(void)
{
__asm volatile ("wfi");
@@ -109,3 +126,4 @@ void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *init);
#define GPIO_read_pin(gpio, pin) (((gpio)->PDIR >> (pin)) & 1)
#define GPIO_set_pin(gpio, pin_mask) (((gpio)->PSOR) = (pin_mask))
#define GPIO_clear_pin(gpio, pin_mask) (((gpio)->PCOR) = (pin_mask))
+#define GPIO_read_output_pin(gpio, pin) (((gpio)->PDOR >> (pin)) & 1)