From 51dabac0961165cd38cdd0ba227aaf014190091c Mon Sep 17 00:00:00 2001 From: Dave Hylands Date: Mon, 17 Feb 2014 17:57:13 -0800 Subject: [PATCH] Add pin mapping code. This commit also introduces board directories and moves board specific config into the appropriate board directory. boards/stm32f4xx-af.csv was extracted from the STM32F4xx datasheet and hand-tweaked. make-pins.py takes boards/stm32f4xx-af.csv, boards/stm32f4xx-prefix.c, and boards/BOARD-NAME/pins.csv as input and generates the file build/pins_BOARD_NAME.c The generated pin file for PYBOARD4 looks like this: https://gist.github.com/dhylands/9063231 The generated pins file includes all of the supported alternate functions, and includes upsupported alternate functions as comments. See the commnet block at the top of stm/pin_map.c for details on how to use the pin mapper. I also went ahead and modified stm/gpio.c to use the pin mapper. --- py/objfun.c | 20 +- py/runtime.h | 2 + stm/Makefile | 19 ++ stm/boards/NETDUINO_PLUS_2/mpconfigboard.h | 48 ++++ stm/boards/NETDUINO_PLUS_2/pins.csv | 28 +++ stm/boards/PYBOARD3/mpconfigboard.h | 42 ++++ stm/boards/PYBOARD3/pins.csv | 37 ++++ stm/boards/PYBOARD4/mpconfigboard.h | 42 ++++ stm/boards/PYBOARD4/pins.csv | 45 ++++ stm/boards/STM32F4DISC/mpconfigboard.h | 43 ++++ stm/boards/STM32F4DISC/pins.csv | 85 ++++++++ stm/boards/make-pins.py | 241 +++++++++++++++++++++ stm/boards/stm32f4xx-af.csv | 142 ++++++++++++ stm/boards/stm32f4xx-prefix.c | 34 +++ stm/gpio.c | 59 ++--- stm/main.c | 2 + stm/mpconfigport.h | 181 +--------------- stm/pin.c | 62 ++++++ stm/pin.h | 117 ++++++++++ stm/pin_map.c | 228 +++++++++++++++++++ stm/pin_named_pins.c | 67 ++++++ stm/qstrdefsport.h | 4 + 22 files changed, 1318 insertions(+), 230 deletions(-) create mode 100644 stm/boards/NETDUINO_PLUS_2/mpconfigboard.h create mode 100644 stm/boards/NETDUINO_PLUS_2/pins.csv create mode 100644 stm/boards/PYBOARD3/mpconfigboard.h create mode 100644 stm/boards/PYBOARD3/pins.csv create mode 100644 stm/boards/PYBOARD4/mpconfigboard.h create mode 100644 stm/boards/PYBOARD4/pins.csv create mode 100644 stm/boards/STM32F4DISC/mpconfigboard.h create mode 100644 stm/boards/STM32F4DISC/pins.csv create mode 100755 stm/boards/make-pins.py create mode 100644 stm/boards/stm32f4xx-af.csv create mode 100644 stm/boards/stm32f4xx-prefix.c create mode 100644 stm/pin.c create mode 100644 stm/pin.h create mode 100644 stm/pin_map.c create mode 100644 stm/pin_named_pins.c diff --git a/py/objfun.c b/py/objfun.c index 354d7ff9ca..7c89c47000 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -26,26 +26,30 @@ // mp_obj_fun_native_t defined in obj.h STATIC void check_nargs(mp_obj_fun_native_t *self, int n_args, int n_kw) { - if (n_kw && !self->is_kw) { + rt_check_nargs(n_args, self->n_args_min, self->n_args_max, n_kw, self->is_kw); +} + +void rt_check_nargs(int n_args, machine_uint_t n_args_min, machine_uint_t n_args_max, int n_kw, bool is_kw) { + if (n_kw && !is_kw) { nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "function does not take keyword arguments")); } - if (self->n_args_min == self->n_args_max) { - if (n_args != self->n_args_min) { + if (n_args_min == n_args_max) { + if (n_args != n_args_min) { nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function takes %d positional arguments but %d were given", - self->n_args_min, n_args)); + n_args_min, n_args)); } } else { - if (n_args < self->n_args_min) { + if (n_args < n_args_min) { nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "() missing %d required positional arguments: ", - self->n_args_min - n_args)); - } else if (n_args > self->n_args_max) { + n_args_min - n_args)); + } else if (n_args > n_args_max) { nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, " expected at most %d arguments, got %d", - self->n_args_max, n_args)); + n_args_max, n_args)); } } } diff --git a/py/runtime.h b/py/runtime.h index 1eef99d2ff..7215cc8890 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -1,3 +1,5 @@ +void rt_check_nargs(int n_args, machine_uint_t n_args_min, machine_uint_t n_args_max, int n_kw, bool is_kw); + int rt_is_true(mp_obj_t arg); mp_obj_t rt_load_const_dec(qstr qstr); diff --git a/stm/Makefile b/stm/Makefile index e2adddbfd9..14b690fc05 100644 --- a/stm/Makefile +++ b/stm/Makefile @@ -24,6 +24,9 @@ CFLAGS += -I$(STMUSBH_DIR) CFLAGS += -I$(FATFS_DIR) #CFLAGS += -I$(CC3K_DIR) +BOARD ?= PYBOARD4 +CFLAGS += -Iboards/$(BOARD) + #Debugging/Optimization ifeq ($(DEBUG), 1) CFLAGS += -g @@ -68,6 +71,9 @@ SRC_C = \ adc.c \ rtc.c \ file.c \ + pin.c \ + pin_named_pins.c \ + pin_map.c \ # pybwlan.c \ SRC_S = \ @@ -155,6 +161,7 @@ OBJ += $(addprefix $(BUILD)/, $(SRC_STMUSBD:.c=.o)) #OBJ += $(addprefix $(BUILD)/, $(SRC_STMUSBH:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_FATFS:.c=.o)) #OBJ += $(addprefix $(BUILD)/, $(SRC_CC3K:.c=.o)) +OBJ += $(BUILD)/pins_$(BOARD).o all: $(BUILD)/flash.dfu @@ -173,4 +180,16 @@ $(BUILD)/flash.elf: $(OBJ) $(Q)$(LD) $(LDFLAGS) -o $@ $(OBJ) $(LIBS) $(Q)$(SIZE) $@ +MAKE_PINS = boards/make-pins.py +BOARD_PINS = boards/$(BOARD)/pins.csv +AF_FILE = boards/stm32f4xx-af.csv +PREFIX_FILE = boards/stm32f4xx-prefix.c + +$(BUILD)/pins_$(BOARD).c: $(MAKE_PINS) $(BOARD_PINS) $(AF_FILE) $(PREFIX_FILE) + $(ECHO) "Create $@" + $(Q)python $(MAKE_PINS) --board $(BOARD_PINS) --af $(AF_FILE) --prefix $(PREFIX_FILE) > $@ + +$(BUILD)/pins_$(BOARD).o: $(BUILD)/pins_$(BOARD).c + $(call compile_c) + include ../py/mkrules.mk diff --git a/stm/boards/NETDUINO_PLUS_2/mpconfigboard.h b/stm/boards/NETDUINO_PLUS_2/mpconfigboard.h new file mode 100644 index 0000000000..9c407d9cd4 --- /dev/null +++ b/stm/boards/NETDUINO_PLUS_2/mpconfigboard.h @@ -0,0 +1,48 @@ +#define NETDUINO_PLUS_2 + +#define MICROPY_HW_BOARD_NAME "NetduinoPlus2" + +#define MICROPY_HW_HAS_SWITCH (1) + +// On the netuino, the sdcard appears to be wired up as a 1-bit +// SPI, so the driver needs to be converted to support that before +// we can turn this on. +#define MICROPY_HW_HAS_SDCARD (0) +#define MICROPY_HW_HAS_MMA7660 (0) +#define MICROPY_HW_HAS_LIS3DSH (0) +#define MICROPY_HW_HAS_LCD (0) +#define MICROPY_HW_HAS_WLAN (0) +#define MICROPY_HW_ENABLE_RNG (1) +#define MICROPY_HW_ENABLE_RTC (0) +#define MICROPY_HW_ENABLE_TIMER (1) +#define MICROPY_HW_ENABLE_SERVO (1) +#define MICROPY_HW_ENABLE_AUDIO (0) + +#define USRSW_PORT (GPIOB) +#define USRSW_PIN (GPIO_Pin_11) +#define USRSW_PUPD (GPIO_PuPd_NOPULL) +#define USRSW_EXTI_PIN (EXTI_PinSource11) +#define USRSW_EXTI_PORT (EXTI_PortSourceGPIOB) +#define USRSW_EXTI_LINE (EXTI_Line11) +#define USRSW_EXTI_IRQN (EXTI15_10_IRQn) +#define USRSW_EXTI_EDGE (EXTI_Trigger_Rising) + +/* LED */ +#define PYB_LED1_PORT (GPIOA) // Blue LED +#define PYB_LED1_PIN (GPIO_Pin_10) + +#define PYB_LED2_PORT (GPIOC) // White LED (aka Power) +#define PYB_LED2_PIN (GPIO_Pin_13) + +#define PYB_LED3_PORT (GPIOA) // Same as Led(1) +#define PYB_LED3_PIN (GPIO_Pin_10) + +#define PYB_LED4_PORT (GPIOC) // Same as Led(2) +#define PYB_LED4_PIN (GPIO_Pin_13) + +#define PYB_OTYPE (GPIO_OType_PP) + +#define PYB_LED_ON(port, pin) (port->BSRRL = pin) +#define PYB_LED_OFF(port, pin) (port->BSRRH = pin) + +#define HSE_VALUE (25000000) diff --git a/stm/boards/NETDUINO_PLUS_2/pins.csv b/stm/boards/NETDUINO_PLUS_2/pins.csv new file mode 100644 index 0000000000..f9b94a6c87 --- /dev/null +++ b/stm/boards/NETDUINO_PLUS_2/pins.csv @@ -0,0 +1,28 @@ +D0,PC7 +D1,PC6 +D2,PA3 +D3,PA2 +D4,PB12 +D5,PB8 +D6,PB9 +D7,PA1 +D8,PA0 +D9,PA6 +D10,PB10 +D11,PB15 +D12,PB14 +D13,PB13 +A0,PC0 +A1,PC1 +A2,PC2 +A3,PC3 +A4,PC4 +A5,PC5 +LED,PA10 +SW,PB11 +PWR_LED,PC13 +PWR_SD,PB1 +PWR_HDR,PB2 +PWR_ETH,PC15 +RST_ETH,PD2 + diff --git a/stm/boards/PYBOARD3/mpconfigboard.h b/stm/boards/PYBOARD3/mpconfigboard.h new file mode 100644 index 0000000000..1632445741 --- /dev/null +++ b/stm/boards/PYBOARD3/mpconfigboard.h @@ -0,0 +1,42 @@ +#define PYBOARD3 + +#define MICROPY_HW_BOARD_NAME "PYBv3" + +#define MICROPY_HW_HAS_SWITCH (1) +#define MICROPY_HW_HAS_SDCARD (1) +#define MICROPY_HW_HAS_MMA7660 (1) +#define MICROPY_HW_HAS_LIS3DSH (0) +#define MICROPY_HW_HAS_LCD (0) +#define MICROPY_HW_HAS_WLAN (0) +#define MICROPY_HW_ENABLE_RNG (1) +#define MICROPY_HW_ENABLE_RTC (1) +#define MICROPY_HW_ENABLE_TIMER (1) +#define MICROPY_HW_ENABLE_SERVO (1) +#define MICROPY_HW_ENABLE_AUDIO (0) + +#define USRSW_PORT (GPIOA) +#define USRSW_PIN (GPIO_Pin_13) +#define USRSW_PUPD (GPIO_PuPd_UP) +#define USRSW_EXTI_PIN (EXTI_PinSource13) +#define USRSW_EXTI_PORT (EXTI_PortSourceGPIOA) +#define USRSW_EXTI_LINE (EXTI_Line13) +#define USRSW_EXTI_IRQN (EXTI15_10_IRQn) +#define USRSW_EXTI_EDGE (EXTI_Trigger_Rising) + +/* LED */ +#define PYB_LED1_PORT (GPIOA) +#define PYB_LED1_PIN (GPIO_Pin_8) + +#define PYB_LED2_PORT (GPIOA) +#define PYB_LED2_PIN (GPIO_Pin_10) + +#define PYB_LED3_PORT (GPIOC) +#define PYB_LED3_PIN (GPIO_Pin_4) + +#define PYB_LED4_PORT (GPIOC) +#define PYB_LED4_PIN (GPIO_Pin_5) + +#define PYB_OTYPE (GPIO_OType_OD) + +#define PYB_LED_ON(port, pin) (port->BSRRH = pin) +#define PYB_LED_OFF(port, pin) (port->BSRRL = pin) diff --git a/stm/boards/PYBOARD3/pins.csv b/stm/boards/PYBOARD3/pins.csv new file mode 100644 index 0000000000..cc07b15445 --- /dev/null +++ b/stm/boards/PYBOARD3/pins.csv @@ -0,0 +1,37 @@ +B13,PB13 +B14,PB14 +B15,PB15 +C6,PC6 +C7,PC7 +A13,PA13 +A14,PA14 +A15,PA15 +B3,PB3 +B4,PB4 +B6,PB6 +B7,PB7 +B8,PB8 +B9,PB9 +C0,PC0 +C1,PC1 +C2,PC2 +C3,PC3 +A0,PA0 +A1,PA1 +A2,PA2 +A3,PA3 +A4,PA4 +A5,PA5 +A6,PA6 +A7,PA7 +B0,PB0 +B1,PB1 +B10,PB10 +B11,PB11 +B12,PB12 +LED_R1,PA8 +LED_R2,PA10 +LED_G1,PC4 +LED_G2,PC5 +SW,PA13 + diff --git a/stm/boards/PYBOARD4/mpconfigboard.h b/stm/boards/PYBOARD4/mpconfigboard.h new file mode 100644 index 0000000000..3cb00b4027 --- /dev/null +++ b/stm/boards/PYBOARD4/mpconfigboard.h @@ -0,0 +1,42 @@ +#define PYBOARD4 + +#define MICROPY_HW_BOARD_NAME "PYBv4" + +#define MICROPY_HW_HAS_SWITCH (1) +#define MICROPY_HW_HAS_SDCARD (1) +#define MICROPY_HW_HAS_MMA7660 (1) +#define MICROPY_HW_HAS_LIS3DSH (0) +#define MICROPY_HW_HAS_LCD (1) +#define MICROPY_HW_HAS_WLAN (0) +#define MICROPY_HW_ENABLE_RNG (1) +#define MICROPY_HW_ENABLE_RTC (1) +#define MICROPY_HW_ENABLE_TIMER (1) +#define MICROPY_HW_ENABLE_SERVO (1) +#define MICROPY_HW_ENABLE_AUDIO (0) + +#define USRSW_PORT (GPIOB) +#define USRSW_PIN (GPIO_Pin_3) +#define USRSW_PUPD (GPIO_PuPd_UP) +#define USRSW_EXTI_PIN (EXTI_PinSource3) +#define USRSW_EXTI_PORT (EXTI_PortSourceGPIOB) +#define USRSW_EXTI_LINE (EXTI_Line3) +#define USRSW_EXTI_IRQN (EXTI3_IRQn) +#define USRSW_EXTI_EDGE (EXTI_Trigger_Rising) + +/* LED */ +#define PYB_LED1_PORT (GPIOA) +#define PYB_LED1_PIN (GPIO_Pin_13) + +#define PYB_LED2_PORT (GPIOA) +#define PYB_LED2_PIN (GPIO_Pin_14) + +#define PYB_LED3_PORT (GPIOA) +#define PYB_LED3_PIN (GPIO_Pin_15) + +#define PYB_LED4_PORT (GPIOB) +#define PYB_LED4_PIN (GPIO_Pin_4) + +#define PYB_OTYPE (GPIO_OType_PP) + +#define PYB_LED_ON(port, pin) (port->BSRRL = pin) +#define PYB_LED_OFF(port, pin) (port->BSRRH = pin) diff --git a/stm/boards/PYBOARD4/pins.csv b/stm/boards/PYBOARD4/pins.csv new file mode 100644 index 0000000000..44166bf7a8 --- /dev/null +++ b/stm/boards/PYBOARD4/pins.csv @@ -0,0 +1,45 @@ +X1,PB6 +X2,PB7 +X3,PC4 +X4,PB5 +X5,Reset +X6,GND +X7,3.3V +X8,VIN +X9,PA0 +X10,PA1 +X11,PA2 +X12,PA3 +X13,PA4 +X14,PA5 +X15,PA6 +X16,PA7 +X17,PB3 +X18,PC13 +X19,PC0 +X20,PC1 +X21,PC2 +X22,PC3 +X23,A3.3V +X24,AGND +Y1,PB10 +Y2,PB11 +Y3,PB0 +Y4,PB1 +Y5,Reset +Y6,GND +Y7,3.3V +Y8,VIN +Y9,PC6 +Y10,PC7 +Y11,PB8 +Y12,PB9 +Y13,PB12 +Y14,PB13 +Y15,PB14 +Y16,PB15 +LED_BLUE,PB4 +LED_RED,PA13 +LED_GREEN,PA14 +LED_YELLOW,PA15 +SW,PB3 diff --git a/stm/boards/STM32F4DISC/mpconfigboard.h b/stm/boards/STM32F4DISC/mpconfigboard.h new file mode 100644 index 0000000000..2708504cb0 --- /dev/null +++ b/stm/boards/STM32F4DISC/mpconfigboard.h @@ -0,0 +1,43 @@ +#define STM32F4DISC + +#define MICROPY_HW_BOARD_NAME "F4DISC" + +#define MICROPY_HW_HAS_SWITCH (1) +#define MICROPY_HW_HAS_SDCARD (0) +#define MICROPY_HW_HAS_MMA7660 (0) +#define MICROPY_HW_HAS_LIS3DSH (1) +#define MICROPY_HW_HAS_LCD (0) +#define MICROPY_HW_HAS_WLAN (0) +#define MICROPY_HW_ENABLE_RNG (1) +#define MICROPY_HW_ENABLE_RTC (1) +#define MICROPY_HW_ENABLE_TIMER (1) +#define MICROPY_HW_ENABLE_SERVO (0) +#define MICROPY_HW_ENABLE_AUDIO (0) + +#define USRSW_PORT (GPIOA) +#define USRSW_PIN (GPIO_Pin_0) +#define USRSW_PUPD (GPIO_PuPd_NOPULL) +#define USRSW_EXTI_PIN (EXTI_PinSource0) +#define USRSW_EXTI_PORT (EXTI_PortSourceGPIOA) +#define USRSW_EXTI_LINE (EXTI_Line0) +#define USRSW_EXTI_IRQN (EXTI0_IRQn) +#define USRSW_EXTI_EDGE (EXTI_Trigger_Falling) + +/* LED */ +#define PYB_LED1_PORT (GPIOD) +#define PYB_LED1_PIN (GPIO_Pin_14) + +#define PYB_LED2_PORT (GPIOD) +#define PYB_LED2_PIN (GPIO_Pin_12) + +#define PYB_LED3_PORT (GPIOD) +#define PYB_LED3_PIN (GPIO_Pin_15) + +#define PYB_LED4_PORT (GPIOD) +#define PYB_LED4_PIN (GPIO_Pin_13) + +#define PYB_OTYPE (GPIO_OType_PP) + +#define PYB_LED_ON(port, pin) (port->BSRRL = pin) +#define PYB_LED_OFF(port, pin) (port->BSRRH = pin) + diff --git a/stm/boards/STM32F4DISC/pins.csv b/stm/boards/STM32F4DISC/pins.csv new file mode 100644 index 0000000000..4049fef7d9 --- /dev/null +++ b/stm/boards/STM32F4DISC/pins.csv @@ -0,0 +1,85 @@ +PC0,PC0 +PC1,PC1 +PC2,PC2 +PC3,PC3 +PA0,PA0 +PA1,PA1 +PA2,PA2 +PA3,PA3 +PA4,PA4 +PA5,PA5 +PA6,PA6 +PA7,PA7 +PC4,PC4 +PC5,PC5 +PB0,PB0 +PB1,PB1 +PB2,PB2 +PE7,PE7 +PE8,PE8 +PE9,PE9 +PE10,PE10 +PE11,PE11 +PE12,PE12 +PE13,PE13 +PE14,PE14 +PE15,PE15 +PB10,PB10 +PB11,PB11 +PB12,PB12 +PB13,PB13 +PB14,PB14 +PB15,PB15 +PD8,PD8 +PD9,PD9 +PD10,PD10 +PD11,PD11 +PD12,PD12 +PD13,PD13 +PD14,PD14 +PD15,PD15 +PC6,PC6 +PC7,PC7 +PC8,PC8 +PC9,PC9 +PA8,PA8 +PA9,PA9 +PA10,PA10 +PA13,PA13 +PA14,PA14 +PA15,PA15 +PC10,PC10 +PC11,PC11 +PC12,PC12 +PD0,PD0 +PD1,PD1 +PD2,PD2 +PD3,PD3 +PD4,PD4 +PD5,PD5 +PD6,PD6 +PD7,PD7 +PB4,PB4 +PB5,PB5 +PB6,PB6 +PB7,PB7 +PB8,PB8 +PB9,PB9 +PE0,PE0 +PE1,PE1 +PE2,PE2 +PE3,PE3 +PE4,PE4 +PE5,PE5 +PE6,PE6 +PC13,PC13 +PC14,PC14 +PC15,PC15 +PH0,PH0 +PH1,PH1 +LED_GREEN,PD12 +LED_ORANGE,PD13 +LED_RED,PD14 +LED_BLUE,PD15 +SW,PA0 + diff --git a/stm/boards/make-pins.py b/stm/boards/make-pins.py new file mode 100755 index 0000000000..0bc9118b08 --- /dev/null +++ b/stm/boards/make-pins.py @@ -0,0 +1,241 @@ +#!/usr/bin/env python +"""Creates the pin file for the STM32F4xx.""" + +from __future__ import print_function + +import argparse +import sys +import csv + +SUPPORTED_FN = { + 'TIM' : ['CH1', 'CH2', 'CH3', 'CH4', + 'CH1N', 'CH2N', 'CH3N', 'CH1_ETR', 'ETR', 'BKIN'], + 'I2C' : ['SDA', 'SCL'], + 'USART' : ['RX', 'TX', 'CTS', 'RTS', 'CK'], + 'UART' : ['RX', 'TX', 'CTS', 'RTS'], + 'SPI' : ['NSS', 'SCK', 'MISO', 'MOSI'] +} + +def parse_port_pin(name_str): + """Parses a string and returns a (port-num, pin-num) tuple.""" + if len(name_str) < 3: + raise ValueError("Expecting pin name to be at least 3 charcters.") + if name_str[0] != 'P': + raise ValueError("Expecting pin name to start with P") + if name_str[1] < 'A' or name_str[1] > 'J': + raise ValueError("Expecting pin port to be between A and J") + port = ord(name_str[1]) - ord('A') + pin_str = name_str[2:] + if not pin_str.isdigit(): + raise ValueError("Expecting numeric pin number.") + return (port, int(pin_str)) + +def split_name_num(name_num): + num = None + for num_idx in range(len(name_num) - 1, -1, -1): + if not name_num[num_idx].isdigit(): + name = name_num[0:num_idx + 1] + num_str = name_num[num_idx + 1:] + if len(num_str) > 0: + num = int(num_str) + break + return name, num + + +class AlternateFunction(object): + """Holds the information associated with a pins alternate function.""" + + def __init__(self, idx, af_str): + self.idx = idx + self.af_str = af_str + + self.func = '' + self.fn_num = None + self.pin_type = '' + self.supported = False + + af_words = af_str.split('_', 1) + self.func, self.fn_num = split_name_num(af_words[0]) + if len(af_words) > 1: + self.pin_type = af_words[1] + if self.func in SUPPORTED_FN: + pin_types = SUPPORTED_FN[self.func] + if self.pin_type in pin_types: + self.supported = True + + def is_supported(self): + return self.supported + + def ptr(self): + """Returns the numbered function (i.e. USART6) for this AF.""" + if self.fn_num is None: + return self.func + return '{:s}{:d}'.format(self.func, self.fn_num) + + def print(self): + """Prints the C representation of this AF.""" + if self.supported: + print(' AF', end='') + else: + print(' //', end='') + fn_num = self.fn_num + if fn_num is None: + fn_num = 0 + print('({:2d}, {:8s}, {:2d}, {:10s}, {:8s}), // {:s}'.format(self.idx, + self.func, fn_num, self.pin_type, self.ptr(), self.af_str)) + + +class Pin(object): + """Holds the information associated with a pin.""" + + def __init__(self, port, pin): + self.port = port + self.pin = pin + self.alt_fn = [] + self.board_name = None + self.alt_fn_count = 0 + + def port_letter(self): + return chr(self.port + ord('A')) + + def pin_name(self): + return '{:s}{:d}'.format(self.port_letter(), self.pin) + + def parse_af(self, af_idx, af_strs_in): + if len(af_strs_in) == 0: + return + # If there is a slash, then the slash separates 2 aliases for the + # same alternate function. + af_strs = af_strs_in.split('/') + for af_str in af_strs: + alt_fn = AlternateFunction(af_idx, af_str) + self.alt_fn.append(alt_fn) + if alt_fn.is_supported(): + self.alt_fn_count += 1 + + def alt_fn_name(self): + if self.alt_fn_count > 0: + return 'pin_{:s}_af'.format(self.pin_name()) + return 'NULL' + + def print(self): + if self.alt_fn_count == 0: + print("// ", end='') + print('const pin_af_obj_t {:s}[] = {{'.format(self.alt_fn_name())) + for alt_fn in self.alt_fn: + alt_fn.print() + if self.alt_fn_count == 0: + print("// ", end='') + print('};') + print('') + print('const pin_obj_t pin_{:s} = PIN({:s}, {:d}, {:d}, {:s});'.format( + self.pin_name(), self.port_letter(), self.pin, + self.alt_fn_count, self.alt_fn_name())) + print('') + + +class Pins(object): + + def __init__(self): + self.pins = [] + self.board_pins = [] + + def find_pin(self, port_num, pin_num): + for pin in self.pins: + if pin.port == port_num and pin.pin == pin_num: + return pin + + def parse_af_file(self, filename, pinname_col, af_col): + with open(filename, 'r') as csvfile: + rows = csv.reader(csvfile) + for row in rows: + try: + (port_num, pin_num) = parse_port_pin(row[pinname_col]) + except: + continue + pin = Pin(port_num, pin_num) + for af_idx in range(af_col, len(row)): + pin.parse_af(af_idx - af_col, row[af_idx]) + self.pins.append(pin) + + def parse_board_file(self, filename): + with open(filename, 'r') as csvfile: + rows = csv.reader(csvfile) + for row in rows: + try: + (port_num, pin_num) = parse_port_pin(row[1]) + except: + continue + pin = self.find_pin(port_num, pin_num) + if pin: + pin.board_name = row[0] + self.board_pins.append(pin) + + def print_named(self, label, pins): + print('const pin_named_pin_t pin_{:s}_pins[] = {{'.format(label)) + for pin in pins: + if pin.board_name: + if label == 'board': + pin_name = pin.board_name + else: + pin_name = pin.pin_name() + print(' {{ "{:s}", &pin_{:s} }},'.format(pin_name, pin.pin_name())) + print(' { NULL, NULL }') + print('};') + + def print(self): + for pin in self.pins: + if pin.board_name: + pin.print() + self.print_named('cpu', self.pins) + print('') + self.print_named('board', self.board_pins) + + +def main(): + parser = argparse.ArgumentParser( + prog="make-pins.py", + usage="%(prog)s [options] [command]", + description="Generate board specific pin file" + ) + parser.add_argument( + "-a", "--af", + dest="af_filename", + help="Specifies the alternate function file for the chip", + default="stm32f4xx-af.csv" + ) + parser.add_argument( + "-b", "--board", + dest="board_filename", + help="Specifies the board file", + ) + parser.add_argument( + "-p", "--prefix", + dest="prefix_filename", + help="Specifies beginning portion of generated pins file", + default="stm32f4xx-prefix.c" + ) + args = parser.parse_args(sys.argv[1:]) + + pins = Pins() + + print('// This file was automatically generated by make-pins.py') + print('//') + if args.af_filename: + print('// --af {:s}'.format(args.af_filename)) + pins.parse_af_file(args.af_filename, 1, 2) + + if args.board_filename: + print('// --board {:s}'.format(args.board_filename)) + pins.parse_board_file(args.board_filename) + + if args.prefix_filename: + print('// --prefix {:s}'.format(args.prefix_filename)) + print('') + with open(args.prefix_filename, 'r') as prefix_file: + print(prefix_file.read()) + pins.print() + + +if __name__ == "__main__": + main() diff --git a/stm/boards/stm32f4xx-af.csv b/stm/boards/stm32f4xx-af.csv new file mode 100644 index 0000000000..fde7fcfc11 --- /dev/null +++ b/stm/boards/stm32f4xx-af.csv @@ -0,0 +1,142 @@ +Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15 +,,SYS,TIM1/2,TIM3/4/5,TIM8/9/10/11,I2C1/2/3,SPI1/SPI2/I2S2/I2S2ext,SPI3/I2Sext/I2S3,USART1/2/3/I2S3ext,UART4/5/USART6,CAN1/CAN2/TIM12/13/14,OTG_FS/OTG_HS,ETH,FSMC/SDIO/OTG_FS,DCMI,, +PortA,PA0,,TIM2_CH1_ETR,TIM5_CH1,TIM8_ETR,,,,USART2_CTS,UART4_TX,,,ETH_MII_CRS,,,,EVENTOUT +PortA,PA1,,TIM2_CH2,TIM5_CH2,,,,,USART2_RTS,UART4_RX,,,ETH_MII_RX_CLK/ETH_RMII__REF_CLK,,,,EVENTOUT +PortA,PA2,,TIM2_CH3,TIM5_CH3,TIM9_CH1,,,,USART2_TX,,,,ETH_MDIO,,,,EVENTOUT +PortA,PA3,,TIM2_CH4,TIM5_CH4,TIM9_CH2,,,,USART2_RX,,,OTG_HS_ULPI_D0,ETH_MII_COL,,,,EVENTOUT +PortA,PA4,,,,,,SPI1_NSS,SPI3_NSS/I2S3_WS,USART2_CK,,,,,OTG_HS_SOF,DCMI_HSYNC,,EVENTOUT +PortA,PA5,,TIM2_CH1_ETR,,TIM8_CH1N,,SPI1_SCK,,,,,OTG_HS_ULPI_CK,,,,,EVENTOUT +PortA,PA6,,TIM1_BKIN,TIM3_CH1,TIM8_BKIN,,SPI1_MISO,,,,TIM13_CH1,,,,DCMI_PIXCK,,EVENTOUT +PortA,PA7,,TIM1_CH1N,TIM3_CH2,TIM8_CH1N,,SPI1_MOSI,,,,TIM14_CH1,,ETH_MII_RX_DV/ETH_RMII_CRS_DV,,,,EVENTOUT +PortA,PA8,MCO1,TIM1_CH1,,,I2C3_SCL,,,USART1_CK,,,OTG_FS_SOF,,,,,EVENTOUT +PortA,PA9,,TIM1_CH2,,,I2C3_SMBA,,,USART1_TX,,,,,,DCMI_D0,,EVENTOUT +PortA,PA10,,TIM1_CH3,,,,,,USART1_RX,,,OTG_FS_ID,,,DCMI_D1,,EVENTOUT +PortA,PA11,,TIM1_CH4,,,,,,USART1_CTS,,CAN1_RX,OTG_FS_DM,,,,,EVENTOUT +PortA,PA12,,TIM1_ETR,,,,,,USART1_RTS,,CAN1_TX,OTG_FS_DP,,,,,EVENTOUT +PortA,PA13,JTMS-SWDIO,,,,,,,,,,,,,,,EVENTOUT +PortA,PA14,JTCK-SWCLK,,,,,,,,,,,,,,,EVENTOUT +PortA,PA15,JTDI,TIM2_CH1/TIM2_ETR,,,,SPI1_NSS,SPI3_NSS/I2S3_WS,,,,,,,,,EVENTOUT +PortB,PB0,,TIM1_CH2N,TIM3_CH3,TIM8_CH2N,,,,,,,OTG_HS_ULPI_D1,ETH_MII_RXD2,,,,EVENTOUT +PortB,PB1,,TIM1_CH3N,TIM3_CH4,TIM8_CH3N,,,,,,,OTG_HS_ULPI_D2,ETH_MII_RXD3,,,,EVENTOUT +PortB,PB2,,,,,,,,,,,,,,,,EVENTOUT +PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK,SPI3_SCKI2S3_CK,,,,,,,,,EVENTOUT +PortB,PB4,NJTRST,,TIM3_CH1,,,SPI1_MISO,SPI3_MISO,I2S3ext_SD,,,,,,,,EVENTOUT +PortB,PB5,,,TIM3_CH2,,I2C1_SMBA,SPI1_MOSI,SPI3_MOSI/I2S3_SD,,,CAN2_RX,OTG_HS_ULPI_D7,ETH_PPS_OUT,,DCMI_D10,,EVENTOUT +PortB,PB6,,,TIM4_CH1,,I2C1_SCL,,,USART1_TX,,CAN2_TX,,,,DCMI_D5,,EVENTOUT +PortB,PB7,,,TIM4_CH2,,I2C1_SDA,,,USART1_RX,,,,,FSMC_NL,DCMI_VSYNC,,EVENTOUT +PortB,PB8,,,TIM4_CH3,TIM10_CH1,I2C1_SCL,,,,,CAN1_RX,,ETH_MII_TXD3,SDIO_D4,DCMI_D6,,EVENTOUT +PortB,PB9,,,TIM4_CH4,TIM11_CH1,I2C1_SDA,SPI2_NSS/I2S2_WS,,,,CAN1_TX,,,SDIO_D5,DCMI_D7,,EVENTOUT +PortB,PB10,,TIM2_CH3,,,I2C2_SCL,SPI2_SCKI2S2_CK,,USART3_TX,,,OTG_HS_ULPI_D3,ETH_MII_RX_ER,,,,EVENTOUT +PortB,PB11,,TIM2_CH4,,,I2C2_SDA,,,USART3_RX,,,OTG_HS_ULPI_D4,ETH_MII_TX_EN/ETH_RMII_TX_EN,,,,EVENTOUT +PortB,PB12,,TIM1_BKIN,,,I2C2_SMBA,SPI2_NSS/I2S2_WS,,USART3_CK,,CAN2_RX,OTG_HS_ULPI_D5,ETH_MII_TXD0/ETH_RMII_TXD0,OTG_HS_ID,,,EVENTOUT +PortB,PB13,,TIM1_CH1N,,,,SPI2_SCKI2S2_CK,,USART3_CTS,,CAN2_TX,OTG_HS_ULPI_D6,ETH_MII_TXD1/ETH_RMII_TXD1,,,,EVENTOUT +PortB,PB14,,TIM1_CH2N,,TIM8_CH2N,,SPI2_MISO,I2S2ext_SD,USART3_RTS,,TIM12_CH1,,,OTG_HS_DM,,,EVENTOUT +PortB,PB15,RTC_REFIN,TIM1_CH3N,,TIM8_CH3N,,SPI2_MOSI/I2S2_SD,,,,TIM12_CH2,,,OTG_HS_DP,,,EVENTOUT +PortC,PC0,,,,,,,,,,,OTG_HS_ULPI_STP,,,,,EVENTOUT +PortC,PC1,,,,,,,,,,,,ETH_MDC,,,,EVENTOUT +PortC,PC2,,,,,,SPI2_MISO,I2S2ext_SD,,,,OTG_HS_ULPI_DIR,ETH_MII_TXD2,,,,EVENTOUT +PortC,PC3,,,,,,SPI2_MOSI/I2S2_SD,,,,,OTG_HS_ULPI_NXT,ETH_MII_TX_CLK,,,,EVENTOUT +PortC,PC4,,,,,,,,,,,,ETH_MII_RXD0/ETH_RMII_RXD0,,,,EVENTOUT +PortC,PC5,,,,,,,,,,,,ETH_MII_RXD1/ETH_RMII_RXD1,,,,EVENTOUT +PortC,PC6,,,TIM3_CH1,TIM8_CH1,,I2S2_MCK,,,USART6_TX,,,,SDIO_D6,DCMI_D0,,EVENTOUT +PortC,PC7,,,TIM3_CH2,TIM8_CH2,,,I2S3_MCK,,USART6_RX,,,,SDIO_D7,DCMI_D1,,EVENTOUT +PortC,PC8,,,TIM3_CH3,TIM8_CH3,,,,,USART6_CK,,,,SDIO_D0,DCMI_D2,,EVENTOUT +PortC,PC9,MCO2,,TIM3_CH4,TIM8_CH4,I2C3_SDA,I2S_CKIN,,,,,,,SDIO_D1,DCMI_D3,,EVENTOUT +PortC,PC10,,,,,,,SPI3_SCK/I2S3_CK,USART3_TX,UART4_TX,,,,SDIO_D2,DCMI_D8,,EVENTOUT +PortC,PC11,,,,,,I2S3ext_SD,SPI3_MISO,USART3_RX,UART4_RX,,,,SDIO_D3,DCMI_D4,,EVENTOUT +PortC,PC12,,,,,,,SPI3_MOSI/I2S3_SD,USART3_CK,UART5_TX,,,,SDIO_CK,DCMI_D9,,EVENTOUT +PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT +PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT +PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT +PortD,PD0,,,,,,,,,,CAN1_RX,,,FSMC_D2,,,EVENTOUT +PortD,PD1,,,,,,,,,,CAN1_TX,,,FSMC_D3,,,EVENTOUT +PortD,PD2,,,TIM3_ETR,,,,,,UART5_RX,,,,SDIO_CMD,DCMI_D11,,EVENTOUT +PortD,PD3,,,,,,,,USART2_CTS,,,,,FSMC_CLK,,,EVENTOUT +PortD,PD4,,,,,,,,USART2_RTS,,,,,FSMC_NOE,,,EVENTOUT +PortD,PD5,,,,,,,,USART2_TX,,,,,FSMC_NWE,,,EVENTOUT +PortD,PD6,,,,,,,,USART2_RX,,,,,FSMC_NWAIT,,,EVENTOUT +PortD,PD7,,,,,,,,USART2_CK,,,,,FSMC_NE1/FSMC_NCE2,,,EVENTOUT +PortD,PD8,,,,,,,,USART3_TX,,,,,FSMC_D13,,,EVENTOUT +PortD,PD9,,,,,,,,USART3_RX,,,,,FSMC_D14,,,EVENTOUT +PortD,PD10,,,,,,,,USART3_CK,,,,,FSMC_D15,,,EVENTOUT +PortD,PD11,,,,,,,,USART3_CTS,,,,,FSMC_A16,,,EVENTOUT +PortD,PD12,,,TIM4_CH1,,,,,USART3_RTS,,,,,FSMC_A17,,,EVENTOUT +PortD,PD13,,,TIM4_CH2,,,,,,,,,,FSMC_A18,,,EVENTOUT +PortD,PD14,,,TIM4_CH3,,,,,,,,,,FSMC_D0,,,EVENTOUT +PortD,PD15,,,TIM4_CH4,,,,,,,,,,FSMC_D1,,,EVENTOUT +PortE,PE0,,,TIM4_ETR,,,,,,,,,,FSMC_NBL0,DCMI_D2,,EVENTOUT +PortE,PE1,,,,,,,,,,,,,FSMC_NBL1,DCMI_D3,,EVENTOUT +PortE,PE2,TRACECLK,,,,,,,,,,,ETH_MII_TXD3,FSMC_A23,,,EVENTOUT +PortE,PE3,TRACED0,,,,,,,,,,,,FSMC_A19,,,EVENTOUT +PortE,PE4,TRACED1,,,,,,,,,,,,FSMC_A20,DCMI_D4,,EVENTOUT +PortE,PE5,TRACED2,,,TIM9_CH1,,,,,,,,,FSMC_A21,DCMI_D6,,EVENTOUT +PortE,PE6,TRACED3,,,TIM9_CH2,,,,,,,,,FSMC_A22,DCMI_D7,,EVENTOUT +PortE,PE7,,TIM1_ETR,,,,,,,,,,,FSMC_D4,,,EVENTOUT +PortE,PE8,,TIM1_CH1N,,,,,,,,,,,FSMC_D5,,,EVENTOUT +PortE,PE9,,TIM1_CH1,,,,,,,,,,,FSMC_D6,,,EVENTOUT +PortE,PE10,,TIM1_CH2N,,,,,,,,,,,FSMC_D7,,,EVENTOUT +PortE,PE11,,TIM1_CH2,,,,,,,,,,,FSMC_D8,,,EVENTOUT +PortE,PE12,,TIM1_CH3N,,,,,,,,,,,FSMC_D9,,,EVENTOUT +PortE,PE13,,TIM1_CH3,,,,,,,,,,,FSMC_D10,,,EVENTOUT +PortE,PE14,,TIM1_CH4,,,,,,,,,,,FSMC_D11,,,EVENTOUT +PortE,PE15,,TIM1_BKIN,,,,,,,,,,,FSMC_D12,,,EVENTOUT +PortF,PF0,,,,,I2C2_SDA,,,,,,,,FSMC_A0,,,EVENTOUT +PortF,PF1,,,,,I2C2_SCL,,,,,,,,FSMC_A1,,,EVENTOUT +PortF,PF2,,,,,I2C2_SMBA,,,,,,,,FSMC_A2,,,EVENTOUT +PortF,PF3,,,,,,,,,,,,,FSMC_A3,,,EVENTOUT +PortF,PF4,,,,,,,,,,,,,FSMC_A4,,,EVENTOUT +PortF,PF5,,,,,,,,,,,,,FSMC_A5,,,EVENTOUT +PortF,PF6,,,,TIM10_CH1,,,,,,,,,FSMC_NIORD,,,EVENTOUT +PortF,PF7,,,,TIM11_CH1,,,,,,,,,FSMC_NREG,,,EVENTOUT +PortF,PF8,,,,,,,,,,TIM13_CH1,,,FSMC_NIOWR,,,EVENTOUT +PortF,PF9,,,,,,,,,,TIM14_CH1,,,FSMC_CD,,,EVENTOUT +PortF,PF10,,,,,,,,,,,,,FSMC_INTR,,,EVENTOUT +PortF,PF11,,,,,,,,,,,,,,DCMI_D12,,EVENTOUT +PortF,PF12,,,,,,,,,,,,,FSMC_A6,,,EVENTOUT +PortF,PF13,,,,,,,,,,,,,FSMC_A7,,,EVENTOUT +PortF,PF14,,,,,,,,,,,,,FSMC_A8,,,EVENTOUT +PortF,PF15,,,,,,,,,,,,,FSMC_A9,,,EVENTOUT +PortG,PG0,,,,,,,,,,,,,FSMC_A10,,,EVENTOUT +PortG,PG1,,,,,,,,,,,,,FSMC_A11,,,EVENTOUT +PortG,PG2,,,,,,,,,,,,,FSMC_A12,,,EVENTOUT +PortG,PG3,,,,,,,,,,,,,FSMC_A13,,,EVENTOUT +PortG,PG4,,,,,,,,,,,,,FSMC_A14,,,EVENTOUT +PortG,PG5,,,,,,,,,,,,,FSMC_A15,,,EVENTOUT +PortG,PG6,,,,,,,,,,,,,FSMC_INT2,,,EVENTOUT +PortG,PG7,,,,,,,,,USART6_CK,,,,FSMC_INT3,,,EVENTOUT +PortG,PG8,,,,,,,,,USART6_RTS,,,ETH_PPS_OUT,,,,EVENTOUT +PortG,PG9,,,,,,,,,USART6_RX,,,,FSMC_NE2/FSMC_NCE3,,,EVENTOUT +PortG,PG10,,,,,,,,,,,,,FSMC_NCE4_1/FSMC_NE3,,,EVENTOUT +PortG,PG11,,,,,,,,,,,,ETH_MII_TX_EN/ETH_RMII_TX_EN,FSMC_NCE4_2,,,EVENTOUT +PortG,PG12,,,,,,,,,USART6_RTS,,,,FSMC_NE4,,,EVENTOUT +PortG,PG13,,,,,,,,,USART6_CTS,,,ETH_MII_TXD0/ETH_RMII_TXD0,FSMC_A24,,,EVENTOUT +PortG,PG14,,,,,,,,,USART6_TX,,,ETH_MII_TXD1/ETH_RMII_TXD1,FSMC_A25,,,EVENTOUT +PortG,PG15,,,,,,,,,USART6_CTS,,,,,DCMI_D13,,EVENTOUT +PortH,PH0,,,,,,,,,,,,,,,,EVENTOUT +PortH,PH1,,,,,,,,,,,,,,,,EVENTOUT +PortH,PH2,,,,,,,,,,,,ETH_MII_CRS,,,,EVENTOUT +PortH,PH3,,,,,,,,,,,,ETH_MII_COL,,,,EVENTOUT +PortH,PH4,,,,,I2C2_SCL,,,,,,OTG_HS_ULPI_NXT,,,,,EVENTOUT +PortH,PH5,,,,,I2C2_SDA,,,,,,,,,,,EVENTOUT +PortH,PH6,,,,,I2C2_SMBA,,,,,TIM12_CH1,,ETH_MII_RXD2,,,,EVENTOUT +PortH,PH7,,,,,I2C3_SCL,,,,,,,ETH_MII_RXD3,,,,EVENTOUT +PortH,PH8,,,,,I2C3_SDA,,,,,,,,,DCMI_HSYNC,,EVENTOUT +PortH,PH9,,,,,I2C3_SMBA,,,,,TIM12_CH2,,,,DCMI_D0,,EVENTOUT +PortH,PH10,,,TIM5_CH1,,,,,,,,,,,DCMI_D1,,EVENTOUT +PortH,PH11,,,TIM5_CH2,,,,,,,,,,,DCMI_D2,,EVENTOUT +PortH,PH12,,,TIM5_CH3,,,,,,,,,,,DCMI_D3,,EVENTOUT +PortH,PH13,,,,TIM8_CH1N,,,,,,CAN1_TX,,,,,,EVENTOUT +PortH,PH14,,,,TIM8_CH2N,,,,,,,,,,DCMI_D4,,EVENTOUT +PortH,PH15,,,,TIM8_CH3N,,,,,,,,,,DCMI_D11,,EVENTOUT +PortI,PI0,,,TIM5_CH4,,,SPI2_NSS/I2S2_WS,,,,,,,,DCMI_D13,,EVENTOUT +PortI,PI1,,,,,,SPI2_SCKI2S2_CK,,,,,,,,DCMI_D8,,EVENTOUT +PortI,PI2,,,,TIM8_CH4,,SPI2_MISO,I2S2ext_SD,,,,,,,DCMI_D9,,EVENTOUT +PortI,PI3,,,,TIM8_ETR,,SPI2_MOSI/I2S2_SD,,,,,,,,DCMI_D10,,EVENTOUT +PortI,PI4,,,,TIM8_BKIN,,,,,,,,,,DCMI_D5,,EVENTOUT +PortI,PI5,,,,TIM8_CH1,,,,,,,,,,DCMI_VSYNC,,EVENTOUT +PortI,PI6,,,,TIM8_CH2,,,,,,,,,,DCMI_D6,,EVENTOUT +PortI,PI7,,,,TIM8_CH3,,,,,,,,,,DCMI_D7,,EVENTOUT +PortI,PI8,,,,,,,,,,,,,,,,EVENTOUT +PortI,PI9,,,,,,,,,,CAN1_RX,,,,,,EVENTOUT +PortI,PI10,,,,,,,,,,,,ETH_MII_RX_ER,,,,EVENTOUT +PortI,PI11,,,,,,,,,,,OTG_HS_ULPI_DIR,,,,,EVENTOUT diff --git a/stm/boards/stm32f4xx-prefix.c b/stm/boards/stm32f4xx-prefix.c new file mode 100644 index 0000000000..e68de4cf4e --- /dev/null +++ b/stm/boards/stm32f4xx-prefix.c @@ -0,0 +1,34 @@ +// stm32fxx-prefix.c becomes the initial portion of the generated pins file. + +#include +#include +#include + +#include "misc.h" +#include "mpconfig.h" +#include "qstr.h" +#include "obj.h" + +#include "pin.h" + +#define AF(af_idx, af_fn, af_unit, af_type, af_ptr) \ +{ \ + { &pin_af_obj_type }, \ + .idx = (af_idx), \ + .fn = AF_FN_ ## af_fn, \ + .unit = (af_unit), \ + .type = AF_PIN_TYPE_ ## af_fn ## _ ## af_type, \ + .af_fn = (af_ptr) \ +} + +#define PIN(p_port, p_pin, p_num_af, p_af) \ +{ \ + { &pin_obj_type }, \ + .name = #p_port #p_pin, \ + .port = PORT_ ## p_port, \ + .pin = (p_pin), \ + .num_af = (p_num_af), \ + .pin_mask = (1 << ((p_pin) & 0x0f)), \ + .gpio = GPIO ## p_port, \ + .af = p_af, \ +} diff --git a/stm/gpio.c b/stm/gpio.c index 99fb49be4f..e3db4086e7 100644 --- a/stm/gpio.c +++ b/stm/gpio.c @@ -28,43 +28,18 @@ #include "runtime.h" #include "systick.h" #include "gpio.h" - -void parse_pin_name(mp_obj_t name, GPIO_TypeDef **port, uint *pin) { - const char *pin_name = mp_obj_str_get_str(name); - switch (pin_name[0]) { - case 'A': case 'a': *port = GPIOA; break; - case 'B': case 'b': *port = GPIOB; break; - case 'C': case 'c': *port = GPIOC; break; - case 'D': case 'd': *port = GPIOD; break; - default: goto pin_error; - } - *pin = 0; - for (const char *s = pin_name + 1; *s; s++) { - if (!('0' <= *s && *s <= '9')) { - goto pin_error; - } - *pin = 10 * (*pin) + *s - '0'; - } - if (!(0 <= *pin && *pin <= 15)) { - goto pin_error; - } - - return; - -pin_error: - nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin %s does not exist", pin_name)); -} +#include "pin.h" mp_obj_t pyb_gpio(uint n_args, mp_obj_t *args) { //assert(1 <= n_args && n_args <= 2); - GPIO_TypeDef *port; - uint pin; - parse_pin_name(args[0], &port, &pin); + const pin_obj_t *pin = pin_map_user_obj(args[0]); + GPIO_TypeDef *port = pin->gpio; + uint16_t pin_mask = pin->pin_mask; if (n_args == 1) { // get pin - if ((port->IDR & (1 << pin)) != (uint32_t)Bit_RESET) { + if ((port->IDR & pin_mask) != (uint32_t)Bit_RESET) { return MP_OBJ_NEW_SMALL_INT(1); } else { return MP_OBJ_NEW_SMALL_INT(0); @@ -73,10 +48,10 @@ mp_obj_t pyb_gpio(uint n_args, mp_obj_t *args) { // set pin if (rt_is_true(args[1])) { // set pin high - port->BSRRL = 1 << pin; + port->BSRRL = pin_mask; } else { // set pin low - port->BSRRH = 1 << pin; + port->BSRRH = pin_mask; } return mp_const_none; } @@ -84,13 +59,13 @@ mp_obj_t pyb_gpio(uint n_args, mp_obj_t *args) { MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_gpio_obj, 1, 2, pyb_gpio); -mp_obj_t pyb_gpio_input(mp_obj_t arg_port_pin, mp_obj_t arg_mode) { - GPIO_TypeDef *port; - uint pin; - parse_pin_name(arg_port_pin, &port, &pin); +mp_obj_t pyb_gpio_input(mp_obj_t arg_pin, mp_obj_t arg_mode) { + const pin_obj_t *pin = pin_map_user_obj(arg_pin); + GPIO_TypeDef *port = pin->gpio; + uint16_t pin_mask = pin->pin_mask; GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.GPIO_Pin = 1 << pin; + GPIO_InitStructure.GPIO_Pin = pin_mask; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_PuPd = mp_obj_get_int(arg_mode); GPIO_Init(port, &GPIO_InitStructure); @@ -100,13 +75,13 @@ mp_obj_t pyb_gpio_input(mp_obj_t arg_port_pin, mp_obj_t arg_mode) { MP_DEFINE_CONST_FUN_OBJ_2(pyb_gpio_input_obj, pyb_gpio_input); -mp_obj_t pyb_gpio_output(mp_obj_t arg_port_pin, mp_obj_t arg_mode) { - GPIO_TypeDef *port; - uint pin; - parse_pin_name(arg_port_pin, &port, &pin); +mp_obj_t pyb_gpio_output(mp_obj_t arg_pin, mp_obj_t arg_mode) { + const pin_obj_t *pin = pin_map_user_obj(arg_pin); + GPIO_TypeDef *port = pin->gpio; + uint16_t pin_mask = pin->pin_mask; GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.GPIO_Pin = 1 << pin; + GPIO_InitStructure.GPIO_Pin = pin_mask; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_Speed = GPIO_Fast_Speed; GPIO_InitStructure.GPIO_OType = mp_obj_get_int(arg_mode); diff --git a/stm/main.c b/stm/main.c index b283821bba..f82a18692e 100644 --- a/stm/main.c +++ b/stm/main.c @@ -50,6 +50,7 @@ #include "adc.h" #include "rtc.h" #include "file.h" +#include "pin.h" int errno; @@ -445,6 +446,7 @@ soft_reset: rt_store_attr(m, MP_QSTR_ADC, (mp_obj_t)&pyb_ADC_obj); rt_store_attr(m, qstr_from_str("millis"), rt_make_function_n(0, pyb_millis)); + pin_map_init(m); gpio_init(m); rt_store_name(MP_QSTR_pyb, m); diff --git a/stm/mpconfigport.h b/stm/mpconfigport.h index 51e4bb9a82..c5614f4bb8 100644 --- a/stm/mpconfigport.h +++ b/stm/mpconfigport.h @@ -34,186 +34,7 @@ machine_float_t machine_sqrt(machine_float_t x); // board specific definitions -// choose 1 of these boards -//#define PYBOARD3 -#define PYBOARD4 -//#define STM32F4DISC -//#define NETDUINO_PLUS_2 - -#if defined (PYBOARD3) - #define MICROPY_HW_BOARD_NAME "PYBv3" - - #define MICROPY_HW_HAS_SWITCH (1) - #define MICROPY_HW_HAS_SDCARD (1) - #define MICROPY_HW_HAS_MMA7660 (1) - #define MICROPY_HW_HAS_LIS3DSH (0) - #define MICROPY_HW_HAS_LCD (0) - #define MICROPY_HW_HAS_WLAN (0) - #define MICROPY_HW_ENABLE_RNG (1) - #define MICROPY_HW_ENABLE_RTC (1) - #define MICROPY_HW_ENABLE_TIMER (1) - #define MICROPY_HW_ENABLE_SERVO (1) - #define MICROPY_HW_ENABLE_AUDIO (0) - - #define USRSW_PORT (GPIOA) - #define USRSW_PIN (GPIO_Pin_13) - #define USRSW_PUPD (GPIO_PuPd_UP) - #define USRSW_EXTI_PIN (EXTI_PinSource13) - #define USRSW_EXTI_PORT (EXTI_PortSourceGPIOA) - #define USRSW_EXTI_LINE (EXTI_Line13) - #define USRSW_EXTI_IRQN (EXTI15_10_IRQn) - #define USRSW_EXTI_EDGE (EXTI_Trigger_Rising) - - /* LED */ - #define PYB_LED1_PORT (GPIOA) - #define PYB_LED1_PIN (GPIO_Pin_8) - - #define PYB_LED2_PORT (GPIOA) - #define PYB_LED2_PIN (GPIO_Pin_10) - - #define PYB_LED3_PORT (GPIOC) - #define PYB_LED3_PIN (GPIO_Pin_4) - - #define PYB_LED4_PORT (GPIOC) - #define PYB_LED4_PIN (GPIO_Pin_5) - - #define PYB_OTYPE (GPIO_OType_OD) - - #define PYB_LED_ON(port, pin) (port->BSRRH = pin) - #define PYB_LED_OFF(port, pin) (port->BSRRL = pin) - -#elif defined (PYBOARD4) - #define MICROPY_HW_BOARD_NAME "PYBv4" - - #define MICROPY_HW_HAS_SWITCH (1) - #define MICROPY_HW_HAS_SDCARD (1) - #define MICROPY_HW_HAS_MMA7660 (1) - #define MICROPY_HW_HAS_LIS3DSH (0) - #define MICROPY_HW_HAS_LCD (1) - #define MICROPY_HW_HAS_WLAN (0) - #define MICROPY_HW_ENABLE_RNG (1) - #define MICROPY_HW_ENABLE_RTC (1) - #define MICROPY_HW_ENABLE_TIMER (1) - #define MICROPY_HW_ENABLE_SERVO (1) - #define MICROPY_HW_ENABLE_AUDIO (0) - - #define USRSW_PORT (GPIOB) - #define USRSW_PIN (GPIO_Pin_3) - #define USRSW_PUPD (GPIO_PuPd_UP) - #define USRSW_EXTI_PIN (EXTI_PinSource3) - #define USRSW_EXTI_PORT (EXTI_PortSourceGPIOB) - #define USRSW_EXTI_LINE (EXTI_Line3) - #define USRSW_EXTI_IRQN (EXTI3_IRQn) - #define USRSW_EXTI_EDGE (EXTI_Trigger_Rising) - - /* LED */ - #define PYB_LED1_PORT (GPIOA) - #define PYB_LED1_PIN (GPIO_Pin_13) - - #define PYB_LED2_PORT (GPIOA) - #define PYB_LED2_PIN (GPIO_Pin_14) - - #define PYB_LED3_PORT (GPIOA) - #define PYB_LED3_PIN (GPIO_Pin_15) - - #define PYB_LED4_PORT (GPIOB) - #define PYB_LED4_PIN (GPIO_Pin_4) - - #define PYB_OTYPE (GPIO_OType_PP) - - #define PYB_LED_ON(port, pin) (port->BSRRL = pin) - #define PYB_LED_OFF(port, pin) (port->BSRRH = pin) - -#elif defined (STM32F4DISC) - #define MICROPY_HW_BOARD_NAME "F4DISC" - - #define MICROPY_HW_HAS_SWITCH (1) - #define MICROPY_HW_HAS_SDCARD (0) - #define MICROPY_HW_HAS_MMA7660 (0) - #define MICROPY_HW_HAS_LIS3DSH (1) - #define MICROPY_HW_HAS_LCD (0) - #define MICROPY_HW_HAS_WLAN (0) - #define MICROPY_HW_ENABLE_RNG (1) - #define MICROPY_HW_ENABLE_RTC (1) - #define MICROPY_HW_ENABLE_TIMER (1) - #define MICROPY_HW_ENABLE_SERVO (0) - #define MICROPY_HW_ENABLE_AUDIO (0) - - #define USRSW_PORT (GPIOA) - #define USRSW_PIN (GPIO_Pin_0) - #define USRSW_PUPD (GPIO_PuPd_NOPULL) - #define USRSW_EXTI_PIN (EXTI_PinSource0) - #define USRSW_EXTI_PORT (EXTI_PortSourceGPIOA) - #define USRSW_EXTI_LINE (EXTI_Line0) - #define USRSW_EXTI_IRQN (EXTI0_IRQn) - #define USRSW_EXTI_EDGE (EXTI_Trigger_Falling) - - /* LED */ - #define PYB_LED1_PORT (GPIOD) - #define PYB_LED1_PIN (GPIO_Pin_14) - - #define PYB_LED2_PORT (GPIOD) - #define PYB_LED2_PIN (GPIO_Pin_12) - - #define PYB_LED3_PORT (GPIOD) - #define PYB_LED3_PIN (GPIO_Pin_15) - - #define PYB_LED4_PORT (GPIOD) - #define PYB_LED4_PIN (GPIO_Pin_13) - - #define PYB_OTYPE (GPIO_OType_PP) - - #define PYB_LED_ON(port, pin) (port->BSRRL = pin) - #define PYB_LED_OFF(port, pin) (port->BSRRH = pin) - -#elif defined (NETDUINO_PLUS_2) - #define MICROPY_HW_BOARD_NAME "NetduinoPlus2" - - #define MICROPY_HW_HAS_SWITCH (1) - - // On the netuino, the sdcard appears to be wired up as a 1-bit - // SPI, so the driver needs to be converted to support that before - // we can turn this on. - #define MICROPY_HW_HAS_SDCARD (0) - #define MICROPY_HW_HAS_MMA7660 (0) - #define MICROPY_HW_HAS_LIS3DSH (0) - #define MICROPY_HW_HAS_LCD (0) - #define MICROPY_HW_HAS_WLAN (0) - #define MICROPY_HW_ENABLE_RNG (1) - #define MICROPY_HW_ENABLE_RTC (0) - #define MICROPY_HW_ENABLE_TIMER (1) - #define MICROPY_HW_ENABLE_SERVO (1) - #define MICROPY_HW_ENABLE_AUDIO (0) - - #define USRSW_PORT (GPIOB) - #define USRSW_PIN (GPIO_Pin_11) - #define USRSW_PUPD (GPIO_PuPd_NOPULL) - #define USRSW_EXTI_PIN (EXTI_PinSource11) - #define USRSW_EXTI_PORT (EXTI_PortSourceGPIOB) - #define USRSW_EXTI_LINE (EXTI_Line11) - #define USRSW_EXTI_IRQN (EXTI15_10_IRQn) - #define USRSW_EXTI_EDGE (EXTI_Trigger_Rising) - - /* LED */ - #define PYB_LED1_PORT (GPIOA) // Blue LED - #define PYB_LED1_PIN (GPIO_Pin_10) - - #define PYB_LED2_PORT (GPIOC) // White LED (aka Power) - #define PYB_LED2_PIN (GPIO_Pin_13) - - #define PYB_LED3_PORT (GPIOA) // Same as Led(1) - #define PYB_LED3_PIN (GPIO_Pin_10) - - #define PYB_LED4_PORT (GPIOC) // Same as Led(2) - #define PYB_LED4_PIN (GPIO_Pin_13) - - #define PYB_OTYPE (GPIO_OType_PP) - - #define PYB_LED_ON(port, pin) (port->BSRRL = pin) - #define PYB_LED_OFF(port, pin) (port->BSRRH = pin) - - #define HSE_VALUE (25000000) -#endif +#include "mpconfigboard.h" #define STM32F40_41xxx #define USE_STDPERIPH_DRIVER diff --git a/stm/pin.c b/stm/pin.c new file mode 100644 index 0000000000..e7f6998874 --- /dev/null +++ b/stm/pin.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include + +#include "misc.h" +#include "mpconfig.h" +#include "qstr.h" +#include "obj.h" + +#include "pin.h" + +void pin_obj_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, "", self->name); +} + +mp_obj_t pin_obj_name(mp_obj_t self_in) { + pin_obj_t *self = self_in; + return MP_OBJ_NEW_QSTR(qstr_from_str(self->name)); +} + +mp_obj_t pin_obj_port(mp_obj_t self_in) { + pin_obj_t *self = self_in; + return MP_OBJ_NEW_SMALL_INT((mp_small_int_t)self->port); +} + +mp_obj_t pin_obj_pin(mp_obj_t self_in) { + pin_obj_t *self = self_in; + return MP_OBJ_NEW_SMALL_INT((mp_small_int_t)self->pin); +} + +static MP_DEFINE_CONST_FUN_OBJ_1(pin_obj_name_obj, pin_obj_name); +static MP_DEFINE_CONST_FUN_OBJ_1(pin_obj_port_obj, pin_obj_port); +static MP_DEFINE_CONST_FUN_OBJ_1(pin_obj_pin_obj, pin_obj_pin); + +static const mp_method_t pin_methods[] = { + { "name", &pin_obj_name_obj }, + { "port", &pin_obj_port_obj }, + { "pin", &pin_obj_pin_obj }, + { NULL, NULL }, +}; + +const mp_obj_type_t pin_obj_type = { + { &mp_type_type }, + .name = MP_QSTR_Pin, + .print = pin_obj_print, + .methods = pin_methods, +}; + +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, "", self->idx, self->fn, + self->unit, self->type); +} + +const mp_obj_type_t pin_af_obj_type = { + { &mp_type_type }, + .name = MP_QSTR_PinAF, + .print = pin_af_obj_print, +}; + diff --git a/stm/pin.h b/stm/pin.h new file mode 100644 index 0000000000..5cfd9fb0f2 --- /dev/null +++ b/stm/pin.h @@ -0,0 +1,117 @@ +enum { + PORT_A, + PORT_B, + PORT_C, + PORT_D, + PORT_E, + PORT_F, + PORT_G, + PORT_H, + PORT_I, + PORT_J, +}; + +enum { + AF_FN_TIM, + AF_FN_I2C, + AF_FN_USART, + AF_FN_UART = AF_FN_USART, + AF_FN_SPI +}; + +enum { + AF_PIN_TYPE_TIM_CH1 = 0, + AF_PIN_TYPE_TIM_CH2, + AF_PIN_TYPE_TIM_CH3, + AF_PIN_TYPE_TIM_CH4, + AF_PIN_TYPE_TIM_CH1N, + AF_PIN_TYPE_TIM_CH2N, + AF_PIN_TYPE_TIM_CH3N, + AF_PIN_TYPE_TIM_CH1_ETR, + AF_PIN_TYPE_TIM_ETR, + AF_PIN_TYPE_TIM_BKIN, + + AF_PIN_TYPE_I2C_SDA = 0, + AF_PIN_TYPE_I2C_SCL, + + AF_PIN_TYPE_USART_TX = 0, + AF_PIN_TYPE_USART_RX, + AF_PIN_TYPE_USART_CTS, + AF_PIN_TYPE_USART_RTS, + AF_PIN_TYPE_USART_CK, + AF_PIN_TYPE_UART_TX = AF_PIN_TYPE_USART_TX, + AF_PIN_TYPE_UART_RX = AF_PIN_TYPE_USART_RX, + AF_PIN_TYPE_UART_CTS = AF_PIN_TYPE_USART_CTS, + AF_PIN_TYPE_UART_RTS = AF_PIN_TYPE_USART_RTS, + + AF_PIN_TYPE_SPI_MOSI = 0, + AF_PIN_TYPE_SPI_MISO, + AF_PIN_TYPE_SPI_SCK, + AF_PIN_TYPE_SPI_NSS, +}; + +typedef struct { + mp_obj_base_t base; + uint8_t idx; + uint8_t fn; + uint8_t unit; + uint8_t type; + + union { + void *reg; + TIM_TypeDef *TIM; + I2C_TypeDef *I2C; + USART_TypeDef *USART; + USART_TypeDef *UART; + SPI_TypeDef *SPI; + }; +} pin_af_obj_t; + +typedef struct { + mp_obj_base_t base; + const char *name; + uint16_t port : 4; + uint16_t pin : 4; + uint16_t num_af : 4; + uint16_t pin_mask; + GPIO_TypeDef *gpio; + const pin_af_obj_t *af; +} pin_obj_t; + +extern const mp_obj_type_t pin_obj_type; +extern const mp_obj_type_t pin_af_obj_type; + +typedef struct { + const char *name; + const pin_obj_t *pin; +} pin_named_pin_t; + +extern const pin_named_pin_t pin_board_pins[]; +extern const pin_named_pin_t pin_cpu_pins[]; + +typedef struct { + mp_obj_base_t base; + mp_obj_t mapper; + mp_obj_t map_dict; + bool debug; +} pin_map_obj_t; + +extern pin_map_obj_t pin_map_obj; + +typedef struct { + mp_obj_base_t base; + const char *name; + 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; + +const pin_obj_t *pin_find_named_pin(const pin_named_pin_t *pins, const char *name); +const pin_af_obj_t *pin_find_af(const pin_obj_t *pin, uint8_t fn, uint8_t unit, uint8_t pin_type); + +void pin_map_init(mp_obj_t mod); + +// C function for mapping python pin identifier into an ordinal pin number. +const pin_obj_t *pin_map_user_obj(mp_obj_t user_obj); + diff --git a/stm/pin_map.c b/stm/pin_map.c new file mode 100644 index 0000000000..bd2cfb9e9d --- /dev/null +++ b/stm/pin_map.c @@ -0,0 +1,228 @@ +#include +#include +#include +#include + +#include "misc.h" +#include "mpconfig.h" +#include "qstr.h" +#include "obj.h" +#include "runtime.h" +#include "nlr.h" +#include "map.h" + +#include "pin.h" + +// Usage Model: +// +// All Board Pins are predefined as pyb.Pin.board.Name +// +// x1_pin = pyb.Pin.board.X1 +// +// g = pyb.gpio(pyb.Pin.board.X1, 0) +// +// CPU pins which correspond to the board pins are available +// as pyb.cpu.Name. For the CPU pins, the names are the port letter +// followed by the pin number. On the PYBOARD4, pyb.Pin.board.X1 and +// pyb.Pin.cpu.B6 are the same pin. +// +// You can also use strings: +// +// g = pyb.gpio('X1', 0) +// +// Users can add their own names: +// +// pyb.Pin("LeftMotorDir", pyb.Pin.cpu.C12) +// g = pyb.gpio("LeftMotorDir", 0) +// +// and can query mappings +// +// pin = pyb.Pin("LeftMotorDir"); +// +// Users can also add their own mapping function: +// +// def MyMapper(pin_name): +// if pin_name == "LeftMotorDir": +// return pyb.Pin.cpu.A0 +// +// pyb.Pin.mapper(MyMapper) +// +// So, if you were to call: pyb.gpio("LeftMotorDir", 0) +// then "LeftMotorDir" is passed directly to the mapper function. +// +// To summarize, the following order determines how things get mapped into +// an ordinal pin number: +// +// 1 - Directly specify a pin object +// 2 - User supplied mapping function +// 3 - User supplied mapping (object must be usable as a dictionary key) +// 4 - Supply a string which matches a board pin +// 5 - Supply a string which matches a CPU port/pin +// +// You can set pyb.Pin.debug(True) to get some debug information about +// how a particular object gets mapped to a pin. + +static void pin_map_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { + (void)self_in; + print(env, ""); +} + +static mp_obj_t pin_map_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) { + pin_map_obj_t *self = self_in; + rt_check_nargs(n_args, 1, 2, n_kw, false); + + if (n_args > 1) { + if (!self->map_dict) { + self->map_dict = mp_obj_new_dict(1); + } + mp_obj_dict_store(self->map_dict, args[0], args[1]); + return mp_const_none; + } + + // Run an argument through the mapper and return the result. + return (mp_obj_t)pin_map_user_obj(args[0]); +} + +static mp_obj_t pin_map_obj_mapper(uint n_args, mp_obj_t *args) { + pin_map_obj_t *self = args[0]; + if (n_args > 1) { + self->mapper = args[1]; + return mp_const_none; + } + return self->mapper; +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_map_obj_mapper_obj, 1, 2, pin_map_obj_mapper); + +static mp_obj_t pin_map_obj_debug(uint n_args, mp_obj_t *args) { + pin_map_obj_t *self = args[0]; + if (n_args > 1) { + self->debug = rt_is_true(args[1]); + return mp_const_none; + } + return MP_BOOL(self->debug); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_map_obj_debug_obj, 1, 2, pin_map_obj_debug); + +static void pin_map_load_attr(mp_obj_t self_in, qstr attr_qstr, mp_obj_t *dest) { + (void)self_in; + const char *attr = qstr_str(attr_qstr); + + if (strcmp(attr, "mapper") == 0) { + dest[0] = (mp_obj_t)&pin_map_obj_mapper_obj; + dest[1] = self_in; + } + if (strcmp(attr, "debug") == 0) { + dest[0] = (mp_obj_t)&pin_map_obj_debug_obj; + dest[1] = self_in; + } + if (strcmp(attr, pin_board_pins_obj.name) == 0) { + dest[0] = (mp_obj_t)&pin_board_pins_obj; + dest[1] = MP_OBJ_NULL; + } + if (strcmp(attr, pin_cpu_pins_obj.name) == 0) { + dest[0] = (mp_obj_t)&pin_cpu_pins_obj; + dest[1] = MP_OBJ_NULL; + } +} + +static const mp_obj_type_t pin_map_obj_type = { + { &mp_type_type }, + .name = MP_QSTR_PinMap, + .print = pin_map_obj_print, + .call = pin_map_call, + .load_attr = pin_map_load_attr, +}; + +static const pin_map_obj_t pin_map_obj_init = { + { &pin_map_obj_type }, + .mapper = MP_OBJ_NULL, + .map_dict = MP_OBJ_NULL, + .debug = false, +}; + +pin_map_obj_t pin_map_obj; + +void pin_map_init(mp_obj_t mod) { + pin_map_obj = pin_map_obj_init; + rt_store_attr(mod, MP_QSTR_Pin, (mp_obj_t)&pin_map_obj); +} + +// C API used to convert a user-supplied pin name into an ordinal pin number. +const pin_obj_t *pin_map_user_obj(mp_obj_t user_obj) { + const pin_obj_t *pin_obj; + + // If a pin was provided, then use it + if (MP_OBJ_IS_TYPE(user_obj, &pin_obj_type)) { + pin_obj = user_obj; + if (pin_map_obj.debug) { + printf("Pin map passed pin "); + mp_obj_print((mp_obj_t)pin_obj, PRINT_STR); + printf("\n"); + } + return pin_obj; + } + + if (pin_map_obj.mapper) { + pin_obj = rt_call_function_1(pin_map_obj.mapper, user_obj); + if (pin_obj != mp_const_none) { + if (!MP_OBJ_IS_TYPE(pin_obj, &pin_obj_type)) { + nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "Pin.mapper didn't return a Pin object")); + } + if (pin_map_obj.debug) { + printf("Pin.mapper maps "); + mp_obj_print(user_obj, PRINT_REPR); + printf(" to "); + mp_obj_print((mp_obj_t)pin_obj, PRINT_STR); + printf("\n"); + } + return pin_obj; + } + // The pin mapping function returned mp_const_none, fall through to + // other lookup methods. + } + + if (pin_map_obj.map_dict) { + mp_map_t *pin_map_map = mp_obj_dict_get_map(pin_map_obj.map_dict); + mp_map_elem_t *elem = mp_map_lookup(pin_map_map, user_obj, MP_MAP_LOOKUP); + if (elem != NULL && elem->value != NULL) { + pin_obj = elem->value; + if (pin_map_obj.debug) { + printf("Pin.map_dict maps "); + mp_obj_print(user_obj, PRINT_REPR); + printf(" to "); + mp_obj_print((mp_obj_t)pin_obj, PRINT_STR); + printf("\n"); + } + return pin_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); + if (pin_obj) { + if (pin_map_obj.debug) { + printf("Pin.board maps "); + mp_obj_print(user_obj, PRINT_REPR); + printf(" to "); + mp_obj_print((mp_obj_t)pin_obj, PRINT_STR); + printf("\n"); + } + return pin_obj; + } + + // See if the pin name matches a cpu pin + pin_obj = pin_find_named_pin(pin_cpu_pins, pin_name); + if (pin_obj) { + if (pin_map_obj.debug) { + printf("Pin.cpu maps "); + mp_obj_print(user_obj, PRINT_REPR); + printf(" to "); + mp_obj_print((mp_obj_t)pin_obj, PRINT_STR); + printf("\n"); + } + return pin_obj; + } + + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin '%s' not a valid pin identifier", pin_name)); +} diff --git a/stm/pin_named_pins.c b/stm/pin_named_pins.c new file mode 100644 index 0000000000..d68722b4a1 --- /dev/null +++ b/stm/pin_named_pins.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include + +#include "misc.h" +#include "mpconfig.h" +#include "qstr.h" +#include "obj.h" +#include "runtime.h" + +#include "pin.h" + +static void pin_named_pins_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { + pin_named_pins_obj_t *self = self_in; + print(env, "", 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 = { + { &mp_type_type }, + .name = MP_QSTR_PinNamed, + .print = pin_named_pins_obj_print, + .load_attr = pin_named_pins_obj_load_attr, +}; + +const pin_named_pins_obj_t pin_board_pins_obj = { + { &pin_named_pins_obj_type }, + .name = "board", + .named_pins = pin_board_pins, +}; + +const pin_named_pins_obj_t pin_cpu_pins_obj = { + { &pin_named_pins_obj_type }, + .name = "cpu", + .named_pins = pin_cpu_pins, +}; + +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++; + } + 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++) { + if (af->fn == fn && af->unit == unit && af->type == type) { + return af; + } + } + return NULL; +} diff --git a/stm/qstrdefsport.h b/stm/qstrdefsport.h index 65c4f81a94..3b20e3acd3 100644 --- a/stm/qstrdefsport.h +++ b/stm/qstrdefsport.h @@ -36,3 +36,7 @@ Q(File) Q(0:/) Q(0:/src) Q(0:/lib) +Q(Pin) +Q(PinMap) +Q(PinAF) +Q(PinNamed)