stm32: Add initial support for H5 MCUs.

This commit adds initial support for STM32H5xx MCUs.  The following
features have been confirmed to be working on an STM32H573:
- UART over REPL and USB CDC
- USB CDC and MSC
- internal flash filesystem
- machine.Pin
- machine.SPI transfers with DMA
- machine.ADC
- machine.RTC
- pyb.LED
- pyb.Switch
- pyb.rng
- mboot

Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
Damien George 2023-03-22 16:38:49 +11:00
parent bd7196e123
commit 61339aa506
33 changed files with 624 additions and 115 deletions

View File

@ -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))

View File

@ -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

View File

@ -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;

View File

@ -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();

View File

@ -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.

View File

@ -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;

View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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

View File

@ -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 \

View File

@ -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) {

View File

@ -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;

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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) {

View File

@ -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;

View File

@ -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) {

View File

@ -24,6 +24,7 @@
* THE SOFTWARE.
*/
#include "py/mphal.h"
#include "rtc.h"
#include "rng.h"

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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;