diff options
author | Dave Hylands <dhylands@gmail.com> | 2014-07-22 07:57:36 -0700 |
---|---|---|
committer | Dave Hylands <dhylands@gmail.com> | 2014-08-07 23:15:41 -0700 |
commit | 6f418fc1b068c1a41113bb2b019a5803765e1deb (patch) | |
tree | 79477835459eb424012f58d77a150bdf9a80eed5 /teensy | |
parent | 3ef911345c94a6d612ab50c1e912e81cb2cc3f71 (diff) | |
download | micropython-6f418fc1b068c1a41113bb2b019a5803765e1deb.tar.gz micropython-6f418fc1b068c1a41113bb2b019a5803765e1deb.zip |
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())))
```
Diffstat (limited to 'teensy')
-rw-r--r-- | teensy/Makefile | 9 | ||||
-rw-r--r-- | teensy/hal_gpio.c | 15 | ||||
-rw-r--r-- | teensy/main.c | 4 | ||||
-rwxr-xr-x | teensy/make-pins.py | 67 | ||||
-rw-r--r-- | teensy/memzip_files/boot.py | 10 | ||||
-rw-r--r-- | teensy/mk20dx256-prefix.c | 3 | ||||
-rw-r--r-- | teensy/pin_defs_teensy.c | 61 | ||||
-rw-r--r-- | teensy/pin_defs_teensy.h | 1 | ||||
-rw-r--r-- | teensy/qstrdefsport.h | 8 | ||||
-rw-r--r-- | teensy/teensy_hal.h | 18 |
10 files changed, 181 insertions, 15 deletions
diff --git a/teensy/Makefile b/teensy/Makefile index 54e6ef050e..5b8e266219 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 0811f76fda..218560e29b 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 53f500d571..8de26f25e8 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 1fd05ec207..6df1e4162b 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 4702d7b5d3..6dd5516a97 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 2485dc01ab..048b64316a 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 0000000000..dd2f0dc21f --- /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 66942c2ea8..70fd47d8fd 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 2fb70af7b4..bdafd14286 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 ff16c98c5c..9c9e628424 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) |