diff options
Diffstat (limited to 'stmhal')
-rw-r--r-- | stmhal/Makefile | 4 | ||||
-rw-r--r-- | stmhal/adc.c | 80 | ||||
-rw-r--r-- | stmhal/boards/STM32F7DISC/mpconfigboard.h | 13 | ||||
-rwxr-xr-x | stmhal/boards/make-pins.py | 6 | ||||
-rw-r--r-- | stmhal/boards/stm32l476_af.csv | 238 | ||||
-rw-r--r-- | stmhal/dac.c | 8 | ||||
-rw-r--r-- | stmhal/irq.h | 3 | ||||
-rw-r--r-- | stmhal/main.c | 7 | ||||
-rw-r--r-- | stmhal/modmachine.c | 65 | ||||
-rw-r--r-- | stmhal/modmachine.h | 2 | ||||
-rw-r--r-- | stmhal/modusocket.c | 1 | ||||
-rw-r--r-- | stmhal/mpconfigport.h | 3 | ||||
-rw-r--r-- | stmhal/pin.c | 8 | ||||
-rw-r--r-- | stmhal/spi.c | 171 | ||||
-rw-r--r-- | stmhal/stm32_it.c | 18 | ||||
-rw-r--r-- | stmhal/timer.c | 26 | ||||
-rw-r--r-- | stmhal/wdt.c | 108 | ||||
-rw-r--r-- | stmhal/wdt.h | 27 |
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; |