Commit 51dabac0 authored by Dave Hylands's avatar Dave Hylands
Browse files

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.
parent 46239413
......@@ -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,
"<fun name>() missing %d required positional arguments: <list of names of params>",
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,
"<fun name> expected at most %d arguments, got %d",
self->n_args_max, n_args));
n_args_max, n_args));
}
}
}
......
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);
......
......@@ -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
#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)
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
#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)
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
#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)
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
#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)
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
#!/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)