diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 2b99a98788..d75101159b 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -403,7 +403,7 @@ HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_,\ ll_utils.c \ ) -ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 g0 g4 h7 l0 l4 wb)) +ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 g0 g4 h5 h7 l0 l4 wb)) HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_,\ hal_pcd.c \ hal_pcd_ex.c \ @@ -432,12 +432,18 @@ $(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 h7)) +ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 g0 g4 h5 h7)) HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_,\ hal_dma_ex.c \ ) endif +ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),h5)) +HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_,\ + hal_icache.c \ + ) +endif + ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 f4 f7)) HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_, hal_can.c) else ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),g0 g4 h7)) diff --git a/ports/stm32/adc.c b/ports/stm32/adc.c index fc966e822d..7c51a8b39c 100644 --- a/ports/stm32/adc.c +++ b/ports/stm32/adc.c @@ -102,7 +102,7 @@ #define ADC_CAL2 ((uint16_t *)(ADC_CAL_ADDRESS + 4)) #define ADC_CAL_BITS (12) -#elif defined(STM32G0) || defined(STM32G4) +#elif defined(STM32G0) || defined(STM32G4) || defined(STM32H5) #define ADC_SCALE_V (((float)VREFINT_CAL_VREF) / 1000.0f) #define ADC_CAL_ADDRESS VREFINT_CAL_ADDR @@ -160,6 +160,8 @@ #define VBAT_DIV (4) #elif defined(STM32G0) || defined(STM32G4) #define VBAT_DIV (3) +#elif defined(STM32H5) +#define VBAT_DIV (4) #elif defined(STM32H723xx) || defined(STM32H733xx) || \ defined(STM32H743xx) || defined(STM32H747xx) || \ defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || \ @@ -248,6 +250,10 @@ STATIC bool is_adcx_channel(int channel) { handle.Instance = ADCx; return __HAL_ADC_IS_CHANNEL_INTERNAL(channel) || IS_ADC_CHANNEL(&handle, __HAL_ADC_DECIMAL_NB_TO_CHANNEL(channel)); + #elif defined(STM32H5) + // The first argument to the IS_ADC_CHANNEL macro is unused. + return __HAL_ADC_IS_CHANNEL_INTERNAL(channel) + || IS_ADC_CHANNEL(NULL, __HAL_ADC_DECIMAL_NB_TO_CHANNEL(channel)); #else #error Unsupported processor #endif @@ -257,7 +263,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(STM32H7) || defined(STM32L4) || defined(STM32WB) + #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) while (READ_BIT(adcHandle->Instance->ISR, ADC_FLAG_EOC) != ADC_FLAG_EOC) { #else #error Unsupported processor @@ -278,6 +284,8 @@ STATIC void adcx_clock_enable(ADC_HandleTypeDef *adch) { __HAL_RCC_ADC_CLK_ENABLE(); #elif defined(STM32G4) __HAL_RCC_ADC12_CLK_ENABLE(); + #elif defined(STM32H5) + __HAL_RCC_ADC_CLK_ENABLE(); #elif defined(STM32H7) if (adch->Instance == ADC3) { __HAL_RCC_ADC3_CLK_ENABLE(); @@ -335,7 +343,7 @@ 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(STM32L4) || defined(STM32WB) + #elif defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L4) || defined(STM32WB) adch->Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1; adch->Init.ScanConvMode = ADC_SCAN_DISABLE; adch->Init.LowPowerAutoWait = DISABLE; @@ -354,7 +362,7 @@ STATIC void adcx_init_periph(ADC_HandleTypeDef *adch, uint32_t resolution) { #endif #if defined(STM32G0) HAL_ADCEx_Calibration_Start(adch); - #elif defined(STM32G4) || defined(STM32L4) || defined(STM32WB) + #elif defined(STM32G4) || defined(STM32H5) || defined(STM32L4) || defined(STM32WB) HAL_ADCEx_Calibration_Start(adch, ADC_SINGLE_ENDED); #endif } @@ -415,7 +423,7 @@ STATIC void adc_config_channel(ADC_HandleTypeDef *adc_handle, uint32_t channel) } else { sConfig.SamplingTime = ADC_SAMPLETIME_12CYCLES_5; } - #elif defined(STM32G4) || defined(STM32L4) || defined(STM32WB) + #elif defined(STM32G4) || defined(STM32H5) || defined(STM32L4) || defined(STM32WB) if (__HAL_ADC_IS_CHANNEL_INTERNAL(channel)) { sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5; } else { @@ -599,7 +607,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(STM32H7) || defined(STM32L4) || defined(STM32WB) + #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) SET_BIT(self->handle.Instance->CR, ADC_CR_ADSTART); #else #error Unsupported processor @@ -709,7 +717,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(STM32H7) || defined(STM32L4) || defined(STM32WB) + #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) SET_BIT(adc->handle.Instance->CR, ADC_CR_ADSTART); #else #error Unsupported processor diff --git a/ports/stm32/adc.h b/ports/stm32/adc.h index c61bad459c..0518cdcd9a 100644 --- a/ports/stm32/adc.h +++ b/ports/stm32/adc.h @@ -48,7 +48,7 @@ static inline void adc_deselect_vbat(ADC_TypeDef *adc, uint32_t channel) { adc_common = ADC_COMMON_REGISTER(0); #elif defined(STM32F7) adc_common = ADC123_COMMON; - #elif defined(STM32G4) + #elif defined(STM32G4) || defined(STM32H5) adc_common = ADC12_COMMON; #elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ) adc_common = ADC12_COMMON; diff --git a/ports/stm32/dac.c b/ports/stm32/dac.c index feadbe5c58..e44e519b63 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(STM32H7) +#if defined(STM32H5) || defined(STM32H7) #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(STM32H7) || defined(STM32L4) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) 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(STM32H7) || defined(STM32L4) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) DAC->MCR = (DAC->MCR & ~(DAC_MCR_MODE1_Msk << dac_channel)) | (outbuf << dac_channel); #else cr_off |= DAC_CR_BOFF1; @@ -259,7 +259,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(STM32L4) + #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L4) __HAL_RCC_DAC1_CLK_ENABLE(); #elif defined(STM32L1) __HAL_RCC_DAC_CLK_ENABLE(); diff --git a/ports/stm32/dma.c b/ports/stm32/dma.c index 29306f1b27..cdbb90e5d8 100644 --- a/ports/stm32/dma.c +++ b/ports/stm32/dma.c @@ -80,7 +80,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(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) DMA_Channel_TypeDef *instance; #else #error "Unsupported Processor" @@ -92,6 +92,23 @@ 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) +static const DMA_InitTypeDef dma_init_struct_spi_i2c = { + .Request = 0, // set by dma_init_handle + .BlkHWRequest = DMA_BREQ_SINGLE_BURST, + .Direction = 0, // set by dma_init_handle + .SrcInc = 0, // set by dma_init_handle + .DestInc = 0, // set by dma_init_handle + .SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE, + .DestDataWidth = DMA_DEST_DATAWIDTH_BYTE, + .Priority = DMA_LOW_PRIORITY_LOW_WEIGHT, + .SrcBurstLength = 1, + .DestBurstLength = 1, + .TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0 | DMA_DEST_ALLOCATED_PORT0, + .TransferEventMode = DMA_TCEM_BLOCK_TRANSFER, + .Mode = DMA_NORMAL, // DMA_NORMAL or DMA_PFCTRL (peripheral flow control mode) +}; +#else static const DMA_InitTypeDef dma_init_struct_spi_i2c = { #if defined(STM32F4) || defined(STM32F7) .Channel = 0, @@ -112,6 +129,7 @@ static const DMA_InitTypeDef dma_init_struct_spi_i2c = { .PeriphBurst = DMA_PBURST_INC4 #endif }; +#endif #if MICROPY_HW_ENABLE_I2S // Default parameters to dma_init() for i2s; Channel and Direction @@ -678,6 +696,39 @@ static const uint8_t dma_irqn[NSTREAM] = { #endif }; +#elif defined(STM32H5) + +#define NCONTROLLERS (2) +#define NSTREAMS_PER_CONTROLLER (8) +#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_2_RX = { GPDMA1_Channel0, GPDMA1_REQUEST_SPI2_RX, dma_id_0, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_SPI_2_TX = { GPDMA1_Channel1, GPDMA1_REQUEST_SPI2_TX, dma_id_1, &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, + GPDMA2_Channel0_IRQn, + GPDMA2_Channel1_IRQn, + GPDMA2_Channel2_IRQn, + GPDMA2_Channel3_IRQn, + GPDMA2_Channel4_IRQn, + GPDMA2_Channel5_IRQn, + GPDMA2_Channel6_IRQn, + GPDMA2_Channel7_IRQn, +}; + #elif defined(STM32H7) #define NCONTROLLERS (2) @@ -761,6 +812,13 @@ 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) +#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 +#define __HAL_RCC_DMA2_CLK_ENABLE __HAL_RCC_GPDMA2_CLK_ENABLE +#define __HAL_RCC_DMA1_CLK_DISABLE __HAL_RCC_GPDMA1_CLK_DISABLE +#define __HAL_RCC_DMA2_CLK_DISABLE __HAL_RCC_GPDMA2_CLK_DISABLE #else #define DMA1_IS_CLK_ENABLED() ((RCC->AHB1ENR & RCC_AHB1ENR_DMA1EN) != 0) #define DMA2_IS_CLK_ENABLED() ((RCC->AHB1ENR & RCC_AHB1ENR_DMA2EN) != 0) @@ -1093,6 +1151,34 @@ void DMA2_Channel8_IRQHandler(void) { } #endif +#elif defined(STM32H5) + +#define DEFINE_IRQ_HANDLER(periph, channel, id) \ + void GPDMA##periph##_Channel##channel##_IRQHandler(void) { \ + IRQ_ENTER(GPDMA##periph##_Channel##channel##_IRQn); \ + if (dma_handle[id] != NULL) { \ + HAL_DMA_IRQHandler(dma_handle[id]); \ + } \ + IRQ_EXIT(GPDMA##periph##_Channel##channel##_IRQn); \ + } + +DEFINE_IRQ_HANDLER(1, 0, dma_id_0) +DEFINE_IRQ_HANDLER(1, 1, dma_id_1) +DEFINE_IRQ_HANDLER(1, 2, dma_id_2) +DEFINE_IRQ_HANDLER(1, 3, dma_id_3) +DEFINE_IRQ_HANDLER(1, 4, dma_id_4) +DEFINE_IRQ_HANDLER(1, 5, dma_id_5) +DEFINE_IRQ_HANDLER(1, 6, dma_id_6) +DEFINE_IRQ_HANDLER(1, 7, dma_id_7) +DEFINE_IRQ_HANDLER(2, 0, dma_id_8) +DEFINE_IRQ_HANDLER(2, 1, dma_id_9) +DEFINE_IRQ_HANDLER(2, 2, dma_id_10) +DEFINE_IRQ_HANDLER(2, 3, dma_id_11) +DEFINE_IRQ_HANDLER(2, 4, dma_id_12) +DEFINE_IRQ_HANDLER(2, 5, dma_id_13) +DEFINE_IRQ_HANDLER(2, 6, dma_id_14) +DEFINE_IRQ_HANDLER(2, 7, dma_id_15) + #elif defined(STM32L0) void DMA1_Channel1_IRQHandler(void) { @@ -1276,7 +1362,7 @@ static void dma_enable_clock(dma_id_t dma_id) { } } } - #if defined(DMA2) + #if defined(DMA2) || defined(GPDMA2) else { if (((old_enable_mask & DMA2_ENABLE_MASK) == 0) && !DMA2_IS_CLK_ENABLED()) { __HAL_RCC_DMA2_CLK_ENABLE(); @@ -1310,13 +1396,25 @@ 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(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) dma->Init.Request = dma_descr->sub_instance; #else #if !defined(STM32F0) && !defined(STM32L1) dma->Init.Channel = dma_descr->sub_instance; #endif #endif + + #if defined(STM32H5) + // Configure src/dest settings based on the DMA direction. + if (dir == DMA_MEMORY_TO_PERIPH) { + dma->Init.SrcInc = DMA_SINC_INCREMENTED; + dma->Init.DestInc = DMA_DINC_FIXED; + } else if (dir == DMA_PERIPH_TO_MEMORY) { + dma->Init.SrcInc = DMA_SINC_FIXED; + dma->Init.DestInc = DMA_DINC_INCREMENTED; + } + #endif + // half of __HAL_LINKDMA(data, xxx, *dma) // caller must implement other half by doing: data->xxx = dma dma->Parent = data; @@ -1337,11 +1435,12 @@ 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(STM32H7) || defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || 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 HAL_DMA_DeInit(dma); + dma->Parent = data; // HAL_DMA_DeInit may clear Parent, so set it again HAL_DMA_Init(dma); NVIC_SetPriority(IRQn_NONNEG(dma_irqn[dma_id]), IRQ_PRI_DMA); #else @@ -1418,7 +1517,7 @@ static void dma_idle_handler(uint32_t tick) { static const uint32_t controller_mask[] = { DMA1_ENABLE_MASK, - #if defined(DMA2) + #if defined(DMA2) || defined(GPDMA2) DMA2_ENABLE_MASK, #endif }; @@ -1435,7 +1534,7 @@ static void dma_idle_handler(uint32_t tick) { if (controller == 0) { __HAL_RCC_DMA1_CLK_DISABLE(); #if defined(STM32G4) - #if defined(DMA2) + #if defined(DMA2) || defined(GPDMA2) if (__HAL_RCC_DMA2_IS_CLK_DISABLED()) #endif { @@ -1443,7 +1542,7 @@ static void dma_idle_handler(uint32_t tick) { } #endif } - #if defined(DMA2) + #if defined(DMA2) || defined(GPDMA2) else { __HAL_RCC_DMA2_CLK_DISABLE(); #if defined(STM32G4) @@ -1514,7 +1613,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(STM32G0) || defined(STM32WB) || defined(STM32WL) +#elif defined(STM32G0) || defined(STM32H5) || defined(STM32WB) || defined(STM32WL) // These functions are currently not implemented or needed for this MCU. diff --git a/ports/stm32/dma.h b/ports/stm32/dma.h index 37b8710c21..92d5db6c0a 100644 --- a/ports/stm32/dma.h +++ b/ports/stm32/dma.h @@ -28,7 +28,7 @@ typedef struct _dma_descr_t dma_descr_t; -#if defined(STM32F0) || defined(STM32F4) || defined(STM32F7) || defined(STM32G0) || defined(STM32H7) +#if defined(STM32F0) || defined(STM32F4) || defined(STM32F7) || defined(STM32G0) || defined(STM32H5) || defined(STM32H7) 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 f810bc4e0d..7698569149 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(STM32L4) || defined(STM32WB) || defined(STM32WL) +#if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L4) || 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,6 +170,25 @@ STATIC const uint8_t nvic_irq_channel[EXTI_NUM_VECTORS] = { ADC1_COMP_IRQn, #endif + #elif defined(STM32H5) + + EXTI0_IRQn, + EXTI1_IRQn, + EXTI2_IRQn, + EXTI3_IRQn, + EXTI4_IRQn, + EXTI5_IRQn, + EXTI6_IRQn, + EXTI7_IRQn, + EXTI8_IRQn, + EXTI9_IRQn, + EXTI10_IRQn, + EXTI11_IRQn, + EXTI12_IRQn, + EXTI13_IRQn, + EXTI14_IRQn, + EXTI15_IRQn, + #else EXTI0_IRQn, EXTI1_IRQn, EXTI2_IRQn, EXTI3_IRQn, EXTI4_IRQn, @@ -327,10 +346,10 @@ void extint_register_pin(const pin_obj_t *pin, uint32_t mode, bool hard_irq, mp_ pyb_extint_callback_arg[line] = MP_OBJ_FROM_PTR(pin); // Route the GPIO to EXTI - #if !defined(STM32WB) && !defined(STM32WL) + #if !defined(STM32H5) && !defined(STM32WB) && !defined(STM32WL) __HAL_RCC_SYSCFG_CLK_ENABLE(); #endif - #if defined(STM32G0) + #if defined(STM32G0) || defined(STM32H5) EXTI->EXTICR[line >> 2] = (EXTI->EXTICR[line >> 2] & ~(0x0f << (4 * (line & 0x03)))) | ((uint32_t)(GPIO_GET_INDEX(pin->gpio)) << (4 * (line & 0x03))); @@ -370,10 +389,10 @@ void extint_set(const pin_obj_t *pin, uint32_t mode) { pyb_extint_callback_arg[line] = MP_OBJ_FROM_PTR(pin); // Route the GPIO to EXTI - #if !defined(STM32WB) && !defined(STM32WL) + #if !defined(STM32H5) && !defined(STM32WB) && !defined(STM32WL) __HAL_RCC_SYSCFG_CLK_ENABLE(); #endif - #if defined(STM32G0) + #if defined(STM32G0) || defined(STM32H5) EXTI->EXTICR[line >> 2] = (EXTI->EXTICR[line >> 2] & ~(0x0f << (4 * (line & 0x03)))) | ((uint32_t)(GPIO_GET_INDEX(pin->gpio)) << (4 * (line & 0x03))); @@ -416,7 +435,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(STM32WB) || defined(STM32WL) + #elif defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32WB) || defined(STM32WL) EXTI->IMR1 |= (1 << line); #else EXTI->IMR |= (1 << line); @@ -424,7 +443,7 @@ void extint_enable(uint line) { } else { #if defined(STM32H7) EXTI_D1->EMR1 |= (1 << line); - #elif defined(STM32G0) || defined(STM32G4) || defined(STM32WB) || defined(STM32WL) + #elif defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32WB) || defined(STM32WL) EXTI->EMR1 |= (1 << line); #else EXTI->EMR |= (1 << line); @@ -450,7 +469,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(STM32WB) || defined(STM32WL) + #elif defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32WB) || defined(STM32WL) EXTI->IMR1 &= ~(1 << line); EXTI->EMR1 &= ~(1 << line); #else @@ -472,7 +491,7 @@ void extint_swint(uint line) { return; } // we need 0 to 1 transition to trigger the interrupt - #if defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) EXTI->SWIER1 &= ~(1 << line); EXTI->SWIER1 |= (1 << line); #else @@ -552,7 +571,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_swint_obj, extint_obj_swint); STATIC mp_obj_t extint_regs(void) { const mp_print_t *print = &mp_plat_print; - #if defined(STM32G0) || defined(STM32G4) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) mp_printf(print, "EXTI_IMR1 %08x\n", (unsigned int)EXTI->IMR1); mp_printf(print, "EXTI_IMR2 %08x\n", (unsigned int)EXTI->IMR2); mp_printf(print, "EXTI_EMR1 %08x\n", (unsigned int)EXTI->EMR1); @@ -563,7 +582,7 @@ STATIC mp_obj_t extint_regs(void) { mp_printf(print, "EXTI_FTSR2 %08x\n", (unsigned int)EXTI->FTSR2); mp_printf(print, "EXTI_SWIER1 %08x\n", (unsigned int)EXTI->SWIER1); mp_printf(print, "EXTI_SWIER2 %08x\n", (unsigned int)EXTI->SWIER2); - #if defined(STM32G0) + #if defined(STM32G0) || defined(STM32H5) mp_printf(print, "EXTI_RPR1 %08x\n", (unsigned int)EXTI->RPR1); mp_printf(print, "EXTI_FPR1 %08x\n", (unsigned int)EXTI->FPR1); mp_printf(print, "EXTI_RPR2 %08x\n", (unsigned int)EXTI->RPR2); diff --git a/ports/stm32/extint.h b/ports/stm32/extint.h index 84eb876d8d..919e4bb2e8 100644 --- a/ports/stm32/extint.h +++ b/ports/stm32/extint.h @@ -46,12 +46,17 @@ #if defined(STM32F0) || defined(STM32G4) || defined(STM32L1) || defined(STM32L4) || defined(STM32WL) #define EXTI_RTC_TIMESTAMP (19) #define EXTI_RTC_WAKEUP (20) +#elif defined(STM32H5) +#define EXTI_RTC_WAKEUP (17) +#define EXTI_RTC_TAMP (19) #elif defined(STM32H7) || defined(STM32WB) #define EXTI_RTC_TIMESTAMP (18) #define EXTI_RTC_WAKEUP (19) #elif defined(STM32G0) #define EXTI_RTC_WAKEUP (19) #define EXTI_RTC_TIMESTAMP (21) +#elif defined(STM32H5) +#define EXTI_RTC_WAKEUP (17) #else #define EXTI_RTC_TIMESTAMP (21) #define EXTI_RTC_WAKEUP (22) diff --git a/ports/stm32/flash.c b/ports/stm32/flash.c index 12fa523cd5..a8f50dbcba 100644 --- a/ports/stm32/flash.c +++ b/ports/stm32/flash.c @@ -123,6 +123,12 @@ static const flash_layout_t flash_layout[] = { { (uint32_t)FLASH_BASE, 0x200, 1024 }, }; +#elif defined(STM32H5) + +static const flash_layout_t flash_layout[] = { + { 0x08000000, 8192, 256 }, +}; + #elif defined(STM32H7) static const flash_layout_t flash_layout[] = { @@ -140,11 +146,11 @@ static uint32_t get_bank(uint32_t addr) { return FLASH_BANK_1; } -#elif (defined(STM32L4) && defined(SYSCFG_MEMRMP_FB_MODE)) || defined(STM32H7) +#elif (defined(STM32L4) && defined(SYSCFG_MEMRMP_FB_MODE)) || defined(STM32H5) || defined(STM32H7) // get the bank of a given flash address static uint32_t get_bank(uint32_t addr) { - #if defined(STM32H7) + #if defined(STM32H5) || defined(STM32H7) if (READ_BIT(FLASH->OPTCR, FLASH_OPTCR_SWAP_BANK) == 0) { #else if (READ_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_FB_MODE) == 0) { @@ -297,7 +303,9 @@ int flash_erase(uint32_t flash_dest, uint32_t num_word32) { EraseInitStruct.NbPages = get_page(flash_dest + 4 * num_word32 - 1) - EraseInitStruct.Page + 1; #else - #if defined(STM32H7) + #if defined(STM32H5) + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); + #elif defined(STM32H7) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS_BANK1 | FLASH_FLAG_ALL_ERRORS_BANK2); #elif defined(STM32L1) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR); @@ -309,14 +317,17 @@ int flash_erase(uint32_t flash_dest, uint32_t num_word32) { EraseInitStruct.TypeErase = TYPEERASE_SECTORS; #if defined(FLASH_CR_PSIZE) EraseInitStruct.VoltageRange = VOLTAGE_RANGE_3; // voltage range needs to be 2.7V to 3.6V - #else + #elif !defined(STM32H5) EraseInitStruct.VoltageRange = 0; // unused parameter on STM32H7A3/B3 #endif - #if defined(STM32G0) || defined(STM32G4) || defined(STM32H7) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) EraseInitStruct.Banks = get_bank(flash_dest); #endif EraseInitStruct.Sector = flash_get_sector_info(flash_dest, NULL, NULL); EraseInitStruct.NbSectors = flash_get_sector_info(flash_dest + 4 * num_word32 - 1, NULL, NULL) - EraseInitStruct.Sector + 1; + #if defined(STM32H5) + EraseInitStruct.Sector &= 0x7f; // second bank should start counting at 0 + #endif #endif @@ -439,6 +450,18 @@ int flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) { #endif } + #elif defined(STM32H5) + + // program the flash 128 bits (4 words) at a time + for (int i = 0; i < num_word32 / 4; i++) { + status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, flash_dest, (uint64_t)(uint32_t)src); + if (status != HAL_OK) { + break; + } + flash_dest += 16; + src += 4; + } + #elif defined(STM32H7) // program the flash 256 bits at a time diff --git a/ports/stm32/i2cslave.h b/ports/stm32/i2cslave.h index 3f9022aa70..a4b2957de3 100644 --- a/ports/stm32/i2cslave.h +++ b/ports/stm32/i2cslave.h @@ -47,7 +47,7 @@ static inline void i2c_slave_init(i2c_slave_t *i2c, int irqn, int irq_pri, int a RCC->APBENR1 |= 1 << (RCC_APBENR1_I2C1EN_Pos + i2c_idx); volatile uint32_t tmp = RCC->APBENR1; // Delay after enabling clock (void)tmp; - #elif defined(STM32H7) + #elif defined(STM32H5) || defined(STM32H7) RCC->APB1LENR |= 1 << (RCC_APB1LENR_I2C1EN_Pos + i2c_idx); volatile uint32_t tmp = RCC->APB1LENR; // Delay after enabling clock (void)tmp; diff --git a/ports/stm32/machine_adc.c b/ports/stm32/machine_adc.c index f68ed0ec84..3a348e18bf 100644 --- a/ports/stm32/machine_adc.c +++ b/ports/stm32/machine_adc.c @@ -28,7 +28,7 @@ #include "py/mphal.h" #include "adc.h" -#if defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) +#if defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) #define ADC_V2 (1) #else #define ADC_V2 (0) @@ -45,7 +45,7 @@ #if defined(STM32F0) || defined(STM32G0) || defined(STM32L0) || defined(STM32L1) || defined(STM32WL) #define ADC_STAB_DELAY_US (1) #define ADC_TEMPSENSOR_DELAY_US (10) -#elif defined(STM32G4) +#elif defined(STM32G4) || defined(STM32H5) #define ADC_STAB_DELAY_US (1) // TODO: Check if this is enough #elif defined(STM32L4) #define ADC_STAB_DELAY_US (10) @@ -59,7 +59,7 @@ #elif defined(STM32F4) || defined(STM32F7) #define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_15CYCLES #define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_480CYCLES -#elif defined(STM32G4) +#elif defined(STM32G4) || defined(STM32H5) #define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_12CYCLES_5 #define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_247CYCLES_5 #elif defined(STM32H7) @@ -113,7 +113,9 @@ void adc_config(ADC_TypeDef *adc, uint32_t bits) { __HAL_RCC_ADC_CLK_ENABLE(); #else if (adc == ADC1) { - #if defined(STM32G4) || defined(STM32H7) + #if defined(STM32H5) + __HAL_RCC_ADC_CLK_ENABLE(); + #elif defined(STM32G4) || defined(STM32H7) __HAL_RCC_ADC12_CLK_ENABLE(); #else __HAL_RCC_ADC1_CLK_ENABLE(); @@ -121,7 +123,9 @@ void adc_config(ADC_TypeDef *adc, uint32_t bits) { } #if defined(ADC2) if (adc == ADC2) { - #if defined(STM32G4) || defined(STM32H7) + #if defined(STM32H5) + __HAL_RCC_ADC_CLK_ENABLE(); + #elif defined(STM32G4) || defined(STM32H7) __HAL_RCC_ADC12_CLK_ENABLE(); #else __HAL_RCC_ADC2_CLK_ENABLE(); @@ -144,7 +148,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(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ) + #elif defined(STM32H5) || defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ) ADC12_COMMON->CCR = 3 << ADC_CCR_CKMODE_Pos; #elif defined(STM32H7) ADC12_COMMON->CCR = 3 << ADC_CCR_CKMODE_Pos; @@ -157,13 +161,13 @@ void adc_config(ADC_TypeDef *adc, uint32_t bits) { ADC_COMMON->CCR = 0 << ADC_CCR_PRESC_Pos; // PRESC=1 #endif - #if defined(STM32H7) || defined(STM32L4) || defined(STM32WB) + #if defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) if (adc->CR & ADC_CR_DEEPPWD) { adc->CR = 0; // disable deep powerdown } #endif - #if defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32H5) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) if (!(adc->CR & ADC_CR_ADVREGEN)) { adc->CR = ADC_CR_ADVREGEN; // enable VREG #if defined(STM32H7) @@ -179,7 +183,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(STM32L4) || defined(STM32WB) + #elif defined(STM32G4) || defined(STM32H5) || defined(STM32L4) || defined(STM32WB) LL_ADC_StartCalibration(adc, LL_ADC_SINGLE_ENDED); #else LL_ADC_StartCalibration(adc, LL_ADC_CALIB_OFFSET_LINEARITY, LL_ADC_SINGLE_ENDED); @@ -225,7 +229,7 @@ void adc_config(ADC_TypeDef *adc, uint32_t bits) { adc->CR2 = (adc->CR2 & ~cr2_clr) | cr2; adc->SQR1 = 1 << ADC_SQR1_L_Pos; // 1 conversion in regular sequence - #elif defined(STM32H7) || defined(STM32L4) || defined(STM32WB) + #elif defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) uint32_t cfgr_clr = ADC_CFGR_CONT | ADC_CFGR_EXTEN | ADC_CFGR_RES; #if defined(STM32H7) @@ -244,7 +248,7 @@ STATIC int adc_get_bits(ADC_TypeDef *adc) { 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; - #elif defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) + #elif defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) uint32_t res = (adc->CFGR & ADC_CFGR_RES) >> ADC_CFGR_RES_Pos; #endif return adc_cr_to_bits_table[res]; @@ -311,8 +315,8 @@ 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(STM32H7) || defined(STM32L4) || defined(STM32WB) - #if defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ) + #elif defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) + #if defined(STM32H5) || defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ) ADC_Common_TypeDef *adc_common = ADC12_COMMON; #elif defined(STM32H7) #if defined(ADC_VER_V5_V90) diff --git a/ports/stm32/machine_uart.c b/ports/stm32/machine_uart.c index 20def373fb..ba8c1a9111 100644 --- a/ports/stm32/machine_uart.c +++ b/ports/stm32/machine_uart.c @@ -477,7 +477,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_readchar_obj, pyb_uart_readchar); // uart.sendbreak() STATIC mp_obj_t pyb_uart_sendbreak(mp_obj_t self_in) { pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - #if defined(STM32F0) || defined(STM32F7) || defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32F0) || defined(STM32F7) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || 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/main.c b/ports/stm32/main.c index 15be21d481..2235e4de35 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -306,8 +306,10 @@ void stm32_main(uint32_t reset_mode) { SCB->VTOR = MICROPY_HW_VTOR; #endif + #if __CORTEX_M != 33 // Enable 8-byte stack alignment for IRQ handlers, in accord with EABI SCB->CCR |= SCB_CCR_STKALIGN_Msk; + #endif // Hook for a board to run code at start up, for example check if a // bootloader should be entered instead of the main application. @@ -336,6 +338,10 @@ void stm32_main(uint32_t reset_mode) { SCB_EnableICache(); SCB_EnableDCache(); + #elif defined(STM32H5) + + HAL_ICACHE_Enable(); + #elif defined(STM32L4) #if !INSTRUCTION_CACHE_ENABLE @@ -387,6 +393,13 @@ void stm32_main(uint32_t reset_mode) { MICROPY_BOARD_EARLY_INIT(); // basic sub-system init + #if defined(STM32H5) + volatile uint32_t *src = (volatile uint32_t *)UID_BASE; + uint32_t *dest = (uint32_t *)&mp_hal_unique_id_address[0]; + dest[0] = src[0]; + dest[1] = src[1]; + dest[2] = src[2]; + #endif #if defined(STM32WB) rfcore_init(); #endif diff --git a/ports/stm32/mboot/Makefile b/ports/stm32/mboot/Makefile index 4e3f7597f7..1f6ba063b2 100755 --- a/ports/stm32/mboot/Makefile +++ b/ports/stm32/mboot/Makefile @@ -152,12 +152,14 @@ endif $(BUILD)/$(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_ll_usb.o: CFLAGS += -Wno-attributes SRC_HAL += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_,\ + hal.c \ hal_cortex.c \ hal_dma.c \ hal_flash.c \ hal_flash_ex.c \ hal_pcd.c \ hal_pcd_ex.c \ + hal_pwr_ex.c \ hal_rcc.c \ hal_rcc_ex.c \ ll_usb.c \ diff --git a/ports/stm32/mboot/main.c b/ports/stm32/mboot/main.c index 80e2a710ad..afd4a2f1ce 100644 --- a/ports/stm32/mboot/main.c +++ b/ports/stm32/mboot/main.c @@ -36,6 +36,7 @@ #include "i2cslave.h" #include "irq.h" #include "mboot.h" +#include "mpu.h" #include "powerctrl.h" #include "sdcard.h" #include "dfu.h" @@ -377,7 +378,7 @@ void SystemClock_Config(void) { #elif defined(STM32H7) #define AHBxENR AHB4ENR #define AHBxENR_GPIOAEN_Pos RCC_AHB4ENR_GPIOAEN_Pos -#elif defined(STM32WB) +#elif defined(STM32H5) || defined(STM32WB) #define AHBxENR AHB2ENR #define AHBxENR_GPIOAEN_Pos RCC_AHB2ENR_GPIOAEN_Pos #endif @@ -411,6 +412,8 @@ void mp_hal_pin_config_speed(uint32_t port_pin, uint32_t speed) { #if defined(STM32G0) #define FLASH_END (FLASH_BASE + FLASH_SIZE - 1) +#elif defined(STM32H5) +#define FLASH_END (0x08000000 + 2 * 1024 * 1024) #elif defined(STM32WB) #define FLASH_END FLASH_END_ADDR #endif @@ -433,6 +436,8 @@ void mp_hal_pin_config_speed(uint32_t port_pin, uint32_t speed) { #define FLASH_LAYOUT_STR "@Internal Flash /0x08000000/04*032Kg,01*128Kg,07*256Kg" MBOOT_SPIFLASH_LAYOUT MBOOT_SPIFLASH2_LAYOUT #elif defined(STM32G0) #define FLASH_LAYOUT_STR "@Internal Flash /0x08000000/256*02Kg" MBOOT_SPIFLASH_LAYOUT MBOOT_SPIFLASH2_LAYOUT +#elif defined(STM32H5) +#define FLASH_LAYOUT_STR "@Internal Flash /0x08000000/256*08Kg" MBOOT_SPIFLASH_LAYOUT MBOOT_SPIFLASH2_LAYOUT #elif defined(STM32H743xx) #define FLASH_LAYOUT_STR "@Internal Flash /0x08000000/16*128Kg" MBOOT_SPIFLASH_LAYOUT MBOOT_SPIFLASH2_LAYOUT #elif defined(STM32H750xx) @@ -1314,6 +1319,10 @@ static void leave_bootloader(void) { NVIC_SystemReset(); } +#if defined(STM32H5) +uint8_t mp_hal_unique_id_address[12]; +#endif + extern PCD_HandleTypeDef pcd_fs_handle; extern PCD_HandleTypeDef pcd_hs_handle; @@ -1337,8 +1346,10 @@ void stm32_main(uint32_t initial_r0) { // Make sure IRQ vector table points to flash where this bootloader lives. SCB->VTOR = MBOOT_VTOR; + #if __CORTEX_M != 33 // Enable 8-byte stack alignment for IRQ handlers, in accord with EABI SCB->CCR |= SCB_CCR_STKALIGN_Msk; + #endif #if defined(STM32F4) #if INSTRUCTION_CACHE_ENABLE @@ -1388,6 +1399,18 @@ void stm32_main(uint32_t initial_r0) { enter_bootloader: + #if defined(STM32H5) + // MPU is needed for H5 to access the unique id. + mpu_init(); + + // Copy unique id to byte-addressable buffer. + volatile uint32_t *src = (volatile uint32_t *)UID_BASE; + uint32_t *dest = (uint32_t *)&mp_hal_unique_id_address[0]; + dest[0] = src[0]; + dest[1] = src[1]; + dest[2] = src[2]; + #endif + MBOOT_BOARD_ENTRY_INIT(&initial_r0); #if USE_USB_POLLING @@ -1562,6 +1585,12 @@ void USB_UCPD1_2_IRQHandler(void) { HAL_PCD_IRQHandler(&pcd_fs_handle); } +#elif defined(STM32H5) + +void USB_DRD_FS_IRQHandler(void) { + HAL_PCD_IRQHandler(&pcd_fs_handle); +} + #elif defined(STM32WB) void USB_LP_IRQHandler(void) { diff --git a/ports/stm32/mboot/mphalport.h b/ports/stm32/mboot/mphalport.h index aa36026646..45bf11d42b 100644 --- a/ports/stm32/mboot/mphalport.h +++ b/ports/stm32/mboot/mphalport.h @@ -28,6 +28,8 @@ #include "genhdr/pins.h" +extern uint8_t mp_hal_unique_id_address[12]; + // For simplicity just convert all HAL errors to one errno. static inline int mp_hal_status_to_neg_errno(HAL_StatusTypeDef status) { return status == HAL_OK ? 0 : -1; diff --git a/ports/stm32/modmachine.c b/ports/stm32/modmachine.c index 25fc66eb9c..1869b984da 100644 --- a/ports/stm32/modmachine.c +++ b/ports/stm32/modmachine.c @@ -58,23 +58,20 @@ #include "uart.h" #include "wdt.h" -#if defined(STM32L0) -// L0 does not have a BOR, so use POR instead -#define RCC_CSR_BORRSTF RCC_CSR_PORRSTF -#endif - -#if defined(STM32G4) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) -// L4 does not have a POR, so use BOR instead -#define RCC_CSR_PORRSTF RCC_CSR_BORRSTF -#endif - #if defined(STM32G0) // G0 has BOR and POR combined #define RCC_CSR_BORRSTF RCC_CSR_PWRRSTF #define RCC_CSR_PORRSTF RCC_CSR_PWRRSTF #endif -#if defined(STM32H7) +#if defined(STM32H5) +#define RCC_SR RSR +#define RCC_SR_IWDGRSTF RCC_RSR_IWDGRSTF +#define RCC_SR_WWDGRSTF RCC_RSR_WWDGRSTF +#define RCC_SR_BORRSTF RCC_RSR_BORRSTF +#define RCC_SR_PINRSTF RCC_RSR_PINRSTF +#define RCC_SR_RMVF RCC_RSR_RMVF +#elif defined(STM32H7) #define RCC_SR RSR #define RCC_SR_IWDGRSTF RCC_RSR_IWDG1RSTF #define RCC_SR_WWDGRSTF RCC_RSR_WWDG1RSTF @@ -86,8 +83,12 @@ #define RCC_SR CSR #define RCC_SR_IWDGRSTF RCC_CSR_IWDGRSTF #define RCC_SR_WWDGRSTF RCC_CSR_WWDGRSTF +#if defined(RCC_CSR_PORRSTF) #define RCC_SR_PORRSTF RCC_CSR_PORRSTF +#endif +#if defined(RCC_CSR_BORRSTF) #define RCC_SR_BORRSTF RCC_CSR_BORRSTF +#endif #define RCC_SR_PINRSTF RCC_CSR_PINRSTF #define RCC_SR_RMVF RCC_CSR_RMVF #endif @@ -137,9 +138,12 @@ void machine_init(void) { uint32_t state = RCC->RCC_SR; if (state & RCC_SR_IWDGRSTF || state & RCC_SR_WWDGRSTF) { reset_cause = PYB_RESET_WDT; - } else if (state & RCC_SR_PORRSTF - #if !defined(STM32F0) && !defined(STM32F412Zx) && !defined(STM32L1) - || state & RCC_SR_BORRSTF + } else if (0 + #if defined(RCC_SR_PORRSTF) + || (state & RCC_SR_PORRSTF) + #endif + #if defined(RCC_SR_BORRSTF) + || (state & RCC_SR_BORRSTF) #endif ) { reset_cause = PYB_RESET_POWER_ON; @@ -286,6 +290,8 @@ NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) { #if defined(STM32F7) || defined(STM32H7) powerctrl_enter_bootloader(0, 0x1ff00000); + #elif defined(STM32H5) + powerctrl_enter_bootloader(0, 0x0bf97000); #else powerctrl_enter_bootloader(0, 0x00000000); #endif diff --git a/ports/stm32/mpconfigboard_common.h b/ports/stm32/mpconfigboard_common.h index 62311324aa..8f2a6e530a 100644 --- a/ports/stm32/mpconfigboard_common.h +++ b/ports/stm32/mpconfigboard_common.h @@ -339,6 +339,16 @@ #define MICROPY_HW_MAX_UART (5) // UART1-5 + LPUART1 #define MICROPY_HW_MAX_LPUART (1) +// Configuration for STM32H5 series +#elif defined(STM32H5) + +#define MP_HAL_UNIQUE_ID_ADDRESS (mp_hal_unique_id_address) +#define PYB_EXTI_NUM_VECTORS (58) +#define MICROPY_HW_MAX_I2C (4) +#define MICROPY_HW_MAX_TIMER (17) +#define MICROPY_HW_MAX_UART (12) +#define MICROPY_HW_MAX_LPUART (1) + // Configuration for STM32H7A3/B3 series #elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || \ defined(STM32H7B3xx) || defined(STM32H7B3xxQ) @@ -574,9 +584,9 @@ #endif // Whether the USB peripheral is device-only, or multiple OTG -// For STM32G0 the USB peripheral supports device and host mode, +// For STM32G0 and STM32H5 the USB peripheral supports device and host mode, // but otherwise acts like a non-multi-OTG peripheral. -#if defined(STM32G0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L432xx) || defined(STM32WB) +#if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L0) || defined(STM32L432xx) || defined(STM32WB) #define MICROPY_HW_USB_IS_MULTI_OTG (0) #else #define MICROPY_HW_USB_IS_MULTI_OTG (1) diff --git a/ports/stm32/mphalport.c b/ports/stm32/mphalport.c index 727517f5bd..8edafa9bfc 100644 --- a/ports/stm32/mphalport.c +++ b/ports/stm32/mphalport.c @@ -16,6 +16,10 @@ const byte mp_hal_status_to_errno_table[4] = { [HAL_TIMEOUT] = MP_ETIMEDOUT, }; +#if defined(STM32H5) +uint8_t mp_hal_unique_id_address[12]; +#endif + NORETURN void mp_hal_raise(HAL_StatusTypeDef status) { mp_raise_OSError(mp_hal_status_to_errno_table[status]); } @@ -102,7 +106,7 @@ void mp_hal_gpio_clock_enable(GPIO_TypeDef *gpio) { #elif defined(STM32G0) #define AHBxENR IOPENR #define AHBxENR_GPIOAEN_Pos RCC_IOPENR_GPIOAEN_Pos - #elif defined(STM32G4) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #elif defined(STM32G4) || defined(STM32H5) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) #define AHBxENR AHB2ENR #define AHBxENR_GPIOAEN_Pos RCC_AHB2ENR_GPIOAEN_Pos #endif diff --git a/ports/stm32/mphalport.h b/ports/stm32/mphalport.h index 728f5fefbd..2757d39841 100644 --- a/ports/stm32/mphalport.h +++ b/ports/stm32/mphalport.h @@ -2,6 +2,8 @@ #include STM32_HAL_H #include "pin.h" +extern uint8_t mp_hal_unique_id_address[12]; + // 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+L4-1.17.0+WB-1.10.0+WL-1.1.0 #if defined(STM32F0) #define MICROPY_PLATFORM_VERSION "HAL1.9.0" @@ -13,6 +15,8 @@ #define MICROPY_PLATFORM_VERSION "HAL1.5.1" #elif defined(STM32G4) #define MICROPY_PLATFORM_VERSION "HAL1.3.0" +#elif defined(STM32H5) +#define MICROPY_PLATFORM_VERSION "HAL1.0.0" #elif defined(STM32H7) #define MICROPY_PLATFORM_VERSION "HAL1.11.0" #elif defined(STM32L0) diff --git a/ports/stm32/mpu.h b/ports/stm32/mpu.h index ff51f382ee..106112073e 100644 --- a/ports/stm32/mpu.h +++ b/ports/stm32/mpu.h @@ -95,6 +95,36 @@ static inline void mpu_config_end(uint32_t irq_state) { enable_irq(irq_state); } +#elif defined(STM32H5) + +#define ST_DEVICE_SIGNATURE_BASE (0x08fff800) +#define ST_DEVICE_SIGNATURE_LIMIT (0x08ffffff) + +static inline void mpu_init(void) { + // Configure attribute 0, inner-outer non-cacheable (=0x44). + __DMB(); + MPU->MAIR0 = (MPU->MAIR0 & ~MPU_MAIR0_Attr0_Msk) + | 0x44 << MPU_MAIR0_Attr0_Pos; + + // Configure region 0 to make device signature non-cacheable. + // This allows the memory region at ST_DEVICE_SIGNATURE_BASE to be readable. + __DMB(); + MPU->RNR = MPU_REGION_NUMBER0; + MPU->RBAR = (ST_DEVICE_SIGNATURE_BASE & MPU_RBAR_BASE_Msk) + | MPU_ACCESS_NOT_SHAREABLE << MPU_RBAR_SH_Pos + | MPU_REGION_ALL_RW << MPU_RBAR_AP_Pos + | MPU_INSTRUCTION_ACCESS_DISABLE << MPU_RBAR_XN_Pos; + MPU->RLAR = (ST_DEVICE_SIGNATURE_LIMIT & MPU_RLAR_LIMIT_Msk) + | MPU_ATTRIBUTES_NUMBER0 << MPU_RLAR_AttrIndx_Pos + | MPU_REGION_ENABLE << MPU_RLAR_EN_Pos; + + // Enable the MPU. + MPU->CTRL = MPU_PRIVILEGED_DEFAULT | MPU_CTRL_ENABLE_Msk; + SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; + __DMB(); + __ISB(); +} + #else static inline void mpu_init(void) { diff --git a/ports/stm32/powerctrl.c b/ports/stm32/powerctrl.c index d5fa9095d8..80195f04ae 100644 --- a/ports/stm32/powerctrl.c +++ b/ports/stm32/powerctrl.c @@ -31,7 +31,7 @@ #include "genhdr/pllfreqtable.h" #include "extmod/modbluetooth.h" -#if defined(STM32H7) +#if defined(STM32H5) || defined(STM32H7) #define RCC_SR RSR #if defined(STM32H747xx) #define RCC_SR_SFTRSTF RCC_RSR_SFT2RSTF @@ -379,7 +379,7 @@ STATIC uint32_t calc_apb2_div(uint32_t wanted_div) { #endif } -#if defined(STM32F4) || defined(STM32F7) || defined(STM32G0) || defined(STM32G4) || defined(STM32H7) +#if defined(STM32F4) || defined(STM32F7) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) 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 @@ -453,13 +453,20 @@ set_clk: // 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(STM32H7) + #if defined(STM32H5) + ahb = sysclk >> AHBPrescTable[RCC_ClkInitStruct.AHBCLKDivider >> RCC_CFGR2_HPRE_Pos]; + #elif defined(STM32H7) + // Do nothing. + #else ahb = sysclk >> AHBPrescTable[RCC_ClkInitStruct.AHBCLKDivider >> RCC_CFGR_HPRE_Pos]; #endif RCC_ClkInitStruct.APB1CLKDivider = calc_apb1_div(ahb / apb1); #if !defined(STM32G0) RCC_ClkInitStruct.APB2CLKDivider = calc_apb2_div(ahb / apb2); #endif + #if defined(STM32H5) + RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1; + #endif #if defined(STM32H7) RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB3CLKDivider = MICROPY_HW_CLK_APB3_DIV; @@ -842,6 +849,18 @@ void powerctrl_enter_stop_mode(void) { HAL_PWREx_EnableOverDrive(); #endif + #if defined(STM32H5) + + // Enable PLL1, and switch the system clock source to PLL1P. + LL_RCC_PLL1_Enable(); + while (!LL_RCC_PLL1_IsReady()) { + } + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL1); + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL1) { + } + + #else + // enable PLL __HAL_RCC_PLL_ENABLE(); while (!__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY)) { @@ -860,6 +879,8 @@ void powerctrl_enter_stop_mode(void) { } #endif + #endif + powerctrl_disable_hsi_if_unused(); #if HAVE_PLL48 @@ -967,7 +988,7 @@ void powerctrl_enter_standby_mode(void) { #if defined(STM32F0) || defined(STM32L0) #define CR_BITS (RTC_CR_ALRAIE | RTC_CR_WUTIE | RTC_CR_TSIE) #define ISR_BITS (RTC_ISR_ALRAF | RTC_ISR_WUTF | RTC_ISR_TSF) - #elif defined(STM32G0) || defined(STM32G4) || defined(STM32WL) + #elif defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32WL) #define CR_BITS (RTC_CR_ALRAIE | RTC_CR_ALRBIE | RTC_CR_WUTIE | RTC_CR_TSIE) #define ISR_BITS (RTC_MISR_ALRAMF | RTC_MISR_ALRBMF | RTC_MISR_WUTMF | RTC_MISR_TSMF) #elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ) @@ -991,7 +1012,7 @@ void powerctrl_enter_standby_mode(void) { // clear RTC wake-up flags #if defined(SR_BITS) RTC->SR &= ~SR_BITS; - #elif defined(STM32G0) || defined(STM32G4) || defined(STM32WL) + #elif defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32WL) RTC->MISR &= ~ISR_BITS; #else RTC->ISR &= ~ISR_BITS; @@ -1006,6 +1027,8 @@ void powerctrl_enter_standby_mode(void) { PWR->CR2 |= PWR_CR2_CWUPF6 | PWR_CR2_CWUPF5 | PWR_CR2_CWUPF4 | PWR_CR2_CWUPF3 | PWR_CR2_CWUPF2 | PWR_CR2_CWUPF1; // Restore EWUP state PWR->CSR2 |= csr2_ewup; + #elif defined(STM32H5) + LL_PWR_ClearFlag_WU(); #elif defined(STM32H7) // Clear and mask D1 EXTIs. EXTI_D1->PR1 = 0x3fffffu; diff --git a/ports/stm32/powerctrlboot.c b/ports/stm32/powerctrlboot.c index e970b81a9f..149c34ae63 100644 --- a/ports/stm32/powerctrlboot.c +++ b/ports/stm32/powerctrlboot.c @@ -52,7 +52,7 @@ void powerctrl_config_systick(void) { SysTick_Config(HAL_RCC_GetHCLKFreq() / 1000); NVIC_SetPriority(SysTick_IRQn, IRQ_PRI_SYSTICK); - #if !BUILDING_MBOOT && (defined(STM32H7) || defined(STM32L4) || defined(STM32WB)) + #if !BUILDING_MBOOT && (defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB)) // Set SysTick IRQ priority variable in case the HAL needs to use it uwTickPrio = IRQ_PRI_SYSTICK; #endif @@ -192,6 +192,106 @@ void SystemClock_Config(void) { #endif } +#elif defined(STM32H5) + +void SystemClock_Config(void) { + // Set power voltage scaling. + __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0); + while (!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) { + } + + #if MICROPY_HW_CLK_USE_HSI + LL_RCC_HSI_Enable(); + while (!LL_RCC_HSI_IsReady()) { + } + const uint32_t pll1_source = LL_RCC_PLL1SOURCE_HSI; + #else + // Enable HSE. + #if MICROPY_HW_CLK_USE_BYPASS + LL_RCC_HSE_EnableBypass(); + #endif + LL_RCC_HSE_Enable(); + while (!LL_RCC_HSE_IsReady()) { + } + const uint32_t pll1_source = LL_RCC_PLL1SOURCE_HSE; + #endif + + // Configure PLL1 for use as system clock. + LL_RCC_PLL1_ConfigDomain_SYS(pll1_source, MICROPY_HW_CLK_PLLM, MICROPY_HW_CLK_PLLN, MICROPY_HW_CLK_PLLP); + LL_RCC_PLL1_SetQ(MICROPY_HW_CLK_PLLQ); + LL_RCC_PLL1_SetR(MICROPY_HW_CLK_PLLR); + LL_RCC_PLL1_SetFRACN(MICROPY_HW_CLK_PLLFRAC); + LL_RCC_PLL1_SetVCOInputRange(MICROPY_HW_CLK_PLLVCI_LL); + LL_RCC_PLL1_SetVCOOutputRange(MICROPY_HW_CLK_PLLVCO_LL); + LL_RCC_PLL1P_Enable(); + + // Enable PLL1. + LL_RCC_PLL1_Enable(); + while (!LL_RCC_PLL1_IsReady()) { + } + + // Configure bus dividers. + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); + LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); + LL_RCC_SetAPB3Prescaler(LL_RCC_APB3_DIV_1); + + // Configure the flash latency before switching the system clock source. + __HAL_FLASH_SET_LATENCY(MICROPY_HW_FLASH_LATENCY); + while (__HAL_FLASH_GET_LATENCY() != MICROPY_HW_FLASH_LATENCY) { + } + + // Switch the system clock source to PLL1P. + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL1); + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL1) { + } + + // Reconfigure clock state and SysTick. + SystemCoreClockUpdate(); + powerctrl_config_systick(); + + // USB clock configuration, either HSI48 or PLL3. + #if 1 + + // Enable HSI48. + LL_RCC_HSI48_Enable(); + while (!LL_RCC_HSI48_IsReady()) { + } + + // Select HSI48 for USB clock source + LL_RCC_SetUSBClockSource(LL_RCC_USB_CLKSOURCE_HSI48); + + // Synchronise HSI48 with 1kHz USB SoF + __HAL_RCC_CRS_CLK_ENABLE(); + CRS->CFGR = 2 << CRS_CFGR_SYNCSRC_Pos | 0x22 << CRS_CFGR_FELIM_Pos + | __HAL_RCC_CRS_RELOADVALUE_CALCULATE(48000000, 1000) << CRS_CFGR_RELOAD_Pos; + CRS->CR = 0x20 << CRS_CR_TRIM_Pos | CRS_CR_AUTOTRIMEN | CRS_CR_CEN; + + #else + + // Configure PLL3 for use by USB at Q=48MHz. + LL_RCC_PLL3_SetSource(LL_RCC_PLL3SOURCE_HSE); + LL_RCC_PLL3_SetM(MICROPY_HW_CLK_PLL3M); + LL_RCC_PLL3_SetN(MICROPY_HW_CLK_PLL3N); + LL_RCC_PLL3_SetP(MICROPY_HW_CLK_PLL3P); + LL_RCC_PLL3_SetQ(MICROPY_HW_CLK_PLL3Q); + LL_RCC_PLL3_SetR(MICROPY_HW_CLK_PLL3R); + LL_RCC_PLL3_SetFRACN(MICROPY_HW_CLK_PLL3FRAC); + LL_RCC_PLL3_SetVCOInputRange(MICROPY_HW_CLK_PLL3VCI_LL); + LL_RCC_PLL3_SetVCOOutputRange(MICROPY_HW_CLK_PLL3VCO_LL); + LL_RCC_PLL3Q_Enable(); + + // Enable PLL3. + LL_RCC_PLL3_Enable(); + while (!LL_RCC_PLL3_IsReady()) { + } + + // Select PLL3-Q for USB clock source + LL_RCC_SetUSBClockSource(LL_RCC_USB_CLKSOURCE_PLL3Q); + + #endif +} + #elif defined(STM32L0) void SystemClock_Config(void) { diff --git a/ports/stm32/rng.c b/ports/stm32/rng.c index 5d6ddf6d62..236d79ea87 100644 --- a/ports/stm32/rng.c +++ b/ports/stm32/rng.c @@ -24,6 +24,7 @@ * THE SOFTWARE. */ +#include "py/mphal.h" #include "rtc.h" #include "rng.h" diff --git a/ports/stm32/rtc.c b/ports/stm32/rtc.c index 92f64626a3..3b05fb40eb 100644 --- a/ports/stm32/rtc.c +++ b/ports/stm32/rtc.c @@ -101,8 +101,10 @@ STATIC bool rtc_need_init_finalise = false; #endif void rtc_init_start(bool force_init) { - #if defined(STM32WL) // Enable the RTC APB bus clock, to communicate with the RTC. + #if defined(STM32H5) + __HAL_RCC_RTC_CLK_ENABLE(); + #elif defined(STM32WL) __HAL_RCC_RTCAPB_CLK_ENABLE(); #endif @@ -147,14 +149,23 @@ 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) + RCC->BDCR |= RCC_BDCR_LSION; + #else RCC->CSR |= RCC_CSR_LSION; + #endif // provide some status information rtc_info |= 0x80000; } 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) + 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; + #endif // Check that the sync and async prescaler values are correct. If the RTC // gets into a state where they are wrong then it will run slow or fast and @@ -234,7 +245,7 @@ void rtc_init_finalise() { RTC_CalendarConfig(); #if defined(STM32G0) if (__HAL_RCC_GET_FLAG(RCC_FLAG_PWRRST) != RESET) { - #elif defined(STM32G4) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #elif defined(STM32G4) || defined(STM32H5) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) if (__HAL_RCC_GET_FLAG(RCC_FLAG_BORRST) != RESET) { #else if (__HAL_RCC_GET_FLAG(RCC_FLAG_PORRST) != RESET) { @@ -266,7 +277,7 @@ STATIC HAL_StatusTypeDef PYB_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct /*------------------------------ LSE Configuration -------------------------*/ if ((RCC_OscInitStruct->OscillatorType & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE) { - #if !defined(STM32H7) && !defined(STM32WB) && !defined(STM32WL) + #if !defined(STM32H5) && !defined(STM32H7) && !defined(STM32WB) && !defined(STM32WL) // Enable Power Clock __HAL_RCC_PWR_CLK_ENABLE(); #endif @@ -285,6 +296,13 @@ STATIC HAL_StatusTypeDef PYB_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct return HAL_TIMEOUT; } } + #elif defined(STM32H5) + // Wait for Backup domain Write protection disable + while (!LL_PWR_IsEnabledBkUpAccess()) { + if (HAL_GetTick() - tickstart > RCC_DBP_TIMEOUT_VALUE) { + return HAL_TIMEOUT; + } + } #else // Enable write access to Backup domain // PWR->CR |= PWR_CR_DBP; @@ -363,7 +381,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(STM32WL) + #elif defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32WL) hrtc->Instance->CR &= (uint32_t) ~RTC_CR_TAMPALRM_TYPE_Msk; hrtc->Instance->CR |= (uint32_t)(hrtc->Init.OutPutType); #else @@ -629,7 +647,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(STM32L0) +#if defined(STM32F0) || defined(STM32H5) || defined(STM32L0) #define RTC_WKUP_IRQn RTC_IRQn #elif defined(STM32G0) #define RTC_WKUP_IRQn RTC_TAMP_IRQn @@ -738,7 +756,7 @@ mp_obj_t pyb_rtc_wakeup(size_t n_args, const mp_obj_t *args) { RTC->WPR = 0xff; // enable external interrupts on line EXTI_RTC_WAKEUP - #if defined(STM32G0) || defined(STM32G4) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) EXTI->IMR1 |= 1 << EXTI_RTC_WAKEUP; EXTI->RTSR1 |= 1 << EXTI_RTC_WAKEUP; #elif defined(STM32H7) @@ -750,7 +768,7 @@ mp_obj_t pyb_rtc_wakeup(size_t n_args, const mp_obj_t *args) { #endif // clear interrupt flags - #if defined(STM32G0) || defined(STM32G4) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32WL) RTC->ICSR &= ~RTC_ICSR_WUTWF; #elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ) RTC->SR &= ~RTC_SR_WUTF; @@ -761,7 +779,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) + #elif defined(STM32G0) || defined(STM32H5) // Do nothing #else EXTI->PR = 1 << EXTI_RTC_WAKEUP; @@ -777,7 +795,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(STM32L4) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L4) || 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 e61c837692..11a9a74ea3 100644 --- a/ports/stm32/spi.c +++ b/ports/stm32/spi.c @@ -96,8 +96,8 @@ const spi_t spi_obj[6] = { #endif }; -#if defined(STM32H7) -// STM32H7 HAL requires SPI IRQs to be enabled and handled. +#if defined(STM32H5) || defined(STM32H7) +// STM32H5/H7 HAL requires SPI IRQs to be enabled and handled. #if defined(MICROPY_HW_SPI1_SCK) void SPI1_IRQHandler(void) { IRQ_ENTER(SPI1_IRQn); @@ -217,6 +217,20 @@ int spi_find_index(mp_obj_t id) { STATIC uint32_t spi_get_source_freq(SPI_HandleTypeDef *spi) { #if defined(STM32F0) || defined(STM32G0) return HAL_RCC_GetPCLK1Freq(); + #elif defined(STM32H5) + if (spi->Instance == SPI1) { + return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI1); + } else if (spi->Instance == SPI2) { + return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI2); + } else if (spi->Instance == SPI3) { + return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI3); + } else if (spi->Instance == SPI4) { + return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI4); + } else if (spi->Instance == SPI5) { + return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI5); + } else { + return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI6); + } #elif defined(STM32H7) if (spi->Instance == SPI1 || spi->Instance == SPI2 || spi->Instance == SPI3) { return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI123); @@ -252,6 +266,11 @@ void spi_set_params(const spi_t *spi_obj, uint32_t prescale, int32_t baudrate, SPI_HandleTypeDef *spi = spi_obj->spi; SPI_InitTypeDef *init = &spi->Init; + #if defined(STM32H5) + // Enable PLL1Q output to be used as SPI clock (this is the default SPI clock source). + LL_RCC_PLL1Q_Enable(); + #endif + if (prescale != 0xffffffff || baudrate != -1) { if (prescale == 0xffffffff) { // prescaler not given, so select one that yields at most the requested baudrate @@ -419,7 +438,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(STM32H7) + #if defined(STM32H5) || defined(STM32H7) NVIC_SetPriority(irqn, IRQ_PRI_SPI); HAL_NVIC_EnableIRQ(irqn); #else @@ -647,7 +666,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(STM32H7) + #if defined(STM32H5) || defined(STM32H7) 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 ae267a5995..b9f70db73e 100644 --- a/ports/stm32/stm32.mk +++ b/ports/stm32/stm32.mk @@ -66,6 +66,7 @@ CFLAGS_MCU_g4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 CFLAGS_MCU_l0 = $(CFLAGS_CORTEX_M) -mtune=cortex-m0plus -mcpu=cortex-m0plus CFLAGS_MCU_l1 = $(CFLAGS_CORTEX_M) -mtune=cortex-m3 -mcpu=cortex-m3 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_wb = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 CFLAGS_MCU_wl = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 @@ -78,6 +79,7 @@ MPY_CROSS_MCU_ARCH_g4 = armv7m MPY_CROSS_MCU_ARCH_l0 = armv6m MPY_CROSS_MCU_ARCH_l1 = armv7m MPY_CROSS_MCU_ARCH_l4 = armv7m +MPY_CROSS_MCU_ARCH_h5 = armv7m MPY_CROSS_MCU_ARCH_h7 = 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 78e7f15190..84c05602b5 100644 --- a/ports/stm32/stm32_it.c +++ b/ports/stm32/stm32_it.c @@ -304,6 +304,14 @@ void USB_UCPD1_2_IRQHandler(void) { } #endif +#elif defined(STM32H5) + +#if MICROPY_HW_USB_FS +void USB_DRD_FS_IRQHandler(void) { + HAL_PCD_IRQHandler(&pcd_fs_handle); +} +#endif + #elif defined(STM32L0) || defined(STM32L432xx) #if MICROPY_HW_USB_FS @@ -404,7 +412,7 @@ void OTG_FS_WKUP_IRQHandler(void) { #if defined(STM32L4) EXTI->PR1 = USB_OTG_FS_WAKEUP_EXTI_LINE; - #elif !defined(STM32H7) + #elif !defined(STM32H5) && !defined(STM32H7) /* Clear EXTI pending Bit*/ __HAL_USB_FS_EXTI_CLEAR_FLAG(); #endif @@ -424,7 +432,7 @@ void OTG_HS_WKUP_IRQHandler(void) { OTG_CMD_WKUP_Handler(&pcd_hs_handle); - #if !defined(STM32H7) + #if !defined(STM32H5) && !defined(STM32H7) /* Clear EXTI pending Bit*/ __HAL_USB_HS_EXTI_CLEAR_FLAG(); #endif @@ -528,7 +536,13 @@ void ETH_WKUP_IRQHandler(void) { } #endif -#if defined(STM32L1) +#if defined(STM32H5) +void TAMP_IRQHandler(void) { + IRQ_ENTER(TAMP_IRQn); + Handle_EXTI_Irq(EXTI_RTC_TAMP); + IRQ_EXIT(TAMP_IRQn); +} +#elif defined(STM32L1) void TAMPER_STAMP_IRQHandler(void) { IRQ_ENTER(TAMPER_STAMP_IRQn); Handle_EXTI_Irq(EXTI_RTC_TIMESTAMP); @@ -542,10 +556,17 @@ void TAMP_STAMP_IRQHandler(void) { } #endif -void RTC_WKUP_IRQHandler(void) { +#if defined(STM32H5) +void RTC_IRQHandler(void) +#else +void RTC_WKUP_IRQHandler(void) +#endif +{ IRQ_ENTER(RTC_WKUP_IRQn); #if defined(STM32G0) || defined(STM32G4) || defined(STM32WL) RTC->MISR &= ~RTC_MISR_WUTMF; // clear wakeup interrupt flag + #elif defined(STM32H5) + RTC->SCR = RTC_SCR_CWUTF; // clear wakeup interrupt flag #elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ) RTC->SR &= ~RTC_SR_WUTF; // clear wakeup interrupt flag #else diff --git a/ports/stm32/timer.c b/ports/stm32/timer.c index 6c110f87ea..b4fa1d6cf9 100644 --- a/ports/stm32/timer.c +++ b/ports/stm32/timer.c @@ -233,6 +233,36 @@ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { // APB clock. Otherwise (APB prescaler > 1) the timer clock is twice its // respective APB clock. See DM00031020 Rev 4, page 115. uint32_t timer_get_source_freq(uint32_t tim_id) { + #if defined(STM32H5) + + uint32_t source, ppre; + if ((2 <= tim_id && tim_id <= 7) || (12 <= tim_id && tim_id <= 14)) { + // TIM{2-7,12-14} are on APB1 + source = HAL_RCC_GetPCLK1Freq(); + ppre = (RCC->CFGR2 >> RCC_CFGR2_PPRE1_Pos) & 7; + } else { + // TIM{1,8,15-17} are on APB2 + source = HAL_RCC_GetPCLK2Freq(); + ppre = (RCC->CFGR2 >> RCC_CFGR2_PPRE2_Pos) & 7; + } + if (RCC->CFGR1 & RCC_CFGR1_TIMPRE) { + if (ppre == 0 || ppre == 4 || ppre == 5) { + // PPREx divider is 1, 2 or 4. + return 2 * source; + } else { + return 4 * source; + } + } else { + if (ppre == 0 || ppre == 4) { + // PPREx divider is 1 or 2. + return HAL_RCC_GetHCLKFreq(); + } else { + return 2 * source; + } + } + + #else + uint32_t source, clk_div; if (tim_id == 1 || (8 <= tim_id && tim_id <= 11)) { // TIM{1,8,9,10,11} are on APB2 @@ -267,6 +297,8 @@ uint32_t timer_get_source_freq(uint32_t tim_id) { source *= 2; } return source; + + #endif } /******************************************************************************/ @@ -837,6 +869,8 @@ 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) + TIM_ENTRY(6, TIM6_IRQn), #else TIM_ENTRY(6, TIM6_DAC_IRQn), #endif @@ -857,6 +891,7 @@ STATIC const uint32_t tim_instance_table[MICROPY_HW_MAX_TIMER] = { TIM_ENTRY(8, TIM8_UP_IRQn), #endif #endif + #if defined(TIM9) #if defined(STM32L1) TIM_ENTRY(9, TIM9_IRQn), @@ -864,6 +899,7 @@ STATIC const uint32_t tim_instance_table[MICROPY_HW_MAX_TIMER] = { TIM_ENTRY(9, TIM1_BRK_TIM9_IRQn), #endif #endif + #if defined(TIM10) #if defined(STM32L1) TIM_ENTRY(10, TIM10_IRQn), @@ -871,6 +907,7 @@ STATIC const uint32_t tim_instance_table[MICROPY_HW_MAX_TIMER] = { TIM_ENTRY(10, TIM1_UP_TIM10_IRQn), #endif #endif + #if defined(TIM11) #if defined(STM32L1) TIM_ENTRY(11, TIM11_IRQn), @@ -878,42 +915,57 @@ STATIC const uint32_t tim_instance_table[MICROPY_HW_MAX_TIMER] = { TIM_ENTRY(11, TIM1_TRG_COM_TIM11_IRQn), #endif #endif + #if defined(TIM12) + #if defined(STM32H5) + TIM_ENTRY(12, TIM12_IRQn), + #else TIM_ENTRY(12, TIM8_BRK_TIM12_IRQn), #endif + #endif + #if defined(TIM13) + #if defined(STM32H5) + TIM_ENTRY(13, TIM13_IRQn), + #else TIM_ENTRY(13, TIM8_UP_TIM13_IRQn), #endif - #if defined(STM32F0) || defined(STM32G0) + #endif + + #if defined(STM32F0) || defined(STM32G0) || defined(STM32H5) TIM_ENTRY(14, TIM14_IRQn), #elif defined(TIM14) TIM_ENTRY(14, TIM8_TRG_COM_TIM14_IRQn), #endif + #if defined(TIM15) - #if defined(STM32F0) || defined(STM32G0) || defined(STM32H7) + #if defined(STM32F0) || defined(STM32G0) || defined(STM32H5) || defined(STM32H7) TIM_ENTRY(15, TIM15_IRQn), #else TIM_ENTRY(15, TIM1_BRK_TIM15_IRQn), #endif #endif + #if defined(TIM16) #if defined(STM32G0B1xx) || defined(STM32G0C1xx) TIM_ENTRY(16, TIM16_FDCAN_IT0_IRQn), - #elif defined(STM32F0) || defined(STM32G0) || defined(STM32H7) || defined(STM32WL) + #elif defined(STM32F0) || defined(STM32G0) || defined(STM32H5) || defined(STM32H7) || defined(STM32WL) TIM_ENTRY(16, TIM16_IRQn), #else TIM_ENTRY(16, TIM1_UP_TIM16_IRQn), #endif #endif + #if defined(TIM17) #if defined(STM32G0B1xx) || defined(STM32G0C1xx) TIM_ENTRY(17, TIM17_FDCAN_IT1_IRQn), - #elif defined(STM32F0) || defined(STM32G0) || defined(STM32H7) || defined(STM32WL) + #elif defined(STM32F0) || defined(STM32G0) || defined(STM32H5) || defined(STM32H7) || defined(STM32WL) TIM_ENTRY(17, TIM17_IRQn), #else TIM_ENTRY(17, TIM1_TRG_COM_TIM17_IRQn), #endif #endif + #if defined(TIM20) TIM_ENTRY(20, TIM20_UP_IRQn), #endif diff --git a/ports/stm32/uart.c b/ports/stm32/uart.c index 6d1240cf8d..e477c5c16c 100644 --- a/ports/stm32/uart.c +++ b/ports/stm32/uart.c @@ -82,7 +82,7 @@ #define USART_CR3_IE_ALL (USART_CR3_IE_BASE) #endif -#elif defined(STM32G0) || defined(STM32G4) +#elif defined(STM32G0) || defined(STM32G4) || defined(STM32H5) #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) @@ -903,14 +903,14 @@ uint32_t uart_get_baudrate(pyb_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(STM32H7) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || 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(STM32H7) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32WB) || defined(STM32WL) self->uartx->PRESC, #endif LL_USART_OVERSAMPLING_16); @@ -920,7 +920,7 @@ void uart_set_baudrate(pyb_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(STM32H7) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32WB) || defined(STM32WL) LL_LPUART_PRESCALER_DIV1, #endif baudrate); @@ -928,7 +928,7 @@ void uart_set_baudrate(pyb_uart_obj_t *self, uint32_t baudrate) { } #endif LL_USART_SetBaudRate(self->uartx, uart_get_source_freq(self), - #if defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32WB) || defined(STM32WL) LL_USART_PRESCALER_DIV1, #endif LL_USART_OVERSAMPLING_16, baudrate); @@ -979,7 +979,7 @@ int uart_rx_char(pyb_uart_obj_t *self) { return data; } else { // no buffering - #if defined(STM32F0) || defined(STM32F7) || defined(STM32G0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32F0) || defined(STM32F7) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) || 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; @@ -1129,7 +1129,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(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32F0) || defined(STM32F7) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || 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 c9c29cc50c..94d62f7625 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -59,7 +59,7 @@ #endif // Maximum number of endpoints (excluding EP0) -#if defined(STM32G0) || defined(STM32G4) || defined(STM32L0) || defined(STM32WB) +#if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L0) || defined(STM32WB) #define MAX_ENDPOINT(dev_id) (7) #elif defined(STM32L4) #define MAX_ENDPOINT(dev_id) (5) diff --git a/ports/stm32/usbd_cdc_interface.c b/ports/stm32/usbd_cdc_interface.c index 1e5d6c80a4..f25dcc380a 100644 --- a/ports/stm32/usbd_cdc_interface.c +++ b/ports/stm32/usbd_cdc_interface.c @@ -52,7 +52,7 @@ #if !MICROPY_HW_USB_IS_MULTI_OTG #define USE_USB_CNTR_SOFM (1) -#if defined(STM32G0) +#if defined(STM32G0) || defined(STM32H5) #define USB USB_DRD_FS #endif #else diff --git a/ports/stm32/usbd_conf.c b/ports/stm32/usbd_conf.c index 9c53c6323a..9f187fc08b 100644 --- a/ports/stm32/usbd_conf.c +++ b/ports/stm32/usbd_conf.c @@ -44,7 +44,7 @@ PCD_HandleTypeDef pcd_fs_handle; PCD_HandleTypeDef pcd_hs_handle; #endif -#if defined(STM32G0) +#if defined(STM32G0) || defined(STM32H5) #define USB_OTG_FS USB_DRD_FS #elif !MICROPY_HW_USB_IS_MULTI_OTG // The MCU has a single USB device-only instance @@ -85,7 +85,7 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) { const uint32_t otg_alt = GPIO_AF0_USB; #elif defined(STM32L432xx) const uint32_t otg_alt = GPIO_AF10_USB_FS; - #elif defined(STM32WB) + #elif defined(STM32H5) || defined(STM32WB) const uint32_t otg_alt = GPIO_AF10_USB; #else const uint32_t otg_alt = GPIO_AF10_OTG_FS; @@ -108,10 +108,10 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) { mp_hal_pin_config(MICROPY_HW_USB_OTG_ID_PIN, MP_HAL_PIN_MODE_ALT_OPEN_DRAIN, MP_HAL_PIN_PULL_UP, otg_alt); #endif - #if defined(STM32G0) + // Keep USB clock running during sleep or else __WFI() will disable the USB + #if defined(STM32G0) || defined(STM32H5) __HAL_RCC_USB_CLK_SLEEP_ENABLE(); #elif defined(STM32H7) - // Keep USB clock running during sleep or else __WFI() will disable the USB __HAL_RCC_USB2_OTG_FS_CLK_SLEEP_ENABLE(); __HAL_RCC_USB2_OTG_FS_ULPI_CLK_SLEEP_DISABLE(); #endif @@ -123,8 +123,10 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) { __USB_OTG_FS_CLK_ENABLE(); #endif - #if defined(STM32L4) // Enable VDDUSB + #if defined(STM32H5) + HAL_PWREx_EnableVddUSB(); + #elif defined(STM32L4) if (__HAL_RCC_PWR_IS_CLK_DISABLED()) { __HAL_RCC_PWR_CLK_ENABLE(); HAL_PWREx_EnableVddUSB(); @@ -138,6 +140,9 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) { #if defined(STM32G0) NVIC_SetPriority(USB_UCPD1_2_IRQn, IRQ_PRI_OTG_FS); HAL_NVIC_EnableIRQ(USB_UCPD1_2_IRQn); + #elif defined(STM32H5) + NVIC_SetPriority(USB_DRD_FS_IRQn, IRQ_PRI_OTG_FS); + HAL_NVIC_EnableIRQ(USB_DRD_FS_IRQn); #elif defined(STM32L0) NVIC_SetPriority(USB_IRQn, IRQ_PRI_OTG_FS); HAL_NVIC_EnableIRQ(USB_IRQn); @@ -437,8 +442,8 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed, const pcd_fs_handle.Init.speed = PCD_SPEED_FULL; pcd_fs_handle.Init.lpm_enable = DISABLE; pcd_fs_handle.Init.battery_charging_enable = DISABLE; - #if MICROPY_HW_USB_IS_MULTI_OTG || defined(STM32G0) - #if !defined(STM32G0) + #if MICROPY_HW_USB_IS_MULTI_OTG || defined(STM32G0) || defined(STM32H5) + #if !defined(STM32G0) && !defined(STM32H5) pcd_fs_handle.Init.use_dedicated_ep1 = 0; #endif pcd_fs_handle.Init.dma_enable = 0; @@ -448,6 +453,10 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed, const pcd_fs_handle.Init.vbus_sensing_enable = 1; #endif #endif + #if defined(STM32G0) || defined(STM32H5) + pcd_fs_handle.Init.bulk_doublebuffer_enable = DISABLE; + pcd_fs_handle.Init.iso_singlebuffer_enable = DISABLE; + #endif // Link The driver to the stack pcd_fs_handle.pData = pdev;