summaryrefslogtreecommitdiffstatshomepage
path: root/stmhal
diff options
context:
space:
mode:
Diffstat (limited to 'stmhal')
-rw-r--r--stmhal/Makefile4
-rw-r--r--stmhal/adc.c80
-rw-r--r--stmhal/boards/STM32F7DISC/mpconfigboard.h13
-rwxr-xr-xstmhal/boards/make-pins.py6
-rw-r--r--stmhal/boards/stm32l476_af.csv238
-rw-r--r--stmhal/dac.c8
-rw-r--r--stmhal/irq.h3
-rw-r--r--stmhal/main.c7
-rw-r--r--stmhal/modmachine.c65
-rw-r--r--stmhal/modmachine.h2
-rw-r--r--stmhal/modusocket.c1
-rw-r--r--stmhal/mpconfigport.h3
-rw-r--r--stmhal/pin.c8
-rw-r--r--stmhal/spi.c171
-rw-r--r--stmhal/stm32_it.c18
-rw-r--r--stmhal/timer.c26
-rw-r--r--stmhal/wdt.c108
-rw-r--r--stmhal/wdt.h27
18 files changed, 535 insertions, 253 deletions
diff --git a/stmhal/Makefile b/stmhal/Makefile
index 1ad2783fca..b320e0c898 100644
--- a/stmhal/Makefile
+++ b/stmhal/Makefile
@@ -111,7 +111,6 @@ SRC_LIB = $(addprefix lib/,\
timeutils/timeutils.c \
utils/pyexec.c \
utils/pyhelp.c \
- utils/printf.c \
)
SRC_C = \
@@ -138,6 +137,7 @@ SRC_C = \
uart.c \
can.c \
usb.c \
+ wdt.c \
gccollect.c \
pybstdio.c \
help.c \
@@ -284,7 +284,7 @@ endif
ifneq ($(FROZEN_MPY_DIR),)
# To use frozen bytecode, put your .py files in a subdirectory (eg frozen/) and
# then invoke make with FROZEN_MPY_DIR=frozen (be sure to build from scratch).
-FROZEN_MPY_PY_FILES := $(shell find $(FROZEN_MPY_DIR)/ -type f -name '*.py')
+FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py')
FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/,$(FROZEN_MPY_PY_FILES:.py=.mpy))
CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool
CFLAGS += -DMICROPY_MODULE_FROZEN_MPY
diff --git a/stmhal/adc.c b/stmhal/adc.c
index da93a44741..bcf8956254 100644
--- a/stmhal/adc.c
+++ b/stmhal/adc.c
@@ -54,7 +54,16 @@
#define ADCx (ADC1)
#define ADCx_CLK_ENABLE __ADC1_CLK_ENABLE
#define ADC_NUM_CHANNELS (19)
-#define ADC_NUM_GPIO_CHANNELS (16)
+
+#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
+#define ADC_FIRST_GPIO_CHANNEL (0)
+#define ADC_LAST_GPIO_CHANNEL (15)
+#elif defined(MCU_SERIES_L4)
+#define ADC_FIRST_GPIO_CHANNEL (1)
+#define ADC_LAST_GPIO_CHANNEL (16)
+#else
+#error Unsupported processor
+#endif
#if defined(STM32F405xx) || defined(STM32F415xx) || \
defined(STM32F407xx) || defined(STM32F417xx) || \
@@ -124,14 +133,20 @@ STATIC void adc_init_single(pyb_obj_adc_t *adc_obj) {
return;
}
- if (adc_obj->channel < ADC_NUM_GPIO_CHANNELS) {
+ if (ADC_FIRST_GPIO_CHANNEL <= adc_obj->channel && adc_obj->channel <= ADC_LAST_GPIO_CHANNEL) {
// Channels 0-16 correspond to real pins. Configure the GPIO pin in
// ADC mode.
const pin_obj_t *pin = pin_adc1[adc_obj->channel];
mp_hal_gpio_clock_enable(pin->gpio);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Pin = pin->pin_mask;
+#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
+#elif defined(MCU_SERIES_L4)
+ GPIO_InitStructure.Mode = GPIO_MODE_ANALOG_ADC_CONTROL;
+#else
+ #error Unsupported processor
+#endif
GPIO_InitStructure.Pull = GPIO_NOPULL;
HAL_GPIO_Init(pin->gpio, &GPIO_InitStructure);
}
@@ -140,7 +155,6 @@ STATIC void adc_init_single(pyb_obj_adc_t *adc_obj) {
ADC_HandleTypeDef *adcHandle = &adc_obj->handle;
adcHandle->Instance = ADCx;
- adcHandle->Init.Resolution = ADC_RESOLUTION12b;
adcHandle->Init.ContinuousConvMode = DISABLE;
adcHandle->Init.DiscontinuousConvMode = DISABLE;
adcHandle->Init.NbrOfDiscConversion = 0;
@@ -148,15 +162,19 @@ STATIC void adc_init_single(pyb_obj_adc_t *adc_obj) {
adcHandle->Init.DataAlign = ADC_DATAALIGN_RIGHT;
adcHandle->Init.NbrOfConversion = 1;
adcHandle->Init.DMAContinuousRequests = DISABLE;
- adcHandle->Init.EOCSelection = DISABLE;
#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
+ adcHandle->Init.Resolution = ADC_RESOLUTION12b;
adcHandle->Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2;
adcHandle->Init.ScanConvMode = DISABLE;
adcHandle->Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1;
+ adcHandle->Init.EOCSelection = DISABLE;
#elif defined(MCU_SERIES_L4)
- adcHandle->Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2;
+ adcHandle->Init.Resolution = ADC_RESOLUTION_12B;
+ adcHandle->Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
adcHandle->Init.ScanConvMode = ADC_SCAN_DISABLE;
- adcHandle->Init.ExternalTrigConv = ADC_EXTERNALTRIG_T1_CC1;
+ adcHandle->Init.EOCSelection = ADC_EOC_SINGLE_CONV;
+ adcHandle->Init.ExternalTrigConv = ADC_SOFTWARE_START;
+ adcHandle->Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
adcHandle->Init.LowPowerAutoWait = DISABLE;
adcHandle->Init.Overrun = ADC_OVR_DATA_PRESERVED;
adcHandle->Init.OversamplingMode = DISABLE;
@@ -165,30 +183,42 @@ STATIC void adc_init_single(pyb_obj_adc_t *adc_obj) {
#endif
HAL_ADC_Init(adcHandle);
+
+#if defined(MCU_SERIES_L4)
+ ADC_MultiModeTypeDef multimode;
+ multimode.Mode = ADC_MODE_INDEPENDENT;
+ if (HAL_ADCEx_MultiModeConfigChannel(adcHandle, &multimode) != HAL_OK)
+ {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Can not set multimode on ADC1 channel: %d", adc_obj->channel));
+ }
+#endif
}
-STATIC void adc_config_channel(pyb_obj_adc_t *adc_obj) {
+STATIC void adc_config_channel(ADC_HandleTypeDef *adc_handle, uint32_t channel) {
ADC_ChannelConfTypeDef sConfig;
- sConfig.Channel = adc_obj->channel;
+ sConfig.Channel = channel;
sConfig.Rank = 1;
#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES;
#elif defined(MCU_SERIES_L4)
sConfig.SamplingTime = ADC_SAMPLETIME_12CYCLES_5;
+ sConfig.SingleDiff = ADC_SINGLE_ENDED;
+ sConfig.OffsetNumber = ADC_OFFSET_NONE;
#else
#error Unsupported processor
#endif
sConfig.Offset = 0;
- HAL_ADC_ConfigChannel(&adc_obj->handle, &sConfig);
+ HAL_ADC_ConfigChannel(adc_handle, &sConfig);
}
STATIC uint32_t adc_read_channel(ADC_HandleTypeDef *adcHandle) {
uint32_t rawValue = 0;
HAL_ADC_Start(adcHandle);
- if (HAL_ADC_PollForConversion(adcHandle, 10) == HAL_OK && HAL_ADC_GetState(adcHandle) == HAL_ADC_STATE_EOC_REG) {
+ if (HAL_ADC_PollForConversion(adcHandle, 10) == HAL_OK
+ && (HAL_ADC_GetState(adcHandle) & HAL_ADC_STATE_EOC_REG) == HAL_ADC_STATE_EOC_REG) {
rawValue = HAL_ADC_GetValue(adcHandle);
}
HAL_ADC_Stop(adcHandle);
@@ -232,8 +262,14 @@ STATIC mp_obj_t adc_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uin
if (!is_adcx_channel(channel)) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "not a valid ADC Channel: %d", channel));
}
- if (pin_adc1[channel] == NULL) {
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "channel %d not available on this board", channel));
+
+
+ if (ADC_FIRST_GPIO_CHANNEL <= channel && channel <= ADC_LAST_GPIO_CHANNEL) {
+ // these channels correspond to physical GPIO ports so make sure they exist
+ if (pin_adc1[channel] == NULL) {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
+ "channel %d not available on this board", channel));
+ }
}
pyb_obj_adc_t *o = m_new_obj(pyb_obj_adc_t);
@@ -252,7 +288,7 @@ STATIC mp_obj_t adc_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uin
STATIC mp_obj_t adc_read(mp_obj_t self_in) {
pyb_obj_adc_t *self = self_in;
- adc_config_channel(self);
+ adc_config_channel(&self->handle, self->channel);
uint32_t data = adc_read_channel(&self->handle);
return mp_obj_new_int(data);
}
@@ -313,7 +349,7 @@ STATIC mp_obj_t adc_read_timed(mp_obj_t self_in, mp_obj_t buf_in, mp_obj_t freq_
}
// configure the ADC channel
- adc_config_channel(self);
+ adc_config_channel(&self->handle, self->channel);
// This uses the timer in polling mode to do the sampling
// TODO use DMA
@@ -402,7 +438,7 @@ void adc_init_all(pyb_adc_all_obj_t *adc_all, uint32_t resolution) {
"resolution %d not supported", resolution));
}
- for (uint32_t channel = 0; channel < ADC_NUM_GPIO_CHANNELS; channel++) {
+ for (uint32_t channel = ADC_FIRST_GPIO_CHANNEL; channel <= ADC_LAST_GPIO_CHANNEL; ++channel) {
// Channels 0-16 correspond to real pins. Configure the GPIO pin in
// ADC mode.
const pin_obj_t *pin = pin_adc1[channel];
@@ -446,19 +482,7 @@ void adc_init_all(pyb_adc_all_obj_t *adc_all, uint32_t resolution) {
}
uint32_t adc_config_and_read_channel(ADC_HandleTypeDef *adcHandle, uint32_t channel) {
- ADC_ChannelConfTypeDef sConfig;
- sConfig.Channel = channel;
- sConfig.Rank = 1;
-#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
- sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES;
-#elif defined(MCU_SERIES_L4)
- sConfig.SamplingTime = ADC_SAMPLETIME_12CYCLES_5;
-#else
- #error Unsupported processor
-#endif
- sConfig.Offset = 0;
- HAL_ADC_ConfigChannel(adcHandle, &sConfig);
-
+ adc_config_channel(adcHandle, channel);
return adc_read_channel(adcHandle);
}
diff --git a/stmhal/boards/STM32F7DISC/mpconfigboard.h b/stmhal/boards/STM32F7DISC/mpconfigboard.h
index c0e47c3ceb..a1dbc0f468 100644
--- a/stmhal/boards/STM32F7DISC/mpconfigboard.h
+++ b/stmhal/boards/STM32F7DISC/mpconfigboard.h
@@ -20,12 +20,19 @@
void STM32F7DISC_board_early_init(void);
// HSE is 25MHz
+// VCOClock = HSE * PLLN / PLLM = 25 MHz * 432 / 25 = 432 MHz
+// SYSCLK = VCOClock / PLLP = 432 MHz / 2 = 216 MHz
+// USB/SDMMC/RNG Clock = VCOClock / PLLQ = 432 MHz / 9 = 48 MHz
#define MICROPY_HW_CLK_PLLM (25)
-#define MICROPY_HW_CLK_PLLN (336)
+#define MICROPY_HW_CLK_PLLN (432)
#define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2)
-#define MICROPY_HW_CLK_PLLQ (7)
+#define MICROPY_HW_CLK_PLLQ (9)
-#define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_6
+// From the reference manual, for 2.7V to 3.6V
+// 151-180 MHz => 5 wait states
+// 181-210 MHz => 6 wait states
+// 211-216 MHz => 7 wait states
+#define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_7 // 210-216 MHz needs 7 wait states
// UART config
#define MICROPY_HW_UART1_TX_PORT (GPIOA)
diff --git a/stmhal/boards/make-pins.py b/stmhal/boards/make-pins.py
index b7f4842144..ae614877d5 100755
--- a/stmhal/boards/make-pins.py
+++ b/stmhal/boards/make-pins.py
@@ -303,7 +303,9 @@ class Pins(object):
def print_adc(self, adc_num):
print('');
print('const pin_obj_t * const pin_adc{:d}[] = {{'.format(adc_num))
- for channel in range(16):
+ for channel in range(17):
+ if channel == 16:
+ print('#if defined(MCU_SERIES_L4)')
adc_found = False
for named_pin in self.cpu_pins:
pin = named_pin.pin()
@@ -314,6 +316,8 @@ class Pins(object):
break
if not adc_found:
print(' NULL, // {:d}'.format(channel))
+ if channel == 16:
+ print('#endif')
print('};')
diff --git a/stmhal/boards/stm32l476_af.csv b/stmhal/boards/stm32l476_af.csv
index 6dea7e092e..d67c33880f 100644
--- a/stmhal/boards/stm32l476_af.csv
+++ b/stmhal/boards/stm32l476_af.csv
@@ -1,122 +1,116 @@
-Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15
-,,SYS_AF,TIM1/TIM2/TIM5/TIM8/LPTIM1,TIM1/TIM2/TIM3/TIM4/TIM5,TIM8,I2C1/I2C2/I2C3,SPI1/SPI2,SPI3/DFSDM,USART1/USART2/USART3,"UART4,
-UART5,
-LPUART1","CAN1, TSC","OTG_FS, QUADSPI",LCD,"SDMMC1, COMP1,
-COMP2, FMC,
-SWPMI1","SAI1, SAI2","TIM2, TIM15,
-TIM16, TIM17,
-LPTIM2",EVENTOUT
-PortA,PA0,,TIM2_CH1,TIM5_CH1,TIM8_ETR,,,,USART2_CTS,UART4_TX,,,,,SAI1_EXTCLK,TIM2_ETR,EVENTOUT
-PortA,PA1,,TIM2_CH2,TIM5_CH2,,,,,USART2_RTS_DE,UART4_RX,,,LCD_SEG0,,,TIM15_CH1N,EVENTOUT
-PortA,PA2,,TIM2_CH3,TIM5_CH3,,,,,USART2_TX,,,,LCD_SEG1,,SAI2_EXTCLK,TIM15_CH1,EVENTOUT
-PortA,PA3,,TIM2_CH4,TIM5_CH4,,,,,USART2_RX,,,,LCD_SEG2,,,TIM15_CH2,EVENTOUT
-PortA,PA4,,,,,,SPI1_NSS,SPI3_NSS,USART2_CK,,,,,,SAI1_FS_B,LPTIM2_OUT,EVENTOUT
-PortA,PA5,,TIM2_CH1,TIM2_ETR,TIM8_CH1N,,SPI1_SCK,,,,,,,,,LPTIM2_ETR,EVENTOUT
-PortA,PA6,,TIM1_BKIN,TIM3_CH1,TIM8_BKIN,,SPI1_MISO,,USART3_CTS,,,QUADSPI_BK1_IO3,LCD_SEG3,TIM1_BKIN_COMP2,TIM8_BKIN_COMP2,TIM16_CH1,EVENTOUT
-PortA,PA7,,TIM1_CH1N,TIM3_CH2,TIM8_CH1N,,SPI1_MOSI,,,,,QUADSPI_BK1_IO2,LCD_SEG4,,,TIM17_CH1,EVENTOUT
-PortA,PA8,MCO,TIM1_CH1,,,,,,USART1_CK,,,OTG_FS_SOF,LCD_COM0,,,LPTIM2_OUT,EVENTOUT
-PortA,PA9,,TIM1_CH2,,,,,,USART1_TX,,,,LCD_COM1,,,TIM15_BKIN,EVENTOUT
-PortA,PA10,,TIM1_CH3,,,,,,USART1_RX,,,OTG_FS_ID,LCD_COM2,,,TIM17_BKIN,EVENTOUT
-PortA,PA11,,TIM1_CH4,TIM1_BKIN2,,,,,USART1_CTS,,CAN1_RX,OTG_FS_DM,,TIM1_BKIN2_COMP1,,,EVENTOUT
-PortA,PA12,,TIM1_ETR,,,,,,USART1_RTS_DE,,CAN1_TX,OTG_FS_DP,,,,,EVENTOUT
-PortA,PA13,JTMS-SWDIO,IR_OUT,,,,,,,,,OTG_FS_NOE,,,,,EVENTOUT
-PortA,PA14,JTCK-SWCLK,,,,,,,,,,,,,,,EVENTOUT
-PortA,PA15,JTDI,TIM2_CH1,TIM2_ETR,,,SPI1_NSS,SPI3_NSS,,UART4_RTS_DE,TSC_G3_IO1,,LCD_SEG17,,SAI2_FS_B,,EVENTOUT
-PortB,PB0,,TIM1_CH2N,TIM3_CH3,TIM8_CH2N,,,,USART3_CK,,,QUADSPI_BK1_IO1,LCD_SEG5,COMP1_OUT,,,EVENTOUT
-PortB,PB1,,TIM1_CH3N,TIM3_CH4,TIM8_CH3N,,,DFSDM_DATIN0,USART3_RTS_DE,,,QUADSPI_BK1_IO0,LCD_SEG6,,,LPTIM2_IN1,EVENTOUT
-PortB,PB2,RTC_OUT,LPTIM1_OUT,,,I2C3_SMBA,,DFSDM_CKIN0,,,,,,,,,EVENTOUT
-PortB,PB3,JTDO-TRACESWO,TIM2_CH2,,,,SPI1_SCK,SPI3_SCK,USART1_RTS_DE,,,,LCD_SEG7,,SAI1_SCK_B,,EVENTOUT
-PortB,PB4,NJTRST,,TIM3_CH1,,,SPI1_MISO,SPI3_MISO,USART1_CTS,UART5_RTS_DE,TSC_G2_IO1,,LCD_SEG8,,SAI1_MCLK_B,TIM17_BKIN,EVENTOUT
-PortB,PB5,,LPTIM1_IN1,TIM3_CH2,,I2C1_SMBA,SPI1_MOSI,SPI3_MOSI,USART1_CK,UART5_CTS,TSC_G2_IO2,,LCD_SEG9,COMP2_OUT,SAI1_SD_B,TIM16_BKIN,EVENTOUT
-PortB,PB6,,LPTIM1_ETR,TIM4_CH1,TIM8_BKIN2,I2C1_SCL,,DFSDM_DATIN5,USART1_TX,,TSC_G2_IO3,,,TIM8_BKIN2_COMP2,SAI1_FS_B,TIM16_CH1N,EVENTOUT
-PortB,PB7,,LPTIM1_IN2,TIM4_CH2,TIM8_BKIN,I2C1_SDA,,DFSDM_CKIN5,USART1_RX,UART4_CTS,TSC_G2_IO4,,LCD_SEG21,FMC_NL,TIM8_BKIN_COMP1,TIM17_CH1N,EVENTOUT
-PortB,PB8,,,TIM4_CH3,,I2C1_SCL,,DFSDM_DATIN6,,,CAN1_RX,,LCD_SEG16,SDMMC1_D4,SAI1_MCLK_A,TIM16_CH1,EVENTOUT
-PortB,PB9,,IR_OUT,TIM4_CH4,,I2C1_SDA,SPI2_NSS,DFSDM_CKIN6,,,CAN1_TX,,LCD_COM3,SDMMC1_D5,SAI1_FS_A,TIM17_CH1,EVENTOUT
-PortB,PB10,,TIM2_CH3,,,I2C2_SCL,SPI2_SCK,DFSDM_DATIN7,USART3_TX,LPUART1_RX,,QUADSPI_CLK,LCD_SEG10,COMP1_OUT,SAI1_SCK_A,,EVENTOUT
-PortB,PB11,,TIM2_CH4,,,I2C2_SDA,,DFSDM_CKIN7,USART3_RX,LPUART1_TX,,QUADSPI_NCS,LCD_SEG11,COMP2_OUT,,,EVENTOUT
-PortB,PB12,,TIM1_BKIN,,TIM1_BKIN_COMP2,I2C2_SMBA,SPI2_NSS,DFSDM_DATIN1,USART3_CK,LPUART1_RTS_DE,TSC_G1_IO1,,LCD_SEG12,SWPMI1_IO,SAI2_FS_A,TIM15_BKIN,EVENTOUT
-PortB,PB13,,TIM1_CH1N,,,I2C2_SCL,SPI2_SCK,DFSDM_CKIN1,USART3_CTS,LPUART1_CTS,TSC_G1_IO2,,LCD_SEG13,SWPMI1_TX,SAI2_SCK_A,TIM15_CH1N,EVENTOUT
-PortB,PB14,,TIM1_CH2N,,TIM8_CH2N,I2C2_SDA,SPI2_MISO,DFSDM_DATIN2,USART3_RTS_DE,,TSC_G1_IO3,,LCD_SEG14,SWPMI1_RX,SAI2_MCLK_A,TIM15_CH1,EVENTOUT
-PortB,PB15,RTC_REFIN,TIM1_CH3N,,TIM8_CH3N,,SPI2_MOSI,DFSDM_CKIN2,,,TSC_G1_IO4,,LCD_SEG15,SWPMI1_SUSPEND,SAI2_SD_A,TIM15_CH2,EVENTOUT
-PortC,PC0,,LPTIM1_IN1,,,I2C3_SCL,,DFSDM_DATIN4,,LPUART1_RX,,,LCD_SEG18,,,LPTIM2_IN1,EVENTOUT
-PortC,PC1,,LPTIM1_OUT,,,I2C3_SDA,,DFSDM_CKIN4,,LPUART1_TX,,,LCD_SEG19,,,,EVENTOUT
-PortC,PC2,,LPTIM1_IN2,,,,SPI2_MISO,DFSDM_CKOUT,,,,,LCD_SEG20,,,,EVENTOUT
-PortC,PC3,,LPTIM1_ETR,,,,SPI2_MOSI,,,,,,LCD_VLCD,,SAI1_SD_A,LPTIM2_ETR,EVENTOUT
-PortC,PC4,,,,,,,,USART3_TX,,,,LCD_SEG22,,,,EVENTOUT
-PortC,PC5,,,,,,,,USART3_RX,,,,LCD_SEG23,,,,EVENTOUT
-PortC,PC6,,,TIM3_CH1,TIM8_CH1,,,DFSDM_CKIN3,,,TSC_G4_IO1,,LCD_SEG24,SDMMC1_D6,SAI2_MCLK_A,,EVENTOUT
-PortC,PC7,,,TIM3_CH2,TIM8_CH2,,,DFSDM_DATIN3,,,TSC_G4_IO2,,LCD_SEG25,SDMMC1_D7,SAI2_MCLK_B,,EVENTOUT
-PortC,PC8,,,TIM3_CH3,TIM8_CH3,,,,,,TSC_G4_IO3,,LCD_SEG26,SDMMC1_D0,,,EVENTOUT
-PortC,PC9,,TIM8_BKIN2,TIM3_CH4,TIM8_CH4,,,,,,TSC_G4_IO4,OTG_FS_NOE,LCD_SEG27,SDMMC1_D1,SAI2_EXTCLK,TIM8_BKIN2_COMP1,EVENTOUT
-PortC,PC10,,,,,,,SPI3_SCK,USART3_TX,UART4_TX,TSC_G3_IO2,,LCD_COM4/LCD_SEG28/LCD_SEG40,SDMMC1_D2,SAI2_SCK_B,,EVENTOUT
-PortC,PC11,,,,,,,SPI3_MISO,USART3_RX,UART4_RX,TSC_G3_IO3,,LCD_COM5/LCD_SEG29/LCD_SEG41,SDMMC1_D3,SAI2_MCLK_B,,EVENTOUT
-PortC,PC12,,,,,,,SPI3_MOSI,USART3_CK,UART5_TX,TSC_G3_IO4,,LCD_COM6/LCD_SEG30/LCD_SEG42,SDMMC1_CK,SAI2_SD_B,,EVENTOUT
-PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT
-PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT
-PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT
-PortD,PD0,,,,,,SPI2_NSS,DFSDM_DATIN7,,,CAN1_RX,,,FMC_D2,,,EVENTOUT
-PortD,PD1,,,,,,SPI2_SCK,DFSDM_CKIN7,,,CAN1_TX,,,FMC_D3,,,EVENTOUT
-PortD,PD2,,,TIM3_ETR,,,,,USART3_RTS_DE,UART5_RX,TSC_SYNC,,LCD_COM7/LCD_SEG31/LCD_SEG43,SDMMC1_CMD,,,EVENTOUT
-PortD,PD3,,,,,,SPI2_MISO,DFSDM_DATIN0,USART2_CTS,,,,,FMC_CLK,,,EVENTOUT
-PortD,PD4,,,,,,SPI2_MOSI,DFSDM_CKIN0,USART2_RTS_DE,,,,,FMC_NOE,,,EVENTOUT
-PortD,PD5,,,,,,,,USART2_TX,,,,,FMC_NWE,,,EVENTOUT
-PortD,PD6,,,,,,,DFSDM_DATIN1,USART2_RX,,,,,FMC_NWAIT,SAI1_SD_A,,EVENTOUT
-PortD,PD7,,,,,,,DFSDM_CKIN1,USART2_CK,,,,,FMC_NE1,,,EVENTOUT
-PortD,PD8,,,,,,,,USART3_TX,,,,LCD_SEG28,FMC_D13,,,EVENTOUT
-PortD,PD9,,,,,,,,USART3_RX,,,,LCD_SEG29,FMC_D14,SAI2_MCLK_A,,EVENTOUT
-PortD,PD10,,,,,,,,USART3_CK,,TSC_G6_IO1,,LCD_SEG30,FMC_D15,SAI2_SCK_A,,EVENTOUT
-PortD,PD11,,,,,,,,USART3_CTS,,TSC_G6_IO2,,LCD_SEG31,FMC_A16,SAI2_SD_A,LPTIM2_ETR,EVENTOUT
-PortD,PD12,,,TIM4_CH1,,,,,USART3_RTS_DE,,TSC_G6_IO3,,LCD_SEG32,FMC_A17,SAI2_FS_A,LPTIM2_IN1,EVENTOUT
-PortD,PD13,,,TIM4_CH2,,,,,,,TSC_G6_IO4,,LCD_SEG33,FMC_A18,,LPTIM2_OUT,EVENTOUT
-PortD,PD14,,,TIM4_CH3,,,,,,,,,LCD_SEG34,FMC_D0,,,EVENTOUT
-PortD,PD15,,,TIM4_CH4,,,,,,,,,LCD_SEG35,FMC_D1,,,EVENTOUT
-PortE,PE0,,,TIM4_ETR,,,,,,,,,LCD_SEG36,FMC_NBL0,,TIM16_CH1,EVENTOUT
-PortE,PE1,,,,,,,,,,,,LCD_SEG37,FMC_NBL1,,TIM17_CH1,EVENTOUT
-PortE,PE2,TRACECK,,TIM3_ETR,,,,,,,TSC_G7_IO1,,LCD_SEG38,FMC_A23,SAI1_MCLK_A,,EVENTOUT
-PortE,PE3,TRACED0,,TIM3_CH1,,,,,,,TSC_G7_IO2,,LCD_SEG39,FMC_A19,SAI1_SD_B,,EVENTOUT
-PortE,PE4,TRACED1,,TIM3_CH2,,,,DFSDM_DATIN3,,,TSC_G7_IO3,,,FMC_A20,SAI1_FS_A,,EVENTOUT
-PortE,PE5,TRACED2,,TIM3_CH3,,,,DFSDM_CKIN3,,,TSC_G7_IO4,,,FMC_A21,SAI1_SCK_A,,EVENTOUT
-PortE,PE6,TRACED3,,TIM3_CH4,,,,,,,,,,FMC_A22,SAI1_SD_A,,EVENTOUT
-PortE,PE7,,TIM1_ETR,,,,,DFSDM_DATIN2,,,,,,FMC_D4,SAI1_SD_B,,EVENTOUT
-PortE,PE8,,TIM1_CH1N,,,,,DFSDM_CKIN2,,,,,,FMC_D5,SAI1_SCK_B,,EVENTOUT
-PortE,PE9,,TIM1_CH1,,,,,DFSDM_CKOUT,,,,,,FMC_D6,SAI1_FS_B,,EVENTOUT
-PortE,PE10,,TIM1_CH2N,,,,,DFSDM_DATIN4,,,TSC_G5_IO1,QUADSPI_CLK,,FMC_D7,SAI1_MCLK_B,,EVENTOUT
-PortE,PE11,,TIM1_CH2,,,,,DFSDM_CKIN4,,,TSC_G5_IO2,QUADSPI_NCS,,FMC_D8,,,EVENTOUT
-PortE,PE12,,TIM1_CH3N,,,,SPI1_NSS,DFSDM_DATIN5,,,TSC_G5_IO3,QUADSPI_BK1_IO0,,FMC_D9,,,EVENTOUT
-PortE,PE13,,TIM1_CH3,,,,SPI1_SCK,DFSDM_CKIN5,,,TSC_G5_IO4,QUADSPI_BK1_IO1,,FMC_D10,,,EVENTOUT
-PortE,PE14,,TIM1_CH4,TIM1_BKIN2,TIM1_BKIN2_COMP2,,SPI1_MISO,,,,,QUADSPI_BK1_IO2,,FMC_D11,,,EVENTOUT
-PortE,PE15,,TIM1_BKIN,,TIM1_BKIN_COMP1,,SPI1_MOSI,,,,,QUADSPI_BK1_IO3,,FMC_D12,,,EVENTOUT
-PortF,PF0,,,,,I2C2_SDA,,,,,,,,FMC_A0,,,EVENTOUT
-PortF,PF1,,,,,I2C2_SCL,,,,,,,,FMC_A1,,,EVENTOUT
-PortF,PF2,,,,,I2C2_SMBA,,,,,,,,FMC_A2,,,EVENTOUT
-PortF,PF3,,,,,,,,,,,,,FMC_A3,,,EVENTOUT
-PortF,PF4,,,,,,,,,,,,,FMC_A4,,,EVENTOUT
-PortF,PF5,,,,,,,,,,,,,FMC_A5,,,EVENTOUT
-PortF,PF6,,TIM5_ETR,TIM5_CH1,,,,,,,,,,,SAI1_SD_B,,EVENTOUT
-PortF,PF7,,,TIM5_CH2,,,,,,,,,,,SAI1_MCLK_B,,EVENTOUT
-PortF,PF8,,,TIM5_CH3,,,,,,,,,,,SAI1_SCK_B,,EVENTOUT
-PortF,PF9,,,TIM5_CH4,,,,,,,,,,,SAI1_FS_B,TIM15_CH1,EVENTOUT
-PortF,PF10,,,,,,,,,,,,,,,TIM15_CH2,EVENTOUT
-PortF,PF11,,,,,,,,,,,,,,,,EVENTOUT
-PortF,PF12,,,,,,,,,,,,,FMC_A6,,,EVENTOUT
-PortF,PF13,,,,,,,DFSDM_DATIN6,,,,,,FMC_A7,,,EVENTOUT
-PortF,PF14,,,,,,,DFSDM_CKIN6,,,TSC_G8_IO1,,,FMC_A8,,,EVENTOUT
-PortF,PF15,,,,,,,,,,TSC_G8_IO2,,,FMC_A9,,,EVENTOUT
-PortG,PG0,,,,,,,,,,TSC_G8_IO3,,,FMC_A10,,,EVENTOUT
-PortG,PG1,,,,,,,,,,TSC_G8_IO4,,,FMC_A11,,,EVENTOUT
-PortG,PG2,,,,,,SPI1_SCK,,,,,,,FMC_A12,SAI2_SCK_B,,EVENTOUT
-PortG,PG3,,,,,,SPI1_MISO,,,,,,,FMC_A13,SAI2_FS_B,,EVENTOUT
-PortG,PG4,,,,,,SPI1_MOSI,,,,,,,FMC_A14,SAI2_MCLK_B,,EVENTOUT
-PortG,PG5,,,,,,SPI1_NSS,,,LPUART1_CTS,,,,FMC_A15,SAI2_SD_B,,EVENTOUT
-PortG,PG6,,,,,I2C3_SMBA,,,,LPUART1_RTS_DE,,,,,,,EVENTOUT
-PortG,PG7,,,,,I2C3_SCL,,,,LPUART1_TX,,,,FMC_INT3,,,EVENTOUT
-PortG,PG8,,,,,I2C3_SDA,,,,LPUART1_RX,,,,,,,EVENTOUT
-PortG,PG9,,,,,,,SPI3_SCK,USART1_TX,,,,,FMC_NCE3/FMC_NE2,SAI2_SCK_A,TIM15_CH1N,EVENTOUT
-PortG,PG10,,LPTIM1_IN1,,,,,SPI3_MISO,USART1_RX,,,,,FMC_NE3,SAI2_FS_A,TIM15_CH1,EVENTOUT
-PortG,PG11,,LPTIM1_IN2,,,,,SPI3_MOSI,USART1_CTS,,,,,,SAI2_MCLK_A,TIM15_CH2,EVENTOUT
-PortG,PG12,,LPTIM1_ETR,,,,,SPI3_NSS,USART1_RTS_DE,,,,,FMC_NE4,SAI2_SD_A,,EVENTOUT
-PortG,PG13,,,,,I2C1_SDA,,,USART1_CK,,,,,FMC_A24,,,EVENTOUT
-PortG,PG14,,,,,I2C1_SCL,,,,,,,,FMC_A25,,,EVENTOUT
-PortG,PG15,,LPTIM1_OUT,,,I2C1_SMBA,,,,,,,,,,,EVENTOUT
-PortH,PH0,,,,,,,,,,,,,,,,EVENTOUT
-PortH,PH1,,,,,,,,,,,,,,,,EVENTOUT
+Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15,,
+,,SYS_AF,TIM1/TIM2/TIM5/TIM8/LPTIM1,TIM1/TIM2/TIM3/TIM4/TIM5,TIM8,I2C1/I2C2/I2C3,SPI1/SPI2,SPI3/DFSDM,USART1/USART2/USART3,UART4/UART5/LPUART1,CAN1/TSC,OTG_FS/QUADSPI,LCD,SDMMC1/COMP1/COMP2/FMC/SWPMI1,SAI1/SAI2,TIM2/TIM15/TIM16/TIM17/LPTIM2,EVENTOUT,ADC,COMP
+PortA,PA0,,TIM2_CH1,TIM5_CH1,TIM8_ETR,,,,USART2_CTS,UART4_TX,,,,,SAI1_EXTCLK,TIM2_ETR,EVENTOUT,ADC12_IN5,
+PortA,PA1,,TIM2_CH2,TIM5_CH2,,,,,USART2_RTS_DE,UART4_RX,,,LCD_SEG0,,,TIM15_CH1N,EVENTOUT,ADC12_IN6,
+PortA,PA2,,TIM2_CH3,TIM5_CH3,,,,,USART2_TX,,,,LCD_SEG1,,SAI2_EXTCLK,TIM15_CH1,EVENTOUT,ADC12_IN7,
+PortA,PA3,,TIM2_CH4,TIM5_CH4,,,,,USART2_RX,,,,LCD_SEG2,,,TIM15_CH2,EVENTOUT,ADC12_IN8,
+PortA,PA4,,,,,,SPI1_NSS,SPI3_NSS,USART2_CK,,,,,,SAI1_FS_B,LPTIM2_OUT,EVENTOUT,ADC12_IN9,
+PortA,PA5,,TIM2_CH1,TIM2_ETR,TIM8_CH1N,,SPI1_SCK,,,,,,,,,LPTIM2_ETR,EVENTOUT,ADC12_IN10,
+PortA,PA6,,TIM1_BKIN,TIM3_CH1,TIM8_BKIN,,SPI1_MISO,,USART3_CTS,,,QUADSPI_BK1_IO3,LCD_SEG3,TIM1_BKIN_COMP2,TIM8_BKIN_COMP2,TIM16_CH1,EVENTOUT,ADC12_IN11,
+PortA,PA7,,TIM1_CH1N,TIM3_CH2,TIM8_CH1N,,SPI1_MOSI,,,,,QUADSPI_BK1_IO2,LCD_SEG4,,,TIM17_CH1,EVENTOUT,ADC12_IN12,
+PortA,PA8,MCO,TIM1_CH1,,,,,,USART1_CK,,,OTG_FS_SOF,LCD_COM0,,,LPTIM2_OUT,EVENTOUT,,
+PortA,PA9,,TIM1_CH2,,,,,,USART1_TX,,,,LCD_COM1,,,TIM15_BKIN,EVENTOUT,,
+PortA,PA10,,TIM1_CH3,,,,,,USART1_RX,,,OTG_FS_ID,LCD_COM2,,,TIM17_BKIN,EVENTOUT,,
+PortA,PA11,,TIM1_CH4,TIM1_BKIN2,,,,,USART1_CTS,,CAN1_RX,OTG_FS_DM,,TIM1_BKIN2_COMP1,,,EVENTOUT,,
+PortA,PA12,,TIM1_ETR,,,,,,USART1_RTS_DE,,CAN1_TX,OTG_FS_DP,,,,,EVENTOUT,,
+PortA,PA13,JTMS-SWDIO,IR_OUT,,,,,,,,,OTG_FS_NOE,,,,,EVENTOUT,,
+PortA,PA14,JTCK-SWCLK,,,,,,,,,,,,,,,EVENTOUT,,
+PortA,PA15,JTDI,TIM2_CH1,TIM2_ETR,,,SPI1_NSS,SPI3_NSS,,UART4_RTS_DE,TSC_G3_IO1,,LCD_SEG17,,SAI2_FS_B,,EVENTOUT,,
+PortB,PB0,,TIM1_CH2N,TIM3_CH3,TIM8_CH2N,,,,USART3_CK,,,QUADSPI_BK1_IO1,LCD_SEG5,COMP1_OUT,,,EVENTOUT,ADC12_IN15,
+PortB,PB1,,TIM1_CH3N,TIM3_CH4,TIM8_CH3N,,,DFSDM_DATIN0,USART3_RTS_DE,,,QUADSPI_BK1_IO0,LCD_SEG6,,,LPTIM2_IN1,EVENTOUT,ADC12_IN16,COMP1_INN
+PortB,PB2,RTC_OUT,LPTIM1_OUT,,,I2C3_SMBA,,DFSDM_CKIN0,,,,,,,,,EVENTOUT,,COMP1_INP
+PortB,PB3,JTDO-TRACESWO,TIM2_CH2,,,,SPI1_SCK,SPI3_SCK,USART1_RTS_DE,,,,LCD_SEG7,,SAI1_SCK_B,,EVENTOUT,,COMP2_INM
+PortB,PB4,NJTRST,,TIM3_CH1,,,SPI1_MISO,SPI3_MISO,USART1_CTS,UART5_RTS_DE,TSC_G2_IO1,,LCD_SEG8,,SAI1_MCLK_B,TIM17_BKIN,EVENTOUT,,COMP2_INP
+PortB,PB5,,LPTIM1_IN1,TIM3_CH2,,I2C1_SMBA,SPI1_MOSI,SPI3_MOSI,USART1_CK,UART5_CTS,TSC_G2_IO2,,LCD_SEG9,COMP2_OUT,SAI1_SD_B,TIM16_BKIN,EVENTOUT,,
+PortB,PB6,,LPTIM1_ETR,TIM4_CH1,TIM8_BKIN2,I2C1_SCL,,DFSDM_DATIN5,USART1_TX,,TSC_G2_IO3,,,TIM8_BKIN2_COMP2,SAI1_FS_B,TIM16_CH1N,EVENTOUT,,COMP2_INP
+PortB,PB7,,LPTIM1_IN2,TIM4_CH2,TIM8_BKIN,I2C1_SDA,,DFSDM_CKIN5,USART1_RX,UART4_CTS,TSC_G2_IO4,,LCD_SEG21,FMC_NL,TIM8_BKIN_COMP1,TIM17_CH1N,EVENTOUT,,COMP2_INM
+PortB,PB8,,,TIM4_CH3,,I2C1_SCL,,DFSDM_DATIN6,,,CAN1_RX,,LCD_SEG16,SDMMC1_D4,SAI1_MCLK_A,TIM16_CH1,EVENTOUT,,
+PortB,PB9,,IR_OUT,TIM4_CH4,,I2C1_SDA,SPI2_NSS,DFSDM_CKIN6,,,CAN1_TX,,LCD_COM3,SDMMC1_D5,SAI1_FS_A,TIM17_CH1,EVENTOUT,,
+PortB,PB10,,TIM2_CH3,,,I2C2_SCL,SPI2_SCK,DFSDM_DATIN7,USART3_TX,LPUART1_RX,,QUADSPI_CLK,LCD_SEG10,COMP1_OUT,SAI1_SCK_A,,EVENTOUT,,
+PortB,PB11,,TIM2_CH4,,,I2C2_SDA,,DFSDM_CKIN7,USART3_RX,LPUART1_TX,,QUADSPI_NCS,LCD_SEG11,COMP2_OUT,,,EVENTOUT,,
+PortB,PB12,,TIM1_BKIN,,TIM1_BKIN_COMP2,I2C2_SMBA,SPI2_NSS,DFSDM_DATIN1,USART3_CK,LPUART1_RTS_DE,TSC_G1_IO1,,LCD_SEG12,SWPMI1_IO,SAI2_FS_A,TIM15_BKIN,EVENTOUT,,
+PortB,PB13,,TIM1_CH1N,,,I2C2_SCL,SPI2_SCK,DFSDM_CKIN1,USART3_CTS,LPUART1_CTS,TSC_G1_IO2,,LCD_SEG13,SWPMI1_TX,SAI2_SCK_A,TIM15_CH1N,EVENTOUT,,
+PortB,PB14,,TIM1_CH2N,,TIM8_CH2N,I2C2_SDA,SPI2_MISO,DFSDM_DATIN2,USART3_RTS_DE,,TSC_G1_IO3,,LCD_SEG14,SWPMI1_RX,SAI2_MCLK_A,TIM15_CH1,EVENTOUT,,
+PortB,PB15,RTC_REFIN,TIM1_CH3N,,TIM8_CH3N,,SPI2_MOSI,DFSDM_CKIN2,,,TSC_G1_IO4,,LCD_SEG15,SWPMI1_SUSPEND,SAI2_SD_A,TIM15_CH2,EVENTOUT,,
+PortC,PC0,,LPTIM1_IN1,,,I2C3_SCL,,DFSDM_DATIN4,,LPUART1_RX,,,LCD_SEG18,,,LPTIM2_IN1,EVENTOUT,ADC123_IN1,
+PortC,PC1,,LPTIM1_OUT,,,I2C3_SDA,,DFSDM_CKIN4,,LPUART1_TX,,,LCD_SEG19,,,,EVENTOUT,ADC123_IN2,
+PortC,PC2,,LPTIM1_IN2,,,,SPI2_MISO,DFSDM_CKOUT,,,,,LCD_SEG20,,,,EVENTOUT,ADC123_IN3,
+PortC,PC3,,LPTIM1_ETR,,,,SPI2_MOSI,,,,,,LCD_VLCD,,SAI1_SD_A,LPTIM2_ETR,EVENTOUT,ADC123_IN4,
+PortC,PC4,,,,,,,,USART3_TX,,,,LCD_SEG22,,,,EVENTOUT,ADC12_IN13,COMP1_INM
+PortC,PC5,,,,,,,,USART3_RX,,,,LCD_SEG23,,,,EVENTOUT,ADC12_IN14,COMP1_INP
+PortC,PC6,,,TIM3_CH1,TIM8_CH1,,,DFSDM_CKIN3,,,TSC_G4_IO1,,LCD_SEG24,SDMMC1_D6,SAI2_MCLK_A,,EVENTOUT,,
+PortC,PC7,,,TIM3_CH2,TIM8_CH2,,,DFSDM_DATIN3,,,TSC_G4_IO2,,LCD_SEG25,SDMMC1_D7,SAI2_MCLK_B,,EVENTOUT,,
+PortC,PC8,,,TIM3_CH3,TIM8_CH3,,,,,,TSC_G4_IO3,,LCD_SEG26,SDMMC1_D0,,,EVENTOUT,,
+PortC,PC9,,TIM8_BKIN2,TIM3_CH4,TIM8_CH4,,,,,,TSC_G4_IO4,OTG_FS_NOE,LCD_SEG27,SDMMC1_D1,SAI2_EXTCLK,TIM8_BKIN2_COMP1,EVENTOUT,,
+PortC,PC10,,,,,,,SPI3_SCK,USART3_TX,UART4_TX,TSC_G3_IO2,,LCD_COM4/LCD_SEG28/LCD_SEG40,SDMMC1_D2,SAI2_SCK_B,,EVENTOUT,,
+PortC,PC11,,,,,,,SPI3_MISO,USART3_RX,UART4_RX,TSC_G3_IO3,,LCD_COM5/LCD_SEG29/LCD_SEG41,SDMMC1_D3,SAI2_MCLK_B,,EVENTOUT,,
+PortC,PC12,,,,,,,SPI3_MOSI,USART3_CK,UART5_TX,TSC_G3_IO4,,LCD_COM6/LCD_SEG30/LCD_SEG42,SDMMC1_CK,SAI2_SD_B,,EVENTOUT,,
+PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT,,
+PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT,,
+PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT,,
+PortD,PD0,,,,,,SPI2_NSS,DFSDM_DATIN7,,,CAN1_RX,,,FMC_D2,,,EVENTOUT,,
+PortD,PD1,,,,,,SPI2_SCK,DFSDM_CKIN7,,,CAN1_TX,,,FMC_D3,,,EVENTOUT,,
+PortD,PD2,,,TIM3_ETR,,,,,USART3_RTS_DE,UART5_RX,TSC_SYNC,,LCD_COM7/LCD_SEG31/LCD_SEG43,SDMMC1_CMD,,,EVENTOUT,,
+PortD,PD3,,,,,,SPI2_MISO,DFSDM_DATIN0,USART2_CTS,,,,,FMC_CLK,,,EVENTOUT,,
+PortD,PD4,,,,,,SPI2_MOSI,DFSDM_CKIN0,USART2_RTS_DE,,,,,FMC_NOE,,,EVENTOUT,,
+PortD,PD5,,,,,,,,USART2_TX,,,,,FMC_NWE,,,EVENTOUT,,
+PortD,PD6,,,,,,,DFSDM_DATIN1,USART2_RX,,,,,FMC_NWAIT,SAI1_SD_A,,EVENTOUT,,
+PortD,PD7,,,,,,,DFSDM_CKIN1,USART2_CK,,,,,FMC_NE1,,,EVENTOUT,,
+PortD,PD8,,,,,,,,USART3_TX,,,,LCD_SEG28,FMC_D13,,,EVENTOUT,,
+PortD,PD9,,,,,,,,USART3_RX,,,,LCD_SEG29,FMC_D14,SAI2_MCLK_A,,EVENTOUT,,
+PortD,PD10,,,,,,,,USART3_CK,,TSC_G6_IO1,,LCD_SEG30,FMC_D15,SAI2_SCK_A,,EVENTOUT,,
+PortD,PD11,,,,,,,,USART3_CTS,,TSC_G6_IO2,,LCD_SEG31,FMC_A16,SAI2_SD_A,LPTIM2_ETR,EVENTOUT,,
+PortD,PD12,,,TIM4_CH1,,,,,USART3_RTS_DE,,TSC_G6_IO3,,LCD_SEG32,FMC_A17,SAI2_FS_A,LPTIM2_IN1,EVENTOUT,,
+PortD,PD13,,,TIM4_CH2,,,,,,,TSC_G6_IO4,,LCD_SEG33,FMC_A18,,LPTIM2_OUT,EVENTOUT,,
+PortD,PD14,,,TIM4_CH3,,,,,,,,,LCD_SEG34,FMC_D0,,,EVENTOUT,,
+PortD,PD15,,,TIM4_CH4,,,,,,,,,LCD_SEG35,FMC_D1,,,EVENTOUT,,
+PortE,PE0,,,TIM4_ETR,,,,,,,,,LCD_SEG36,FMC_NBL0,,TIM16_CH1,EVENTOUT,,
+PortE,PE1,,,,,,,,,,,,LCD_SEG37,FMC_NBL1,,TIM17_CH1,EVENTOUT,,
+PortE,PE2,TRACECK,,TIM3_ETR,,,,,,,TSC_G7_IO1,,LCD_SEG38,FMC_A23,SAI1_MCLK_A,,EVENTOUT,,
+PortE,PE3,TRACED0,,TIM3_CH1,,,,,,,TSC_G7_IO2,,LCD_SEG39,FMC_A19,SAI1_SD_B,,EVENTOUT,,
+PortE,PE4,TRACED1,,TIM3_CH2,,,,DFSDM_DATIN3,,,TSC_G7_IO3,,,FMC_A20,SAI1_FS_A,,EVENTOUT,,
+PortE,PE5,TRACED2,,TIM3_CH3,,,,DFSDM_CKIN3,,,TSC_G7_IO4,,,FMC_A21,SAI1_SCK_A,,EVENTOUT,,
+PortE,PE6,TRACED3,,TIM3_CH4,,,,,,,,,,FMC_A22,SAI1_SD_A,,EVENTOUT,,
+PortE,PE7,,TIM1_ETR,,,,,DFSDM_DATIN2,,,,,,FMC_D4,SAI1_SD_B,,EVENTOUT,,
+PortE,PE8,,TIM1_CH1N,,,,,DFSDM_CKIN2,,,,,,FMC_D5,SAI1_SCK_B,,EVENTOUT,,
+PortE,PE9,,TIM1_CH1,,,,,DFSDM_CKOUT,,,,,,FMC_D6,SAI1_FS_B,,EVENTOUT,,
+PortE,PE10,,TIM1_CH2N,,,,,DFSDM_DATIN4,,,TSC_G5_IO1,QUADSPI_CLK,,FMC_D7,SAI1_MCLK_B,,EVENTOUT,,
+PortE,PE11,,TIM1_CH2,,,,,DFSDM_CKIN4,,,TSC_G5_IO2,QUADSPI_NCS,,FMC_D8,,,EVENTOUT,,
+PortE,PE12,,TIM1_CH3N,,,,SPI1_NSS,DFSDM_DATIN5,,,TSC_G5_IO3,QUADSPI_BK1_IO0,,FMC_D9,,,EVENTOUT,,
+PortE,PE13,,TIM1_CH3,,,,SPI1_SCK,DFSDM_CKIN5,,,TSC_G5_IO4,QUADSPI_BK1_IO1,,FMC_D10,,,EVENTOUT,,
+PortE,PE14,,TIM1_CH4,TIM1_BKIN2,TIM1_BKIN2_COMP2,,SPI1_MISO,,,,,QUADSPI_BK1_IO2,,FMC_D11,,,EVENTOUT,,
+PortE,PE15,,TIM1_BKIN,,TIM1_BKIN_COMP1,,SPI1_MOSI,,,,,QUADSPI_BK1_IO3,,FMC_D12,,,EVENTOUT,,
+PortF,PF0,,,,,I2C2_SDA,,,,,,,,FMC_A0,,,EVENTOUT,,
+PortF,PF1,,,,,I2C2_SCL,,,,,,,,FMC_A1,,,EVENTOUT,,
+PortF,PF2,,,,,I2C2_SMBA,,,,,,,,FMC_A2,,,EVENTOUT,,
+PortF,PF3,,,,,,,,,,,,,FMC_A3,,,EVENTOUT,ADC3_IN6,
+PortF,PF4,,,,,,,,,,,,,FMC_A4,,,EVENTOUT,ADC3_IN7,
+PortF,PF5,,,,,,,,,,,,,FMC_A5,,,EVENTOUT,ADC3_IN8,
+PortF,PF6,,TIM5_ETR,TIM5_CH1,,,,,,,,,,,SAI1_SD_B,,EVENTOUT,ADC3_IN9,
+PortF,PF7,,,TIM5_CH2,,,,,,,,,,,SAI1_MCLK_B,,EVENTOUT,ADC3_IN10,
+PortF,PF8,,,TIM5_CH3,,,,,,,,,,,SAI1_SCK_B,,EVENTOUT,ADC3_IN11,
+PortF,PF9,,,TIM5_CH4,,,,,,,,,,,SAI1_FS_B,TIM15_CH1,EVENTOUT,ADC3_IN12,
+PortF,PF10,,,,,,,,,,,,,,,TIM15_CH2,EVENTOUT,ADC3_IN13,
+PortF,PF11,,,,,,,,,,,,,,,,EVENTOUT,,
+PortF,PF12,,,,,,,,,,,,,FMC_A6,,,EVENTOUT,,
+PortF,PF13,,,,,,,DFSDM_DATIN6,,,,,,FMC_A7,,,EVENTOUT,,
+PortF,PF14,,,,,,,DFSDM_CKIN6,,,TSC_G8_IO1,,,FMC_A8,,,EVENTOUT,,
+PortF,PF15,,,,,,,,,,TSC_G8_IO2,,,FMC_A9,,,EVENTOUT,,
+PortG,PG0,,,,,,,,,,TSC_G8_IO3,,,FMC_A10,,,EVENTOUT,,
+PortG,PG1,,,,,,,,,,TSC_G8_IO4,,,FMC_A11,,,EVENTOUT,,
+PortG,PG2,,,,,,SPI1_SCK,,,,,,,FMC_A12,SAI2_SCK_B,,EVENTOUT,,
+PortG,PG3,,,,,,SPI1_MISO,,,,,,,FMC_A13,SAI2_FS_B,,EVENTOUT,,
+PortG,PG4,,,,,,SPI1_MOSI,,,,,,,FMC_A14,SAI2_MCLK_B,,EVENTOUT,,
+PortG,PG5,,,,,,SPI1_NSS,,,LPUART1_CTS,,,,FMC_A15,SAI2_SD_B,,EVENTOUT,,
+PortG,PG6,,,,,I2C3_SMBA,,,,LPUART1_RTS_DE,,,,,,,EVENTOUT,,
+PortG,PG7,,,,,I2C3_SCL,,,,LPUART1_TX,,,,FMC_INT3,,,EVENTOUT,,
+PortG,PG8,,,,,I2C3_SDA,,,,LPUART1_RX,,,,,,,EVENTOUT,,
+PortG,PG9,,,,,,,SPI3_SCK,USART1_TX,,,,,FMC_NCE3/FMC_NE2,SAI2_SCK_A,TIM15_CH1N,EVENTOUT,,
+PortG,PG10,,LPTIM1_IN1,,,,,SPI3_MISO,USART1_RX,,,,,FMC_NE3,SAI2_FS_A,TIM15_CH1,EVENTOUT,,
+PortG,PG11,,LPTIM1_IN2,,,,,SPI3_MOSI,USART1_CTS,,,,,,SAI2_MCLK_A,TIM15_CH2,EVENTOUT,,
+PortG,PG12,,LPTIM1_ETR,,,,,SPI3_NSS,USART1_RTS_DE,,,,,FMC_NE4,SAI2_SD_A,,EVENTOUT,,
+PortG,PG13,,,,,I2C1_SDA,,,USART1_CK,,,,,FMC_A24,,,EVENTOUT,,
+PortG,PG14,,,,,I2C1_SCL,,,,,,,,FMC_A25,,,EVENTOUT,,
+PortG,PG15,,LPTIM1_OUT,,,I2C1_SMBA,,,,,,,,,,,EVENTOUT,,
+PortH,PH0,,,,,,,,,,,,,,,,EVENTOUT,,
+PortH,PH1,,,,,,,,,,,,,,,,EVENTOUT,,
diff --git a/stmhal/dac.c b/stmhal/dac.c
index 7493bb59ab..a9b1b9eca7 100644
--- a/stmhal/dac.c
+++ b/stmhal/dac.c
@@ -171,6 +171,14 @@ STATIC mp_obj_t pyb_dac_init_helper(pyb_dac_obj_t *self, mp_uint_t n_args, const
#endif
// stop anything already going on
+ __DMA1_CLK_ENABLE();
+ DMA_HandleTypeDef DMA_Handle;
+ /* Get currently configured dma */
+ dma_init_handle(&DMA_Handle, self->tx_dma_descr, (void*)NULL);
+ // Need to deinit DMA first
+ DMA_Handle.State = HAL_DMA_STATE_READY;
+ HAL_DMA_DeInit(&DMA_Handle);
+
HAL_DAC_Stop(&DAC_Handle, self->dac_channel);
if ((self->dac_channel == DAC_CHANNEL_1 && DAC_Handle.DMA_Handle1 != NULL)
|| (self->dac_channel == DAC_CHANNEL_2 && DAC_Handle.DMA_Handle2 != NULL)) {
diff --git a/stmhal/irq.h b/stmhal/irq.h
index f3a8a2cc9e..5a08a7d501 100644
--- a/stmhal/irq.h
+++ b/stmhal/irq.h
@@ -126,9 +126,6 @@ MP_DECLARE_CONST_FUN_OBJ(pyb_irq_stats_obj);
#define IRQ_PRI_OTG_HS 6
#define IRQ_SUBPRI_OTG_HS 0
-#define IRQ_PRI_TIM3 6
-#define IRQ_SUBPRI_TIM3 0
-
#define IRQ_PRI_TIM5 6
#define IRQ_SUBPRI_TIM5 0
diff --git a/stmhal/main.c b/stmhal/main.c
index 30dddaf989..2446225034 100644
--- a/stmhal/main.c
+++ b/stmhal/main.c
@@ -44,6 +44,7 @@
#include "pendsv.h"
#include "gccollect.h"
#include "readline.h"
+#include "modmachine.h"
#include "i2c.h"
#include "spi.h"
#include "uart.h"
@@ -137,8 +138,8 @@ static const char fresh_boot_py[] =
"import machine\r\n"
"import pyb\r\n"
"#pyb.main('main.py') # main script to run after this one\r\n"
-"#pyb.usb_mode('CDC+MSC') # act as a serial and a storage device\r\n"
-"#pyb.usb_mode('CDC+HID') # act as a serial device and a mouse\r\n"
+"#pyb.usb_mode('VCP+MSC') # act as a serial and a storage device\r\n"
+"#pyb.usb_mode('VCP+HID') # act as a serial device and a mouse\r\n"
;
static const char fresh_main_py[] =
@@ -410,6 +411,8 @@ soft_reset:
led_state(4, 0);
uint reset_mode = update_reset_mode(1);
+ machine_init();
+
#if MICROPY_HW_ENABLE_RTC
if (first_soft_reset) {
rtc_init_start(false);
diff --git a/stmhal/modmachine.c b/stmhal/modmachine.c
index 0b01058fa5..ca17eff807 100644
--- a/stmhal/modmachine.c
+++ b/stmhal/modmachine.c
@@ -44,6 +44,50 @@
#include "rtc.h"
#include "i2c.h"
#include "spi.h"
+#include "wdt.h"
+
+#if defined(MCU_SERIES_F4)
+// the HAL does not define these constants
+#define RCC_CSR_IWDGRSTF (0x20000000)
+#define RCC_CSR_PINRSTF (0x04000000)
+#elif defined(MCU_SERIES_L4)
+// L4 does not have a POR, so use BOR instead
+#define RCC_CSR_PORRSTF RCC_CSR_BORRSTF
+#endif
+
+#define PYB_RESET_SOFT (0)
+#define PYB_RESET_POWER_ON (1)
+#define PYB_RESET_HARD (2)
+#define PYB_RESET_WDT (3)
+#define PYB_RESET_DEEPSLEEP (4)
+
+STATIC uint32_t reset_cause;
+
+void machine_init(void) {
+ #if defined(MCU_SERIES_F4)
+ if (PWR->CSR & PWR_CSR_SBF) {
+ // came out of standby
+ reset_cause = PYB_RESET_DEEPSLEEP;
+ PWR->CR = PWR_CR_CSBF;
+ } else
+ #endif
+ {
+ // get reset cause from RCC flags
+ uint32_t state = RCC->CSR;
+ if (state & RCC_CSR_IWDGRSTF || state & RCC_CSR_WWDGRSTF) {
+ reset_cause = PYB_RESET_WDT;
+ } else if (state & RCC_CSR_PORRSTF || state & RCC_CSR_BORRSTF) {
+ reset_cause = PYB_RESET_POWER_ON;
+ } else if (state & RCC_CSR_PINRSTF) {
+ reset_cause = PYB_RESET_HARD;
+ } else {
+ // default is soft reset
+ reset_cause = PYB_RESET_SOFT;
+ }
+ }
+ // clear RCC reset flags
+ RCC->CSR = RCC_CSR_RMVF;
+}
// machine.info([dump_alloc_table])
// Print out lots of information about the board.
@@ -447,13 +491,10 @@ STATIC mp_obj_t machine_deepsleep(void) {
}
MP_DEFINE_CONST_FUN_OBJ_0(machine_deepsleep_obj, machine_deepsleep);
-#if 0
STATIC mp_obj_t machine_reset_cause(void) {
- return mp_obj_new_int(0);
- //return mp_obj_new_int(pyb_sleep_get_reset_cause());
+ return MP_OBJ_NEW_SMALL_INT(reset_cause);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause);
-#endif
STATIC const mp_map_elem_t machine_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_umachine) },
@@ -468,8 +509,8 @@ STATIC const mp_map_elem_t machine_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_idle), (mp_obj_t)&pyb_wfi_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sleep), (mp_obj_t)&machine_sleep_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_deepsleep), (mp_obj_t)&machine_deepsleep_obj },
-#if 0
{ MP_OBJ_NEW_QSTR(MP_QSTR_reset_cause), (mp_obj_t)&machine_reset_cause_obj },
+#if 0
{ MP_OBJ_NEW_QSTR(MP_QSTR_wake_reason), (mp_obj_t)&machine_wake_reason_obj },
#endif
@@ -490,10 +531,10 @@ STATIC const mp_map_elem_t machine_module_globals_table[] = {
// initialize master mode on the peripheral.
{ MP_OBJ_NEW_QSTR(MP_QSTR_I2C), (mp_obj_t)&machine_i2c_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SPI), (mp_obj_t)&pyb_spi_type },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_WDT), (mp_obj_t)&pyb_wdt_type },
#if 0
{ MP_OBJ_NEW_QSTR(MP_QSTR_UART), (mp_obj_t)&pyb_uart_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_Timer), (mp_obj_t)&pyb_timer_type },
- { MP_OBJ_NEW_QSTR(MP_QSTR_WDT), (mp_obj_t)&pyb_wdt_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_HeartBeat), (mp_obj_t)&pyb_heartbeat_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SD), (mp_obj_t)&pyb_sd_type },
@@ -501,11 +542,13 @@ STATIC const mp_map_elem_t machine_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_IDLE), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_ACTIVE) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SLEEP), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_LPDS) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_DEEPSLEEP), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_HIBERNATE) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_POWER_ON), MP_OBJ_NEW_SMALL_INT(PYB_SLP_PWRON_RESET) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_HARD_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_HARD_RESET) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_WDT_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_WDT_RESET) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_DEEPSLEEP_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_HIB_RESET) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_SOFT_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_SOFT_RESET) },
+#endif
+ { MP_OBJ_NEW_QSTR(MP_QSTR_PWRON_RESET), MP_OBJ_NEW_SMALL_INT(PYB_RESET_POWER_ON) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_HARD_RESET), MP_OBJ_NEW_SMALL_INT(PYB_RESET_HARD) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_WDT_RESET), MP_OBJ_NEW_SMALL_INT(PYB_RESET_WDT) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_DEEPSLEEP_RESET), MP_OBJ_NEW_SMALL_INT(PYB_RESET_DEEPSLEEP) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SOFT_RESET), MP_OBJ_NEW_SMALL_INT(PYB_RESET_SOFT) },
+#if 0
{ MP_OBJ_NEW_QSTR(MP_QSTR_WLAN_WAKE), MP_OBJ_NEW_SMALL_INT(PYB_SLP_WAKED_BY_WLAN) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_PIN_WAKE), MP_OBJ_NEW_SMALL_INT(PYB_SLP_WAKED_BY_GPIO) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_RTC_WAKE), MP_OBJ_NEW_SMALL_INT(PYB_SLP_WAKED_BY_RTC) },
diff --git a/stmhal/modmachine.h b/stmhal/modmachine.h
index 981728c272..042afb850c 100644
--- a/stmhal/modmachine.h
+++ b/stmhal/modmachine.h
@@ -31,6 +31,8 @@
#include "py/nlr.h"
#include "py/obj.h"
+void machine_init(void);
+
MP_DECLARE_CONST_FUN_OBJ(machine_info_obj);
MP_DECLARE_CONST_FUN_OBJ(machine_unique_id_obj);
MP_DECLARE_CONST_FUN_OBJ(machine_reset_obj);
diff --git a/stmhal/modusocket.c b/stmhal/modusocket.c
index fbd1196446..c0e30ce050 100644
--- a/stmhal/modusocket.c
+++ b/stmhal/modusocket.c
@@ -83,6 +83,7 @@ STATIC mp_obj_t socket_close(mp_obj_t self_in) {
mod_network_socket_obj_t *self = self_in;
if (self->nic != MP_OBJ_NULL) {
self->nic_type->close(self);
+ self->nic = MP_OBJ_NULL;
}
return mp_const_none;
}
diff --git a/stmhal/mpconfigport.h b/stmhal/mpconfigport.h
index c2a2cbc1f1..98d1e17e3d 100644
--- a/stmhal/mpconfigport.h
+++ b/stmhal/mpconfigport.h
@@ -93,6 +93,7 @@
#define MICROPY_PY_UHASHLIB (1)
#define MICROPY_PY_MACHINE (1)
#define MICROPY_PY_MACHINE_I2C (1)
+#define MICROPY_PY_MACHINE_SPI (1)
#define MICROPY_PY_FRAMEBUF (1)
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1)
@@ -202,8 +203,6 @@ extern const struct _mp_obj_module_t mp_module_network;
typedef int mp_int_t; // must be pointer size
typedef unsigned int mp_uint_t; // must be pointer size
-typedef void *machine_ptr_t; // must be of pointer size
-typedef const void *machine_const_ptr_t; // must be of pointer size
typedef long mp_off_t;
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)
diff --git a/stmhal/pin.c b/stmhal/pin.c
index e3ae0be400..9bd4e7a6d9 100644
--- a/stmhal/pin.c
+++ b/stmhal/pin.c
@@ -199,15 +199,15 @@ STATIC void pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t
if (mode == GPIO_MODE_INPUT) {
mode_qst = MP_QSTR_IN;
} else if (mode == GPIO_MODE_OUTPUT_PP) {
- mode_qst = MP_QSTR_OUT_PP;
+ mode_qst = MP_QSTR_OUT;
} else if (mode == GPIO_MODE_OUTPUT_OD) {
- mode_qst = MP_QSTR_OUT_OD;
+ mode_qst = MP_QSTR_OPEN_DRAIN;
} else {
af = true;
if (mode == GPIO_MODE_AF_PP) {
- mode_qst = MP_QSTR_AF_PP;
+ mode_qst = MP_QSTR_ALT;
} else {
- mode_qst = MP_QSTR_AF_OD;
+ mode_qst = MP_QSTR_ALT_OPEN_DRAIN;
}
}
mp_print_str(print, qstr_str(mode_qst));
diff --git a/stmhal/spi.c b/stmhal/spi.c
index fbc5f9aa48..85f1709200 100644
--- a/stmhal/spi.c
+++ b/stmhal/spi.c
@@ -30,6 +30,7 @@
#include "py/nlr.h"
#include "py/runtime.h"
#include "py/mphal.h"
+#include "extmod/machine_spi.h"
#include "irq.h"
#include "pin.h"
#include "genhdr/pins.h"
@@ -327,6 +328,90 @@ STATIC HAL_StatusTypeDef spi_wait_dma_finished(SPI_HandleTypeDef *spi, uint32_t
return HAL_OK;
}
+STATIC void spi_transfer(mp_obj_base_t *self_in, size_t src_len, const uint8_t *src_buf, size_t dest_len, uint8_t *dest_buf, uint32_t timeout) {
+ // Note: there seems to be a problem sending 1 byte using DMA the first
+ // time directly after the SPI/DMA is initialised. The cause of this is
+ // unknown but we sidestep the issue by using polling for 1 byte transfer.
+
+ pyb_spi_obj_t *self = (pyb_spi_obj_t*)self_in;
+ HAL_StatusTypeDef status;
+
+ if (dest_len == 0) {
+ // send only
+ if (src_len == 1 || query_irq() == IRQ_STATE_DISABLED) {
+ status = HAL_SPI_Transmit(self->spi, (uint8_t*)src_buf, src_len, timeout);
+ } else {
+ DMA_HandleTypeDef tx_dma;
+ dma_init(&tx_dma, self->tx_dma_descr, self->spi);
+ self->spi->hdmatx = &tx_dma;
+ self->spi->hdmarx = NULL;
+ status = HAL_SPI_Transmit_DMA(self->spi, (uint8_t*)src_buf, src_len);
+ if (status == HAL_OK) {
+ status = spi_wait_dma_finished(self->spi, timeout);
+ }
+ dma_deinit(self->tx_dma_descr);
+ }
+ } else if (src_len == 0) {
+ // receive only
+ if (dest_len == 1 || query_irq() == IRQ_STATE_DISABLED) {
+ status = HAL_SPI_Receive(self->spi, dest_buf, dest_len, timeout);
+ } else {
+ DMA_HandleTypeDef tx_dma, rx_dma;
+ if (self->spi->Init.Mode == SPI_MODE_MASTER) {
+ // in master mode the HAL actually does a TransmitReceive call
+ dma_init(&tx_dma, self->tx_dma_descr, self->spi);
+ self->spi->hdmatx = &tx_dma;
+ } else {
+ self->spi->hdmatx = NULL;
+ }
+ dma_init(&rx_dma, self->rx_dma_descr, self->spi);
+ self->spi->hdmarx = &rx_dma;
+
+ status = HAL_SPI_Receive_DMA(self->spi, dest_buf, dest_len);
+ if (status == HAL_OK) {
+ status = spi_wait_dma_finished(self->spi, timeout);
+ }
+ if (self->spi->hdmatx != NULL) {
+ dma_deinit(self->tx_dma_descr);
+ }
+ dma_deinit(self->rx_dma_descr);
+ }
+ } else {
+ // send and receive
+ // requires src_len==dest_len
+ if (src_len == 1 || query_irq() == IRQ_STATE_DISABLED) {
+ status = HAL_SPI_TransmitReceive(self->spi, (uint8_t*)src_buf, dest_buf, src_len, timeout);
+ } else {
+ DMA_HandleTypeDef tx_dma, rx_dma;
+ dma_init(&tx_dma, self->tx_dma_descr, self->spi);
+ self->spi->hdmatx = &tx_dma;
+ dma_init(&rx_dma, self->rx_dma_descr, self->spi);
+ self->spi->hdmarx = &rx_dma;
+ status = HAL_SPI_TransmitReceive_DMA(self->spi, (uint8_t*)src_buf, dest_buf, src_len);
+ if (status == HAL_OK) {
+ status = spi_wait_dma_finished(self->spi, timeout);
+ }
+ dma_deinit(self->tx_dma_descr);
+ dma_deinit(self->rx_dma_descr);
+ }
+ }
+
+ if (status != HAL_OK) {
+ mp_hal_raise(status);
+ }
+}
+
+STATIC void spi_transfer_machine(mp_obj_base_t *self_in, size_t src_len, const uint8_t *src_buf, size_t dest_len, uint8_t *dest_buf) {
+ if (src_len == 1 && dest_len > 1) {
+ // this catches read and readinto
+ // copy the single output byte to the dest buffer and use that as source
+ memset(dest_buf, src_buf[0], dest_len);
+ src_len = dest_len;
+ src_buf = dest_buf;
+ }
+ spi_transfer(self_in, src_len, src_buf, dest_len, dest_buf, 100);
+}
+
/******************************************************************************/
/* Micro Python bindings */
@@ -556,27 +641,7 @@ STATIC mp_obj_t pyb_spi_send(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
pyb_buf_get_for_send(args[0].u_obj, &bufinfo, data);
// send the data
- // Note: there seems to be a problem sending 1 byte using DMA the first
- // time directly after the SPI/DMA is initialised. The cause of this is
- // unknown but we sidestep the issue by using polling for 1 byte transfer.
- HAL_StatusTypeDef status;
- if (bufinfo.len == 1 || query_irq() == IRQ_STATE_DISABLED) {
- status = HAL_SPI_Transmit(self->spi, bufinfo.buf, bufinfo.len, args[1].u_int);
- } else {
- DMA_HandleTypeDef tx_dma;
- dma_init(&tx_dma, self->tx_dma_descr, self->spi);
- self->spi->hdmatx = &tx_dma;
- self->spi->hdmarx = NULL;
- status = HAL_SPI_Transmit_DMA(self->spi, bufinfo.buf, bufinfo.len);
- if (status == HAL_OK) {
- status = spi_wait_dma_finished(self->spi, args[1].u_int);
- }
- dma_deinit(self->tx_dma_descr);
- }
-
- if (status != HAL_OK) {
- mp_hal_raise(status);
- }
+ spi_transfer((mp_obj_base_t*)self, bufinfo.len, bufinfo.buf, 0, NULL, args[1].u_int);
return mp_const_none;
}
@@ -610,34 +675,7 @@ STATIC mp_obj_t pyb_spi_recv(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
mp_obj_t o_ret = pyb_buf_get_for_recv(args[0].u_obj, &vstr);
// receive the data
- HAL_StatusTypeDef status;
- if (vstr.len == 1 || query_irq() == IRQ_STATE_DISABLED) {
- status = HAL_SPI_Receive(self->spi, (uint8_t*)vstr.buf, vstr.len, args[1].u_int);
- } else {
- DMA_HandleTypeDef tx_dma, rx_dma;
- if (self->spi->Init.Mode == SPI_MODE_MASTER) {
- // in master mode the HAL actually does a TransmitReceive call
- dma_init(&tx_dma, self->tx_dma_descr, self->spi);
- self->spi->hdmatx = &tx_dma;
- } else {
- self->spi->hdmatx = NULL;
- }
- dma_init(&rx_dma, self->rx_dma_descr, self->spi);
- self->spi->hdmarx = &rx_dma;
-
- status = HAL_SPI_Receive_DMA(self->spi, (uint8_t*)vstr.buf, vstr.len);
- if (status == HAL_OK) {
- status = spi_wait_dma_finished(self->spi, args[1].u_int);
- }
- if (self->spi->hdmatx != NULL) {
- dma_deinit(self->tx_dma_descr);
- }
- dma_deinit(self->rx_dma_descr);
- }
-
- if (status != HAL_OK) {
- mp_hal_raise(status);
- }
+ spi_transfer((mp_obj_base_t*)self, 0, NULL, vstr.len, (uint8_t*)vstr.buf, args[1].u_int);
// return the received data
if (o_ret != MP_OBJ_NULL) {
@@ -706,27 +744,8 @@ STATIC mp_obj_t pyb_spi_send_recv(mp_uint_t n_args, const mp_obj_t *pos_args, mp
}
}
- // send and receive the data
- HAL_StatusTypeDef status;
- if (bufinfo_send.len == 1 || query_irq() == IRQ_STATE_DISABLED) {
- status = HAL_SPI_TransmitReceive(self->spi, bufinfo_send.buf, bufinfo_recv.buf, bufinfo_send.len, args[2].u_int);
- } else {
- DMA_HandleTypeDef tx_dma, rx_dma;
- dma_init(&tx_dma, self->tx_dma_descr, self->spi);
- self->spi->hdmatx = &tx_dma;
- dma_init(&rx_dma, self->rx_dma_descr, self->spi);
- self->spi->hdmarx = &rx_dma;
- status = HAL_SPI_TransmitReceive_DMA(self->spi, bufinfo_send.buf, bufinfo_recv.buf, bufinfo_send.len);
- if (status == HAL_OK) {
- status = spi_wait_dma_finished(self->spi, args[2].u_int);
- }
- dma_deinit(self->tx_dma_descr);
- dma_deinit(self->rx_dma_descr);
- }
-
- if (status != HAL_OK) {
- mp_hal_raise(status);
- }
+ // do the transfer
+ spi_transfer((mp_obj_base_t*)self, bufinfo_send.len, bufinfo_send.buf, bufinfo_recv.len, bufinfo_recv.buf, args[2].u_int);
// return the received data
if (o_ret != MP_OBJ_NULL) {
@@ -741,6 +760,13 @@ STATIC const mp_map_elem_t pyb_spi_locals_dict_table[] = {
// instance methods
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_spi_init_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&pyb_spi_deinit_obj },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_machine_spi_read_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&mp_machine_spi_readinto_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_machine_spi_write_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_write_readinto), (mp_obj_t)&mp_machine_spi_write_readinto_obj },
+
+ // legacy methods
{ MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&pyb_spi_send_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&pyb_spi_recv_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_send_recv), (mp_obj_t)&pyb_spi_send_recv_obj },
@@ -766,10 +792,15 @@ STATIC const mp_map_elem_t pyb_spi_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pyb_spi_locals_dict, pyb_spi_locals_dict_table);
+STATIC const mp_machine_spi_p_t pyb_spi_p = {
+ .transfer = spi_transfer_machine,
+};
+
const mp_obj_type_t pyb_spi_type = {
{ &mp_type_type },
.name = MP_QSTR_SPI,
.print = pyb_spi_print,
.make_new = pyb_spi_make_new,
+ .protocol = &pyb_spi_p,
.locals_dict = (mp_obj_t)&pyb_spi_locals_dict,
};
diff --git a/stmhal/stm32_it.c b/stmhal/stm32_it.c
index c9af20ce58..d2f8c271c4 100644
--- a/stmhal/stm32_it.c
+++ b/stmhal/stm32_it.c
@@ -556,6 +556,12 @@ void TIM1_TRG_COM_TIM17_IRQHandler(void) {
}
#endif
+void TIM1_CC_IRQHandler(void) {
+ IRQ_ENTER(TIM1_CC_IRQn);
+ timer_irq_handler(1);
+ IRQ_EXIT(TIM1_CC_IRQn);
+}
+
void TIM2_IRQHandler(void) {
IRQ_ENTER(TIM2_IRQn);
timer_irq_handler(2);
@@ -581,18 +587,23 @@ void TIM5_IRQHandler(void) {
IRQ_EXIT(TIM5_IRQn);
}
+#if defined(TIM6) // STM32F401 doesn't have TIM6
void TIM6_DAC_IRQHandler(void) {
IRQ_ENTER(TIM6_DAC_IRQn);
timer_irq_handler(6);
IRQ_EXIT(TIM6_DAC_IRQn);
}
+#endif
+#if defined(TIM7) // STM32F401 doesn't have TIM7
void TIM7_IRQHandler(void) {
IRQ_ENTER(TIM7_IRQn);
timer_irq_handler(7);
IRQ_EXIT(TIM7_IRQn);
}
+#endif
+#if defined(TIM8) // STM32F401 doesn't have TIM8
void TIM8_BRK_TIM12_IRQHandler(void) {
IRQ_ENTER(TIM8_BRK_TIM12_IRQn);
timer_irq_handler(12);
@@ -614,11 +625,18 @@ void TIM8_UP_IRQHandler(void) {
}
#endif
+void TIM8_CC_IRQHandler(void) {
+ IRQ_ENTER(TIM8_CC_IRQn);
+ timer_irq_handler(8);
+ IRQ_EXIT(TIM8_CC_IRQn);
+}
+
void TIM8_TRG_COM_TIM14_IRQHandler(void) {
IRQ_ENTER(TIM8_TRG_COM_TIM14_IRQn);
timer_irq_handler(14);
IRQ_EXIT(TIM8_TRG_COM_TIM14_IRQn);
}
+#endif
// UART/USART IRQ handlers
void USART1_IRQHandler(void) {
diff --git a/stmhal/timer.c b/stmhal/timer.c
index f1f14f3315..5727a95b73 100644
--- a/stmhal/timer.c
+++ b/stmhal/timer.c
@@ -601,8 +601,15 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *self, mp_uint_t n_args, c
}
// set IRQ priority (if not a special timer)
- if (self->tim_id != 3 && self->tim_id != 5) {
+ if (self->tim_id != 5) {
HAL_NVIC_SetPriority(self->irqn, IRQ_PRI_TIMX, IRQ_SUBPRI_TIMX);
+ if (self->tim_id == 1) {
+ HAL_NVIC_SetPriority(TIM1_CC_IRQn, IRQ_PRI_TIMX, IRQ_SUBPRI_TIMX);
+ #if defined(TIM8)
+ } else if (self->tim_id == 8) {
+ HAL_NVIC_SetPriority(TIM8_CC_IRQn, IRQ_PRI_TIMX, IRQ_SUBPRI_TIMX);
+ #endif
+ }
}
// init TIM
@@ -932,7 +939,7 @@ STATIC mp_obj_t pyb_timer_channel(mp_uint_t n_args, const mp_obj_t *pos_args, mp
if (chan->callback == mp_const_none) {
HAL_TIM_PWM_Start(&self->tim, TIMER_CHANNEL(chan));
} else {
- HAL_TIM_PWM_Start_IT(&self->tim, TIMER_CHANNEL(chan));
+ pyb_timer_channel_callback(chan, chan->callback);
}
// Start the complimentary channel too (if its supported)
if (IS_TIM_CCXN_INSTANCE(self->tim.Instance, TIMER_CHANNEL(chan))) {
@@ -970,7 +977,7 @@ STATIC mp_obj_t pyb_timer_channel(mp_uint_t n_args, const mp_obj_t *pos_args, mp
if (chan->callback == mp_const_none) {
HAL_TIM_OC_Start(&self->tim, TIMER_CHANNEL(chan));
} else {
- HAL_TIM_OC_Start_IT(&self->tim, TIMER_CHANNEL(chan));
+ pyb_timer_channel_callback(chan, chan->callback);
}
// Start the complimentary channel too (if its supported)
if (IS_TIM_CCXN_INSTANCE(self->tim.Instance, TIMER_CHANNEL(chan))) {
@@ -997,7 +1004,7 @@ STATIC mp_obj_t pyb_timer_channel(mp_uint_t n_args, const mp_obj_t *pos_args, mp
if (chan->callback == mp_const_none) {
HAL_TIM_IC_Start(&self->tim, TIMER_CHANNEL(chan));
} else {
- HAL_TIM_IC_Start_IT(&self->tim, TIMER_CHANNEL(chan));
+ pyb_timer_channel_callback(chan, chan->callback);
}
break;
}
@@ -1294,7 +1301,16 @@ STATIC mp_obj_t pyb_timer_channel_callback(mp_obj_t self_in, mp_obj_t callback)
self->callback = mp_const_none;
} else if (mp_obj_is_callable(callback)) {
self->callback = callback;
- HAL_NVIC_EnableIRQ(self->timer->irqn);
+ uint8_t tim_id = self->timer->tim_id;
+ if (tim_id == 1) {
+ HAL_NVIC_EnableIRQ(TIM1_CC_IRQn);
+ #if defined(TIM8) // STM32F401 doesn't have a TIM8
+ } else if (tim_id == 8) {
+ HAL_NVIC_EnableIRQ(TIM8_CC_IRQn);
+ #endif
+ } else {
+ HAL_NVIC_EnableIRQ(self->timer->irqn);
+ }
// start timer, so that it interrupts on overflow
switch (self->mode) {
case CHANNEL_MODE_PWM_NORMAL:
diff --git a/stmhal/wdt.c b/stmhal/wdt.c
new file mode 100644
index 0000000000..d9a089d011
--- /dev/null
+++ b/stmhal/wdt.c
@@ -0,0 +1,108 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdio.h>
+
+#include STM32_HAL_H
+
+#include "py/runtime.h"
+#include "wdt.h"
+
+typedef struct _pyb_wdt_obj_t {
+ mp_obj_base_t base;
+} pyb_wdt_obj_t;
+
+STATIC pyb_wdt_obj_t pyb_wdt = {{&pyb_wdt_type}};
+
+STATIC mp_obj_t pyb_wdt_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
+ // parse arguments
+ enum { ARG_id, ARG_timeout };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_id, MP_ARG_INT, {.u_int = 0} },
+ { MP_QSTR_timeout, MP_ARG_INT, {.u_int = 5000} },
+ };
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ mp_int_t id = args[ARG_id].u_int;
+ if (id != 0) {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "WDT(%d) does not exist", id));
+ }
+
+ // timeout is in milliseconds
+ mp_int_t timeout = args[ARG_timeout].u_int;
+
+ // compute prescaler
+ uint32_t prescaler;
+ for (prescaler = 0; prescaler < 6 && timeout >= 512; ++prescaler, timeout /= 2) {
+ }
+
+ // convert milliseconds to ticks
+ timeout *= 8; // 32kHz / 4 = 8 ticks per millisecond (approx)
+ if (timeout <= 0) {
+ mp_raise_ValueError("WDT timeout too short");
+ } else if (timeout > 0xfff) {
+ mp_raise_ValueError("WDT timeout too long");
+ }
+ timeout -= 1;
+
+ // set the reload register
+ while (IWDG->SR & 2) {
+ }
+ IWDG->KR = 0x5555;
+ IWDG->RLR = timeout;
+
+ // set the prescaler
+ while (IWDG->SR & 1) {
+ }
+ IWDG->KR = 0x5555;
+ IWDG->PR = prescaler;
+
+ // start the watch dog
+ IWDG->KR = 0xcccc;
+
+ return (mp_obj_t)&pyb_wdt;
+}
+
+STATIC mp_obj_t pyb_wdt_feed(mp_obj_t self_in) {
+ (void)self_in;
+ IWDG->KR = 0xaaaa;
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_wdt_feed_obj, pyb_wdt_feed);
+
+STATIC const mp_map_elem_t pyb_wdt_locals_dict_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR_feed), (mp_obj_t)&pyb_wdt_feed_obj },
+};
+
+STATIC MP_DEFINE_CONST_DICT(pyb_wdt_locals_dict, pyb_wdt_locals_dict_table);
+
+const mp_obj_type_t pyb_wdt_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_WDT,
+ .make_new = pyb_wdt_make_new,
+ .locals_dict = (mp_obj_t)&pyb_wdt_locals_dict,
+};
diff --git a/stmhal/wdt.h b/stmhal/wdt.h
new file mode 100644
index 0000000000..362d6ef68b
--- /dev/null
+++ b/stmhal/wdt.h
@@ -0,0 +1,27 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+extern const mp_obj_type_t pyb_wdt_type;