From 7d096160c017559cf6e42cf4d80f6c859df446d5 Mon Sep 17 00:00:00 2001 From: Yuuki NAGAO Date: Wed, 23 Jul 2025 07:56:24 +0900 Subject: [PATCH 1/3] lib/stm32: Add STM32U5 platform. Temporary reference to: https://github.com/yn386/stm32lib/tree/stm32u5-1.8.0 Signed-off-by: Yuuki NAGAO --- .gitmodules | 4 ++-- lib/stm32lib | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index 02849ec9bdd11..16d03b5b6e2db 100644 --- a/.gitmodules +++ b/.gitmodules @@ -12,8 +12,8 @@ url = https://github.com/micropython/berkeley-db-1.xx [submodule "lib/stm32lib"] path = lib/stm32lib - url = https://github.com/micropython/stm32lib - branch = work-F0-1.9.0+F4-1.16.0+F7-1.7.0+G0-1.5.1+G4-1.3.0+H7-1.6.0+L0-1.11.2+L1-1.10.3+L4-1.17.0+WB-1.10.0+WL-1.1.0 + url = https://github.com/yn386/stm32lib.git + branch = stm32u5-v1.8.0 [submodule "lib/nrfx"] path = lib/nrfx url = https://github.com/NordicSemiconductor/nrfx.git diff --git a/lib/stm32lib b/lib/stm32lib index 8b2bb4ef44fbf..0ee11dae08989 160000 --- a/lib/stm32lib +++ b/lib/stm32lib @@ -1 +1 @@ -Subproject commit 8b2bb4ef44fbfab5075ed9d09e83ddc3754b9257 +Subproject commit 0ee11dae08989a0f18252e4fb065aeb4b676d3bc From 9f56804a476463833f6186414fc39565c7d1db5e Mon Sep 17 00:00:00 2001 From: Yuuki NAGAO Date: Tue, 22 Jul 2025 23:17:09 +0900 Subject: [PATCH 2/3] stm32: Add STM32U5 support. This change adds STM32U5 support to the STM32 port. STM32U5A5ZJ: https://www.st.com/ja/microcontrollers-microprocessors/stm32u5a5zj.html Signed-off-by: Yuuki NAGAO --- ports/stm32/Makefile | 4 +- ports/stm32/adc.c | 56 ++++-- ports/stm32/adc.h | 2 + ports/stm32/boards/stm32u5a5_af.csv | 158 +++++++++++++++++ ports/stm32/boards/stm32u5a5xj.ld | 35 ++++ ports/stm32/boards/stm32u5xx_hal_conf_base.h | 176 +++++++++++++++++++ ports/stm32/dac.c | 16 +- ports/stm32/dma.c | 65 ++++++- ports/stm32/dma.h | 6 +- ports/stm32/extint.c | 44 +++-- ports/stm32/extint.h | 7 +- ports/stm32/flash.c | 14 +- ports/stm32/i2c.c | 17 +- ports/stm32/machine_adc.c | 36 ++-- ports/stm32/machine_i2c.c | 4 +- ports/stm32/machine_uart.c | 2 +- ports/stm32/mpconfigboard_common.h | 19 ++ ports/stm32/mphalport.c | 5 +- ports/stm32/mphalport.h | 2 + ports/stm32/powerctrl.c | 21 ++- ports/stm32/powerctrlboot.c | 2 +- ports/stm32/pyb_i2c.c | 12 +- ports/stm32/rtc.c | 25 ++- ports/stm32/spi.c | 8 +- ports/stm32/stm32.mk | 2 + ports/stm32/stm32_it.c | 36 +++- ports/stm32/system_stm32.c | 83 ++++++++- ports/stm32/timer.c | 13 +- ports/stm32/uart.c | 24 ++- ports/stm32/usb.c | 2 + ports/stm32/usbd_conf.c | 33 +++- 31 files changed, 822 insertions(+), 107 deletions(-) create mode 100644 ports/stm32/boards/stm32u5a5_af.csv create mode 100644 ports/stm32/boards/stm32u5a5xj.ld create mode 100644 ports/stm32/boards/stm32u5xx_hal_conf_base.h diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index abca3a05f8c7a..2c2edc73a2009 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -367,7 +367,7 @@ HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_,\ ) endif -ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 g0 g4 h5 h7 l0 l1 l4 n6 wb)) +ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 g0 g4 h5 h7 l0 l1 l4 n6 u5 wb)) HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_,\ hal_pcd.c \ hal_pcd_ex.c \ @@ -408,7 +408,7 @@ $(BUILD)/$(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_hal_mmc.o: CFLAGS += -Wno endif endif -ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 g0 g4 h5 h7 n6)) +ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 g0 g4 h5 h7 n6 u5)) HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_,\ hal_dma_ex.c \ ) diff --git a/ports/stm32/adc.c b/ports/stm32/adc.c index f47e9eaad7b35..6b99756bd98b2 100644 --- a/ports/stm32/adc.c +++ b/ports/stm32/adc.c @@ -107,13 +107,17 @@ #define ADC_CAL2 ((uint16_t *)(ADC_CAL_ADDRESS + 4)) #define ADC_CAL_BITS (12) -#elif defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L1) || defined(STM32L4) || defined(STM32N6) || defined(STM32WB) +#elif defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L1) || defined(STM32L4) || defined(STM32N6) || defined(STM32U5) || defined(STM32WB) #define ADC_SCALE_V (((float)VREFINT_CAL_VREF) / 1000.0f) #define ADC_CAL_ADDRESS (VREFINT_CAL_ADDR) #define ADC_CAL1 (TEMPSENSOR_CAL1_ADDR) #define ADC_CAL2 (TEMPSENSOR_CAL2_ADDR) +#if defined(STM32U5) +#define ADC_CAL_BITS (14) +#else #define ADC_CAL_BITS (12) // UM2319/UM2570, __HAL_ADC_CALC_TEMPERATURE: 'corresponds to a resolution of 12 bits' +#endif #elif defined(STM32H7) @@ -169,6 +173,8 @@ #elif defined(STM32N6) // ADC2 VINP 16 #define VBAT_DIV (4) +#elif defined(STM32U5) +#define VBAT_DIV (4) #else #error Unsupported processor #endif @@ -228,6 +234,14 @@ static inline uint32_t adc_get_internal_channel(uint32_t channel) { } else if (channel == 18) { channel = ADC_CHANNEL_VBAT; } + #elif defined(STM32U5) + if (channel == 0) { + channel = ADC_CHANNEL_VREFINT; + } else if (channel == 18) { + channel = ADC_CHANNEL_VBAT; + } else if (channel == 19) { + channel = ADC_CHANNEL_TEMPSENSOR; + } #endif return channel; } @@ -242,7 +256,7 @@ static bool is_adcx_channel(int channel) { // The HAL of STM32L1 defines some channels those may not be available on package return __HAL_ADC_IS_CHANNEL_INTERNAL(channel) || (channel < MP_ARRAY_SIZE(pin_adcall_table) && pin_adcall_table[channel]); - #elif defined(STM32G0) || defined(STM32H7) + #elif defined(STM32G0) || defined(STM32H7) || defined(STM32U5) return __HAL_ADC_IS_CHANNEL_INTERNAL(channel) || IS_ADC_CHANNEL(__HAL_ADC_DECIMAL_NB_TO_CHANNEL(channel)); #elif defined(STM32G4) || defined(STM32L4) || defined(STM32WB) @@ -263,7 +277,7 @@ static void adc_wait_for_eoc_or_timeout(ADC_HandleTypeDef *adcHandle, int32_t ti uint32_t tickstart = HAL_GetTick(); #if defined(STM32F4) || defined(STM32F7) || defined(STM32L1) while ((adcHandle->Instance->SR & ADC_FLAG_EOC) != ADC_FLAG_EOC) { - #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32N6) || defined(STM32WB) + #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32N6) || defined(STM32U5) || defined(STM32WB) while (READ_BIT(adcHandle->Instance->ISR, ADC_FLAG_EOC) != ADC_FLAG_EOC) { #else #error Unsupported processor @@ -297,7 +311,8 @@ static void adcx_clock_enable(ADC_HandleTypeDef *adch) { if (__HAL_RCC_GET_ADC_SOURCE() == RCC_ADCCLKSOURCE_NONE) { __HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_SYSCLK); } - __HAL_RCC_ADC_CLK_ENABLE(); + #elif defined(STM32U5) + __HAL_RCC_ADC12_CLK_ENABLE(); #else #error Unsupported processor #endif @@ -343,8 +358,8 @@ static void adcx_init_periph(ADC_HandleTypeDef *adch, uint32_t resolution) { adch->Init.LowPowerAutoWait = DISABLE; adch->Init.DataAlign = ADC_DATAALIGN_RIGHT; adch->Init.DMAContinuousRequests = DISABLE; - #elif defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L4) || defined(STM32WB) - #if defined(STM32G4) || defined(STM32H5) + #elif defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L4) || defined(STM32U5) || defined(STM32WB) + #if defined(STM32G4) || defined(STM32H5) || defined(STM32U5) adch->Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV16; #else adch->Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1; @@ -355,6 +370,12 @@ static void adcx_init_periph(ADC_HandleTypeDef *adch, uint32_t resolution) { adch->Init.OversamplingMode = DISABLE; adch->Init.DataAlign = ADC_DATAALIGN_RIGHT; adch->Init.DMAContinuousRequests = DISABLE; + #if defined(STM32U5) + adch->Init.GainCompensation = 0; + adch->Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH; + adch->Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE; + adch->Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR; + #endif #elif defined(STM32N6) adch->Init.GainCompensation = 0; adch->Init.ScanConvMode = ADC_SCAN_DISABLE; @@ -370,7 +391,7 @@ static void adcx_init_periph(ADC_HandleTypeDef *adch, uint32_t resolution) { HAL_ADC_Init(adch); - #if defined(STM32H7) + #if defined(STM32H7) || defined(STM32U5) HAL_ADCEx_Calibration_Start(adch, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED); #endif #if defined(STM32G0) @@ -401,6 +422,8 @@ static void adc_config_channel(ADC_HandleTypeDef *adc_handle, uint32_t channel) if (__HAL_ADC_IS_CHANNEL_INTERNAL(channel) == 0) { channel = __HAL_ADC_DECIMAL_NB_TO_CHANNEL(channel); } + #elif defined(STM32U5) + sConfig.Rank = ADC_REGULAR_RANK_1; #else sConfig.Rank = 1; #endif @@ -457,6 +480,15 @@ static void adc_config_channel(ADC_HandleTypeDef *adc_handle, uint32_t channel) sConfig.OffsetSignedSaturation = DISABLE; sConfig.OffsetSaturation = DISABLE; sConfig.OffsetSign = ADC_OFFSET_SIGN_POSITIVE; + #elif defined(STM32U5) + if (__HAL_ADC_IS_CHANNEL_INTERNAL(channel)) { + sConfig.SamplingTime = ADC_SAMPLETIME_391CYCLES_5; + } else { + sConfig.SamplingTime = ADC4_SAMPLETIME_3CYCLES_5; + } + sConfig.SingleDiff = ADC_SINGLE_ENDED; + sConfig.OffsetNumber = ADC_OFFSET_NONE; + sConfig.Offset = 0; #else #error Unsupported processor #endif @@ -678,7 +710,7 @@ static mp_obj_t adc_read_timed(mp_obj_t self_in, mp_obj_t buf_in, mp_obj_t freq_ // for subsequent samples we can just set the "start sample" bit #if defined(STM32F4) || defined(STM32F7) || defined(STM32L1) self->handle.Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART; - #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32N6) || defined(STM32WB) + #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32N6) || defined(STM32U5) || defined(STM32WB) SET_BIT(self->handle.Instance->CR, ADC_CR_ADSTART); #else #error Unsupported processor @@ -788,7 +820,7 @@ static mp_obj_t adc_read_timed_multi(mp_obj_t adc_array_in, mp_obj_t buf_array_i // ADC is started: set the "start sample" bit #if defined(STM32F4) || defined(STM32F7) || defined(STM32L1) adc->handle.Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART; - #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32N6) || defined(STM32WB) + #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32N6) || defined(STM32U5) || defined(STM32WB) SET_BIT(adc->handle.Instance->CR, ADC_CR_ADSTART); #else #error Unsupported processor @@ -939,7 +971,7 @@ float adc_read_core_temp_float(ADC_HandleTypeDef *adcHandle) { return 0.0f; // TODO #else - #if defined(STM32G4) || defined(STM32L1) || defined(STM32L4) + #if defined(STM32G4) || defined(STM32L1) || defined(STM32L4) || defined(STM32U5) // Update the reference correction factor before reading tempsensor // because TS_CAL1 and TS_CAL2 of STM32G4,L1/L4 are at VDDA=3.0V adc_read_core_vref(adcHandle); @@ -953,7 +985,7 @@ float adc_read_core_temp_float(ADC_HandleTypeDef *adcHandle) { return 0; } float core_temp_avg_slope = (*ADC_CAL2 - *ADC_CAL1) / 100.0f; - #elif defined(STM32H5) || defined(STM32WB) + #elif defined(STM32H5) || defined(STM32U5) || defined(STM32WB) int32_t raw_value = adc_config_and_read_ref(adcHandle, ADC_CHANNEL_TEMPSENSOR); float core_temp_avg_slope = (*ADC_CAL2 - *ADC_CAL1) / 100.0f; #else @@ -966,7 +998,7 @@ float adc_read_core_temp_float(ADC_HandleTypeDef *adcHandle) { } float adc_read_core_vbat(ADC_HandleTypeDef *adcHandle) { - #if defined(STM32G4) || defined(STM32L4) + #if defined(STM32G4) || defined(STM32L4) || defined(STM32U5) // Update the reference correction factor before reading tempsensor // because VREFINT of STM32G4,L4 is at VDDA=3.0V adc_read_core_vref(adcHandle); diff --git a/ports/stm32/adc.h b/ports/stm32/adc.h index 0adc9ac2be648..96947c3266fb7 100644 --- a/ports/stm32/adc.h +++ b/ports/stm32/adc.h @@ -56,6 +56,8 @@ static inline void adc_deselect_vbat(ADC_TypeDef *adc, uint32_t channel) { adc_common = adc == ADC3 ? ADC3_COMMON : ADC12_COMMON; #elif defined(STM32L4) adc_common = __LL_ADC_COMMON_INSTANCE(0); + #elif defined(STM32U5) + adc_common = ADC12_COMMON; #elif defined(STM32WL) adc_common = ADC_COMMON; #endif diff --git a/ports/stm32/boards/stm32u5a5_af.csv b/ports/stm32/boards/stm32u5a5_af.csv new file mode 100644 index 0000000000000..94afd5aca73ea --- /dev/null +++ b/ports/stm32/boards/stm32u5a5_af.csv @@ -0,0 +1,158 @@ +Port ,Pin ,AF0 ,AF1 ,AF2 ,AF3 ,AF4 ,AF5 ,AF6 ,AF7 ,AF8 ,AF9 ,AF10 ,AF11 ,AF12 ,AF13 ,AF14 ,AF15 ,ADC + , ,CRS/LPTIM1/SYS_AF,LPTIM1/TIM1/2/5/8,I2C5/6/LPTIM1/2/3/TIM1/2/3/4/5,ADF1/I2C4/OCTOSPIM_P1/OTG_HS/SAI1/SPI2/TIM1/8/USART2,DCMI/I2C1/2/3/4/5/LPTIM3,DCMI/I2C4/MDF1/OCTOSPIM_P1/2/SPI1/2/3,I2C3/MDF1/OCTOSPIM_P2/SPI3,LCD/USART1/2/3/6,HSPI1/LCD/LPUART1/SDMMC1/UART4/5,CAN1/TSC,CRS/DCMI/OCTOSPIM_P1/2/OTG_HS,DSI/FMC/LPGPIO1/SDMMC2/UCPD1,COMP1/2/FMC/SDMMC1/2/SYS_AF,LPTIM2/4/SAI1/2,LPTIM2/3/TIM2/15/16/17,SYS ,ADC +PortA,PA0 , ,TIM2_CH1 ,TIM5_CH1 ,TIM8_ETR , ,,SPI3_RDY ,USART2_CTS,UART4_TX ,,OCTOSPIM_P2_NCS,,SDMMC2_CMD,AUDIOCLK,TIM2_ETR ,EVENTOUT,ADC1_IN5/ADC2_IN5 +PortA,PA1 ,LPTIM1_CH2,TIM2_CH2 ,TIM5_CH2 , ,I2C1_SMBA ,SPI1_SCK,,USART2_RTS_DE,UART4_RX ,,OCTOSPIM_P1_DQS,LPGPIO1_P0, , ,TIM15_CH1N,EVENTOUT,ADC1_IN6/ADC2_IN6 +PortA,PA2 , ,TIM2_CH3 ,TIM5_CH3 , , ,SPI1_RDY, ,USART2_TX ,LPUART1_TX, ,OCTOSPIM_P1_NCS,UCPD1_FRSTX1, , ,TIM15_CH1,EVENTOUT,ADC1_IN7/ADC2_IN7 +PortA,PA3 , ,TIM2_CH4 ,TIM5_CH4 ,SAI1_CK1, ,,,USART2_RX ,LPUART1_RX, ,OCTOSPIM_P1_CLK,LPGPIO1_P1, ,SAI1_MCLK_A,TIM15_CH2,EVENTOUT,ADC1_IN8/ADC2_IN8 +PortA,PA4 , , ,,OCTOSPIM_P1_NCS, ,SPI1_NSS,SPI3_NSS,USART2_CK ,, ,DCMI_HSYNC/PSSI_DE, , ,SAI1_FS_B,LPTIM2_CH1,EVENTOUT,ADC1_IN9/ADC2_IN9/ADC4_IN9 +PortA,PA5 ,CSLEEP,TIM2_CH1 ,TIM2_ETR,TIM8_CH1N ,PSSI_D14,SPI1_SCK, ,USART3_RX,,,,,,,LPTIM2_ETR,EVENTOUT,ADC1_IN10/ADC2_IN10/ADC4_IN10 +PortA,PA6 ,CDSTOP,TIM1_BKIN ,TIM3_CH1 ,TIM8_BKIN ,DCMI_PIXCLK/PSSI_PDCK,SPI1_MISO,,USART3_CTS,LPUART1_CTS, ,OCTOSPIM_P1_IO3,LPGPIO1_P2, ,,TIM16_CH1,EVENTOUT,ADC1_IN11/ADC2_IN11/ADC4_IN11 +PortA,PA7 ,SRDSTOP,TIM1_CH1N ,TIM3_CH2 ,TIM8_CH1N ,I2C3_SCL,SPI1_MOSI, ,USART3_TX,, ,OCTOSPIM_P1_IO2,,,LPTIM2_CH2,TIM17_CH1,EVENTOUT,ADC1_IN12/ADC2_IN12/ADC4_IN20 +PortA,PA8 ,MCO,TIM1_CH1 , ,SAI1_CK2,,SPI1_RDY , ,USART1_CK , , ,OTG_HS_SOF,,TRACECLK,SAI1_SCK_A,LPTIM2_CH1,EVENTOUT, +PortA,PA9 , ,TIM1_CH2 , ,SPI2_SCK,,DCMI_D0/PSSI_D0, ,USART1_TX ,,,,,,SAI1_FS_A,TIM15_BKIN,EVENTOUT, +PortA,PA10,CRS_SYNC,TIM1_CH3 ,LPTIM2_IN2,SAI1_D1,,DCMI_D1/PSSI_D1,,USART1_RX , ,,OTG_HS_ID,,,SAI1_SD_A,TIM17_BKIN,EVENTOUT, +PortA,PA11, ,TIM1_CH4 ,TIM1_BKIN2,, ,SPI1_MISO,,USART1_CTS, ,FDCAN1_RX ,,,,,,EVENTOUT, +PortA,PA12, ,TIM1_ETR , ,, ,SPI1_MOSI,OCTOSPIM_P2_NCS,USART1_RTS_DE,,FDCAN1_TX ,, , ,, ,EVENTOUT, +PortA,PA13,JTMS/SWDIO ,IR_OUT, , , , , , , , ,, , ,SAI1_SD_B, ,EVENTOUT, +PortA,PA14,JTCK/SWCLK ,LPTIM1_CH1, , ,I2C1_SMBA,I2C4_SMBA, , , , ,OTG_HS_SOF, , ,SAI1_FS_B, ,EVENTOUT, +PortA,PA15,JTDI ,TIM2_CH1 ,TIM2_ETR,USART2_RX,,SPI1_NSS,SPI3_NSS,USART3_RTS_DE,UART4_RTS_DE,,,,,SAI2_FS_B,,EVENTOUT, +PortB,PB0 , ,TIM1_CH2N ,TIM3_CH3 ,TIM8_CH2N,LPTIM3_CH1,SPI1_NSS,,USART3_CK,, ,OCTOSPIM_P1_IO1,LPGPIO1_P9,COMP1_OUT,AUDIOCLK,,EVENTOUT,ADC1_IN15/ADC2_IN15/ADC4_IN18 +PortB,PB1 , ,TIM1_CH3N ,TIM3_CH4 ,TIM8_CH3N,LPTIM3_CH2, ,MDF1_SDI0,USART3_RTS_DE,LPUART1_RTS_DE, ,OCTOSPIM_P1_IO0,LPGPIO1_P3, , ,LPTIM2_IN1,EVENTOUT,ADC1_IN16/ADC2_IN16/ADC4_IN19 +PortB,PB2 ,,LPTIM1_CH1,,TIM8_CH4N,I2C3_SMBA,SPI1_RDY,MDF1_CKI0,,LCD_B1,,OCTOSPIM_P1_DQS,UCPD1_FRSTX1,,, ,EVENTOUT,ADC1_IN17/ADC2_IN17 +PortB,PB3 ,JTDO/TRACESWO,TIM2_CH2 ,LPTIM1_CH1,ADF1_CCK0,I2C1_SDA,SPI1_SCK,SPI3_SCK,USART1_RTS_DE,,,CRS_SYNC ,LPGPIO1_P11,SDMMC2_D2,SAI1_SCK_B,,EVENTOUT, +PortB,PB4 ,NJTRST ,LPTIM1_CH2 ,TIM3_CH1 ,ADF1_SDI0,I2C3_SDA,SPI1_MISO,SPI3_MISO,USART1_CTS,UART5_RTS_DE,TSC_G2_IO1,DCMI_D12/PSSI_D12,LPGPIO1_P12,SDMMC2_D3,SAI1_MCLK_B,TIM17_BKIN,EVENTOUT, +PortB,PB5 , ,LPTIM1_IN1 ,TIM3_CH2 ,OCTOSPI1_NCLK,I2C1_SMBA ,SPI1_MOSI,SPI3_MOSI,USART1_CK,UART5_CTS,TSC_G2_IO2,DCMI_D10/PSSI_D10,,COMP2_OUT,SAI1_SD_B,TIM16_BKIN,EVENTOUT, +PortB,PB6 , ,LPTIM1_ETR ,TIM4_CH1 ,TIM8_BKIN2,I2C1_SCL ,I2C4_SCL,MDF1_SDI5,USART1_TX ,,TSC_G2_IO3,DCMI_D5/PSSI_D5, ,,SAI1_FS_B,TIM16_CH1N,EVENTOUT, +PortB,PB7 , ,LPTIM1_IN2,TIM4_CH2 ,TIM8_BKIN,I2C1_SDA ,I2C4_SDA,MDF1_CKI5,USART1_RX ,UART4_CTS,TSC_G2_IO4,DCMI_VSYNC/PSSI_RDY,,FMC_NL,,TIM17_CH1N,EVENTOUT, +PortB,PB8 , , ,TIM4_CH3 ,SAI1_CK1,I2C1_SCL ,MDF1_CCK0,SPI3_RDY,LCD_B1,SDMMC1_CKIN,FDCAN1_RX ,DCMI_D6/PSSI_D6,SDMMC2_D4,SDMMC1_D4,SAI1_MCLK_A,TIM16_CH1,EVENTOUT, +PortB,PB9 , ,IR_OUT ,TIM4_CH4 ,SAI1_D2,I2C1_SDA ,SPI2_NSS,,,SDMMC1_CDIR,FDCAN1_TX ,DCMI_D7/PSSI_D7,SDMMC2_D5,SDMMC1_D5,SAI1_FS_A,TIM17_CH1,EVENTOUT, +PortB,PB10, ,TIM2_CH3 ,LPTIM3_CH1 ,I2C4_SCL,I2C2_SCL ,SPI2_SCK, ,USART3_TX ,LPUART1_RX,TSC_SYNC,OCTOSPIM_P1_CLK,LPGPIO1_P4,COMP1_OUT,SAI1_SCK_A, ,EVENTOUT, +PortB,PB11, ,TIM2_CH4 , ,I2C4_SDA,I2C2_SDA ,SPI2_RDY ,,USART3_RX ,LPUART1_TX, ,OCTOSPIM_P1_NCS,,COMP2_OUT, , ,EVENTOUT, +PortB,PB12, ,TIM1_BKIN ,I2C6_SMBA,,I2C2_SMBA,SPI2_NSS,MDF1_SDI1,USART3_CK ,LPUART1_RTS_DE,TSC_G1_IO1,OCTOSPIM_P1_NCLK,, ,SAI2_FS_A,TIM15_BKIN,EVENTOUT, +PortB,PB13, ,TIM1_CH1N ,LPTIM3_IN1 ,,I2C2_SCL,SPI2_SCK,MDF1_CKI1,USART3_CTS,LPUART1_CTS,TSC_G1_IO2,,,,SAI2_SCK_A,TIM15_CH1N,EVENTOUT, +PortB,PB14, ,TIM1_CH2N ,LPTIM3_ETR,TIM8_CH2N,I2C2_SDA,SPI2_MISO,MDF1_SDI2,USART3_RTS_DE,,TSC_G1_IO3, , ,SDMMC2_D0,SAI2_MCLK_A,TIM15_CH1,EVENTOUT, +PortB,PB15,RTC_REFIN ,TIM1_CH3N ,LPTIM2_IN2,TIM8_CH3N , ,SPI2_MOSI,MDF1_CKI2,,,,,FMC_NBL1,SDMMC2_D1,SAI2_SD_A,TIM15_CH2,EVENTOUT, +PortC,PC0 , ,LPTIM1_IN1 , ,OCTOSPIM_P1_IO7,I2C3_SCL,SPI2_RDY,MDF1_SDI4,USART6_CTS,LPUART1_RX,,,,SDMMC1_D5,SAI2_FS_A,LPTIM2_IN1,EVENTOUT,ADC1_IN1/ADC2_IN1/ADC4_IN1 +PortC,PC1 ,TRACED0 ,LPTIM1_CH1,,SPI2_MOSI,I2C3_SDA,,MDF1_CKI4,USART6_CK,LPUART1_TX,,OCTOSPIM_P1_IO4,,SDMMC2_CK,SAI1_SD_A, ,EVENTOUT,ADC1_IN2/ADC2_IN2/ADC4_IN2 +PortC,PC2 ,,LPTIM1_IN2 ,, , ,SPI2_MISO,MDF1_CCK1,USART6_RX, ,,OCTOSPIM_P1_IO5,LPGPIO1_P5,, , ,EVENTOUT,ADC1_IN3/ADC2_IN3/ADC4_IN3 +PortC,PC3 ,,LPTIM1_ETR,LPTIM3_CH1,SAI1_D1, ,SPI2_MOSI,,USART6_TX, ,,OCTOSPIM_P1_IO6,,,SAI1_SD_A,LPTIM2_ETR,EVENTOUT, +PortC,PC4 , ,,I2C6_SMBA,,,,,USART3_RX , , ,OCTOSPIM_P1_IO7,,,, ,EVENTOUT,ADC1_IN13/ADC2_IN13/ADC4_IN22 +PortC,PC5 , ,TIM1_CH4N ,,SAI1_D3,PSSI_D15, ,,USART3_RX,,,,,,,,EVENTOUT,ADC1_IN14/ADC2_IN14/ADC4_IN23 +PortC,PC6 ,CSLEEP, ,TIM3_CH1,TIM8_CH1 , ,,MDF1_CKI3,LCD_R0,SDMMC1_D0DIR ,TSC_G4_IO1,DCMI_D0/PSSI_D0,SDMMC2_D6,SDMMC1_D6,SAI2_MCLK_A, ,EVENTOUT, +PortC,PC7 ,CDSTOP, ,TIM3_CH2 ,TIM8_CH2 , , ,MDF1_SDI3,LCD_R1,SDMMC1_D123DIR ,TSC_G4_IO2,DCMI_D1/PSSI_D1,SDMMC2_D7,SDMMC1_D7,SAI2_MCLK_B,LPTIM2_CH2,EVENTOUT, +PortC,PC8 ,SRDSTOP, ,TIM3_CH3 ,TIM8_CH3 , , , ,USART6_RX,,TSC_G4_IO3,DCMI_D2/PSSI_D2,,SDMMC1_D0 ,,LPTIM3_CH1,EVENTOUT, +PortC,PC9 ,TRACED0,TIM8_BKIN2,TIM3_CH4 ,TIM8_CH4 ,DCMI_D3/PSSI_D3,, ,USART6_TX,,TSC_G4_IO4,,,SDMMC1_D1 ,,LPTIM3_CH2,EVENTOUT, +PortC,PC10,TRACED1, ,LPTIM3_ETR ,ADF1_CCK1, , ,SPI3_SCK,USART3_TX ,UART4_TX ,TSC_G3_IO2,DCMI_D8/PSSI_D8,LPGPIO1_P8,SDMMC1_D2 ,SAI2_SCK_B, ,EVENTOUT, +PortC,PC11, , ,LPTIM3_IN1 ,ADF1_SDI0,DCMI_D2/PSSI_D2,OCTOSPIM_P1_NCS,SPI3_MISO,USART3_RX ,UART4_RX ,TSC_G3_IO3,DCMI_D4/PSSI_D4,UCPD1_FRSTX2,SDMMC1_D3 ,SAI2_MCLK_B, ,EVENTOUT, +PortC,PC12,TRACED3 , , , , ,,SPI3_MOSI,USART3_CK ,UART5_TX ,TSC_G3_IO4,DCMI_D9/PSSI_D9,LPGPIO1_P10,SAI2_SD_B,, ,EVENTOUT, +PortC,PC13, , , , , , , , ,,,,,,,,EVENTOUT, +PortC,PC14, , , , , , , , ,,,,,,,,EVENTOUT, +PortC,PC15, , , , , , , , ,,,,,,,,EVENTOUT, +PortD,PD0 , , ,I2C6_SDA,TIM8_CH4N ,I2C5_SDA,SPI2_NSS , , ,LCD_B4,FDCAN1_RX , ,,FMC_D2, , ,EVENTOUT, +PortD,PD1 , , ,I2C6_SCL,,I2C5_SCL,SPI2_SCK, , ,LCD_B5,FDCAN1_TX , , ,FMC_D3, , ,EVENTOUT, +PortD,PD2 ,TRACED2 , ,TIM3_ETR , ,I2C5_SMBA, , ,USART3_RTS_DE,UART5_RX ,TSC_SYNC,DCMI_D11/PSSI_D11,LPGPIO1_P7,SDMMC1_CMD ,LPTIM4_ETR,,EVENTOUT, +PortD,PD3 , , ,I2C6_SMBA,SPI2_SCK,DCMI_D5/PSSI_D5,SPI2_MISO ,MDF1_SDI0,USART2_CTS,LCD_CLK, ,OCTOSPIM_P2_NCS, ,FMC_CLK ,, ,EVENTOUT, +PortD,PD4 , , , , , ,SPI2_MOSI,MDF1_CKI0,USART2_RTS_DE, , ,OCTOSPIM_P1_IO4, ,FMC_NOE , , ,EVENTOUT, +PortD,PD5 , ,, , , ,SPI2_RDY , ,USART2_TX , ,,OCTOSPIM_P1_IO5, ,FMC_NWE , , ,EVENTOUT, +PortD,PD6 , , ,,SAI1_D1,DCMI_D10/PSSI_D10,SPI3_MOSI,MDF1_SDI1,USART2_RX ,LCD_DE, ,OCTOSPIM_P1_IO6,SDMMC2_CK ,FMC_NWAIT ,SAI1_SD_A, ,EVENTOUT, +PortD,PD7 , , , , , ,SPI1_MOSI/I2S1_SDO , ,USART2_CK , , ,OCTOSPIM_P1_IO7,SDMMC2_CMD ,FMC_NCE/FMC_NE1 ,LPTIM4_OUT,,EVENTOUT, +PortD,PD8 , , , , , , , ,USART3_TX ,LCD_R3, ,DCMI_HSYNC/PSSI_DE, ,FMC_D13, , ,EVENTOUT, +PortD,PD9 , , ,LPTIM2_IN2, , , , ,USART3_RX ,LCD_R4,,DCMI_PIXCLK/PSSI_PDCK, ,FMC_D14,SAI2_MCLK_A,LPTIM3_IN1,EVENTOUT, +PortD,PD10, , ,LPTIM2_CH2,,I2C5_SMBA, , ,USART3_CK ,LCD_R5,TSC_G6_IO1, , ,FMC_D15,SAI2_SCK_A,LPTIM3_ETR,EVENTOUT, +PortD,PD11, , ,,,I2C4_SMBA , , ,USART3_CTS,LCD_R6,TSC_G6_IO2,, ,FMC_A16/FMC_CLE,SAI2_SD_A,LPTIM2_ETR,EVENTOUT,ADC4_IN15 +PortD,PD12, ,,TIM4_CH1 ,,I2C4_SCL ,,,USART3_RTS_DE,LCD_R7,TSC_G6_IO3,,,FMC_ALE/FMC_A17,SAI2_FS_A,LPTIM2_IN1,EVENTOUT,ADC4_IN16 +PortD,PD13, ,,TIM4_CH2 ,,I2C4_SDA ,, ,USART6_CTS,LCD_VSYNC,TSC_G6_IO4,,LPGPIO1_P6,FMC_A18 ,LPTIM4_IN1,LPTIM2_CH1,EVENTOUT,ADC4_IN17 +PortD,PD14, , ,TIM4_CH3 , , , , ,USART6_CK,LCD_B2,,,,FMC_D0, ,LPTIM3_CH1,EVENTOUT, +PortD,PD15, , ,TIM4_CH4 , , , , ,USART6_RTS_DE,LCD_B3, , ,,FMC_D1, ,LPTIM3_CH2,EVENTOUT, +PortE,PE0 , ,,TIM4_ETR ,,,,,USART6_RX,LCD_HSYNC,,DCMI_D2/PSSI_D2,LPGPIO1_P13,FMC_NBL0 ,,TIM16_CH1,EVENTOUT, +PortE,PE1 , ,, , , , , ,USART6_TX,LCD_VSYNC,,DCMI_D3/PSSI_D3, ,FMC_NBL1 ,,TIM17_CH1,EVENTOUT, +PortE,PE2 ,TRACECLK ,,TIM3_ETR,SAI1_CK1 , ,,,USART6_CK,LCD_R0,TSC_G7_IO1, ,LPGPIO1_P14,FMC_A23 ,SAI1_MCLK_A, ,EVENTOUT, +PortE,PE3 ,TRACED0 , ,TIM3_CH1,OCTOSPIM_P1_DQS, , ,,USART6_CTS,LCD_R1,TSC_G7_IO2, ,LPGPIO1_P15,FMC_A19 ,SAI1_SD_B, ,EVENTOUT, +PortE,PE4 ,TRACED1 , ,TIM3_CH2,SAI1_D2, ,,MDF1_SDI3,USART6_RTS_DE,LCD_B0,TSC_G7_IO3,DCMI_D4/PSSI_D4, ,FMC_A20 ,SAI1_FS_A, ,EVENTOUT, +PortE,PE5 ,TRACED2 , ,TIM3_CH3,SAI1_CK2, ,,MDF1_CKI3, ,LCD_G0,TSC_G7_IO4,DCMI_D6/PSSI_D6, ,FMC_A21 ,SAI1_SCK_A, ,EVENTOUT, +PortE,PE6 ,TRACED3 ,,TIM3_CH4,SAI1_D1, ,,, ,LCD_G1, ,DCMI_D7/PSSI_D7, ,FMC_A22 ,SAI1_SD_A, ,EVENTOUT, +PortE,PE7 , ,TIM1_ETR , , , , ,MDF1_SDI2,,LCD_B6, ,, ,FMC_D4,SAI1_SD_B, ,EVENTOUT, +PortE,PE8 , ,TIM1_CH1N , , , , ,MDF1_CKI2,,LCD_B7, ,, ,FMC_D5,SAI1_SCK_B, ,EVENTOUT, +PortE,PE9 , ,TIM1_CH1 , ,ADF1_CCK0, , ,MDF1_CCK0,,LCD_G2, ,OCTOSPIM_P1_NCLK, ,FMC_D6,SAI1_FS_B, ,EVENTOUT, +PortE,PE10, ,TIM1_CH2N , ,ADF1_SDI0, , ,MDF1_SDI4,,LCD_G3,TSC_G5_IO1,OCTOSPIM_P1_CLK, ,FMC_D7,SAI1_MCLK_B, ,EVENTOUT, +PortE,PE11, ,TIM1_CH2 , , ,,SPI1_RDY,MDF1_CKI4,,LCD_G4,TSC_G5_IO2,OCTOSPIM_P1_NCS, ,FMC_D8, , ,EVENTOUT, +PortE,PE12, ,TIM1_CH3N , , , ,SPI1_NSS,MDF1_SDI5, ,LCD_G5,TSC_G5_IO3,OCTOSPIM_P1_IO0, ,FMC_D9, , ,EVENTOUT, +PortE,PE13, ,TIM1_CH3 , , , ,SPI1_SCK,MDF1_CKI5, ,LCD_G6,TSC_G5_IO4,OCTOSPIM_P1_IO1, ,FMC_D10, , ,EVENTOUT, +PortE,PE14, ,TIM1_CH4 ,TIM1_BKIN2, , ,SPI1_MISO, , ,LCD_G7, ,OCTOSPIM_P1_IO2, ,FMC_D11, , ,EVENTOUT, +PortE,PE15, ,TIM1_BKIN , ,TIM1_CH4N, ,SPI1_MOSI, ,,LCD_R2, ,OCTOSPIM_P1_IO3, ,FMC_D12, , ,EVENTOUT, +PortF,PF0 , , ,I2C6_SDA, ,I2C2_SDA,OCTOSPIM_P2_IO0, ,USART6_TX, , , , ,FMC_A0 ,, ,EVENTOUT, +PortF,PF1 , , ,I2C6_SCL, ,I2C2_SCL ,OCTOSPIM_P2_IO1, ,USART6_RX, , , , ,FMC_A1 ,, ,EVENTOUT, +PortF,PF2 , , ,LPTIM3_CH2 ,,I2C2_SMBA ,OCTOSPIM_P2_IO2,,USART6_CK, , , , ,FMC_A2 ,, ,EVENTOUT, +PortF,PF3 , , ,LPTIM3_IN1 ,ADF1_CCK0, ,OCTOSPIM_P2_IO3,MDF1_CCK0,USART6_CTS,UART5_TX, , , ,FMC_A3 ,, ,EVENTOUT, +PortF,PF4 , , ,LPTIM3_ETR ,ADF1_SDI0, ,OCTOSPIM_P2_CLK,MDF1_SDI0,USART6_RTS_DE,UART5_RX, , , ,FMC_A4 , , ,EVENTOUT, +PortF,PF5 , , ,LPTIM3_CH1 , ,,OCTOSPIM_P2_NCLK,MDF1_CKI0,, , , , ,FMC_A5 , ,,EVENTOUT, +PortF,PF6 , ,TIM5_ETR ,TIM5_CH1, ,DCMI_D12/PSSI_D12,OCTOSPIM_P2_NCS,,, , ,OCTOSPIM_P1_IO3, , ,SAI1_SD_B, ,EVENTOUT, +PortF,PF7 , , ,TIM5_CH2,,,,,, ,FDCAN1_RX,OCTOSPIM_P1_IO2, , ,SAI1_MCLK_B, ,EVENTOUT, +PortF,PF8 , , ,TIM5_CH3, ,PSSI_D14,,,, ,FDCAN1_TX,OCTOSPIM_P1_IO0, , ,SAI1_SCK_B, ,EVENTOUT, +PortF,PF9 , , ,TIM5_CH4, ,PSSI_D15,,,, , ,OCTOSPIM_P1_IO1, , ,SAI1_FS_B,TIM15_CH1,EVENTOUT, +PortF,PF10, , ,,OCTOSPIM_P1_CLK,PSSI_D15 , ,MDF1_CCK1, , ,,DCMI_D11/PSSI_D11,DSI_TE, ,SAI1_D3,TIM15_CH2,EVENTOUT, +PortF,PF11, , , ,OCTOSPIM_P1_NCLK, ,, , ,LCD_DE,,DCMI_D12/PSSI_D12,DSI_TE,,LPTIM4_IN1,,EVENTOUT,ADC1_INP2 +PortF,PF12, , , , , ,OCTOSPIM_P2_, , ,LCD_B0, , , ,FMC_A6 ,LPTIM4_ETR,,EVENTOUT,ADC1_INP6/ADC1_INN2 +PortF,PF13, , , , ,I2C4_SMBA , , , ,LCD_B1, , ,UCPD1_FRSTX2,FMC_A7 ,LPTIM4_OUT,,EVENTOUT,ADC2_INP2 +PortF,PF14, , , , ,I2C4_SCL, , , ,LCD_G0,TSC_G8_IO1, , ,FMC_A8 , ,,EVENTOUT,ADC4_IN5 +PortF,PF15, , , , ,I2C4_SDA ,, , ,LCD_G1,TSC_G8_IO2, ,,FMC_A9 , ,,EVENTOUT,ADC4_IN6 +PortG,PG0 , , , , , ,OCTOSPIM_P2_IO4, , , ,TSC_G8_IO3, ,,FMC_A10 , ,,EVENTOUT,ADC4_IN7 +PortG,PG1 , , , , , ,OCTOSPIM_P2_IO5, ,, ,TSC_G8_IO4, ,,FMC_A11 , , ,EVENTOUT,ADC4_IN8 +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_A11 ,SAI2_MCLK_B,,EVENTOUT, +PortG,PG5 ,,,,,,SPI1_NSS, , ,LPUART1_CTS, ,,DSI_TE,FMC_A12 ,SAI2_SD_B, ,EVENTOUT, +PortG,PG6 , , , ,OCTOSPIM_P1_DQS,I2C3_SMBA,SPI1_RDY , ,LCD_R1,LPUART1_RTS_DE, ,,UCPD1_FRSTX1,,, ,EVENTOUT, +PortG,PG7 , , ,,SAI1_CK1,I2C3_SCL,OCTOSPIM_P2_DQS,MDF1_CCK0,,LPUART1_TX, , ,UCPD1_FRSTX2,FMC_INT ,SAI1_MCLK_A, ,EVENTOUT, +PortG,PG8 , , , ,,I2C3_SDA,, ,,LPUART1_RX,,,,,, ,EVENTOUT, +PortG,PG9 , , , , , ,OCTOSPIM_P2_IO6,SPI3_SCK,USART1_TX,,,,,FMC_NCE/FMC_NE2,SAI2_SCK_A,TIM15_CH1N,EVENTOUT, +PortG,PG10, ,LPTIM1_IN1, , , ,OCTOSPIM_P2_IO7,SPI3_MISO,USART1_RX,,,,,FMC_NE3 ,SAI2_FS_A,TIM15_CH1,EVENTOUT, +PortG,PG11, ,LPTIM1_IN2 , ,OCTOSPIM_P1_IO5, ,,SPI3_MOSI,USART1_CTS,,,,,,SAI2_MCLK_A,TIM15_CH2,EVENTOUT, +PortG,PG12,,LPTIM1_ETR, , ,,OCTOSPIM_P2_NCS,SPI3_NSS,USART1_RTS_DE, , ,,,FMC_NE4 ,SAI2_SD_A,,EVENTOUT, +PortG,PG13,,, , ,I2C1_SDA,,SPI3_RDY,USART1_CK,LCD_R0, ,,,FMC_A24 ,, ,EVENTOUT, +PortG,PG14,,LPTIM1_CH2, , ,I2C1_SCL,,,,LCD_R1,,,,FMC_A25 ,, ,EVENTOUT, +PortG,PG15,,LPTIM1_CH1, , ,I2C1_SMBA,OCTOSPIM_P2_DQS,,, ,DCMI_D13/PSSI_D13,,,,, ,EVENTOUT, +PortH,PH0 , , , , , , , , ,,,,,,,,EVENTOUT, +PortH,PH1 , , , , , , , ,,,,,,,,,EVENTOUT, +PortH,PH2 , ,, ,OCTOSPIM_P1_IO4, , , ,,,,,,,,,EVENTOUT, +PortH,PH3 , , , , , , , ,,,,,,,,,EVENTOUT, +PortH,PH4 , ,,I2C5_SDA, ,I2C2_SCL,OCTOSPIM_P2_DQS, ,, , ,PSSI_D14,,,,,EVENTOUT, +PortH,PH5 , ,,I2C5_SCL, ,I2C2_SDA,, ,, , ,DCMI_PIXCLK/PSSI_PDCK,,,,,EVENTOUT, +PortH,PH6 , ,,I2C5_SMBA,,I2C2_SMBA ,OCTOSPIM_P2_CLK, ,, , ,DCMI_D8/PSSI_D8,,,,,EVENTOUT, +PortH,PH7 , ,,,,I2C3_SCL ,OCTOSPIM_P2_NCLK, ,, , ,DCMI_D9/PSSI_D9,,,,,EVENTOUT, +PortH,PH8 , ,,,,I2C3_SDA ,OCTOSPIM_P2_IO3, ,, , ,DCMI_HSYNC/PSSI_DE,,,,,EVENTOUT, +PortH,PH9 , ,, ,,I2C3_SMBA ,OCTOSPIM_P2_IO4, , ,HSPI1_NCS, ,DCMI_D0/PSSI_D0,,,,,EVENTOUT, +PortH,PH10, ,,TIM5_CH1 ,,,OCTOSPIM_P2_IO5, , ,HSPI1_IO0, ,DCMI_D1/PSSI_D1,,,,,EVENTOUT, +PortH,PH11, ,,TIM5_CH2 ,,,OCTOSPIM_P2_IO6, , ,HSPI1_IO1, ,DCMI_D2/PSSI_D2,,,,,EVENTOUT, +PortH,PH12, ,,TIM5_CH3 ,TIM8_CH4N,,OCTOSPIM_P2_IO7, , ,HSPI1_IO2, ,DCMI_D3/PSSI_D3,,,,,EVENTOUT, +PortH,PH13, ,, ,TIM8_CH1N , , , ,,HSPI1_IO3,FDCAN1_TX , ,,,,,EVENTOUT, +PortH,PH14, ,, ,TIM8_CH2N , , , , ,HSPI1_IO4,FDCAN1_RX ,DCMI_D4/PSSI_D4,,,,,EVENTOUT, +PortH,PH15, ,, ,TIM8_CH3N , ,OCTOSPIM_P2_IO6, , ,HSPI1_IO5, ,DCMI_D11/PSSI_D11,,,,,EVENTOUT, +PortI,PI0 , , ,TIM5_CH4 ,OCTOSPIM_P1_IO5, ,SPI2_NSS, , ,HSPI1_IO6, ,DCMI_D13/PSSI_D13,,,,,EVENTOUT, +PortI,PI1 ,,,,,,SPI2_SCK,OCTOSPIM_P2_IO2, ,HSPI1_IO7, ,DCMI_D8/PSSI_D8,,,,,EVENTOUT, +PortI,PI2 , , , ,TIM8_CH4 , ,SPI2_MISO,OCTOSPIM_P2_IO1, ,HSPI1_DQS0, ,DCMI_D9/PSSI_D9,,,,,EVENTOUT, +PortI,PI3 , , , ,TIM8_ETR , ,SPI2_MOSI,OCTOSPIM_P2_IO0, ,HSPI1_CLK, ,DCMI_D10/PSSI_D10,,,,,EVENTOUT, +PortI,PI4 , , , ,TIM8_BKIN , ,SPI2_RDY, , ,HSPI1_NCLK, ,DCMI_D5/PSSI_D5,,,,,EVENTOUT, +PortI,PI5 , , , ,TIM8_CH1 , ,OCTOSPIM_P2_NCS, , , , ,DCMI_VSYNC/PSSI_RDY,,,,,EVENTOUT, +PortI,PI6 , , , ,TIM8_CH2 , ,OCTOSPIM_P2_CLK, , , , ,DCMI_D6/PSSI_D6,,,,,EVENTOUT, +PortI,PI7 , , , ,TIM8_CH3 , ,OCTOSPIM_P2_NCLK, , , , ,DCMI_D7/PSSI_D7,,,,,EVENTOUT, +PortI,PI8 , , , , , , , , ,HSPI1_DQS1,, ,,,,,EVENTOUT, +PortI,PI9 , , , , , , , , ,HSPI1_IO8,, ,,,,,EVENTOUT, +PortI,PI10,PI11,PI12,PI13,PI14,PI15,PI16,PI17,PI18,HSPI1_IO9,, ,,,,,EVENTOUT, +PortI,PI11,PI12,PI13,PI14,PI15,PI16,PI17,PI18,PI19,HSPI1_IO10,, ,,,,,EVENTOUT, +PortI,PI12,,,,,,,,,HSPI1_IO11,,,,,,,EVENTOUT, +PortI,PI13,,,,,,,,,HSPI1_IO12,,,,,,,EVENTOUT, +PortI,PI14,,,,,,,,,HSPI1_IO13,,,,,,,EVENTOUT, +PortI,PI15,,,,,,,,,HSPI1_IO14,,,,,,,EVENTOUT, +PortJ,PJ0,,,,,I2C5_SMBA,,,,HSPI1_IO15,,,,,,,EVENTOUT, +PortJ,PJ1,,,,,I2C5_SDA,,,,,,,,,,,EVENTOUT, +PortJ,PJ2,,,,,I2C5_SCL,,,,,,,,,,,EVENTOUT, +PortJ,PJ3,,,,,,,,USART6_TX,,,,,,,,EVENTOUT, +PortJ,PJ4,,,,,,,,USART6_RX,,,,,,,,EVENTOUT, +PortJ,PJ5,,,,,,,,USART6_RTS_DE,,,,,,,,EVENTOUT, +PortJ,PJ6,,,,,,,,USART6_CK,,,,,,,,EVENTOUT, +PortJ,PJ7,,,,,,,,USART6_CK,,,,,,,,EVENTOUT, +PortJ,PJ8,,,I2C6_SMBA,,,,,,,,,,,,,EVENTOUT, +PortJ,PJ9,,,I2C6_SDA,,,,,,,,,,,,,EVENTOUT, +PortJ,PJ10,,,I2C6_SCL,,,,,,,,,,,,,EVENTOUT, +PortJ,PJ11,,,,,,,,,,,,,,,,EVENTOUT, diff --git a/ports/stm32/boards/stm32u5a5xj.ld b/ports/stm32/boards/stm32u5a5xj.ld new file mode 100644 index 0000000000000..bde31eded0aeb --- /dev/null +++ b/ports/stm32/boards/stm32u5a5xj.ld @@ -0,0 +1,35 @@ +/* + GNU linker script for STM32U5A5xJ +*/ + +/* Specify the memory areas */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 4096K + FLASH_APP (rx) : ORIGIN = 0x08008000, LENGTH = 992K /* sectors 4-127 (for common_bl.ld) */ + FLASH_FS (rx) : ORIGIN = 0x08100000, LENGTH = 1024K /* sectors 128-255 */ + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 768K /* SRAM1: 768KB */ + SRAM4 (xrw) : ORIGIN = 0x28000000, LENGTH = 16K + FS_CACHE (xrw) : ORIGIN = 0x28000000, LENGTH = 8K +} + +/* produce a link error if there is not this amount of RAM for these sections */ +_minimum_stack_size = 2K; +_minimum_heap_size = 16K; + +/* Define the stack. The stack is full descending so begins just above last byte + of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ +_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; +_sstack = _estack - 16K; /* tunable */ + +/* RAM extents for the garbage collector */ +_ram_start = ORIGIN(RAM); +_ram_end = ORIGIN(RAM) + LENGTH(RAM); +_heap_start = _ebss; /* heap starts just after statically allocated memory */ +_heap_end = _sstack; + +/* Filesystem cache in RAM, and storage in flash */ +_micropy_hw_internal_flash_storage_ram_cache_start = ORIGIN(FS_CACHE); +_micropy_hw_internal_flash_storage_ram_cache_end = ORIGIN(FS_CACHE) + LENGTH(FS_CACHE); +_micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS); +_micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); diff --git a/ports/stm32/boards/stm32u5xx_hal_conf_base.h b/ports/stm32/boards/stm32u5xx_hal_conf_base.h new file mode 100644 index 0000000000000..be7ea524639ec --- /dev/null +++ b/ports/stm32/boards/stm32u5xx_hal_conf_base.h @@ -0,0 +1,176 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 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. + */ +#ifndef MICROPY_INCLUDED_STM32U5XX_HAL_CONF_BASE_H +#define MICROPY_INCLUDED_STM32U5XX_HAL_CONF_BASE_H + +// Enable various HAL modules +#define HAL_MODULE_ENABLED +#define HAL_ADC_MODULE_ENABLED +#define HAL_COMP_MODULE_ENABLED +#define HAL_CORDIC_MODULE_ENABLED +#define HAL_CRC_MODULE_ENABLED +#define HAL_CRYP_MODULE_ENABLED +#define HAL_DAC_MODULE_ENABLED +#define HAL_DCACHE_MODULE_ENABLED +#define HAL_DCMI_MODULE_ENABLED +#define HAL_DMA2D_MODULE_ENABLED +#define HAL_DSI_MODULE_ENABLED +#define HAL_FDCAN_MODULE_ENABLED +#define HAL_FMAC_MODULE_ENABLED +#define HAL_GFXMMU_MODULE_ENABLED +#define HAL_GFXTIM_MODULE_ENABLED +#define HAL_GPU2D_MODULE_ENABLED +#define HAL_GTZC_MODULE_ENABLED +#define HAL_HASH_MODULE_ENABLED +#define HAL_HCD_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +#define HAL_ICACHE_MODULE_ENABLED +#define HAL_IRDA_MODULE_ENABLED +#define HAL_IWDG_MODULE_ENABLED +#define HAL_JPEG_MODULE_ENABLED +#define HAL_LPTIM_MODULE_ENABLED +#define HAL_LTDC_MODULE_ENABLED +#define HAL_MDF_MODULE_ENABLED +#define HAL_MMC_MODULE_ENABLED +#define HAL_NAND_MODULE_ENABLED +#define HAL_NOR_MODULE_ENABLED +#define HAL_OPAMP_MODULE_ENABLED +#define HAL_OSPI_MODULE_ENABLED +#define HAL_OTFDEC_MODULE_ENABLED +#define HAL_PCD_MODULE_ENABLED +#define HAL_PKA_MODULE_ENABLED +#define HAL_PSSI_MODULE_ENABLED +#define HAL_RAMCFG_MODULE_ENABLED +#define HAL_RNG_MODULE_ENABLED +#define HAL_RTC_MODULE_ENABLED +#define HAL_SAI_MODULE_ENABLED +#define HAL_SD_MODULE_ENABLED +#define HAL_SDIO_MODULE_ENABLED +#define HAL_SMARTCARD_MODULE_ENABLED +#define HAL_SMBUS_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_SRAM_MODULE_ENABLED +#define HAL_TIM_MODULE_ENABLED +#define HAL_TSC_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +#define HAL_USART_MODULE_ENABLED +#define HAL_WWDG_MODULE_ENABLED +#define HAL_XSPI_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_EXTI_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED + +// Oscillator values in Hz +#define CSI_VALUE (4000000) +#define HSI_VALUE (16000000UL) +#define HSI48_VALUE (48000000UL) +#define LSI_VALUE (32000UL) +#define MSI_VALUE (4000000UL) + +// SysTick has the highest priority +#define TICK_INT_PRIORITY (0x00) + +// Miscellaneous HAL settings +#define USE_RTOS 0 +#define USE_SPI_CRC 1 +#define USE_SDIO_TRANSCEIVER 0U +#define SDIO_MAX_IO_NUMBER 7U +#define PREFETCH_ENABLE 1U + +// Include various HAL modules for convenience +#include "stm32u5xx_hal_rcc.h" +#include "stm32u5xx_hal_gpio.h" +#include "stm32u5xx_hal_icache.h" +#include "stm32u5xx_hal_dcache.h" +#include "stm32u5xx_hal_gtzc.h" +#include "stm32u5xx_hal_dma.h" +#include "stm32u5xx_hal_dma2d.h" +#include "stm32u5xx_hal_dsi.h" +#include "stm32u5xx_hal_cortex.h" +#include "stm32u5xx_hal_pka.h" +#include "stm32u5xx_hal_adc.h" +#include "stm32u5xx_hal_comp.h" +#include "stm32u5xx_hal_crc.h" +#include "stm32u5xx_hal_cryp.h" +#include "stm32u5xx_hal_dac.h" +#include "stm32u5xx_hal_flash.h" +#include "stm32u5xx_hal_hash.h" +#include "stm32u5xx_hal_sram.h" +#include "stm32u5xx_hal_mmc.h" +#include "stm32u5xx_hal_nor.h" +#include "stm32u5xx_hal_nand.h" +#include "stm32u5xx_hal_i2c.h" +#include "stm32u5xx_hal_iwdg.h" +#include "stm32u5xx_hal_jpeg.h" +#include "stm32u5xx_hal_lptim.h" +#include "stm32u5xx_hal_ltdc.h" +#include "stm32u5xx_hal_opamp.h" +#include "stm32u5xx_hal_pwr.h" +#include "stm32u5xx_hal_ospi.h" +#include "stm32u5xx_hal_rng.h" +#include "stm32u5xx_hal_rtc.h" +#include "stm32u5xx_hal_sai.h" +#include "stm32u5xx_hal_sd.h" +#include "stm32u5xx_hal_sdio.h" +#include "stm32u5xx_hal_smbus.h" +#include "stm32u5xx_hal_spi.h" +#include "stm32u5xx_hal_tim.h" +#include "stm32u5xx_hal_tsc.h" +#include "stm32u5xx_hal_uart.h" +#include "stm32u5xx_hal_usart.h" +#include "stm32u5xx_hal_irda.h" +#include "stm32u5xx_hal_smartcard.h" +#include "stm32u5xx_hal_wwdg.h" +#include "stm32u5xx_hal_pcd.h" +#include "stm32u5xx_hal_hcd.h" +#include "stm32u5xx_hal_cordic.h" +#include "stm32u5xx_hal_dcmi.h" +#include "stm32u5xx_hal_exti.h" +#include "stm32u5xx_hal_fdcan.h" +#include "stm32u5xx_hal_fmac.h" +#include "stm32u5xx_hal_gfxmmu.h" +#include "stm32u5xx_hal_gfxtim.h" +#include "stm32u5xx_hal_gpu2d.h" +#include "stm32u5xx_hal_otfdec.h" +#include "stm32u5xx_hal_pssi.h" +#include "stm32u5xx_hal_ramcfg.h" +#include "stm32u5xx_hal_mdf.h" +#include "stm32u5xx_hal_xspi.h" +#include "stm32u5xx_ll_usart.h" +#include "stm32u5xx_ll_lpuart.h" +#include "stm32u5xx_ll_rtc.h" +#include "stm32u5xx_ll_adc.h" +#include "stm32u5xx_ll_pwr.h" +#include "stm32u5xx_ll_rcc.h" + +// HAL parameter assertions are disabled +#define assert_param(expr) ((void)0) + +#endif /* MICROPY_INCLUDED_STM32U5XX_HAL_CONF_BASE_H */ diff --git a/ports/stm32/dac.c b/ports/stm32/dac.c index 8022fd274ce97..eb729a6d4eb77 100644 --- a/ports/stm32/dac.c +++ b/ports/stm32/dac.c @@ -66,7 +66,7 @@ #if defined(MICROPY_HW_ENABLE_DAC) && MICROPY_HW_ENABLE_DAC -#if defined(STM32H5) || defined(STM32H7) +#if defined(STM32H5) || defined(STM32H7) || defined(STM32U5) #define DAC DAC1 #endif @@ -124,7 +124,7 @@ static uint32_t TIMx_Config(mp_obj_t timer) { static void dac_deinit(uint32_t dac_channel) { DAC->CR &= ~(DAC_CR_EN1 << dac_channel); - #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32U5) DAC->MCR = (DAC->MCR & ~(DAC_MCR_MODE1_Msk << dac_channel)) | (DAC_OUTPUTBUFFER_DISABLE << dac_channel); #else DAC->CR |= DAC_CR_BOFF1 << dac_channel; @@ -142,7 +142,7 @@ static void dac_config_channel(uint32_t dac_channel, uint32_t trig, uint32_t out DAC->CR &= ~(DAC_CR_EN1 << dac_channel); uint32_t cr_off = DAC_CR_DMAEN1 | DAC_CR_MAMP1 | DAC_CR_WAVE1 | DAC_CR_TSEL1 | DAC_CR_TEN1; uint32_t cr_on = trig; - #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32U5) DAC->MCR = (DAC->MCR & ~(DAC_MCR_MODE1_Msk << dac_channel)) | (outbuf << dac_channel); #else cr_off |= DAC_CR_BOFF1; @@ -173,7 +173,7 @@ static void dac_start_dma(uint32_t dac_channel, const dma_descr_t *dma_descr, ui #if defined(STM32G4) // For STM32G4, DAC registers have to be accessed by words (32-bit). dma_align = DMA_MDATAALIGN_BYTE | DMA_PDATAALIGN_WORD; - #elif defined(STM32H5) + #elif defined(STM32H5) || defined(STM32U5) dma_align = DMA_SRC_DATAWIDTH_BYTE | DMA_DEST_DATAWIDTH_WORD; #else dma_align = DMA_MDATAALIGN_BYTE | DMA_PDATAALIGN_BYTE; @@ -182,7 +182,7 @@ static void dac_start_dma(uint32_t dac_channel, const dma_descr_t *dma_descr, ui #if defined(STM32G4) // For STM32G4, DAC registers have to be accessed by words (32-bit). dma_align = DMA_MDATAALIGN_HALFWORD | DMA_PDATAALIGN_WORD; - #elif defined(STM32H5) + #elif defined(STM32H5) || defined(STM32U5) dma_align = DMA_SRC_DATAWIDTH_HALFWORD | DMA_DEST_DATAWIDTH_WORD; #else dma_align = DMA_MDATAALIGN_HALFWORD | DMA_PDATAALIGN_HALFWORD; @@ -273,7 +273,7 @@ static mp_obj_t pyb_dac_init_helper(pyb_dac_obj_t *self, size_t n_args, const mp __DAC_CLK_ENABLE(); #elif defined(STM32H7) __HAL_RCC_DAC12_CLK_ENABLE(); - #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L4) + #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L4) || defined(STM32U5) __HAL_RCC_DAC1_CLK_ENABLE(); #elif defined(STM32L1) __HAL_RCC_DAC_CLK_ENABLE(); @@ -493,8 +493,8 @@ mp_obj_t pyb_dac_write_timed(size_t n_args, const mp_obj_t *pos_args, mp_map_t * align = DAC_ALIGN_8B_R; } else { align = DAC_ALIGN_12B_R; - // For STM32H5, the length is the amount of data to be transferred from source to destination in bytes. - #if !defined(STM32H5) + // For STM32H5/U5, the length is the amount of data to be transferred from source to destination in bytes. + #if !defined(STM32H5) && !defined(STM32U5) bufinfo.len /= 2; #endif } diff --git a/ports/stm32/dma.c b/ports/stm32/dma.c index ad199b1fb91d9..346b6b6f70ff4 100644 --- a/ports/stm32/dma.c +++ b/ports/stm32/dma.c @@ -81,7 +81,7 @@ typedef union { struct _dma_descr_t { #if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) DMA_Stream_TypeDef *instance; - #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32N6) || defined(STM32WB) || defined(STM32WL) + #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32N6) || defined(STM32U5) || defined(STM32WB) || defined(STM32WL) DMA_Channel_TypeDef *instance; #else #error "Unsupported Processor" @@ -93,7 +93,7 @@ struct _dma_descr_t { // Default parameters to dma_init() shared by spi and i2c; Channel and Direction // vary depending on the peripheral instance so they get passed separately -#if defined(STM32H5) || defined(STM32N6) +#if defined(STM32H5) || defined(STM32N6) || defined(STM32U5) static const DMA_InitTypeDef dma_init_struct_spi_i2c = { .Request = 0, // set by dma_init_handle .BlkHWRequest = DMA_BREQ_SINGLE_BURST, @@ -186,7 +186,7 @@ static const DMA_InitTypeDef dma_init_struct_sdio = { #endif #if defined(MICROPY_HW_ENABLE_DAC) && MICROPY_HW_ENABLE_DAC -#if defined(STM32H5) +#if defined(STM32H5) || defined(STM32U5) // Default parameters to dma_init() for DAC tx static const DMA_InitTypeDef dma_init_struct_dac = { .Request = 0, // set by dma_init_handle @@ -870,6 +870,50 @@ static const uint8_t dma_irqn[NSTREAM] = { GPDMA1_Channel15_IRQn, }; +#elif defined(STM32U5) + +#define NCONTROLLERS (1) +#define NSTREAMS_PER_CONTROLLER (16) +#define NSTREAM (NCONTROLLERS * NSTREAMS_PER_CONTROLLER) + +#define DMA_SUB_INSTANCE_AS_UINT8(dma_channel) (dma_channel) + +#define DMA1_ENABLE_MASK (0x00ff) // Bits in dma_enable_mask corresponding to GPDMA1 +#define DMA2_ENABLE_MASK (0xff00) // Bits in dma_enable_mask corresponding to GPDMA2 + +const dma_descr_t dma_SPI_1_RX = { GPDMA1_Channel0, GPDMA1_REQUEST_SPI1_RX, dma_id_0, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_SPI_1_TX = { GPDMA1_Channel1, GPDMA1_REQUEST_SPI1_TX, dma_id_1, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_SPI_2_RX = { GPDMA1_Channel2, GPDMA1_REQUEST_SPI2_RX, dma_id_2, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_SPI_2_TX = { GPDMA1_Channel3, GPDMA1_REQUEST_SPI2_TX, dma_id_3, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_SPI_3_RX = { GPDMA1_Channel4, GPDMA1_REQUEST_SPI3_RX, dma_id_4, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_SPI_3_TX = { GPDMA1_Channel5, GPDMA1_REQUEST_SPI3_TX, dma_id_5, &dma_init_struct_spi_i2c }; +#if MICROPY_HW_ENABLE_DAC +const dma_descr_t dma_DAC_1_TX = { GPDMA1_Channel6, GPDMA1_REQUEST_DAC1_CH1, dma_id_6, &dma_init_struct_dac }; +const dma_descr_t dma_DAC_2_TX = { GPDMA1_Channel7, GPDMA1_REQUEST_DAC1_CH2, dma_id_7, &dma_init_struct_dac }; +#endif +const dma_descr_t dma_I2C_1_TX = { GPDMA1_Channel8, GPDMA1_REQUEST_I2C1_TX, dma_id_8, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_I2C_1_RX = { GPDMA1_Channel9, GPDMA1_REQUEST_I2C1_RX, dma_id_9, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_I2C_2_TX = { GPDMA1_Channel10, GPDMA1_REQUEST_I2C2_TX, dma_id_10, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_I2C_2_RX = { GPDMA1_Channel11, GPDMA1_REQUEST_I2C2_RX, dma_id_11, &dma_init_struct_spi_i2c }; + +static const uint8_t dma_irqn[NSTREAM] = { + GPDMA1_Channel0_IRQn, + GPDMA1_Channel1_IRQn, + GPDMA1_Channel2_IRQn, + GPDMA1_Channel3_IRQn, + GPDMA1_Channel4_IRQn, + GPDMA1_Channel5_IRQn, + GPDMA1_Channel6_IRQn, + GPDMA1_Channel7_IRQn, + GPDMA1_Channel8_IRQn, + GPDMA1_Channel9_IRQn, + GPDMA1_Channel10_IRQn, + GPDMA1_Channel11_IRQn, + GPDMA1_Channel12_IRQn, + GPDMA1_Channel13_IRQn, + GPDMA1_Channel14_IRQn, + GPDMA1_Channel15_IRQn, +}; #endif static DMA_HandleTypeDef *dma_handle[NSTREAM] = {NULL}; @@ -886,7 +930,7 @@ volatile dma_idle_count_t dma_idle; #if defined(DMA2) #define DMA2_IS_CLK_ENABLED() ((RCC->AHBENR & RCC_AHBENR_DMA2EN) != 0) #endif -#elif defined(STM32H5) +#elif defined(STM32H5) || defined(STM32U5) #define DMA1_IS_CLK_ENABLED() (__HAL_RCC_GPDMA1_IS_CLK_ENABLED()) #define DMA2_IS_CLK_ENABLED() (__HAL_RCC_GPDMA2_IS_CLK_ENABLED()) #define __HAL_RCC_DMA1_CLK_ENABLE __HAL_RCC_GPDMA1_CLK_ENABLE @@ -1229,7 +1273,7 @@ void DMA2_Channel8_IRQHandler(void) { } #endif -#elif defined(STM32H5) || defined(STM32N6) +#elif defined(STM32H5) || defined(STM32N6) || defined(STM32U5) #define DEFINE_IRQ_HANDLER(periph, channel, id) \ void GPDMA##periph##_Channel##channel##_IRQHandler(void) { \ @@ -1480,7 +1524,7 @@ void dma_init_handle(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint3 dma->Instance = dma_descr->instance; dma->Init = *dma_descr->init; dma->Init.Direction = dir; - #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32N6) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32N6) || defined(STM32U5) || defined(STM32WB) || defined(STM32WL) dma->Init.Request = dma_descr->sub_instance; #else #if !defined(STM32F0) && !defined(STM32L1) @@ -1488,7 +1532,7 @@ void dma_init_handle(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint3 #endif #endif - #if defined(STM32H5) || defined(STM32N6) + #if defined(STM32H5) || defined(STM32N6) || defined(STM32U5) // Configure src/dest settings based on the DMA direction. if (dir == DMA_MEMORY_TO_PERIPH) { dma->Init.SrcInc = DMA_SINC_INCREMENTED; @@ -1519,7 +1563,7 @@ void dma_init(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint32_t dir dma_enable_clock(dma_id); - #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32N6) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32N6) || defined(STM32U5) || defined(STM32WB) || defined(STM32WL) // Always reset and configure the H7 and G0/G4/H7/L0/L4/WB/WL DMA peripheral // (dma->State is set to HAL_DMA_STATE_RESET by memset above) // TODO: understand how L0/L4 DMA works so this is not needed @@ -1538,6 +1582,9 @@ void dma_init(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint32_t dir #endif NVIC_SetPriority(IRQn_NONNEG(dma_irqn[dma_id]), IRQ_PRI_DMA); + #if defined(STM32U5) + HAL_DMA_ConfigChannelAttributes(dma, DMA_CHANNEL_NPRIV); + #endif #else // if this stream was previously configured for this channel/request and direction then we // can skip most of the initialisation @@ -1708,7 +1755,7 @@ void dma_nohal_start(const dma_descr_t *descr, uint32_t src_addr, uint32_t dst_a dma->CCR |= DMA_CCR_EN; } -#elif defined(STM32H5) +#elif defined(STM32H5) || defined(STM32U5) // Fully setup GPDMA linked list entry typedef struct _dma_ll_full_t { diff --git a/ports/stm32/dma.h b/ports/stm32/dma.h index 75e007bc9fa98..c99e0ea32bc07 100644 --- a/ports/stm32/dma.h +++ b/ports/stm32/dma.h @@ -30,13 +30,13 @@ typedef struct _dma_descr_t dma_descr_t; -#if defined(STM32H5) -// STM32H5 GPDMA doesn't feature circular mode directly, so define doesn't exist in +#if defined(STM32H5) || defined(STM32U5) +// STM32H5/U5 GPDMA doesn't feature circular mode directly, so define doesn't exist in // stm32 driver header. Define it here to make users like DAC driver happy. #define DMA_CIRCULAR 0x20000000 #endif -#if defined(STM32F0) || defined(STM32F4) || defined(STM32F7) || defined(STM32G0) || defined(STM32H5) || defined(STM32H7) +#if defined(STM32F0) || defined(STM32F4) || defined(STM32F7) || defined(STM32G0) || defined(STM32H5) || defined(STM32H7) || defined(STM32U5) extern const dma_descr_t dma_I2C_1_RX; extern const dma_descr_t dma_SPI_3_RX; diff --git a/ports/stm32/extint.c b/ports/stm32/extint.c index df0ed6e23e1f6..b6abf3dd15f61 100644 --- a/ports/stm32/extint.c +++ b/ports/stm32/extint.c @@ -92,7 +92,7 @@ #define EXTI_SWIER_BB(line) (*(__IO uint32_t *)(PERIPH_BB_BASE + ((EXTI_OFFSET + offsetof(EXTI_TypeDef, SWIER)) * 32) + ((line) * 4))) #endif -#if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L4) || defined(STM32N6) || defined(STM32WB) || defined(STM32WL) +#if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L4) || defined(STM32N6) || defined(STM32U5) || defined(STM32WB) || defined(STM32WL) // The L4 MCU supports 40 Events/IRQs lines of the type configurable and direct. // Here we only support configurable line types. Details, see page 330 of RM0351, Rev 1. // The USB_FS_WAKUP event is a direct type and there is no support for it. @@ -170,7 +170,7 @@ static const uint8_t nvic_irq_channel[EXTI_NUM_VECTORS] = { ADC1_COMP_IRQn, #endif - #elif defined(STM32N6) || defined(STM32H5) + #elif defined(STM32N6) || defined(STM32H5) || defined(STM32U5) EXTI0_IRQn, EXTI1_IRQn, @@ -314,7 +314,7 @@ void EXTI15_10_IRQHandler(void) { IRQ_EXIT(EXTI15_10_IRQn); } -#elif defined(STM32H5) || defined(STM32N6) +#elif defined(STM32H5) || defined(STM32N6) || defined(STM32U5) DEFINE_EXTI_IRQ_HANDLER(0) DEFINE_EXTI_IRQ_HANDLER(1) @@ -447,7 +447,7 @@ void extint_register_pin(const machine_pin_obj_t *pin, uint32_t mode, bool hard_ #if !defined(STM32H5) && !defined(STM32WB) && !defined(STM32WL) __HAL_RCC_SYSCFG_CLK_ENABLE(); #endif - #if defined(STM32G0) || defined(STM32H5) || defined(STM32N6) + #if defined(STM32G0) || defined(STM32H5) || defined(STM32N6) || defined(STM32U5) EXTI->EXTICR[line >> 2] = (EXTI->EXTICR[line >> 2] & ~(0xff << (8 * (line & 0x03)))) | ((uint32_t)(GPIO_GET_INDEX(pin->gpio)) << (8 * (line & 0x03))); @@ -490,7 +490,7 @@ void extint_set(const machine_pin_obj_t *pin, uint32_t mode) { #if !defined(STM32H5) && !defined(STM32N6) && !defined(STM32WB) && !defined(STM32WL) __HAL_RCC_SYSCFG_CLK_ENABLE(); #endif - #if defined(STM32G0) || defined(STM32H5) || defined(STM32N6) + #if defined(STM32G0) || defined(STM32H5) || defined(STM32N6) || defined(STM32U5) EXTI->EXTICR[line >> 2] = (EXTI->EXTICR[line >> 2] & ~(0xff << (8 * (line & 0x03)))) | ((uint32_t)(GPIO_GET_INDEX(pin->gpio)) << (8 * (line & 0x03))); @@ -533,7 +533,7 @@ void extint_enable(uint line) { if (pyb_extint_mode[line] == EXTI_Mode_Interrupt) { #if defined(STM32H7) EXTI_D1->IMR1 |= (1 << line); - #elif defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32N6) || defined(STM32WB) || defined(STM32WL) + #elif defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32N6) || defined(STM32U5) || defined(STM32WB) || defined(STM32WL) EXTI->IMR1 |= (1 << line); #else EXTI->IMR |= (1 << line); @@ -541,7 +541,7 @@ void extint_enable(uint line) { } else { #if defined(STM32H7) EXTI_D1->EMR1 |= (1 << line); - #elif defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32N6) || defined(STM32WB) || defined(STM32WL) + #elif defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32N6) || defined(STM32U5) || defined(STM32WB) || defined(STM32WL) EXTI->EMR1 |= (1 << line); #else EXTI->EMR |= (1 << line); @@ -567,7 +567,7 @@ void extint_disable(uint line) { #if defined(STM32H7) EXTI_D1->IMR1 &= ~(1 << line); EXTI_D1->EMR1 &= ~(1 << line); - #elif defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32N6) || defined(STM32WB) || defined(STM32WL) + #elif defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32N6) || defined(STM32U5) || defined(STM32WB) || defined(STM32WL) EXTI->IMR1 &= ~(1 << line); EXTI->EMR1 &= ~(1 << line); #else @@ -589,7 +589,7 @@ void extint_swint(uint line) { return; } // we need 0 to 1 transition to trigger the interrupt - #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32N6) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32N6) || defined(STM32U5) || defined(STM32WB) || defined(STM32WL) EXTI->SWIER1 &= ~(1 << line); EXTI->SWIER1 |= (1 << line); #else @@ -708,6 +708,12 @@ static mp_obj_t extint_regs(void) { mp_printf(print, "EXTI_PR1 %08x\n", (unsigned int)EXTI_D1->PR1); mp_printf(print, "EXTI_PR2 %08x\n", (unsigned int)EXTI_D1->PR2); mp_printf(print, "EXTI_PR3 %08x\n", (unsigned int)EXTI_D1->PR3); + #elif defined(STM32U5) + mp_printf(print, "EXTI_IMR1 %08x\n", (unsigned int)EXTI->IMR1); + mp_printf(print, "EXTI_EMR1 %08x\n", (unsigned int)EXTI->EMR1); + mp_printf(print, "EXTI_RTSR1 %08x\n", (unsigned int)EXTI->RTSR1); + mp_printf(print, "EXTI_FTSR1 %08x\n", (unsigned int)EXTI->FTSR1); + mp_printf(print, "EXTI_SWIER1 %08x\n", (unsigned int)EXTI->SWIER1); #else mp_printf(print, "EXTI_IMR %08x\n", (unsigned int)EXTI->IMR); mp_printf(print, "EXTI_EMR %08x\n", (unsigned int)EXTI->EMR); @@ -803,10 +809,26 @@ void extint_init0(void) { } } +#if defined(STM32U5) +static inline bool is_rtc_interrupt(uint32_t line) { + return line == EXTI_RTC_WAKEUP || line == EXTI_RTC_ALARM || line == EXTI_RTC_TIMESTAMP; +} +#endif + // Interrupt handler void Handle_EXTI_Irq(uint32_t line) { - if (__HAL_GPIO_EXTI_GET_FLAG(1 << line)) { - __HAL_GPIO_EXTI_CLEAR_FLAG(1 << line); + if (__HAL_GPIO_EXTI_GET_FLAG(1 << line) + #if defined(STM32U5) + || is_rtc_interrupt(line) + #endif + ) { + #if defined(STM32U5) + if (!is_rtc_interrupt(line)) { + #else + if (1) { + #endif + __HAL_GPIO_EXTI_CLEAR_FLAG(1 << line); + } if (line < EXTI_NUM_VECTORS) { mp_obj_t *cb = &MP_STATE_PORT(pyb_extint_callback)[line]; #if MICROPY_PY_NETWORK_CYW43 && defined(pyb_pin_WL_HOST_WAKE) diff --git a/ports/stm32/extint.h b/ports/stm32/extint.h index 801dcf62b54bd..b403925120b56 100644 --- a/ports/stm32/extint.h +++ b/ports/stm32/extint.h @@ -37,7 +37,7 @@ #if defined(STM32L4) #define EXTI_RTC_ALARM (18) #define EXTI_USB_OTG_FS_WAKEUP (17) -#else +#elif !defined(STM32U5) #define EXTI_RTC_ALARM (17) #define EXTI_USB_OTG_FS_WAKEUP (18) #endif @@ -55,6 +55,11 @@ #elif defined(STM32G0) #define EXTI_RTC_WAKEUP (19) #define EXTI_RTC_TIMESTAMP (21) +#elif defined(STM32U5) +#define EXTI_RTC_TIMESTAMP (26) +#define EXTI_RTC_WAKEUP (27) +#define EXTI_RTC_ALARM (28) +#define EXTI_USB_OTG_FS_WAKEUP (29) #else #define EXTI_RTC_TIMESTAMP (21) #define EXTI_RTC_WAKEUP (22) diff --git a/ports/stm32/flash.c b/ports/stm32/flash.c index 85bcee5a97c91..a1f39e71d7117 100644 --- a/ports/stm32/flash.c +++ b/ports/stm32/flash.c @@ -148,7 +148,7 @@ static const flash_layout_t flash_layout[] = { #define FLASH_LAYOUT_SECTOR_SIZE (0x200) #define FLASH_LAYOUT_NUM_SECTORS (1024) -#elif defined(STM32H5) +#elif defined(STM32H5) || defined(STM32U5) #define FLASH_LAYOUT_IS_HOMOGENEOUS (1) #define FLASH_LAYOUT_START_ADDR (FLASH_BASE_NS) @@ -220,7 +220,7 @@ static uint32_t get_page(uint32_t addr) { return (addr - FLASH_LAYOUT_START_ADDR) / FLASH_LAYOUT_SECTOR_SIZE; } -#elif defined(STM32G0) || defined(STM32G4) +#elif defined(STM32G0) || defined(STM32G4) || defined(STM32U5) static uint32_t get_page(uint32_t addr) { return (addr - FLASH_LAYOUT_START_ADDR) / FLASH_LAYOUT_SECTOR_SIZE; @@ -327,12 +327,12 @@ int flash_erase(uint32_t flash_dest) { // ... the erase type and number of pages/sectors, #if defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32L0) \ - || defined(STM32L1) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + || defined(STM32L1) || defined(STM32L4) || defined(STM32U5) || defined(STM32WB) || defined(STM32WL) EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; EraseInitStruct.NbPages = num_sectors; - #elif defined(STM32F4) || defined(STM32F7) || defined(STM32H5) || defined(STM32H7) + #elif defined(STM32F4) || defined(STM32F7) || defined(STM32H5) || defined(STM32H7) || defined(STM32U5) EraseInitStruct.TypeErase = TYPEERASE_SECTORS; EraseInitStruct.NbSectors = num_sectors; @@ -349,7 +349,7 @@ int flash_erase(uint32_t flash_dest) { // ... and the flash bank and page/sector. #if defined(STM32F0) || defined(STM32L0) || defined(STM32L1) EraseInitStruct.PageAddress = flash_dest; - #elif defined(STM32G0) || defined(STM32G4) || (defined(STM32L4) && defined(SYSCFG_MEMRMP_FB_MODE)) + #elif defined(STM32G0) || defined(STM32G4) || (defined(STM32L4) && defined(SYSCFG_MEMRMP_FB_MODE)) || defined(STM32U5) EraseInitStruct.Page = get_page(flash_dest); EraseInitStruct.Banks = get_bank(flash_dest); #elif (defined(STM32L4) && !defined(SYSCFG_MEMRMP_FB_MODE)) || defined(STM32WB) || defined(STM32WL) @@ -453,9 +453,9 @@ int flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) { #endif } - #elif defined(STM32H5) || defined(STM32H7) + #elif defined(STM32H5) || defined(STM32H7) || defined(STM32U5) - #if defined(STM32H5) + #if defined(STM32H5) || defined(STM32U5) static const unsigned int WORD32_PER_FLASHWORD = 4; static const unsigned int PROGRAM_TYPE = FLASH_TYPEPROGRAM_QUADWORD; #else diff --git a/ports/stm32/i2c.c b/ports/stm32/i2c.c index 4effb23438cf6..915b5c829aa67 100644 --- a/ports/stm32/i2c.c +++ b/ports/stm32/i2c.c @@ -271,7 +271,7 @@ int i2c_write(i2c_t *i2c, const uint8_t *src, size_t len, size_t next_len) { return num_acks; } -#elif defined(STM32F0) || defined(STM32F7) || defined(STM32H7) || defined(STM32L4) +#elif defined(STM32F0) || defined(STM32F7) || defined(STM32H7) || defined(STM32L4) || defined(STM32U5) #if defined(STM32H7) #define APB1ENR APB1LENR @@ -283,6 +283,9 @@ int i2c_write(i2c_t *i2c, const uint8_t *src, size_t len, size_t next_len) { // Not a real peripheral, only needed for i2c_id calculation in i2c_init. #define I2C2_BASE (APB1PERIPH_BASE + 0x5800UL) #endif +#elif defined(STM32U5) +#define APB1ENR APB1ENR1 +#define RCC_APB1ENR_I2C1EN RCC_APB1ENR1_I2C1EN #endif static uint16_t i2c_timeout_ms[MICROPY_HW_MAX_I2C]; @@ -341,6 +344,16 @@ int i2c_init(i2c_t *i2c, mp_hal_pin_obj_t scl, mp_hal_pin_obj_t sda, uint32_t fr } else { return -MP_EINVAL; } + #elif defined(STM32U5) + if (freq >= 1000000) { + i2c->TIMINGR = 0x30909DEC; + } else if (freq >= 400000) { + i2c->TIMINGR = 0x00F07BFF; + } else if (freq >= 100000) { + i2c->TIMINGR = 0x00701F6B; + } else { + return -MP_EINVAL; + } #else // These timing values are for f_I2CCLK=54MHz and are only approximate if (freq >= 1000000) { @@ -516,7 +529,7 @@ int i2c_write(i2c_t *i2c, const uint8_t *src, size_t len, size_t next_len) { #endif -#if defined(STM32F0) || defined(STM32F4) || defined(STM32F7) || defined(STM32H7) +#if defined(STM32F0) || defined(STM32F4) || defined(STM32F7) || defined(STM32H7) || defined(STM32U5) int i2c_readfrom(i2c_t *i2c, uint16_t addr, uint8_t *dest, size_t len, bool stop) { int ret; diff --git a/ports/stm32/machine_adc.c b/ports/stm32/machine_adc.c index 63cd4e089dd8b..bb735841a9152 100644 --- a/ports/stm32/machine_adc.c +++ b/ports/stm32/machine_adc.c @@ -30,7 +30,7 @@ #include "py/mphal.h" #include "adc.h" -#if defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32N6) || defined(STM32WB) || defined(STM32WL) +#if defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32N6) || defined(STM32U5) || defined(STM32WB) || defined(STM32WL) #define ADC_V2 (1) #else #define ADC_V2 (0) @@ -88,6 +88,9 @@ #elif defined(STM32N6) #define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_11CYCLES_5 #define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_246CYCLES_5 +#elif defined(STM32U5) +#define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_5CYCLES +#define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_391CYCLES_5 #endif // Timeout for waiting for end-of-conversion @@ -175,6 +178,8 @@ static void adc_wait_eoc(ADC_TypeDef *adc, int32_t timeout_ms) { #if defined(STM32H7) static const uint8_t adc_cr_to_bits_table[] = {16, 14, 12, 10, 8, 8, 8, 8}; +#elif defined(STM32U5) +static const uint8_t adc_cr_to_bits_table[] = {14, 12, 10, 8}; #else static const uint8_t adc_cr_to_bits_table[] = {12, 10, 8, 6}; #endif @@ -188,7 +193,7 @@ void adc_config(ADC_TypeDef *adc, uint32_t bits) { if (adc == ADC1) { #if defined(STM32H5) __HAL_RCC_ADC_CLK_ENABLE(); - #elif defined(STM32G4) || defined(STM32H7) || defined(STM32N6) + #elif defined(STM32G4) || defined(STM32H7) || defined(STM32N6) || defined(STM32U5) __HAL_RCC_ADC12_CLK_ENABLE(); #else __HAL_RCC_ADC1_CLK_ENABLE(); @@ -198,7 +203,7 @@ void adc_config(ADC_TypeDef *adc, uint32_t bits) { if (adc == ADC2) { #if defined(STM32H5) __HAL_RCC_ADC_CLK_ENABLE(); - #elif defined(STM32G4) || defined(STM32H7) || defined(STM32N6) + #elif defined(STM32G4) || defined(STM32H7) || defined(STM32N6) || defined(STM32U5) __HAL_RCC_ADC12_CLK_ENABLE(); #else __HAL_RCC_ADC2_CLK_ENABLE(); @@ -221,7 +226,7 @@ void adc_config(ADC_TypeDef *adc, uint32_t bits) { adc->CFGR2 = 2 << ADC_CFGR2_CKMODE_Pos; // PCLK/4 (synchronous clock mode) #elif defined(STM32F4) || defined(STM32F7) || defined(STM32L4) ADCx_COMMON->CCR = 0; // ADCPR=PCLK/2 - #elif defined(STM32G4) || defined(STM32H5) + #elif defined(STM32G4) || defined(STM32H5) || defined(STM32U5) ADC12_COMMON->CCR = 7 << ADC_CCR_PRESC_Pos; // PCLK/16 (asynchronous clock mode) #elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ) ADC12_COMMON->CCR = 3 << ADC_CCR_CKMODE_Pos; @@ -238,13 +243,13 @@ void adc_config(ADC_TypeDef *adc, uint32_t bits) { ADC_COMMON->CCR = 0 << ADC_CCR_PRESC_Pos; // PRESC=1 #endif - #if defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32N6) || defined(STM32WB) + #if defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32N6) || defined(STM32U5) || defined(STM32WB) if (adc->CR & ADC_CR_DEEPPWD) { adc->CR = 0; // disable deep powerdown } #endif - #if defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32U5) || defined(STM32WB) || defined(STM32WL) if (!(adc->CR & ADC_CR_ADVREGEN)) { adc->CR = ADC_CR_ADVREGEN; // enable VREG #if defined(STM32H7) @@ -260,7 +265,7 @@ void adc_config(ADC_TypeDef *adc, uint32_t bits) { // ADC isn't enabled so calibrate it now #if defined(STM32F0) || defined(STM32G0) || defined(STM32L0) || defined(STM32WL) LL_ADC_StartCalibration(adc); - #elif defined(STM32G4) || defined(STM32H5) || defined(STM32L4) || defined(STM32WB) + #elif defined(STM32G4) || defined(STM32H5) || defined(STM32L4) || defined(STM32U5) || defined(STM32WB) LL_ADC_StartCalibration(adc, LL_ADC_SINGLE_ENDED); #elif defined(STM32N6) ADC_HandleTypeDef hadc; @@ -328,11 +333,17 @@ void adc_config(ADC_TypeDef *adc, uint32_t bits) { uint32_t cfgr1 = res << ADC_CFGR1_RES_Pos; adc->CFGR1 = (adc->CFGR1 & ~cfgr1_clr) | cfgr1; + #elif defined(STM32U5) + + uint32_t cfgr1_clr = ADC_CFGR1_CONT | ADC_CFGR1_EXTEN | ADC_CFGR1_RES; + uint32_t cfgr1 = res << ADC_CFGR1_RES_Pos; + adc->CFGR1 = (adc->CFGR1 & ~cfgr1_clr) | cfgr1; + #endif } static int adc_get_bits(ADC_TypeDef *adc) { - #if defined(STM32F0) || defined(STM32G0) || defined(STM32L0) || defined(STM32N6) || defined(STM32WL) + #if defined(STM32F0) || defined(STM32G0) || defined(STM32L0) || defined(STM32N6) || defined(STM32U5) || defined(STM32WL) uint32_t res = (adc->CFGR1 & ADC_CFGR1_RES) >> ADC_CFGR1_RES_Pos; #elif defined(STM32F4) || defined(STM32F7) || defined(STM32L1) uint32_t res = (adc->CR1 & ADC_CR1_RES) >> ADC_CR1_RES_Pos; @@ -428,9 +439,9 @@ static void adc_config_channel(ADC_TypeDef *adc, uint32_t channel, uint32_t samp } *smpr = (*smpr & ~(7 << (channel * 3))) | sample_time << (channel * 3); // select sample time - #elif defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32N6) || defined(STM32WB) + #elif defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32N6) || defined(STM32U5) || defined(STM32WB) - #if defined(STM32G4) || defined(STM32H5) || defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ) || defined(STM32N6) + #if defined(STM32G4) || defined(STM32H5) || defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ) || defined(STM32N6) || defined(STM32U5) ADC_Common_TypeDef *adc_common = ADC12_COMMON; #elif defined(STM32H7) #if defined(ADC_VER_V5_V90) @@ -452,6 +463,9 @@ static void adc_config_channel(ADC_TypeDef *adc, uint32_t channel, uint32_t samp #if defined(STM32G4) } else if (channel == ADC_CHANNEL_TEMPSENSOR_ADC1) { adc_common->CCR |= ADC_CCR_VSENSESEL; + #elif defined(STM32U5) + } else if (channel == ADC_CHANNEL_TEMPSENSOR) { + adc_common->CCR |= ADC_CCR_VSENSEEN; #else } else if (channel == ADC_CHANNEL_TEMPSENSOR) { adc_common->CCR |= ADC_CCR_TSEN; @@ -469,7 +483,7 @@ static void adc_config_channel(ADC_TypeDef *adc, uint32_t channel, uint32_t samp adc->OR |= ADC_OR_OP0; // Enable Vddcore channel on ADC2 #endif } - #if defined(STM32G4) || defined(STM32H5) || defined(STM32N6) || defined(STM32WB) + #if defined(STM32G4) || defined(STM32H5) || defined(STM32N6) || defined(STM32U5) || defined(STM32WB) // MCU uses encoded literals for internal channels -> extract ADC channel for following code if (__LL_ADC_IS_CHANNEL_INTERNAL(channel)) { channel = __LL_ADC_CHANNEL_TO_DECIMAL_NB(channel); diff --git a/ports/stm32/machine_i2c.c b/ports/stm32/machine_i2c.c index ca2170e32d3bc..f91068c1af077 100644 --- a/ports/stm32/machine_i2c.c +++ b/ports/stm32/machine_i2c.c @@ -34,7 +34,7 @@ #define I2C_POLL_DEFAULT_TIMEOUT_US (50000) // 50ms -#if defined(STM32F0) || defined(STM32F4) || defined(STM32F7) || defined(STM32H7) || defined(STM32L1) || defined(STM32L4) +#if defined(STM32F0) || defined(STM32F4) || defined(STM32F7) || defined(STM32H7) || defined(STM32L1) || defined(STM32L4) || defined(STM32U5) typedef struct _machine_hard_i2c_obj_t { mp_obj_base_t base; @@ -182,7 +182,7 @@ static void machine_hard_i2c_init(machine_hard_i2c_obj_t *self, uint32_t freq, u /******************************************************************************/ /* MicroPython bindings for machine API */ -#if defined(STM32F0) || defined(STM32F7) || defined(STM32H7) || defined(STM32L4) +#if defined(STM32F0) || defined(STM32F7) || defined(STM32H7) || defined(STM32L4) || defined(STM32U5) #define MACHINE_I2C_TIMINGR (1) #else #define MACHINE_I2C_TIMINGR (0) diff --git a/ports/stm32/machine_uart.c b/ports/stm32/machine_uart.c index c93eade5d3df6..5bb5b6c99c535 100644 --- a/ports/stm32/machine_uart.c +++ b/ports/stm32/machine_uart.c @@ -399,7 +399,7 @@ static bool mp_machine_uart_txdone(machine_uart_obj_t *self) { // Send a break condition. static void mp_machine_uart_sendbreak(machine_uart_obj_t *self) { - #if defined(STM32F0) || defined(STM32F7) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32N6) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32F0) || defined(STM32F7) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32N6) || defined(STM32U5) || defined(STM32WB) || defined(STM32WL) self->uartx->RQR = USART_RQR_SBKRQ; // write-only register #else self->uartx->CR1 |= USART_CR1_SBK; diff --git a/ports/stm32/mpconfigboard_common.h b/ports/stm32/mpconfigboard_common.h index a8e50be5c6a8a..86c57e35a1cf6 100644 --- a/ports/stm32/mpconfigboard_common.h +++ b/ports/stm32/mpconfigboard_common.h @@ -484,6 +484,20 @@ #define MICROPY_HW_MAX_UART (10) #define MICROPY_HW_MAX_LPUART (1) +// Configuration for STM32U5 series +#elif defined(STM32U5) + +#define MP_HAL_UNIQUE_ID_ADDRESS (UID_BASE) +// STM32U5 has 26 EXTI vectors but does not have line for RTC/USB. +// To treat these interrupts as same as exti, add virtual vectors for +// EXTI_RTC_TIMESTAMP (26), EXTI_RTC_WAKEUP (27), +// EXTI_RTC_ALARM (28), and EXTI_USB_OTG_FS_WAKEUP (29) +#define PYB_EXTI_NUM_VECTORS (30) +#define MICROPY_HW_MAX_I2C (6) +#define MICROPY_HW_MAX_TIMER (17) +#define MICROPY_HW_MAX_UART (6) +#define MICROPY_HW_MAX_LPUART (1) + // Configuration for STM32WB series #elif defined(STM32WB) @@ -577,6 +591,11 @@ #define MICROPY_HW_CLK_AHB_DIV (RCC_SYSCLK_DIV1) #define MICROPY_HW_CLK_APB1_DIV (RCC_HCLK_DIV1) #define MICROPY_HW_CLK_APB2_DIV (RCC_HCLK_DIV1) +#elif defined(STM32U5) +#define MICROPY_HW_CLK_AHB_DIV (RCC_SYSCLK_DIV1) +#define MICROPY_HW_CLK_APB1_DIV (RCC_HCLK_DIV1) +#define MICROPY_HW_CLK_APB2_DIV (RCC_HCLK_DIV1) +#define MICROPY_HW_CLK_APB3_DIV (RCC_HCLK_DIV1) #else #define MICROPY_HW_CLK_AHB_DIV (RCC_SYSCLK_DIV1) #define MICROPY_HW_CLK_APB1_DIV (RCC_HCLK_DIV4) diff --git a/ports/stm32/mphalport.c b/ports/stm32/mphalport.c index fcd08cbd84562..b13ed0ee15020 100644 --- a/ports/stm32/mphalport.c +++ b/ports/stm32/mphalport.c @@ -90,7 +90,7 @@ void mp_hal_ticks_cpu_enable(void) { #endif void mp_hal_gpio_clock_enable(GPIO_TypeDef *gpio) { - #if defined(STM32L476xx) || defined(STM32L496xx) + #if defined(STM32L476xx) || defined(STM32L496xx) || defined(STM32U5) if (gpio == GPIOG) { // Port G pins 2 thru 15 are powered using VddIO2 on these MCUs. HAL_PWREx_EnableVddIO2(); @@ -117,6 +117,9 @@ void mp_hal_gpio_clock_enable(GPIO_TypeDef *gpio) { #elif defined(STM32G4) || defined(STM32H5) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) #define AHBxENR AHB2ENR #define AHBxENR_GPIOAEN_Pos RCC_AHB2ENR_GPIOAEN_Pos + #elif defined(STM32U5) + #define AHBxENR AHB2ENR1 + #define AHBxENR_GPIOAEN_Pos RCC_AHB2ENR1_GPIOAEN_Pos #endif uint32_t gpio_idx = ((uint32_t)gpio - GPIOA_BASE) / (GPIOB_BASE - GPIOA_BASE); diff --git a/ports/stm32/mphalport.h b/ports/stm32/mphalport.h index 03b0f8e7722ae..dc5530f532eab 100644 --- a/ports/stm32/mphalport.h +++ b/ports/stm32/mphalport.h @@ -25,6 +25,8 @@ extern uint8_t mp_hal_unique_id_address[12]; #define MICROPY_PLATFORM_VERSION "HAL1.10.3" #elif defined(STM32L4) #define MICROPY_PLATFORM_VERSION "HAL1.17.0" +#elif defined(STM32U5) +#define MICROPY_PLATFORM_VERSION "HAL1.8.0" #elif defined(STM32WB) #define MICROPY_PLATFORM_VERSION "HAL1.10.0" #elif defined(STM32WL) diff --git a/ports/stm32/powerctrl.c b/ports/stm32/powerctrl.c index a750e8f5be7e1..54c1ed993c869 100644 --- a/ports/stm32/powerctrl.c +++ b/ports/stm32/powerctrl.c @@ -404,7 +404,7 @@ static uint32_t calc_apb2_div(uint32_t wanted_div) { #endif } -#if defined(STM32F4) || defined(STM32F7) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) +#if defined(STM32F4) || defined(STM32F7) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32U5) int powerctrl_set_sysclk(uint32_t sysclk, uint32_t ahb, uint32_t apb1, uint32_t apb2) { // Return straight away if the clocks are already at the desired frequency @@ -478,7 +478,7 @@ int powerctrl_set_sysclk(uint32_t sysclk, uint32_t ahb, uint32_t apb1, uint32_t // Determine the bus clock dividers // Note: AHB freq required to be >= 14.2MHz for USB operation RCC_ClkInitStruct.AHBCLKDivider = calc_ahb_div(sysclk / ahb); - #if defined(STM32H5) + #if defined(STM32H5) || defined(STM32U5) ahb = sysclk >> AHBPrescTable[RCC_ClkInitStruct.AHBCLKDivider >> RCC_CFGR2_HPRE_Pos]; #elif defined(STM32H7) // Do nothing. @@ -819,7 +819,7 @@ void powerctrl_enter_stop_mode(void) { __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_MSI); #endif - #if !defined(STM32F0) && !defined(STM32G0) && !defined(STM32G4) && !defined(STM32L0) && !defined(STM32L1) && !defined(STM32L4) && !defined(STM32N6) && !defined(STM32WB) && !defined(STM32WL) + #if !defined(STM32F0) && !defined(STM32G0) && !defined(STM32G4) && !defined(STM32L0) && !defined(STM32L1) && !defined(STM32L4) && !defined(STM32N6) && !defined(STM32U5) && !defined(STM32WB) && !defined(STM32WL) // takes longer to wake but reduces stop current HAL_PWREx_EnableFlashPowerDown(); #endif @@ -939,17 +939,25 @@ void powerctrl_enter_stop_mode(void) { #else // defined(STM32H5) + #if defined(STM32U5) + #define RCC_FLAG_PLLRDY RCC_FLAG_PLL1RDY + #endif + // enable PLL __HAL_RCC_PLL_ENABLE(); while (!__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY)) { } // select PLL as system clock source + #if defined(STM32U5) + MODIFY_REG(RCC->CFGR1, RCC_CFGR1_SW, RCC_SYSCLKSOURCE_PLLCLK); + #else MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_SYSCLKSOURCE_PLLCLK); + #endif #if defined(STM32H7) while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL1) { } - #elif defined(STM32G0) || defined(STM32WB) || defined(STM32WL) + #elif defined(STM32G0) || defined(STM32U5) || defined(STM32WB) || defined(STM32WL) while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_SYSCLKSOURCE_STATUS_PLLCLK) { } #else @@ -1146,6 +1154,8 @@ MP_NORETURN void powerctrl_enter_standby_mode(void) { RTC->SR &= ~SR_BITS; #elif defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32WL) RTC->MISR &= ~ISR_BITS; + #elif defined(STM32U5) + // TODO #else RTC->ISR &= ~ISR_BITS; #endif @@ -1179,6 +1189,9 @@ MP_NORETURN void powerctrl_enter_standby_mode(void) { #elif defined(STM32WL) // clear all wake-up flags PWR->SCR |= PWR_SCR_CWUF3 | PWR_SCR_CWUF2 | PWR_SCR_CWUF1; + #elif defined(STM32U5) + // clear all wake-up flags + PWR->WUSCR |= 0xFFu; #else // clear global wake-up flag PWR->CR |= PWR_CR_CWUF; diff --git a/ports/stm32/powerctrlboot.c b/ports/stm32/powerctrlboot.c index 059d2a45da9ce..9b03fb18904ec 100644 --- a/ports/stm32/powerctrlboot.c +++ b/ports/stm32/powerctrlboot.c @@ -198,7 +198,7 @@ void SystemClock_Config(void) { #endif } -#elif defined(STM32H5) +#elif defined(STM32H5) // || defined(STM32U5) void SystemClock_Config(void) { // Set power voltage scaling. diff --git a/ports/stm32/pyb_i2c.c b/ports/stm32/pyb_i2c.c index 7e1489010d097..dc907c638d5e3 100644 --- a/ports/stm32/pyb_i2c.c +++ b/ports/stm32/pyb_i2c.c @@ -128,7 +128,7 @@ const pyb_i2c_obj_t pyb_i2c_obj[] = { #endif }; -#if defined(STM32F7) || defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) +#if defined(STM32F7) || defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32U5) // The STM32F0, F3, F7, H7 and L4 use a TIMINGR register rather than ClockSpeed and // DutyCycle. @@ -215,6 +215,16 @@ const pyb_i2c_obj_t pyb_i2c_obj[] = { #define MICROPY_HW_I2C_BAUDRATE_DEFAULT (PYB_I2C_SPEED_FULL) #define MICROPY_HW_I2C_BAUDRATE_MAX (PYB_I2C_SPEED_FAST) +#elif defined(STM32U5) +// generated using CubeMX +#define MICROPY_HW_I2C_BAUDRATE_TIMING { \ + {PYB_I2C_SPEED_STANDARD, 0x30909DEC}, \ + {PYB_I2C_SPEED_FULL, 0x00F07BFF}, \ + {PYB_I2C_SPEED_FAST, 0x00701F6B}, \ +} +#define MICROPY_HW_I2C_BAUDRATE_DEFAULT (PYB_I2C_SPEED_FULL) +#define MICROPY_HW_I2C_BAUDRATE_MAX (PYB_I2C_SPEED_FAST) + #else #error "no I2C timings for this MCU" #endif diff --git a/ports/stm32/rtc.c b/ports/stm32/rtc.c index b90d17149bde4..5a616476398d4 100644 --- a/ports/stm32/rtc.c +++ b/ports/stm32/rtc.c @@ -179,7 +179,7 @@ void rtc_init_start(bool force_init) { // Clear source Reset Flag __HAL_RCC_CLEAR_RESET_FLAGS(); // Turn the LSI on (it may need this even if the RTC is running) - #if defined(STM32H5) + #if defined(STM32H5) || defined(STM32U5) RCC->BDCR |= RCC_BDCR_LSION; #else RCC->CSR |= RCC_CSR_LSION; @@ -192,7 +192,7 @@ void rtc_init_start(bool force_init) { if (rtc_running) { // Provide information about the registers that indicated the RTC is running. // Bits are (MSB first): LSIRDY LSION LSEBYP LSERDY LSEON - #if defined(STM32H5) + #if defined(STM32H5) || defined(STM32U5) rtc_info |= (RCC->BDCR >> RCC_BDCR_LSEON_Pos & 7) | (RCC->BDCR >> RCC_BDCR_LSION_Pos & 3) << 8; #else rtc_info |= (RCC->BDCR & 7) | (RCC->CSR & 3) << 8; @@ -276,7 +276,7 @@ void rtc_init_finalise() { RTC_CalendarConfig(); #if defined(STM32G0) if (__HAL_RCC_GET_FLAG(RCC_FLAG_PWRRST) != RESET) { - #elif defined(STM32G4) || defined(STM32H5) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #elif defined(STM32G4) || defined(STM32H5) || defined(STM32L4) || defined(STM32U5) || defined(STM32WB) || defined(STM32WL) if (__HAL_RCC_GET_FLAG(RCC_FLAG_BORRST) != RESET) { #else if (__HAL_RCC_GET_FLAG(RCC_FLAG_PORRST) != RESET) { @@ -327,7 +327,7 @@ static HAL_StatusTypeDef PYB_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct return HAL_TIMEOUT; } } - #elif defined(STM32H5) || defined(STM32N6) + #elif defined(STM32H5) || defined(STM32N6) || defined(STM32U5) // Wait for Backup domain Write protection disable while (!LL_PWR_IsEnabledBkUpAccess()) { if (HAL_GetTick() - tickstart > RCC_DBP_TIMEOUT_VALUE) { @@ -412,7 +412,7 @@ static HAL_StatusTypeDef PYB_RTC_Init(RTC_HandleTypeDef *hrtc) { #elif defined(STM32F7) hrtc->Instance->OR &= (uint32_t) ~RTC_OR_ALARMTYPE; hrtc->Instance->OR |= (uint32_t)(hrtc->Init.OutPutType); - #elif defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32N6) || defined(STM32WL) + #elif defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32N6) || defined(STM32U5) || defined(STM32WL) hrtc->Instance->CR &= (uint32_t) ~RTC_CR_TAMPALRM_TYPE_Msk; hrtc->Instance->CR |= (uint32_t)(hrtc->Init.OutPutType); #else @@ -521,6 +521,11 @@ static HAL_StatusTypeDef PYB_RTC_MspInit_Finalise(RTC_HandleTypeDef *hrtc) { // enable RTC peripheral clock __HAL_RCC_RTC_ENABLE(); + + #if defined(STM32U5) + __HAL_RCC_RTCAPB_CLK_ENABLE(); + __HAL_RCC_RTCAPB_CLKAM_ENABLE(); + #endif return HAL_OK; } @@ -685,7 +690,7 @@ mp_obj_t pyb_rtc_datetime(size_t n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_datetime_obj, 1, 2, pyb_rtc_datetime); -#if defined(STM32F0) || defined(STM32H5) || defined(STM32L0) +#if defined(STM32F0) || defined(STM32H5) || defined(STM32L0) || defined(STM32U5) #define RTC_WKUP_IRQn RTC_IRQn #elif defined(STM32G0) #define RTC_WKUP_IRQn RTC_TAMP_IRQn @@ -805,6 +810,8 @@ mp_obj_t pyb_rtc_wakeup(size_t n_args, const mp_obj_t *args) { #elif defined(STM32H7) EXTI_D1->IMR1 |= 1 << EXTI_RTC_WAKEUP; EXTI->RTSR1 |= 1 << EXTI_RTC_WAKEUP; + #elif defined(STM32U5) + // do nothing #else EXTI->IMR |= 1 << EXTI_RTC_WAKEUP; EXTI->RTSR |= 1 << EXTI_RTC_WAKEUP; @@ -813,7 +820,7 @@ mp_obj_t pyb_rtc_wakeup(size_t n_args, const mp_obj_t *args) { // clear interrupt flags #if defined(STM32G0) || defined(STM32G4) || defined(STM32WL) RTC->ICSR &= ~RTC_ICSR_WUTWF; - #elif defined(STM32H5) || defined(STM32N6) + #elif defined(STM32H5) || defined(STM32N6) || defined(STM32U5) LL_RTC_ClearFlag_WUT(RTC); #elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ) RTC->SR &= ~RTC_SR_WUTF; @@ -824,7 +831,7 @@ mp_obj_t pyb_rtc_wakeup(size_t n_args, const mp_obj_t *args) { EXTI->PR1 = 1 << EXTI_RTC_WAKEUP; #elif defined(STM32H7) EXTI_D1->PR1 = 1 << EXTI_RTC_WAKEUP; - #elif defined(STM32G0) || defined(STM32H5) || defined(STM32N6) + #elif defined(STM32G0) || defined(STM32H5) || defined(STM32N6) || defined(STM32U5) // Do nothing #else EXTI->PR = 1 << EXTI_RTC_WAKEUP; @@ -840,7 +847,7 @@ mp_obj_t pyb_rtc_wakeup(size_t n_args, const mp_obj_t *args) { RTC->WPR = 0xff; // disable external interrupts on line EXTI_RTC_WAKEUP - #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L4) || defined(STM32N6) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L4) || defined(STM32N6) || defined(STM32U5) || defined(STM32WB) || defined(STM32WL) EXTI->IMR1 &= ~(1 << EXTI_RTC_WAKEUP); #elif defined(STM32H7) EXTI_D1->IMR1 |= 1 << EXTI_RTC_WAKEUP; diff --git a/ports/stm32/spi.c b/ports/stm32/spi.c index 248075579a87f..330e4d47425e2 100644 --- a/ports/stm32/spi.c +++ b/ports/stm32/spi.c @@ -106,8 +106,8 @@ const spi_t spi_obj[6] = { #error "spi_obj needs updating for new value of MICROPY_HW_SUBGHZSPI_ID" #endif -#if defined(STM32H5) || defined(STM32H7) || defined(STM32N6) -// STM32H5/H7 HAL requires SPI IRQs to be enabled and handled. +#if defined(STM32H5) || defined(STM32H7) || defined(STM32N6) || defined(STM32U5) +// STM32H5/H7/U5 HAL requires SPI IRQs to be enabled and handled. #if defined(MICROPY_HW_SPI1_SCK) void SPI1_IRQHandler(void) { IRQ_ENTER(SPI1_IRQn); @@ -499,7 +499,7 @@ int spi_init(const spi_t *self, bool enable_nss_pin) { dma_invalidate_channel(self->tx_dma_descr); dma_invalidate_channel(self->rx_dma_descr); - #if defined(STM32H5) || defined(STM32H7) || defined(STM32N6) + #if defined(STM32H5) || defined(STM32H7) || defined(STM32N6) || defined(STM32U5) NVIC_SetPriority(irqn, IRQ_PRI_SPI); HAL_NVIC_EnableIRQ(irqn); #else @@ -753,7 +753,7 @@ void spi_print(const mp_print_t *print, const spi_t *spi_obj, bool legacy) { if (spi->State != HAL_SPI_STATE_RESET) { if (spi->Init.Mode == SPI_MODE_MASTER) { // compute baudrate - #if defined(STM32H5) || defined(STM32H7) || defined(STM32N6) + #if defined(STM32H5) || defined(STM32H7) || defined(STM32N6) || defined(STM32U5) uint log_prescaler = (spi->Init.BaudRatePrescaler >> 28) + 1; #else uint log_prescaler = (spi->Init.BaudRatePrescaler >> 3) + 1; diff --git a/ports/stm32/stm32.mk b/ports/stm32/stm32.mk index e6526fc6bd541..b63cb0cc51b31 100644 --- a/ports/stm32/stm32.mk +++ b/ports/stm32/stm32.mk @@ -67,6 +67,7 @@ CFLAGS_MCU_l4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 CFLAGS_MCU_h5 = $(CFLAGS_CORTEX_M) -mtune=cortex-m33 -mcpu=cortex-m33 CFLAGS_MCU_h7 = $(CFLAGS_CORTEX_M) -mtune=cortex-m7 -mcpu=cortex-m7 CFLAGS_MCU_n6 = $(CFLAGS_CORTEX_M) -mtune=cortex-m55 -mcpu=cortex-m55 -mcmse +CFLAGS_MCU_u5 = $(CFLAGS_CORTEX_M) -mtune=cortex-m33 -mcpu=cortex-m33 CFLAGS_MCU_wb = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 CFLAGS_MCU_wl = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 @@ -81,6 +82,7 @@ MPY_CROSS_MCU_ARCH_l4 = armv7m MPY_CROSS_MCU_ARCH_h5 = armv7m MPY_CROSS_MCU_ARCH_h7 = armv7m MPY_CROSS_MCU_ARCH_n6 = armv7m # really armv8m +MPY_CROSS_MCU_ARCH_u5 = armv7m MPY_CROSS_MCU_ARCH_wb = armv7m MPY_CROSS_MCU_ARCH_wl = armv7m diff --git a/ports/stm32/stm32_it.c b/ports/stm32/stm32_it.c index 9eda3cb23974f..48379b781576e 100644 --- a/ports/stm32/stm32_it.c +++ b/ports/stm32/stm32_it.c @@ -384,16 +384,28 @@ static void OTG_CMD_WKUP_Handler(PCD_HandleTypeDef *pcd_handle) { /* Enable the main PLL. */ __HAL_RCC_PLL_ENABLE(); + #if defined(STM32U5) + /* Wait till PLL is ready */ + while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLL1RDY) == RESET) { + } + + /* Select PLL as SYSCLK */ + MODIFY_REG(RCC->CFGR1, RCC_CFGR1_SW, RCC_SYSCLKSOURCE_PLLCLK); + #else /* Wait till PLL is ready */ while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == RESET) { } /* Select PLL as SYSCLK */ MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_SYSCLKSOURCE_PLLCLK); + #endif #if defined(STM32H7) while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL1) { } + #elif defined(STM32U5) + while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_SYSCLKSOURCE_STATUS_PLLCLK) { + } #else while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL) { } @@ -439,7 +451,7 @@ void OTG_HS_WKUP_IRQHandler(void) { OTG_CMD_WKUP_Handler(&pcd_hs_handle); - #if !defined(STM32H5) && !defined(STM32H7) + #if !defined(STM32H5) && !defined(STM32H7) && !defined(STM32U5) /* Clear EXTI pending Bit*/ __HAL_USB_HS_EXTI_CLEAR_FLAG(); #endif @@ -507,6 +519,7 @@ void TAMP_STAMP_IRQHandler(void) { } #endif +#if !defined(STM32U5) #if defined(STM32H5) void RTC_IRQHandler(void) #elif defined(STM32N6) @@ -529,6 +542,7 @@ void RTC_WKUP_IRQHandler(void) Handle_EXTI_Irq(EXTI_RTC_WAKEUP); // clear EXTI flag and execute optional callback IRQ_EXIT(RTC_WKUP_IRQn); } +#endif #if defined(STM32N6) void RTC_IRQHandler(void) { @@ -573,6 +587,26 @@ void TIM1_BRK_UP_TRG_COM_IRQHandler(void) { #endif +#if defined(STM32U5) +extern RTC_HandleTypeDef RTCHandle; +void RTC_IRQHandler(void) { + IRQ_ENTER(RTC_IRQn); + if (RTC->SR & RTC_SR_WUTF) { + RTC->SCR = RTC_SCR_CWUTF; // clear wakeup interrupt flag + Handle_EXTI_Irq(EXTI_RTC_WAKEUP); // clear EXTI flag and execute optional callback + } + if (RTC->SR & RTC_SR_ALRAF) { + RTC->SCR &= ~RTC_SCR_CALRAF; // clear Alarm A flag + Handle_EXTI_Irq(EXTI_RTC_ALARM); // clear EXTI flag and execute optional callback + } + if (RTC->SR & RTC_SR_TSF) { + RTC->SR &= ~RTC_SR_TSF; // clear timestamp flag + Handle_EXTI_Irq(EXTI_RTC_TIMESTAMP); // clear EXTI flag and execute optional callback + } + IRQ_EXIT(RTC_IRQn); +} +#endif + void TIM1_BRK_TIM9_IRQHandler(void) { IRQ_ENTER(TIM1_BRK_TIM9_IRQn); timer_irq_handler(9); diff --git a/ports/stm32/system_stm32.c b/ports/stm32/system_stm32.c index b76a41e97bf78..cca0f9a80c67f 100644 --- a/ports/stm32/system_stm32.c +++ b/ports/stm32/system_stm32.c @@ -79,7 +79,7 @@ #include "boardctrl.h" #include "powerctrl.h" -#if defined(STM32F4) || defined(STM32F7) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) +#if defined(STM32F4) || defined(STM32F7) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32U5) /** * @brief System Clock Configuration @@ -168,15 +168,23 @@ MP_WEAK void SystemClock_Config(void) { // on reset value, so we set it back here, so the clocksources are the same // whether we were started from DFU or from a power on reset. RCC->DCKCFGR2 = 0; + #elif defined(STM32U5) + __HAL_RCC_PWR_CLK_ENABLE(); + #if MICROPY_HW_ENABLE_USB + HAL_PWREx_EnableVddUSB(); + #endif + #if MICROPY_HW_ENABLE_ADC || MICROPY_HW_ENABLE_DAC + HAL_PWREx_EnableVddA(); + #endif #endif RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_OscInitTypeDef RCC_OscInitStruct = {0}; - #if defined(STM32G4) || defined(STM32H7) + #if defined(STM32G4) || defined(STM32H7) || defined(STM32U5) RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; #endif - #if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) + #if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) || defined(STM32U5) #if defined(STM32H7) && defined(SMPS) // H7 MCUs with SMPS must provide a power supply configuration. @@ -184,6 +192,11 @@ MP_WEAK void SystemClock_Config(void) { #elif defined(STM32H7) // H7 MCUs without SMPS, lock the power supply configuration update. MODIFY_REG(PWR->CR3, PWR_CR3_SCUEN, 0); + #elif defined(STM32U5) + HAL_PWREx_DisableUCPDDeadBattery(); + if (HAL_PWREx_ConfigSupply(PWR_SMPS_SUPPLY) != HAL_OK) { + MICROPY_BOARD_FATAL_ERROR("HAL_PWREx_ConfigSupply"); + } #else // other MCUs, enable power control clock. __PWR_CLK_ENABLE(); @@ -204,6 +217,12 @@ MP_WEAK void SystemClock_Config(void) { #endif // defined(STM32H7) + #if defined(STM32U5) + __HAL_RCC_SYSCFG_CLK_ENABLE(); + if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK) { + MICROPY_BOARD_FATAL_ERROR("HAL_PWREx_ControlVoltageScaling"); + } + #else /* The voltage scaling allows optimizing the power consumption when the device is clocked below the maximum system frequency, to update the voltage scaling value regarding system frequency refer to product datasheet. */ @@ -217,6 +236,7 @@ MP_WEAK void SystemClock_Config(void) { { __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); } + #endif #elif defined(STM32G4) // Configure the main internal regulator output voltage @@ -233,7 +253,7 @@ MP_WEAK void SystemClock_Config(void) { #endif /* Enable HSE Oscillator and activate PLL with HSE as source */ - #if defined(STM32F4) || defined(STM32F7) || defined(STM32G4) || defined(STM32H7) + #if defined(STM32F4) || defined(STM32F7) || defined(STM32G4) || defined(STM32H7) || defined(STM32U5) RCC_OscInitStruct.OscillatorType = MICROPY_HW_RCC_OSCILLATOR_TYPE; RCC_OscInitStruct.HSEState = MICROPY_HW_RCC_HSE_STATE; RCC_OscInitStruct.HSIState = MICROPY_HW_RCC_HSI_STATE; @@ -305,6 +325,8 @@ MP_WEAK void SystemClock_Config(void) { RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); #if defined(STM32H7) RCC_ClkInitStruct.ClockType |= (RCC_CLOCKTYPE_D3PCLK1 | RCC_CLOCKTYPE_D1PCLK1); + #elif defined(STM32U5) + RCC_ClkInitStruct.ClockType |= (RCC_CLOCKTYPE_PCLK3); #endif #if defined(MICROPY_HW_CLK_LAST_FREQ) && MICROPY_HW_CLK_LAST_FREQ @@ -354,7 +376,7 @@ MP_WEAK void SystemClock_Config(void) { RCC_OscInitStruct.PLL.PLLN = MICROPY_HW_CLK_PLLN; RCC_OscInitStruct.PLL.PLLP = MICROPY_HW_CLK_PLLP; RCC_OscInitStruct.PLL.PLLQ = MICROPY_HW_CLK_PLLQ; - #if defined(STM32G4) || defined(STM32H7) || defined(STM32L4) + #if defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32U5) RCC_OscInitStruct.PLL.PLLR = MICROPY_HW_CLK_PLLR; #endif @@ -362,6 +384,20 @@ MP_WEAK void SystemClock_Config(void) { RCC_OscInitStruct.PLL.PLLRGE = MICROPY_HW_CLK_PLLVCI; RCC_OscInitStruct.PLL.PLLVCOSEL = MICROPY_HW_CLK_PLLVCO; RCC_OscInitStruct.PLL.PLLFRACN = MICROPY_HW_CLK_PLLFRAC; + #elif defined(STM32U5) + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + RCC_OscInitStruct.HSIState = RCC_HSI_ON; + #if MICROPY_HW_RTC_USE_LSE + RCC_OscInitStruct.LSEState = RCC_LSE_ON; + #else + RCC_OscInitStruct.LSIState = RCC_LSI_ON; + #endif + RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; + RCC_OscInitStruct.PLL.PLLMBOOST = RCC_PLLMBOOST_DIV1; + RCC_OscInitStruct.PLL.PLLRGE = MICROPY_HW_CLK_PLLVCI; + RCC_OscInitStruct.PLL.PLLFRACN = MICROPY_HW_CLK_PLLFRAC; #endif #if defined(STM32F4) || defined(STM32F7) @@ -385,6 +421,12 @@ MP_WEAK void SystemClock_Config(void) { RCC_ClkInitStruct.APB1CLKDivider = MICROPY_HW_CLK_APB1_DIV; RCC_ClkInitStruct.APB2CLKDivider = MICROPY_HW_CLK_APB2_DIV; RCC_ClkInitStruct.APB4CLKDivider = MICROPY_HW_CLK_APB4_DIV; + #elif defined(STM32U5) + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = MICROPY_HW_CLK_AHB_DIV; + RCC_ClkInitStruct.APB1CLKDivider = MICROPY_HW_CLK_APB1_DIV; + RCC_ClkInitStruct.APB2CLKDivider = MICROPY_HW_CLK_APB2_DIV; + RCC_ClkInitStruct.APB3CLKDivider = MICROPY_HW_CLK_APB3_DIV; #endif #endif @@ -506,6 +548,37 @@ MP_WEAK void SystemClock_Config(void) { PeriphClkInitStruct.RngClockSelection = RCC_RNGCLKSOURCE_HSI48; PeriphClkInitStruct.Adc12ClockSelection = RCC_ADC12CLKSOURCE_SYSCLK; PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { + MICROPY_BOARD_FATAL_ERROR("HAL_RCCEx_PeriphCLKConfig"); + } + #elif defined(STM32U5) + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, MICROPY_HW_FLASH_LATENCY) != HAL_OK) { + MICROPY_BOARD_FATAL_ERROR("HAL_RCC_ClockConfig"); + } + + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 + | RCC_PERIPHCLK_SPI1 | RCC_PERIPHCLK_SPI2 | RCC_PERIPHCLK_SPI3; + PeriphClkInitStruct.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1; + PeriphClkInitStruct.I2c2ClockSelection = RCC_I2C2CLKSOURCE_PCLK1; + PeriphClkInitStruct.Spi1ClockSelection = RCC_SPI1CLKSOURCE_SYSCLK; + PeriphClkInitStruct.Spi2ClockSelection = RCC_SPI2CLKSOURCE_SYSCLK; + PeriphClkInitStruct.Spi3ClockSelection = RCC_SPI3CLKSOURCE_SYSCLK; + + #if defined(MICROPY_HW_ENABLE_ADC) || (MICROPY_HW_ENABLE_DAC) + PeriphClkInitStruct.PeriphClockSelection |= RCC_PERIPHCLK_ADCDAC | RCC_PERIPHCLK_DAC1; + PeriphClkInitStruct.AdcDacClockSelection = RCC_ADCDACCLKSOURCE_HSE; + PeriphClkInitStruct.Dac1ClockSelection = RCC_DAC1CLKSOURCE_LSE; + #endif + #if defined(MICROPY_HW_ENABLE_USB) + PeriphClkInitStruct.PeriphClockSelection |= RCC_PERIPHCLK_USBPHY; + PeriphClkInitStruct.UsbPhyClockSelection = RCC_USBPHYCLKSOURCE_PLL1; + #endif + + #if defined(MICROPY_HW_RCC_RTC_CLKSOURCE) + PeriphClkInitStruct.PeriphClockSelection |= RCC_PERIPHCLK_RTC; + PeriphClkInitStruct.RTCClockSelection = MICROPY_HW_RCC_RTC_CLKSOURCE; + #endif + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { MICROPY_BOARD_FATAL_ERROR("HAL_RCCEx_PeriphCLKConfig"); } diff --git a/ports/stm32/timer.c b/ports/stm32/timer.c index 8aa0b3a2dda4b..18932cdfc66a0 100644 --- a/ports/stm32/timer.c +++ b/ports/stm32/timer.c @@ -281,6 +281,9 @@ uint32_t timer_get_source_freq(uint32_t tim_id) { #elif defined(STM32H7) source = HAL_RCC_GetPCLK2Freq(); clk_div = RCC->D2CFGR & RCC_D2CFGR_D2PPRE2; + #elif defined(STM32U5) + source = HAL_RCC_GetPCLK2Freq(); + clk_div = RCC->CFGR1 & RCC_CFGR2_PPRE2; #else source = HAL_RCC_GetPCLK2Freq(); clk_div = RCC->CFGR & RCC_CFGR_PPRE2; @@ -294,6 +297,8 @@ uint32_t timer_get_source_freq(uint32_t tim_id) { clk_div = RCC->CDCFGR1 & RCC_CDCFGR2_CDPPRE1; #elif defined(STM32H7) clk_div = RCC->D2CFGR & RCC_D2CFGR_D2PPRE1; + #elif defined(STM32U5) + clk_div = RCC->CFGR1 & RCC_CFGR2_PPRE1; #else clk_div = RCC->CFGR & RCC_CFGR_PPRE1; #endif @@ -880,7 +885,7 @@ static const uint32_t tim_instance_table[MICROPY_HW_MAX_TIMER] = { TIM_ENTRY(6, TIM6_IRQn), #elif defined(STM32G0) TIM_ENTRY(6, TIM6_DAC_LPTIM1_IRQn), - #elif defined(STM32H5) || defined(STM32N6) + #elif defined(STM32H5) || defined(STM32N6) || defined(STM32U5) TIM_ENTRY(6, TIM6_IRQn), #else TIM_ENTRY(6, TIM6_DAC_IRQn), @@ -952,7 +957,7 @@ static const uint32_t tim_instance_table[MICROPY_HW_MAX_TIMER] = { #endif #if defined(TIM15) - #if defined(STM32F0) || defined(STM32G0) || defined(STM32H5) || defined(STM32H7) || defined(STM32N6) + #if defined(STM32F0) || defined(STM32G0) || defined(STM32H5) || defined(STM32H7) || defined(STM32N6) || defined(STM32U5) TIM_ENTRY(15, TIM15_IRQn), #else TIM_ENTRY(15, TIM1_BRK_TIM15_IRQn), @@ -962,7 +967,7 @@ static const uint32_t tim_instance_table[MICROPY_HW_MAX_TIMER] = { #if defined(TIM16) #if defined(STM32G0B1xx) || defined(STM32G0C1xx) TIM_ENTRY(16, TIM16_FDCAN_IT0_IRQn), - #elif defined(STM32F0) || defined(STM32G0) || defined(STM32H5) || defined(STM32H7) || defined(STM32N6) || defined(STM32WL) + #elif defined(STM32F0) || defined(STM32G0) || defined(STM32H5) || defined(STM32H7) || defined(STM32N6) || defined(STM32U5) || defined(STM32WL) TIM_ENTRY(16, TIM16_IRQn), #else TIM_ENTRY(16, TIM1_UP_TIM16_IRQn), @@ -972,7 +977,7 @@ static const uint32_t tim_instance_table[MICROPY_HW_MAX_TIMER] = { #if defined(TIM17) #if defined(STM32G0B1xx) || defined(STM32G0C1xx) TIM_ENTRY(17, TIM17_FDCAN_IT1_IRQn), - #elif defined(STM32F0) || defined(STM32G0) || defined(STM32H5) || defined(STM32H7) || defined(STM32N6) || defined(STM32WL) + #elif defined(STM32F0) || defined(STM32G0) || defined(STM32H5) || defined(STM32H7) || defined(STM32N6) || defined(STM32U5) || defined(STM32WL) TIM_ENTRY(17, TIM17_IRQn), #else TIM_ENTRY(17, TIM1_TRG_COM_TIM17_IRQn), diff --git a/ports/stm32/uart.c b/ports/stm32/uart.c index 9354af4a291e3..87666fc650cd7 100644 --- a/ports/stm32/uart.c +++ b/ports/stm32/uart.c @@ -115,6 +115,15 @@ #define USART_CR3_IE_ALL (USART_CR3_IE_BASE | USART_CR3_WUFIE) #endif +#elif defined(STM32U5) +#define USART_CR1_IE_ALL (USART_CR1_IE_BASE | USART_CR1_EOBIE | USART_CR1_RTOIE | USART_CR1_CMIE) +#define USART_CR2_IE_ALL (USART_CR2_IE_BASE) +#if defined(USART_CR3_TCBGTIE) +#define USART_CR3_IE_ALL (USART_CR3_IE_BASE | USART_CR3_TCBGTIE) +#else +#define USART_CR3_IE_ALL (USART_CR3_IE_BASE) +#endif + #endif typedef struct _machine_uart_irq_map_t { @@ -664,6 +673,9 @@ bool uart_init(machine_uart_obj_t *uart_obj, huart.Init.Mode = UART_MODE_TX_RX; huart.Init.HwFlowCtl = flow; huart.Init.OverSampling = UART_OVERSAMPLING_16; + #if defined(STM32U5) + huart.Init.ClockPrescaler = UART_PRESCALER_DIV16; + #endif #if defined(STM32G4) || defined(STM32H7) // WB also has a fifo.. huart.FifoMode = UART_FIFOMODE_ENABLE; @@ -1036,14 +1048,14 @@ uint32_t uart_get_baudrate(machine_uart_obj_t *self) { #if defined(LPUART1) if (self->uart_id == PYB_LPUART_1) { return LL_LPUART_GetBaudRate(self->uartx, uart_get_source_freq(self) - #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32N6) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32N6) || defined(STM32U5) || defined(STM32WB) || defined(STM32WL) , self->uartx->PRESC #endif ); } #endif return LL_USART_GetBaudRate(self->uartx, uart_get_source_freq(self), - #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32N6) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32N6) || defined(STM32U5) || defined(STM32WB) || defined(STM32WL) self->uartx->PRESC, #endif LL_USART_OVERSAMPLING_16); @@ -1053,7 +1065,7 @@ void uart_set_baudrate(machine_uart_obj_t *self, uint32_t baudrate) { #if defined(LPUART1) if (self->uart_id == PYB_LPUART_1) { LL_LPUART_SetBaudRate(self->uartx, uart_get_source_freq(self), - #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32N6) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32N6) || defined(STM32U5) || defined(STM32WB) || defined(STM32WL) LL_LPUART_PRESCALER_DIV1, #endif baudrate); @@ -1061,7 +1073,7 @@ void uart_set_baudrate(machine_uart_obj_t *self, uint32_t baudrate) { } #endif LL_USART_SetBaudRate(self->uartx, uart_get_source_freq(self), - #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32N6) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32N6) || defined(STM32U5) || defined(STM32WB) || defined(STM32WL) LL_USART_PRESCALER_DIV1, #endif LL_USART_OVERSAMPLING_16, baudrate); @@ -1112,7 +1124,7 @@ int uart_rx_char(machine_uart_obj_t *self) { return data; } else { // no buffering - #if defined(STM32F0) || defined(STM32F7) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) || defined(STM32N6) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32F0) || defined(STM32F7) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) || defined(STM32N6) || defined(STM32U5) || defined(STM32WB) || defined(STM32WL) int data = self->uartx->RDR & self->char_mask; self->uartx->ICR = USART_ICR_ORECF; // clear ORE if it was set return data; @@ -1267,7 +1279,7 @@ void uart_irq_handler(mp_uint_t uart_id) { uint16_t next_head = (self->read_buf_head + 1) % self->read_buf_len; if (next_head != self->read_buf_tail) { // only read data if room in buf - #if defined(STM32F0) || defined(STM32F7) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32N6) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32F0) || defined(STM32F7) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32N6) || defined(STM32U5) || defined(STM32WB) || defined(STM32WL) int data = self->uartx->RDR; // clears UART_FLAG_RXNE #else self->mp_irq_flags = self->uartx->SR; // resample to get any new flags since next read of DR will clear SR diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index 2d70dcb2619c5..81025e48bac7e 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -69,6 +69,8 @@ #define MAX_ENDPOINT(dev_id) ((dev_id) == USB_PHY_FS_ID ? 5 : 8) #elif defined(STM32H7) || defined(STM32N6) #define MAX_ENDPOINT(dev_id) (8) +#elif defined(STM32U5) +#define MAX_ENDPOINT(dev_id) (9) #endif // Constants for USB_VCP.irq trigger. diff --git a/ports/stm32/usbd_conf.c b/ports/stm32/usbd_conf.c index 7a9e63c9f32c1..39f70fbfca9e7 100644 --- a/ports/stm32/usbd_conf.c +++ b/ports/stm32/usbd_conf.c @@ -182,7 +182,7 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) { // Configure USB GPIO's. - #if defined(STM32H723xx) + #if defined(STM32H723xx) || defined(STM32U5) // These MCUs don't have an alternate function for USB but rather require // the pins to be disconnected from all peripherals, ie put in analog mode. @@ -196,6 +196,33 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) { mp_hal_pin_config(pin_A12, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0); mp_hal_pin_config_speed(pin_A12, GPIO_SPEED_FREQ_VERY_HIGH); + #if defined(STM32U5) + HAL_SYSCFG_SetOTGPHYReferenceClockSelection(SYSCFG_OTG_HS_PHY_CLK_SELECT_1); + + /* Peripheral clock enable */ + __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); + __HAL_RCC_USBPHYC_CLK_ENABLE(); + + /* Enable VDDUSB */ + if (__HAL_RCC_PWR_IS_CLK_DISABLED()) { + __HAL_RCC_PWR_CLK_ENABLE(); + HAL_PWREx_EnableVddUSB(); + + /*configure VOSR register of USB*/ + HAL_PWREx_EnableUSBHSTranceiverSupply(); + __HAL_RCC_PWR_CLK_DISABLE(); + } else { + HAL_PWREx_EnableVddUSB(); + + /*configure VOSR register of USB*/ + HAL_PWREx_EnableUSBHSTranceiverSupply(); + } + + /*Configuring the SYSCFG registers OTG_HS PHY*/ + /*OTG_HS PHY enable*/ + HAL_SYSCFG_EnableOTGPHY(SYSCFG_OTG_HS_PHY_ENABLE); + #endif + #elif defined(STM32N6) // These MCUs have dedicated USB pins. @@ -247,7 +274,9 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) { #else // Enable calling WFI and correct function of the embedded USB_FS_IN_HS phy + #if !defined(STM32U5) __HAL_RCC_USB_OTG_HS_ULPI_CLK_SLEEP_DISABLE(); + #endif __HAL_RCC_USB_OTG_HS_CLK_SLEEP_ENABLE(); // Enable USB HS Clocks @@ -550,7 +579,7 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed, const #if MICROPY_HW_USB_HS_IN_FS - #if defined(STM32F723xx) || defined(STM32F733xx) || defined(STM32N6) + #if defined(STM32F723xx) || defined(STM32F733xx) || defined(STM32N6) || defined(STM32U5) pcd_hs_handle.Init.phy_itface = USB_OTG_HS_EMBEDDED_PHY; #else pcd_hs_handle.Init.phy_itface = PCD_PHY_EMBEDDED; From b26427847b465bab826910b2ab72ddea12f76018 Mon Sep 17 00:00:00 2001 From: Yuuki NAGAO Date: Tue, 22 Jul 2025 23:25:29 +0900 Subject: [PATCH 3/3] stm32/boards: Add NUCLEO-U5A5ZJ-Q board support. This change adds NUCLEO-U5A5ZJ-Q support to the STM32 port. NUCLEO-U5A5ZJ-Q: https://www.st.com/ja/evaluation-tools/nucleo-u5a5zj-q.html This board use STM32U5A5ZJ: https://www.st.com/ja/microcontrollers-microprocessors/stm32u5a5zj.html Signed-off-by: Yuuki NAGAO --- ports/stm32/boards/NUCLEO_U5A5ZJ_Q/board.json | 15 +++ .../boards/NUCLEO_U5A5ZJ_Q/mpconfigboard.h | 82 ++++++++++++ .../boards/NUCLEO_U5A5ZJ_Q/mpconfigboard.mk | 21 +++ ports/stm32/boards/NUCLEO_U5A5ZJ_Q/pins.csv | 123 ++++++++++++++++++ .../NUCLEO_U5A5ZJ_Q/stm32u5xx_hal_conf.h | 19 +++ 5 files changed, 260 insertions(+) create mode 100644 ports/stm32/boards/NUCLEO_U5A5ZJ_Q/board.json create mode 100644 ports/stm32/boards/NUCLEO_U5A5ZJ_Q/mpconfigboard.h create mode 100644 ports/stm32/boards/NUCLEO_U5A5ZJ_Q/mpconfigboard.mk create mode 100644 ports/stm32/boards/NUCLEO_U5A5ZJ_Q/pins.csv create mode 100644 ports/stm32/boards/NUCLEO_U5A5ZJ_Q/stm32u5xx_hal_conf.h diff --git a/ports/stm32/boards/NUCLEO_U5A5ZJ_Q/board.json b/ports/stm32/boards/NUCLEO_U5A5ZJ_Q/board.json new file mode 100644 index 0000000000000..4386b708480b7 --- /dev/null +++ b/ports/stm32/boards/NUCLEO_U5A5ZJ_Q/board.json @@ -0,0 +1,15 @@ +{ + "deploy": [ + "../deploy.md" + ], + "docs": "", + "features": [], + "images": [ + "nucleo_u5a5zj_q.jpg" + ], + "mcu": "stm32u5", + "product": "Nucleo U5A5ZJ_Q", + "thumbnail": "", + "url": "", + "vendor": "ST Microelectronics" +} diff --git a/ports/stm32/boards/NUCLEO_U5A5ZJ_Q/mpconfigboard.h b/ports/stm32/boards/NUCLEO_U5A5ZJ_Q/mpconfigboard.h new file mode 100644 index 0000000000000..7877924bcad48 --- /dev/null +++ b/ports/stm32/boards/NUCLEO_U5A5ZJ_Q/mpconfigboard.h @@ -0,0 +1,82 @@ +#define MICROPY_HW_BOARD_NAME "NUCLEO_U5A5ZJ_Q" +#define MICROPY_HW_MCU_NAME "STM32U5A5ZJ" + +#define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (1) +#define MICROPY_HW_ENABLE_ADC (1) +#define MICROPY_HW_ENABLE_DAC (1) +#define MICROPY_HW_ENABLE_USB (1) +#define MICROPY_HW_ENABLE_RNG (0) +#define MICROPY_HW_ENABLE_RTC (1) +#define MICROPY_HW_HAS_FLASH (1) +#define MICROPY_HW_HAS_SWITCH (1) + +// The board has a 16MHz oscillator, the following gives 160MHz CPU speed +#define MICROPY_HW_CLK_PLLM (1) +#define MICROPY_HW_CLK_PLLN (10) +#define MICROPY_HW_CLK_PLLP (10) +#define MICROPY_HW_CLK_PLLQ (2) +#define MICROPY_HW_CLK_PLLR (1) +#define MICROPY_HW_CLK_PLLVCI (RCC_PLLVCIRANGE_1) +#define MICROPY_HW_CLK_PLLFRAC (0) + +// 5 wait states, according to Table 37, Reference Manual (RM0481 Rev 1) +#define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_4 + +// There is an external 32kHz oscillator +#define MICROPY_HW_RTC_USE_LSE (1) +#define MICROPY_HW_RCC_RTC_CLKSOURCE (RCC_RTCCLKSOURCE_LSE) + +// UART config +#define MICROPY_HW_UART1_TX (pin_A9) +#define MICROPY_HW_UART1_RX (pin_A10) +#define MICROPY_HW_UART2_TX (pin_D5) +#define MICROPY_HW_UART2_RX (pin_D6) +#define MICROPY_HW_UART2_RTS (pin_D4) +#define MICROPY_HW_UART2_CTS (pin_D3) + +// Connect REPL to UART1 which is provided on ST-Link USB interface +#define MICROPY_HW_UART_REPL PYB_UART_1 +#define MICROPY_HW_UART_REPL_BAUD 115200 + +// I2C buses +#define MICROPY_HW_I2C1_SCL (pin_B8) // Arduino Connector CN7-Pin2 (D15) +#define MICROPY_HW_I2C1_SDA (pin_B9) // Arduino Connector CN7-Pin4 (D14) +#define MICROPY_HW_I2C2_SCL (pin_F1) // Connector CN9-Pin19 +#define MICROPY_HW_I2C2_SDA (pin_F0) // Connector CN9-Pin21 + +// SPI buses +#define MICROPY_HW_SPI1_NSS (pin_D14) // Arduino Connector CN7-Pin16 (D10) +#define MICROPY_HW_SPI1_SCK (pin_A5) // Arduino Connector CN7-Pin10 (D13) +#define MICROPY_HW_SPI1_MISO (pin_A6) // Arduino Connector CN7-Pin12 (D12) +#define MICROPY_HW_SPI1_MOSI (pin_A7) // Arduino Connector CN7-Pin14 (D11) +#define MICROPY_HW_SPI2_NSS (pin_D0) +#define MICROPY_HW_SPI2_SCK (pin_B10) +#define MICROPY_HW_SPI2_MISO (pin_D3) +#define MICROPY_HW_SPI2_MOSI (pin_C1) +#define MICROPY_HW_SPI3_NSS (pin_A4) +#define MICROPY_HW_SPI3_SCK (pin_B3) +#define MICROPY_HW_SPI3_MISO (pin_B4) +#define MICROPY_HW_SPI3_MOSI (pin_B5) + +// USRSW is pulled low. Pressing the button makes the input go high. +#define MICROPY_HW_USRSW_PIN (pin_C13) +#define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) +#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_RISING) +#define MICROPY_HW_USRSW_PRESSED (1) + +// LEDs +#define MICROPY_HW_LED1 (pin_C7) // Green +#define MICROPY_HW_LED2 (pin_B7) // Orange +#define MICROPY_HW_LED3 (pin_G2) // Red +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) + +// USB Configuration +#define MICROPY_HW_USB_HS (1) +#define MICROPY_HW_USB_HS_IN_FS (1) + +#if 0 // FDCAN bus +#define MICROPY_HW_CAN1_NAME "FDCAN1" +#define MICROPY_HW_CAN1_TX (pin_D1) +#define MICROPY_HW_CAN1_RX (pin_D0) +#endif diff --git a/ports/stm32/boards/NUCLEO_U5A5ZJ_Q/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_U5A5ZJ_Q/mpconfigboard.mk new file mode 100644 index 0000000000000..c433adfd16a3e --- /dev/null +++ b/ports/stm32/boards/NUCLEO_U5A5ZJ_Q/mpconfigboard.mk @@ -0,0 +1,21 @@ +USE_MBOOT ?= 0 + +# MCU settings +MCU_SERIES = u5 +CMSIS_MCU = STM32U5A5xx +MICROPY_FLOAT_IMPL = single +AF_FILE = boards/stm32u5a5_af.csv + +ifeq ($(USE_MBOOT),1) +# When using Mboot everything goes after the bootloader +# TODO: not tested +LD_FILES = boards/stm32h573xi.ld boards/common_bl.ld +TEXT0_ADDR = 0x08008000 +else +# When not using Mboot everything goes at the start of flash +LD_FILES = boards/stm32u5a5xj.ld boards/common_basic.ld +TEXT0_ADDR = 0x08000000 +endif + +# MicroPython settings +#MICROPY_HW_ENABLE_ISR_UART_FLASH_FUNCS_IN_RAM = 1 diff --git a/ports/stm32/boards/NUCLEO_U5A5ZJ_Q/pins.csv b/ports/stm32/boards/NUCLEO_U5A5ZJ_Q/pins.csv new file mode 100644 index 0000000000000..fb0a0d4b9b328 --- /dev/null +++ b/ports/stm32/boards/NUCLEO_U5A5ZJ_Q/pins.csv @@ -0,0 +1,123 @@ +A0,PA3 +A1,PA2 +A2,PC3 +A3,PB0 +A4,PC1 +A5,PC0 +A6,PB1 +A7,PC2 +A8,PA1 +D0,PG8 +D1,PG7 +D2,PF15 +D3,PE13 +D4,PF14 +D5,PE11 +D6,PE9 +D7,PF13 +D8,PF12 +D9,PD15 +D10,PD14 +D11,PA7 +D12,PA6 +D13,PA5 +D14,PB9 +D15,PB8 +D16,PC6 +D17,PD11 +D18,PB13 +D19,PD12 +D20,PA4 +D21,PB4 +D22,PB5 +D23,PB3 +D24,PA4 +D25,PB4 +D26,PA2 +D27,PB10 +D28,PE15 +D29,PB0 +D30,PE12 +D31,PE14 +D32,PA0 +D33,PA8 +D34,PE0 +D35,PB11 +D36,PB10 +D37,PE15 +D38,PE14 +D39,PE12 +D40,PE10 +D41,PE7 +D42,PE8 +D43,PC8 +D44,PC9 +D45,PC10 +D46,PC11 +D47,PC12 +D48,PD2 +D49,PF3 +D50,PF5 +D51,PD7 +D52,PD6 +D53,PD5 +D54,PD4 +D55,PD3 +D56,PE2 +D57,PE4 +D58,PE5 +D59,PE6 +D60,PE3 +D61,PF8 +D62,PF7 +D63,PF9 +D64,PG1 +D65,PG0 +D66,PD1 +D67,PD0 +D68,PF0 +D69,PF1 +D70,PF2 +D71,PB6 +D72,PB2 +DAC1,PA4 +DAC2,PA5 +LED1,PC7 +LED2,PB7 +LED3,PG2 +SW,PC13 +I2C1_SDA,PB9 +I2C1_SCL,PB8 +I2C2_SDA,PF0 +I2C2_SCL,PF1 +I2C4_SCL,PF14 +I2C4_SDA,PF15 +SD_D0,PC8 +SD_D1,PC9 +SD_D2,PC10 +SD_D3,PC11 +SD_CMD,PD2 +SD_CK,PC12 +SD_SW,PG2 +OTG_FS_POWER,PD10 +OTG_FS_OVER_CURRENT,PG7 +USB_VBUS,PA9 +USB_ID,PA10 +USB_DM,PA11 +USB_DP,PA12 +UART1_TX,PA9 +UART1_RX,PA10 +UART2_TX,PD5 +UART2_RX,PD6 +UART2_RTS,PD4 +UART2_CTS,PD3 +UART3_TX,PD8 +UART3_RX,PD9 +UART5_TX,PB6 +UART5_RX,PB12 +UART6_TX,PC6 +UART6_RX,PC7 +UART7_TX,PF7 +UART7_RX,PF6 +UART8_TX,PE1 +UART8_RX,PE0 diff --git a/ports/stm32/boards/NUCLEO_U5A5ZJ_Q/stm32u5xx_hal_conf.h b/ports/stm32/boards/NUCLEO_U5A5ZJ_Q/stm32u5xx_hal_conf.h new file mode 100644 index 0000000000000..3af461418428b --- /dev/null +++ b/ports/stm32/boards/NUCLEO_U5A5ZJ_Q/stm32u5xx_hal_conf.h @@ -0,0 +1,19 @@ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2023 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32U5XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32U5XX_HAL_CONF_H + +// Oscillator values in Hz +#define HSE_VALUE (16000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) + +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) + +#include "boards/stm32u5xx_hal_conf_base.h" + +#endif // MICROPY_INCLUDED_STM32U5XX_HAL_CONF_H