diff --git a/lib/stm32lib b/lib/stm32lib index fdb1ec6879bc8..928df866e4d28 160000 --- a/lib/stm32lib +++ b/lib/stm32lib @@ -1 +1 @@ -Subproject commit fdb1ec6879bc8b7bb54ded73bac04839003c5a07 +Subproject commit 928df866e4d287ebc3c60726151513ebee609128 diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index fce81d753f4fa..d5030b7e46da2 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -110,6 +110,8 @@ CFLAGS += -DSTM32_HAL_H='' CFLAGS += -DMBOOT_VTOR=$(MBOOT_TEXT0_ADDR) CFLAGS += -DMICROPY_HW_VTOR=$(TEXT0_ADDR) +AFLAGS += $(filter -mcpu=%,$(CFLAGS_MCU_$(MCU_SERIES))) + # Configure for nan-boxing object model if requested ifeq ($(NANBOX),1) CFLAGS += -DMP_CONFIGFILE='"mpconfigport_nanbox.h"' @@ -318,6 +320,7 @@ SRC_C += \ spi.c \ pyb_spi.c \ qspi.c \ + octospi.c \ uart.c \ ulpi.c \ can.c \ @@ -401,7 +404,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 \ @@ -430,12 +433,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 fc966e822ddf5..7c51a8b39c14b 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 c61bad459cddb..0518cdcd9a59f 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/boards/STM32H573I_DK/bdev.c b/ports/stm32/boards/STM32H573I_DK/bdev.c new file mode 100644 index 0000000000000..b3047342375c2 --- /dev/null +++ b/ports/stm32/boards/STM32H573I_DK/bdev.c @@ -0,0 +1,45 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "storage.h" +#include "octospi.h" + +#if MICROPY_HW_SPIFLASH_ENABLE_CACHE +static mp_spiflash_cache_t spi_bdev_cache; +#endif + +// External SPI flash uses hardware OCTOSPI interface (in 1-line mode). + +const mp_spiflash_config_t spiflash_config = { + .bus_kind = MP_SPIFLASH_BUS_QSPI, // spiflash driver doesn't yet support OSPI + .bus.u_qspi.data = NULL, + .bus.u_qspi.proto = &octospi_proto, + #if MICROPY_HW_SPIFLASH_ENABLE_CACHE + .cache = &spi_bdev_cache, + #endif +}; + +spi_bdev_t spi_bdev; diff --git a/ports/stm32/boards/STM32H573I_DK/mpconfigboard.h b/ports/stm32/boards/STM32H573I_DK/mpconfigboard.h new file mode 100644 index 0000000000000..01064325dafba --- /dev/null +++ b/ports/stm32/boards/STM32H573I_DK/mpconfigboard.h @@ -0,0 +1,113 @@ +#define MICROPY_HW_BOARD_NAME "STM32H573I-DK" +#define MICROPY_HW_MCU_NAME "STM32H573IIK3Q" + +#define MICROPY_PY_PYB_LEGACY (0) +#define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0) +#define MICROPY_HW_ENABLE_RTC (1) +#define MICROPY_HW_ENABLE_RNG (1) +#define MICROPY_HW_ENABLE_ADC (1) +#define MICROPY_HW_ENABLE_DAC (0) // requires DMA +#define MICROPY_HW_ENABLE_USB (1) +#define MICROPY_HW_HAS_SWITCH (1) +#define MICROPY_HW_HAS_FLASH (1) + +#if 1 +// The board has a 25MHz oscillator, the following gives 250MHz CPU speed +#define MICROPY_HW_CLK_USE_BYPASS (1) +#define MICROPY_HW_CLK_PLLM (5) +#define MICROPY_HW_CLK_PLLN (100) +#define MICROPY_HW_CLK_PLLP (2) +#define MICROPY_HW_CLK_PLLQ (2) +#define MICROPY_HW_CLK_PLLR (2) +#define MICROPY_HW_CLK_PLLVCI_LL (LL_RCC_PLLINPUTRANGE_4_8) +#define MICROPY_HW_CLK_PLLVCO_LL (LL_RCC_PLLVCORANGE_WIDE) +#define MICROPY_HW_CLK_PLLFRAC (0) +#define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_5 +#else +// Use 64MHz HSI to clock the CPU at 200MHz +#define MICROPY_HW_CLK_USE_HSI (1) // 64MHz +#define MICROPY_HW_CLK_PLLM (16) +#define MICROPY_HW_CLK_PLLN (100) +#define MICROPY_HW_CLK_PLLP (2) +#define MICROPY_HW_CLK_PLLQ (2) +#define MICROPY_HW_CLK_PLLR (2) +#define MICROPY_HW_CLK_PLLVCI_LL (LL_RCC_PLLINPUTRANGE_4_8) +#define MICROPY_HW_CLK_PLLVCO_LL (LL_RCC_PLLVCORANGE_WIDE) +#define MICROPY_HW_CLK_PLLFRAC (0) +#define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_4 // VOS0, 168-210MHz +#endif + +// PLL3 with Q output at 48MHz for USB +#define MICROPY_HW_CLK_PLL3M (25) +#define MICROPY_HW_CLK_PLL3N (192) +#define MICROPY_HW_CLK_PLL3P (2) +#define MICROPY_HW_CLK_PLL3Q (4) +#define MICROPY_HW_CLK_PLL3R (2) +#define MICROPY_HW_CLK_PLL3FRAC (0) +#define MICROPY_HW_CLK_PLL3VCI_LL (LL_RCC_PLLINPUTRANGE_1_2) +#define MICROPY_HW_CLK_PLL3VCO_LL (LL_RCC_PLLVCORANGE_MEDIUM) + +// There is an external 32kHz oscillator +#define MICROPY_HW_RTC_USE_LSE (1) + +// 512MBit +#if !MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE +#define MICROPY_HW_OSPIFLASH_SIZE_BITS_LOG2 (29) +#define MICROPY_HW_OSPIFLASH_CS (pin_G6) +#define MICROPY_HW_OSPIFLASH_SCK (pin_F10) +#define MICROPY_HW_OSPIFLASH_IO0 (pin_B1) +#define MICROPY_HW_OSPIFLASH_IO1 (pin_D12) +#define MICROPY_HW_OSPIFLASH_IO2 (pin_C2) +#define MICROPY_HW_OSPIFLASH_IO3 (pin_D13) +#define MICROPY_HW_OSPIFLASH_IO4 (pin_H2) +#define MICROPY_HW_OSPIFLASH_IO5 (pin_H3) +#define MICROPY_HW_OSPIFLASH_IO6 (pin_G9) +#define MICROPY_HW_OSPIFLASH_IO7 (pin_C0) +#define MICROPY_HW_SPIFLASH_ENABLE_CACHE (1) +#define MICROPY_HW_BDEV_SPIFLASH (&spi_bdev) +#define MICROPY_HW_BDEV_SPIFLASH_CONFIG (&spiflash_config) +#define MICROPY_HW_BDEV_SPIFLASH_SIZE_BYTES ((1 << MICROPY_HW_OSPIFLASH_SIZE_BITS_LOG2) / 8) +#define MICROPY_HW_BDEV_SPIFLASH_EXTENDED (&spi_bdev) // for extended block protocol +#endif + +// UART buses +#define MICROPY_HW_UART1_TX (pin_A9) +#define MICROPY_HW_UART1_RX (pin_A10) +#define MICROPY_HW_UART3_TX (pin_B10) // Arduino Connector CN15-Pin2 (D1) +#define MICROPY_HW_UART3_RX (pin_B11) // Arduino Connector CN15-Pin1 (D0) +#define MICROPY_HW_UART_REPL PYB_UART_1 +#define MICROPY_HW_UART_REPL_BAUD 115200 + +// I2C buses +#define MICROPY_HW_I2C1_SCL (pin_B6) // Arduino Connector CN13-Pin10 (D15) +#define MICROPY_HW_I2C1_SDA (pin_B7) // Arduino Connector CN13-Pin9 (D14) + +// SPI buses +#define MICROPY_HW_SPI2_NSS (pin_A3) // Arduino Connector CN13-Pin3 (D10) +#define MICROPY_HW_SPI2_SCK (pin_I1) // Arduino Connector CN13-Pin6 (D13) +#define MICROPY_HW_SPI2_MISO (pin_I2) // Arduino Connector CN13-Pin5 (D12) +#define MICROPY_HW_SPI2_MOSI (pin_B15) // Arduino Connector CN13-Pin4 (D11) + +// USRSW is pulled low. Pressing the button makes the input go high. +#define MICROPY_HW_USRSW_PIN (pin_C13) +#define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) +#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_RISING) +#define MICROPY_HW_USRSW_PRESSED (1) + +// LEDs +#define MICROPY_HW_LED1 (pin_I9) // green +#define MICROPY_HW_LED2 (pin_I8) // orange +#define MICROPY_HW_LED3 (pin_F1) // red +#define MICROPY_HW_LED4 (pin_F4) // blue +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_low(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_high(pin)) + +// USB config +#define MICROPY_HW_USB_FS (1) +#define MICROPY_HW_USB_MAIN_DEV (USB_PHY_FS_ID) + +/******************************************************************************/ +// Variable and function declarations + +extern const struct _mp_spiflash_config_t spiflash_config; +extern struct _spi_bdev_t spi_bdev; diff --git a/ports/stm32/boards/STM32H573I_DK/mpconfigboard.mk b/ports/stm32/boards/STM32H573I_DK/mpconfigboard.mk new file mode 100644 index 0000000000000..99d3923f203c0 --- /dev/null +++ b/ports/stm32/boards/STM32H573I_DK/mpconfigboard.mk @@ -0,0 +1,15 @@ +USE_MBOOT ?= 0 + +# MCU settings +MCU_SERIES = h5 +CMSIS_MCU = STM32H573xx +MICROPY_FLOAT_IMPL = single +AF_FILE = boards/stm32h573_af.csv + +ifeq ($(USE_MBOOT),1) +LD_FILES = boards/stm32h573xi.ld boards/common_bl.ld +TEXT0_ADDR = 0x08008000 +else +LD_FILES = boards/stm32h573xi.ld boards/common_basic.ld +TEXT0_ADDR = 0x08000000 +endif diff --git a/ports/stm32/boards/STM32H573I_DK/pins.csv b/ports/stm32/boards/STM32H573I_DK/pins.csv new file mode 100644 index 0000000000000..5672bc4922f4e --- /dev/null +++ b/ports/stm32/boards/STM32H573I_DK/pins.csv @@ -0,0 +1,149 @@ +,PA0 +,PA1 +,PA2 +,PA3 +,PA4 +,PA5 +,PA6 +,PA7 +,PA8 +,PA9 +,PA10 +,PA11 +,PA12 +,PA13 +,PA14 +,PA15 +,PB0 +,PB1 +,PB2 +,PB3 +,PB4 +,PB5 +,PB6 +,PB7 +,PB8 +,PB9 +,PB10 +,PB11 +,PB12 +,PB13 +,PB14 +,PB15 +,PC0 +,PC1 +,PC2 +,PC3 +,PC4 +,PC5 +,PC6 +,PC7 +,PC8 +,PC9 +,PC10 +,PC11 +,PC12 +,PC13 +,PC14 +,PC15 +,PD0 +,PD1 +,PD2 +,PD3 +,PD4 +,PD5 +,PD6 +,PD7 +,PD8 +,PD9 +,PD10 +,PD11 +,PD12 +,PD13 +,PD14 +,PD15 +,PE0 +,PE1 +,PE2 +,PE3 +,PE4 +,PE5 +,PE6 +,PE7 +,PE8 +,PE9 +,PE10 +,PE11 +,PE12 +,PE13 +,PE14 +,PE15 +,PF0 +,PF1 +,PF2 +,PF3 +,PF4 +,PF5 +,PF6 +,PF7 +,PF8 +,PF9 +,PF10 +,PF11 +,PF12 +,PF13 +,PF14 +,PF15 +,PG0 +,PG1 +,PG2 +,PG3 +,PG4 +,PG5 +,PG6 +,PG7 +,PG8 +,PG9 +,PG10 +,PG11 +,PG12 +,PG13 +,PG14 +,PG15 +,PH0 +,PH1 +,PH2 +,PH3 +,PH4 +,PH5 +,PH6 +,PH7 +,PH8 +,PH9 +,PH10 +,PH11 +,PH12 +,PH13 +,PH14 +,PH15 +,PI0 +,PI1 +,PI2 +,PI3 +,PI4 +,PI5 +,PI6 +,PI7 +,PI8 +,PI9 +,PI10 +,PI11 +,PI12 +,PI13 +,PI14 +,PI15 +LED1,G11 +LED2,G2 +SW,PC13 +UART3_TX,PB10 +UART3_RX,PB11 diff --git a/ports/stm32/boards/STM32H573I_DK/stm32h5xx_hal_conf.h b/ports/stm32/boards/STM32H573I_DK/stm32h5xx_hal_conf.h new file mode 100644 index 0000000000000..6b32ffb18508d --- /dev/null +++ b/ports/stm32/boards/STM32H573I_DK/stm32h5xx_hal_conf.h @@ -0,0 +1,19 @@ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2023 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32H5XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32H5XX_HAL_CONF_H + +// Oscillator values in Hz +#define HSE_VALUE (25000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) + +#include "boards/stm32h5xx_hal_conf_base.h" + +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) + +#endif // MICROPY_INCLUDED_STM32H5XX_HAL_CONF_H diff --git a/ports/stm32/boards/stm32h573_af.csv b/ports/stm32/boards/stm32h573_af.csv new file mode 100644 index 0000000000000..bdc29ebe2a0a3 --- /dev/null +++ b/ports/stm32/boards/stm32h573_af.csv @@ -0,0 +1,142 @@ +Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15, +,,SYS,LPTIM1/TIM1/2/16/17,LPTIM3/PDM_SAI1/TIM3/4/5/12/15,I3C1/LPTIM2/3/LPUART1/OCTOSPI/TIM1/8,CEC/DCMI/I2C1/2/3/4/LPTIM1/2/SPI1/I2S1/TIM15/USART1,CEC/I3C1/LPTIM1/SPI1/I2S1/SPI2/I2S2/SPI3/I2S3/SPI4/5/6,I2C4/OCTOSPI/SAI1/SPI3/I2S3/SPI4/UART4/12/USART10/USB_PD,SDMMC1/SPI2/I2S2/SPI3/I2S3/SPI6/UART7/8/12/USART1/2/3/6/10/11,LPUART1/SAI2/SDMMC1/SPI6/UART4/5/8,FDCAN1/2/FMC[NAND16]/FMC[NORmux]/FMC[NOR_RAM]/OCTOSPI/SDMMC2/TIM13/14,CRS/FMC[NAND16]/OCTOSPI/SAI2/SDMMC2/TIM8/USB_,ETH[MII/RMII]/FMC[NAND16]/OCTOSPI/SDMMC2/UART7/9/USB_PD,FMC[NAND16]/FMC[NORmux]/FMC[NOR_RAM]/FMC[SDRAM_16bit]/SDMMC1,DCMI/FMC[NAND16]/FMC[NORmux]/FMC[NOR_RAM]/LPTIM5,LPTIM3/4/5/6/TIM2/UART5,SYS,ADC +PortA,PA0,,TIM2_CH1,TIM5_CH1,TIM8_ETR,TIM15_BKIN,SPI6_NSS,SPI3_RDY,USART2_CTS/USART2_NSS,UART4_TX,SDMMC2_CMD,SAI2_SD_B,ETH_MII_CRS,,,TIM2_ETR,EVENTOUT,ADC12_INP0/ADC12_INN1 +PortA,PA1,,TIM2_CH2,TIM5_CH2,,TIM15_CH1N,LPTIM1_IN1,OCTOSPI1_DQS,USART2_RTS,UART4_RX,OCTOSPI1_IO3,SAI2_MCLK_B,ETH_MII_RX_CLK/ETH_RMII_REF_CLK,,,,EVENTOUT,ADC12_INP1 +PortA,PA2,,TIM2_CH3,TIM5_CH3,,TIM15_CH1,LPTIM1_IN2,,USART2_TX,SAI2_SCK_B,,,ETH_MDIO,,,,EVENTOUT,ADC12_INP14 +PortA,PA3,,TIM2_CH4,TIM5_CH4,OCTOSPI1_CLK,TIM15_CH2,SPI2_NSS/I2S2_WS,SAI1_SD_B,USART2_RX,,,,ETH_MII_COL,,,,EVENTOUT,ADC12_INP15 +PortA,PA4,,,TIM5_ETR,LPTIM2_CH1,,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,USART2_CK,SPI6_NSS,,,,,DCMI_HSYNC/PSSI_DE,,EVENTOUT,ADC12_INP18 +PortA,PA5,,TIM2_CH1,,TIM8_CH1N,,SPI1_SCK/I2S1_CK,,,SPI6_SCK,,,ETH_MII_TX_EN/ETH_RMII_TX_EN,,PSSI_D14,TIM2_ETR,EVENTOUT,ADC12_INP19/ADC12_INN18 +PortA,PA6,,TIM1_BKIN,TIM3_CH1,TIM8_BKIN,,SPI1_MISO/I2S1_SDI,OCTOSPI1_IO3,USART11_TX,SPI6_MISO,TIM13_CH1,,,,DCMI_PIXCLK/PSSI_PDCK,,EVENTOUT,ADC12_INP3 +PortA,PA7,,TIM1_CH1N,TIM3_CH2,TIM8_CH1N,,SPI1_MOSI/I2S1_SDO,,USART11_RX,SPI6_MOSI,TIM14_CH1,OCTOSPI1_IO2,ETH_MII_RX_DV/ETH_RMII_CRS_DV,FMC_SDNWE,FMC_NWE,,EVENTOUT,ADC12_INP7/ADC12_INN3 +PortA,PA8,MCO1,TIM1_CH1,,TIM8_BKIN2,I2C3_SCL,SPI1_RDY,,USART1_CK,,,USB_SOF,UART7_RX,FMC_NOE,DCMI_D3/PSSI_D3,,EVENTOUT, +PortA,PA9,,TIM1_CH2,,LPUART1_TX,I2C3_SMBA,SPI2_SCK/I2S2_CK,,USART1_TX,,,,ETH_MII_TX_ER,FMC_NWE,DCMI_D0/PSSI_D0,,EVENTOUT, +PortA,PA10,,TIM1_CH3,,LPUART1_RX,LPTIM2_IN2,,UCPD1_FRSTX,USART1_RX,,FDCAN2_TX,,,SDMMC1_D0,DCMI_D1/PSSI_D1,,EVENTOUT, +PortA,PA11,,TIM1_CH4,,LPUART1_CTS,,SPI2_NSS/I2S2_WS,UART4_RX,USART1_CTS/USART1_NSS,,FDCAN1_RX,USB_DM,,,,,EVENTOUT, +PortA,PA12,,TIM1_ETR,,LPUART1_RTS,,SPI2_SCK/I2S2_CK,UART4_TX,USART1_RTS,SAI2_FS_B,FDCAN1_TX,USB_DP,,,,,EVENTOUT, +PortA,PA13,JTMS/SWDIO,,,,,,,,,,,,,,,EVENTOUT, +PortA,PA14,JTCK/SWCLK,,,,,,,,,,,,,,,EVENTOUT, +PortA,PA15,JTDI,TIM2_CH1,LPTIM3_IN2,,HDMI_CEC,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,SPI6_NSS,UART4_RTS,,,UART7_TX,FMC_NBL1,DCMI_D11/PSSI_D11,TIM2_ETR,EVENTOUT, +PortB,PB0,,TIM1_CH2N,TIM3_CH3,TIM8_CH2N,,,OCTOSPI1_IO1,USART11_CK,UART4_CTS,,,ETH_MII_RXD2,,,LPTIM3_CH1,EVENTOUT,ADC12_INP9/ADC12_INN5 +PortB,PB1,,TIM1_CH3N,TIM3_CH4,TIM8_CH3N,,,OCTOSPI1_IO0,,,,,ETH_MII_RXD3,,,LPTIM3_CH2,EVENTOUT,ADC12_INP5 +PortB,PB2,RTC_OUT2,,SAI1_D1,TIM8_CH4N,SPI1_RDY,LPTIM1_CH1,SAI1_SD_A,SPI3_MOSI/I2S3_SDO,,OCTOSPI1_CLK,OCTOSPI1_DQS,,SDMMC1_CMD,LPTIM5_ETR,,EVENTOUT, +PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,I2C2_SDA,SPI1_SCK/I2S1_CK,SPI3_SCK/I2S3_CK,UART12_CTS/UART12_NSS,SPI6_SCK,SDMMC2_D2,CRS_SYNC,UART7_RX,,,LPTIM6_ETR,EVENTOUT, +PortB,PB4,NJTRST,TIM16_BKIN,TIM3_CH1,OCTOSPI1_CLK,LPTIM1_CH2,SPI1_MISO/I2S1_SDI,SPI3_MISO/I2S3_SDI,SPI2_NSS/I2S2_WS,SPI6_MISO,SDMMC2_D3,,UART7_TX,,DCMI_D7/PSSI_D7,,EVENTOUT, +PortB,PB5,,TIM17_BKIN,TIM3_CH2,OCTOSPI1_NCLK,I2C1_SMBA,SPI1_MOSI/I2S1_SDO,I2C4_SMBA,SPI3_MOSI/I2S3_SDO,SPI6_MOSI,FDCAN2_RX,,ETH_PPS_OUT,FMC_SDCKE1,DCMI_D10/PSSI_D10,UART5_RX,EVENTOUT, +PortB,PB6,,TIM16_CH1N,TIM4_CH1,I3C1_SCL,I2C1_SCL,HDMI_CEC,I2C4_SCL,USART1_TX,LPUART1_TX,FDCAN2_TX,OCTOSPI1_NCS,,FMC_SDNE1,DCMI_D5/PSSI_D5,UART5_TX,EVENTOUT, +PortB,PB7,,TIM17_CH1N,TIM4_CH2,I3C1_SDA,I2C1_SDA,,I2C4_SDA,USART1_RX,LPUART1_RX,FDCAN1_TX,SDMMC2_D5,SDMMC2_CKIN,FMC_NL,DCMI_VSYNC/PSSI_RDY,,EVENTOUT, +PortB,PB8,,TIM16_CH1,TIM4_CH3,I3C1_SCL,I2C1_SCL,SPI4_RDY,I2C4_SCL,SDMMC1_CKIN,UART4_RX,FDCAN1_RX,SDMMC2_D4,ETH_MII_TXD3,SDMMC1_D4,DCMI_D6/PSSI_D6,,EVENTOUT, +PortB,PB9,,TIM17_CH1,TIM4_CH4,I3C1_SDA,I2C1_SDA,SPI2_NSS/I2S2_WS,I2C4_SDA,SDMMC1_CDIR,UART4_TX,FDCAN1_TX,SDMMC2_D5,SDMMC2_CKIN,SDMMC1_D5,DCMI_D7/PSSI_D7,,EVENTOUT, +PortB,PB10,,TIM2_CH3,LPTIM3_CH1,LPTIM2_IN1,I2C2_SCL,SPI2_SCK/I2S2_CK,,USART3_TX,,OCTOSPI1_NCS,,ETH_MII_RX_ER,,,,EVENTOUT, +PortB,PB11,,TIM2_CH4,,LPTIM2_ETR,I2C2_SDA,SPI2_RDY,SPI4_RDY,USART3_RX,,,,ETH_MII_TX_EN/ETH_RMII_TX_EN,FMC_NBL1,,,EVENTOUT, +PortB,PB12,,TIM1_BKIN,,OCTOSPI1_NCLK,I2C2_SDA,SPI2_NSS/I2S2_WS,UCPD1_FRSTX,USART3_CK,,FDCAN2_RX,,ETH_MII_TXD0/ETH_RMII_TXD0,,,UART5_RX,EVENTOUT, +PortB,PB13,,TIM1_CH1N,LPTIM3_IN1,LPTIM2_CH1,I2C2_SMBA,SPI2_SCK/I2S2_CK,,USART3_CTS/USART3_NSS,,FDCAN2_TX,,,SDMMC1_D0,,UART5_TX,EVENTOUT, +PortB,PB14,,TIM1_CH2N,TIM12_CH1,TIM8_CH2N,USART1_TX,SPI2_MISO/I2S2_SDI,,USART3_RTS,UART4_RTS,SDMMC2_D0,,,,,LPTIM3_ETR,EVENTOUT, +PortB,PB15,RTC_REFIN,TIM1_CH3N,TIM12_CH2,TIM8_CH3N,USART1_RX,SPI2_MOSI/I2S2_SDO,,USART11_CTS/USART11_NSS,UART4_CTS,SDMMC2_D1,OCTOSPI1_CLK,ETH_MII_TXD1/ETH_RMII_TXD1,,DCMI_D2/PSSI_D2,UART5_RX,EVENTOUT, +PortC,PC0,,TIM16_BKIN,,,,,SAI1_MCLK_A,SPI2_RDY,SAI2_FS_B,FMC_A25,OCTOSPI1_IO7,,FMC_SDNWE,,,EVENTOUT,ADC12_INP10 +PortC,PC1,TRACED0,,SAI1_D1,,,SPI2_MOSI/I2S2_SDO,SAI1_SD_A,USART11_RTS,SAI2_SD_A,SDMMC2_CK,OCTOSPI1_IO4,ETH_MDC,,,,EVENTOUT,ADC12_INP11/ADC12_INN10 +PortC,PC2,PWR_CSLEEP,TIM17_CH1,TIM4_CH4,,,SPI2_MISO/I2S2_SDI,OCTOSPI1_IO5,,,OCTOSPI1_IO2,,ETH_MII_TXD2,FMC_SDNE0,,,EVENTOUT,ADC12_INP12/ADC12_INN11 +PortC,PC3,PWR_CSTOP,,SAI1_D3,LPTIM3_CH1,,SPI2_MOSI/I2S2_SDO,OCTOSPI1_IO6,,,OCTOSPI1_IO0,,ETH_MII_TX_CLK,FMC_SDCKE0,,,EVENTOUT,ADC12_INP13/ADC12_INN12 +PortC,PC4,,TIM2_CH4,SAI1_CK1,LPTIM2_ETR,,I2S1_MCK,,USART3_RX,,,,ETH_MII_RXD0/ETH_RMII_RXD0,FMC_SDNE0,,,EVENTOUT,ADC12_INP4 +PortC,PC5,,TIM1_CH4N,SAI1_D3,,PSSI_D15,,SAI1_FS_A,UART12_RTS,,,OCTOSPI1_DQS,ETH_MII_RXD1/ETH_RMII_RXD1,FMC_SDCKE0,,,EVENTOUT,ADC12_INP8/ADC12_INN4 +PortC,PC6,,,TIM3_CH1,TIM8_CH1,,I2S2_MCK,SAI1_SCK_A,USART6_TX,SDMMC1_D0DIR,FMC_NWAIT,SDMMC2_D6,OCTOSPI1_IO5,SDMMC1_D6,DCMI_D0/PSSI_D0,,EVENTOUT, +PortC,PC7,TRGIO,,TIM3_CH2,TIM8_CH2,,,I2S3_MCK,USART6_RX,SDMMC1_D123DIR,FMC_NE1,SDMMC2_D7,OCTOSPI1_IO6,SDMMC1_D7,DCMI_D1/PSSI_D1,,EVENTOUT, +PortC,PC8,TRACED1,,TIM3_CH3,TIM8_CH3,,,,USART6_CK,UART5_RTS,FMC_NE2/FMC_NCE,FMC_INT,FMC_ALE,SDMMC1_D0,DCMI_D2/PSSI_D2,,EVENTOUT, +PortC,PC9,MCO2,,TIM3_CH4,TIM8_CH4,I2C3_SDA,AUDIOCLK,,,UART5_CTS,OCTOSPI1_IO0,,FMC_CLE,SDMMC1_D1,DCMI_D3/PSSI_D3,,EVENTOUT, +PortC,PC10,,,LPTIM3_ETR,,,,SPI3_SCK/I2S3_CK,USART3_TX,UART4_TX,OCTOSPI1_IO1,,ETH_MII_TXD0/ETH_RMII_TXD0,SDMMC1_D2,DCMI_D8/PSSI_D8,,EVENTOUT, +PortC,PC11,,,LPTIM3_IN1,,,,SPI3_MISO/I2S3_SDI,USART3_RX,UART4_RX,OCTOSPI1_NCS,,,SDMMC1_D3,DCMI_D4/PSSI_D4,,EVENTOUT, +PortC,PC12,TRACED3,,TIM15_CH1,,,SPI6_SCK,SPI3_MOSI/I2S3_SDO,USART3_CK,UART5_TX,,,,SDMMC1_CK,DCMI_D9/PSSI_D9,,EVENTOUT, +PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT, +PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT, +PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT, +PortD,PD0,,,,TIM8_CH4N,,,,,UART4_RX,FDCAN1_RX,,UART9_CTS,FMC_D2/FMC_AD2,,,EVENTOUT, +PortD,PD1,,,,,,,,,UART4_TX,FDCAN1_TX,,,FMC_D3/FMC_AD3,,,EVENTOUT, +PortD,PD2,TRACED2,,TIM3_ETR,,TIM15_BKIN,,,,UART5_RX,,,,SDMMC1_CMD,DCMI_D11/PSSI_D11,LPTIM4_ETR,EVENTOUT, +PortD,PD3,,,,,,SPI2_SCK/I2S2_CK,,USART2_CTS/USART2_NSS,,,,,FMC_CLK,DCMI_D5/PSSI_D5,,EVENTOUT, +PortD,PD4,,,,,,,,USART2_RTS,,,OCTOSPI1_IO4,,FMC_NOE,,,EVENTOUT, +PortD,PD5,,TIM1_CH4N,,,,SPI2_RDY,,USART2_TX,,FDCAN1_TX,OCTOSPI1_IO5,,FMC_NWE,,,EVENTOUT, +PortD,PD6,,,SAI1_D1,,,SPI3_MOSI/I2S3_SDO,SAI1_SD_A,USART2_RX,,,OCTOSPI1_IO6,SDMMC2_CK,FMC_NWAIT,DCMI_D10/PSSI_D10,,EVENTOUT, +PortD,PD7,,,,,,SPI1_MOSI/I2S1_SDO,,USART2_CK,,,OCTOSPI1_IO7,SDMMC2_CMD,FMC_NE1/FMC_NCE,,LPTIM4_OUT,EVENTOUT, +PortD,PD8,,,,,,,,USART3_TX,,,,,FMC_D13/FMC_AD13,,,EVENTOUT, +PortD,PD9,,,,,,,,USART3_RX,,FDCAN2_RX,,,FMC_D14/FMC_AD14,,,EVENTOUT, +PortD,PD10,,,,LPTIM2_CH2,,,,USART3_CK,,,,,FMC_D15/FMC_AD15,,,EVENTOUT, +PortD,PD11,,,SAI1_CK1,LPTIM2_IN2,I2C4_SMBA,,,USART3_CTS/USART3_NSS,UART4_RX,OCTOSPI1_IO0,SAI2_SD_A,,FMC_A16/FMC_CLE,,,EVENTOUT, +PortD,PD12,,LPTIM1_IN1,TIM4_CH1,LPTIM2_IN1,I2C4_SCL,I3C1_SCL,SAI1_D1,USART3_RTS,UART4_TX,OCTOSPI1_IO1,SAI2_FS_A,,FMC_A17/FMC_ALE,DCMI_D12/PSSI_D12,,EVENTOUT, +PortD,PD13,,LPTIM1_CH1,TIM4_CH2,LPTIM2_CH1,I2C4_SDA,I3C1_SDA,,,,OCTOSPI1_IO3,SAI2_SCK_A,UART9_RTS,FMC_A18,DCMI_D13/PSSI_D13,LPTIM4_IN1,EVENTOUT, +PortD,PD14,,,TIM4_CH3,,,,,,UART8_CTS,,,UART9_RX,FMC_D0/FMC_AD0,,,EVENTOUT, +PortD,PD15,,,TIM4_CH4,,,,,,UART8_RTS,,,UART9_TX,FMC_D1/FMC_AD1,,,EVENTOUT, +PortE,PE0,,LPTIM1_ETR,TIM4_ETR,LPTIM2_CH2,LPTIM2_ETR,,SPI3_RDY,,UART8_RX,FDCAN1_RX,SAI2_MCLK_A,,FMC_NBL0,DCMI_D2/PSSI_D2,,EVENTOUT, +PortE,PE1,,LPTIM1_IN2,,,,,,,UART8_TX,FDCAN1_TX,,,FMC_NBL1,DCMI_D3/PSSI_D3,,EVENTOUT, +PortE,PE2,TRACECLK,LPTIM1_IN2,SAI1_CK1,,,SPI4_SCK,SAI1_MCLK_A,USART10_RX,UART8_TX,OCTOSPI1_IO2,,ETH_MII_TXD3,FMC_A23,DCMI_D3/PSSI_D3,,EVENTOUT, +PortE,PE3,TRACED0,,,,TIM15_BKIN,,SAI1_SD_B,USART10_TX,,,,,FMC_A19,,,EVENTOUT, +PortE,PE4,TRACED1,,SAI1_D2,,TIM15_CH1N,SPI4_NSS,SAI1_FS_A,,,,,,FMC_A20,DCMI_D4/PSSI_D4,,EVENTOUT, +PortE,PE5,TRACED2,,SAI1_CK2,,TIM15_CH1,SPI4_MISO,SAI1_SCK_A,,,,,,FMC_A21,DCMI_D6/PSSI_D6,,EVENTOUT, +PortE,PE6,TRACED3,TIM1_BKIN2,SAI1_D1,,TIM15_CH2,SPI4_MOSI,SAI1_SD_A,,,,SAI2_MCLK_B,,FMC_A22,DCMI_D7/PSSI_D7,,EVENTOUT, +PortE,PE7,,TIM1_ETR,,,,,UART12_RTS,UART7_RX,,,OCTOSPI1_IO4,,FMC_D4/FMC_AD4,,,EVENTOUT, +PortE,PE8,,TIM1_CH1N,,,,,UART12_CTS/UART12_NSS,UART7_TX,,,OCTOSPI1_IO5,,FMC_D5/FMC_AD5,,,EVENTOUT, +PortE,PE9,,TIM1_CH1,,,,,UART12_RX,UART7_RTS,,,OCTOSPI1_IO6,,FMC_D6/FMC_AD6,,,EVENTOUT, +PortE,PE10,,TIM1_CH2N,,,,,UART12_TX,UART7_CTS,,,OCTOSPI1_IO7,,FMC_D7/FMC_AD7,,,EVENTOUT, +PortE,PE11,,TIM1_CH2,,,SPI1_RDY,SPI4_NSS,OCTOSPI1_NCS,,,,SAI2_SD_B,,FMC_D8/FMC_AD8,,,EVENTOUT, +PortE,PE12,,TIM1_CH3N,,,,SPI4_SCK,,,,,SAI2_SCK_B,,FMC_D9/FMC_AD9,,,EVENTOUT, +PortE,PE13,,TIM1_CH3,,,,SPI4_MISO,,,,,SAI2_FS_B,,FMC_D10/FMC_AD10,,,EVENTOUT, +PortE,PE14,,TIM1_CH4,,,,SPI4_MOSI,,,,,SAI2_MCLK_B,,FMC_D11/FMC_AD11,,,EVENTOUT, +PortE,PE15,,TIM1_BKIN,,TIM1_CH4N,,,,USART10_CK,,,,,FMC_D12/FMC_AD12,,,EVENTOUT, +PortF,PF0,,,,,I2C2_SDA,,,,,,,,FMC_A0,LPTIM5_CH1,,EVENTOUT, +PortF,PF1,,,,,I2C2_SCL,,,,,,,,FMC_A1,LPTIM5_CH2,,EVENTOUT, +PortF,PF2,,,LPTIM3_CH2,LPTIM3_IN2,I2C2_SMBA,,UART12_TX,USART11_CK,,,,,FMC_A2,LPTIM5_IN1,,EVENTOUT, +PortF,PF3,,,LPTIM3_IN1,,,,,USART11_TX,,,,,FMC_A3,LPTIM5_IN2,,EVENTOUT, +PortF,PF4,,,LPTIM3_ETR,,,,,USART11_RX,,,,,FMC_A4,,,EVENTOUT, +PortF,PF5,,,LPTIM3_CH1,,I2C4_SCL,I3C1_SCL,UART12_RX,USART11_CTS/USART11_NSS,,,,,FMC_A5,,LPTIM3_IN1,EVENTOUT, +PortF,PF6,,TIM16_CH1,,,,SPI5_NSS,SAI1_SD_B,UART7_RX,,,OCTOSPI1_IO3,,,LPTIM5_CH1,,EVENTOUT, +PortF,PF7,,TIM17_CH1,,,,SPI5_SCK,SAI1_MCLK_B,UART7_TX,,,OCTOSPI1_IO2,,,LPTIM5_CH2,,EVENTOUT, +PortF,PF8,,TIM16_CH1N,,,,SPI5_MISO,SAI1_SCK_B,UART7_RTS,,TIM13_CH1,OCTOSPI1_IO0,,,LPTIM5_IN1,,EVENTOUT, +PortF,PF9,,TIM17_CH1N,,,,SPI5_MOSI,SAI1_FS_B,UART7_CTS,,TIM14_CH1,OCTOSPI1_IO1,,,LPTIM5_IN2,,EVENTOUT, +PortF,PF10,,TIM16_BKIN,SAI1_D3,,PSSI_D15,,,,,OCTOSPI1_CLK,,,,DCMI_D11/PSSI_D11,,EVENTOUT, +PortF,PF11,,,,,,SPI5_MOSI,,,,OCTOSPI1_NCLK,SAI2_SD_B,,FMC_NRAS,DCMI_D12/PSSI_D12,LPTIM6_CH1,EVENTOUT,ADC1_INP2 +PortF,PF12,,,,,,,,,,,,,FMC_A6,,LPTIM6_CH2,EVENTOUT,ADC1_INP6/ADC1_INN2 +PortF,PF13,,,,,I2C4_SMBA,,,,,,,,FMC_A7,,LPTIM6_IN1,EVENTOUT,ADC2_INP2 +PortF,PF14,,,,,,,,,,,,,FMC_A8,,LPTIM6_IN2,EVENTOUT,ADC2_INP6/ADC2_INN2 +PortF,PF15,,,,,I2C4_SDA,I3C1_SDA,,,,,,,FMC_A9,,,EVENTOUT, +PortG,PG0,,,,,,,,,,,,UART9_RX,FMC_A10,,LPTIM4_IN1,EVENTOUT, +PortG,PG1,,,,,,,,SPI2_MOSI/I2S2_SDO,,,,UART9_TX,FMC_A11,,,EVENTOUT, +PortG,PG2,,,,TIM8_BKIN,,,,UART12_RX,,,,,FMC_A12,,LPTIM6_ETR,EVENTOUT, +PortG,PG3,,,,TIM8_BKIN2,,,,UART12_TX,,,,,FMC_A13,LPTIM5_ETR,,EVENTOUT, +PortG,PG4,,TIM1_BKIN2,,,,,,,,,,,FMC_A14/FMC_BA0,,LPTIM4_ETR,EVENTOUT, +PortG,PG5,,TIM1_ETR,,,,,,,,,,,FMC_A15/FMC_BA1,,,EVENTOUT, +PortG,PG6,,TIM17_BKIN,,I3C1_SDA,I2C4_SDA,SPI1_RDY,,,,,OCTOSPI1_NCS,UCPD1_FRSTX,FMC_NE3,DCMI_D12/PSSI_D12,,EVENTOUT, +PortG,PG7,,,SAI1_CK2,I3C1_SCL,I2C4_SCL,,SAI1_MCLK_A,USART6_CK,,,,UCPD1_FRSTX,FMC_INT,DCMI_D13/PSSI_D13,,EVENTOUT, +PortG,PG8,,,,TIM8_ETR,,SPI6_NSS,,USART6_RTS,,,,ETH_PPS_OUT,FMC_SDCLK,,,EVENTOUT, +PortG,PG9,,,,,,SPI1_MISO/I2S1_SDI,,USART6_RX,,OCTOSPI1_IO6,SAI2_FS_B,SDMMC2_D0,FMC_NE2/FMC_NCE,DCMI_VSYNC/PSSI_RDY,,EVENTOUT, +PortG,PG10,,,,,,SPI1_NSS/I2S1_WS,,,,,SAI2_SD_B,SDMMC2_D1,FMC_NE3,DCMI_D2/PSSI_D2,,EVENTOUT, +PortG,PG11,,LPTIM1_IN2,,,,SPI1_SCK/I2S1_CK,USART10_RX,USART11_RTS,,,SDMMC2_D2,ETH_MII_TX_EN/ETH_RMII_TX_EN,,DCMI_D3/PSSI_D3,,EVENTOUT, +PortG,PG12,,LPTIM1_IN1,,,PSSI_D15,SPI6_MISO,USART10_TX,USART6_RTS,,,SDMMC2_D3,ETH_MII_TXD1/ETH_RMII_TXD1,FMC_NE4,DCMI_D11/PSSI_D11,LPTIM5_CH1,EVENTOUT, +PortG,PG13,TRACED0,LPTIM1_CH1,,,,SPI6_SCK,USART10_CTS/USART10_NSS,USART6_CTS/USART6_NSS,,,SDMMC2_D6,ETH_MII_TXD0/ETH_RMII_TXD0,FMC_A24,LPTIM5_CH2,,EVENTOUT, +PortG,PG14,TRACED1,LPTIM1_ETR,,,LPTIM1_CH2,SPI6_MOSI,USART10_RTS,USART6_TX,,OCTOSPI1_IO7,SDMMC2_D7,ETH_MII_TXD1/ETH_RMII_TXD1,FMC_A25,LPTIM5_IN1,,EVENTOUT, +PortG,PG15,,,,,,SPI4_RDY,USART10_CK,USART6_CTS/USART6_NSS,,,,,FMC_NCAS,DCMI_D13/PSSI_D13,,EVENTOUT, +PortH,PH0,,,,,,,,,,,,,,,,EVENTOUT, +PortH,PH1,,,,,,,,,,,,,,,,EVENTOUT, +PortH,PH2,,LPTIM1_IN2,,,,,,,,OCTOSPI1_IO4,SAI2_SCK_B,ETH_MII_CRS,FMC_SDCKE0,,,EVENTOUT, +PortH,PH3,,,,,,,,,,OCTOSPI1_IO5,SAI2_MCLK_B,ETH_MII_COL,FMC_SDNE0,,,EVENTOUT, +PortH,PH4,,,,,I2C2_SCL,SPI5_RDY,,SPI6_RDY,,,,,,PSSI_D14,,EVENTOUT, +PortH,PH5,,,,,I2C2_SDA,SPI5_NSS,,SPI6_RDY,,,,,FMC_SDNWE,,,EVENTOUT, +PortH,PH6,,TIM1_CH3N,TIM12_CH1,TIM8_CH1,I2C2_SMBA,SPI5_SCK,,,,,,ETH_MII_RXD2,FMC_SDNE1,DCMI_D8/PSSI_D8,,EVENTOUT, +PortH,PH7,,TIM1_CH3,,TIM8_CH1N,I2C3_SCL,SPI5_MISO,,,,,,ETH_MII_RXD3,FMC_SDCKE1,DCMI_D9/PSSI_D9,,EVENTOUT, +PortH,PH8,,TIM1_CH2N,TIM5_ETR,TIM8_CH2,I2C3_SDA,SPI5_MOSI,,,,,,,,DCMI_HSYNC/PSSI_DE,,EVENTOUT, +PortH,PH9,,TIM1_CH2,TIM12_CH2,TIM8_CH2N,I2C3_SMBA,SPI5_NSS,,,,,,,,DCMI_D0/PSSI_D0,,EVENTOUT, +PortH,PH10,,TIM1_CH1N,TIM5_CH1,TIM8_CH3,I2C4_SMBA,SPI5_RDY,,,,,,,,DCMI_D1/PSSI_D1,,EVENTOUT, +PortH,PH11,,TIM1_CH1,TIM5_CH2,TIM8_CH3N,I2C4_SCL,I3C1_SCL,,,,,,,,DCMI_D2/PSSI_D2,,EVENTOUT, +PortH,PH12,,TIM1_BKIN,TIM5_CH3,TIM8_BKIN,I2C4_SDA,I3C1_SDA,,,,,TIM8_CH4N,,,DCMI_D3/PSSI_D3,,EVENTOUT, +PortH,PH13,,LPTIM1_IN2,,TIM8_CH1N,,,,UART8_TX,UART4_TX,FDCAN1_TX,,,,DCMI_D3/PSSI_D3,,EVENTOUT, +PortH,PH14,,,,TIM8_CH2N,,,,,UART4_RX,FDCAN1_RX,,,,DCMI_D4/PSSI_D4,,EVENTOUT, +PortH,PH15,,,,TIM8_CH3N,,,,,,,,,,DCMI_D11/PSSI_D11,,EVENTOUT, +PortI,PI0,,,TIM5_CH4,,,SPI2_NSS/I2S2_WS,,,,,,,,DCMI_D13/PSSI_D13,,EVENTOUT, +PortI,PI1,,,,TIM8_BKIN2,,SPI2_SCK/I2S2_CK,,,,,,,,DCMI_D8/PSSI_D8,,EVENTOUT, +PortI,PI2,,,,TIM8_CH4,,SPI2_MISO/I2S2_SDI,,,,,,,,DCMI_D9/PSSI_D9,,EVENTOUT, +PortI,PI3,,,,TIM8_ETR,,SPI2_MOSI/I2S2_SDO,,,,,,,,DCMI_D10/PSSI_D10,,EVENTOUT, +PortI,PI4,,,,TIM8_BKIN,,,,SPI2_RDY,,,SAI2_MCLK_A,,,DCMI_D5/PSSI_D5,,EVENTOUT, +PortI,PI5,,,,TIM8_CH1,,,,,,,SAI2_SCK_A,,,DCMI_VSYNC/PSSI_RDY,,EVENTOUT, +PortI,PI6,,,,TIM8_CH2,,,,,,,SAI2_SD_A,,,DCMI_D6/PSSI_D6,,EVENTOUT, +PortI,PI7,,,,TIM8_CH3,,,,,,,SAI2_FS_A,,,DCMI_D7/PSSI_D7,,EVENTOUT, +PortI,PI8,,,,,,,,,,,,,,,,EVENTOUT, +PortI,PI9,,,,,,,,,UART4_RX,FDCAN1_RX,,,,,,EVENTOUT, +PortI,PI10,,,,,,,,,,FDCAN1_RX,,ETH_MII_RX_ER,,PSSI_D14,,EVENTOUT, +PortI,PI11,,,,,,,,,,,,,,PSSI_D15,,EVENTOUT, diff --git a/ports/stm32/boards/stm32h573xi.ld b/ports/stm32/boards/stm32h573xi.ld new file mode 100644 index 0000000000000..334e1f7b85124 --- /dev/null +++ b/ports/stm32/boards/stm32h573xi.ld @@ -0,0 +1,34 @@ +/* + GNU linker script for STM32H573xI +*/ + +/* Specify the memory areas */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K /* sectors 0-127 (for common_basic.ld) */ + FLASH_APP (rx) : ORIGIN = 0x08008000, LENGTH = 992K /* sectors 4-127 (for common_bl.ld) */ + FLASH_FS (rx) : ORIGIN = 0x08100000, LENGTH = 1024K /* sectors 128-255 */ + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 632K /* SRAM1+SRAM2+SRAM3 - 8K */ + FS_CACHE (xrw) : ORIGIN = 0x2009e000, LENGTH = 8K /* last 8K of SRAM3 */ +} + +/* produce a link error if there is not this amount of RAM for these sections */ +_minimum_stack_size = 2K; +_minimum_heap_size = 16K; + +/* Define the stack. The stack is full descending so begins just above last byte + of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ +_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; +_sstack = _estack - 16K; /* tunable */ + +/* RAM extents for the garbage collector */ +_ram_start = ORIGIN(RAM); +_ram_end = ORIGIN(RAM) + LENGTH(RAM); +_heap_start = _ebss; /* heap starts just after statically allocated memory */ +_heap_end = _sstack; + +/* Filesystem cache in RAM, and storage in flash */ +_micropy_hw_internal_flash_storage_ram_cache_start = ORIGIN(FS_CACHE); +_micropy_hw_internal_flash_storage_ram_cache_end = ORIGIN(FS_CACHE) + LENGTH(FS_CACHE); +_micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS); +_micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); diff --git a/ports/stm32/boards/stm32h5xx_hal_conf_base.h b/ports/stm32/boards/stm32h5xx_hal_conf_base.h new file mode 100644 index 0000000000000..c40fc7085597e --- /dev/null +++ b/ports/stm32/boards/stm32h5xx_hal_conf_base.h @@ -0,0 +1,108 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_STM32H5XX_HAL_CONF_BASE_H +#define MICROPY_INCLUDED_STM32H5XX_HAL_CONF_BASE_H + +// Enable various HAL modules +#define HAL_MODULE_ENABLED +#define HAL_ADC_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED +#define HAL_CRC_MODULE_ENABLED +#define HAL_DAC_MODULE_ENABLED +#define HAL_DCMI_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_FDCAN_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_HASH_MODULE_ENABLED +#define HAL_HCD_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +#define HAL_I2S_MODULE_ENABLED +#define HAL_ICACHE_MODULE_ENABLED +#define HAL_IWDG_MODULE_ENABLED +#define HAL_PCD_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_RTC_MODULE_ENABLED +#define HAL_SD_MODULE_ENABLED +#define HAL_SDRAM_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_TIM_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +#define HAL_USART_MODULE_ENABLED +#define HAL_WWDG_MODULE_ENABLED + +// Oscillator values in Hz +#define CSI_VALUE (4000000) +#define HSI_VALUE (64000000) +#define HSI48_VALUE (48000000) +#define LSI_VALUE (32000) + +// SysTick has the highest priority +#define TICK_INT_PRIORITY (0x00) + +// Miscellaneous HAL settings +#define USE_RTOS 0 +#define USE_SPI_CRC 1 + +// Include various HAL modules for convenience +#include "stm32h5xx_hal_dma.h" +#include "stm32h5xx_hal_rcc.h" +#include "stm32h5xx_hal_adc.h" +#include "stm32h5xx_hal_cortex.h" +#include "stm32h5xx_hal_crc.h" +#include "stm32h5xx_hal_dac.h" +#include "stm32h5xx_hal_dcmi.h" +#include "stm32h5xx_hal_fdcan.h" +#include "stm32h5xx_hal_flash.h" +#include "stm32h5xx_hal_gpio.h" +#include "stm32h5xx_hal_hash.h" +#include "stm32h5xx_hal_hcd.h" +#include "stm32h5xx_hal_i2c.h" +#include "stm32h5xx_hal_i2s.h" +#include "stm32h5xx_hal_icache.h" +#include "stm32h5xx_hal_iwdg.h" +#include "stm32h5xx_hal_pcd.h" +#include "stm32h5xx_hal_pwr.h" +#include "stm32h5xx_hal_rtc.h" +#include "stm32h5xx_hal_sd.h" +#include "stm32h5xx_hal_sdram.h" +#include "stm32h5xx_hal_spi.h" +#include "stm32h5xx_hal_tim.h" +#include "stm32h5xx_hal_uart.h" +#include "stm32h5xx_hal_usart.h" +#include "stm32h5xx_hal_wwdg.h" +#include "stm32h5xx_ll_adc.h" +#include "stm32h5xx_ll_lpuart.h" +#include "stm32h5xx_ll_pwr.h" +#include "stm32h5xx_ll_rcc.h" +#include "stm32h5xx_ll_rtc.h" +#include "stm32h5xx_ll_usart.h" + +// HAL parameter assertions are disabled +#define assert_param(expr) ((void)0) + +#endif // MICROPY_INCLUDED_STM32H5XX_HAL_CONF_BASE_H diff --git a/ports/stm32/dac.c b/ports/stm32/dac.c index feadbe5c58170..e44e519b636c9 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 29306f1b271cc..cdbb90e5d8b3c 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 37b8710c214c1..92d5db6c0a71c 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 f810bc4e0d41d..7698569149561 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 84eb876d8d1ff..919e4bb2e8483 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 12fa523cd56eb..a8f50dbcbaf7a 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 3f9022aa70b7a..a4b2957de3347 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 34319e9753321..3a348e18bf945 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) @@ -374,12 +378,10 @@ uint32_t adc_config_and_read_u16(ADC_TypeDef *adc, uint32_t channel, uint32_t sa // Scale raw reading to 16 bit value using a Taylor expansion (for bits <= 16). uint32_t bits = adc_get_bits(adc); - #if defined(STM32H7) if (bits < 8) { // For 6 and 7 bits return raw << (16 - bits) | raw << (16 - 2 * bits) | raw >> (3 * bits - 16); } - #endif return raw << (16 - bits) | raw >> (2 * bits - 16); } diff --git a/ports/stm32/machine_uart.c b/ports/stm32/machine_uart.c index 20def373fb146..ba8c1a91115dd 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 cc0367b824e05..2235e4de3537d 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 @@ -411,6 +424,21 @@ void stm32_main(uint32_t reset_mode) { rtc_init_start(false); #endif uart_init0(); + + #if defined(MICROPY_HW_UART_REPL) + // Set up a UART REPL using a statically allocated object + pyb_uart_repl_obj.base.type = &pyb_uart_type; + pyb_uart_repl_obj.uart_id = MICROPY_HW_UART_REPL; + pyb_uart_repl_obj.is_static = true; + pyb_uart_repl_obj.timeout = 0; + pyb_uart_repl_obj.timeout_char = 2; + uart_init(&pyb_uart_repl_obj, MICROPY_HW_UART_REPL_BAUD, UART_WORDLENGTH_8B, UART_PARITY_NONE, UART_STOPBITS_1, 0); + uart_set_rxbuf(&pyb_uart_repl_obj, sizeof(pyb_uart_repl_rxbuf), pyb_uart_repl_rxbuf); + uart_attach_to_repl(&pyb_uart_repl_obj, true); + MP_STATE_PORT(pyb_uart_obj_all)[MICROPY_HW_UART_REPL - 1] = &pyb_uart_repl_obj; + MP_STATE_PORT(pyb_stdio_uart) = &pyb_uart_repl_obj; + #endif + spi_init0(); #if MICROPY_PY_PYB_LEGACY && MICROPY_HW_ENABLE_HW_I2C i2c_init0(); @@ -446,19 +474,6 @@ void stm32_main(uint32_t reset_mode) { } #endif - #if defined(MICROPY_HW_UART_REPL) - // Set up a UART REPL using a statically allocated object - pyb_uart_repl_obj.base.type = &pyb_uart_type; - pyb_uart_repl_obj.uart_id = MICROPY_HW_UART_REPL; - pyb_uart_repl_obj.is_static = true; - pyb_uart_repl_obj.timeout = 0; - pyb_uart_repl_obj.timeout_char = 2; - uart_init(&pyb_uart_repl_obj, MICROPY_HW_UART_REPL_BAUD, UART_WORDLENGTH_8B, UART_PARITY_NONE, UART_STOPBITS_1, 0); - uart_set_rxbuf(&pyb_uart_repl_obj, sizeof(pyb_uart_repl_rxbuf), pyb_uart_repl_rxbuf); - uart_attach_to_repl(&pyb_uart_repl_obj, true); - MP_STATE_PORT(pyb_uart_obj_all)[MICROPY_HW_UART_REPL - 1] = &pyb_uart_repl_obj; - #endif - boardctrl_state_t state; state.reset_mode = reset_mode; state.log_soft_reset = false; @@ -496,12 +511,6 @@ void stm32_main(uint32_t reset_mode) { // we can run Python scripts (eg boot.py), but anything that is configurable // by boot.py must be set after boot.py is run. - #if defined(MICROPY_HW_UART_REPL) - MP_STATE_PORT(pyb_stdio_uart) = &pyb_uart_repl_obj; - #else - MP_STATE_PORT(pyb_stdio_uart) = NULL; - #endif - readline_init0(); pin_init0(); extint_init0(); @@ -659,6 +668,12 @@ void stm32_main(uint32_t reset_mode) { pyb_thread_deinit(); #endif + #if defined(MICROPY_HW_UART_REPL) + MP_STATE_PORT(pyb_stdio_uart) = &pyb_uart_repl_obj; + #else + MP_STATE_PORT(pyb_stdio_uart) = NULL; + #endif + MICROPY_BOARD_END_SOFT_RESET(&state); gc_sweep_all(); diff --git a/ports/stm32/make-stmconst.py b/ports/stm32/make-stmconst.py index bf0543716a8e8..49b5c1a17bed4 100644 --- a/ports/stm32/make-stmconst.py +++ b/ports/stm32/make-stmconst.py @@ -71,6 +71,10 @@ class Lexer: ("typedef struct", re.compile(r"typedef struct$")), ("{", re.compile(r"{$")), ("}", re.compile(r"}$")), + ( + "} _t", + re.compile(r"} *([A-Za-z0-9_]+)_t;$"), + ), ( "} TypeDef", re.compile(r"} *(?P[A-Z][A-Za-z0-9_]*)_(?P([A-Za-z0-9_]+)?)TypeDef;$"), @@ -157,7 +161,7 @@ def parse_file(filename): for i in range(int(d["array"])): regs.append((reg + str(i), offset + i * bits // 8, bits, comment)) m = lexer.next_match() - if m[0] == "}": + if m[0] in ("}", "} _t"): pass elif m[0] == "} TypeDef": d = m[1].groupdict() diff --git a/ports/stm32/mboot/Makefile b/ports/stm32/mboot/Makefile index 4e3f7597f7afc..1f6ba063b22e5 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 80e2a710ad01c..afd4a2f1ceb1b 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 aa36026646392..45bf11d42b73d 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 25fc66eb9c681..1869b984dab0a 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 300ca55d5b4d2..8f2a6e530a540 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,7 +584,9 @@ #endif // Whether the USB peripheral is device-only, or multiple OTG -#if defined(STM32G4) || defined(STM32L0) || defined(STM32L432xx) || defined(STM32WB) +// 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(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 727517f5bda4c..8edafa9bfc2fb 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 728f5fefbded9..2757d39841306 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 ff51f382eeec0..106112073e477 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/octospi.c b/ports/stm32/octospi.c new file mode 100644 index 0000000000000..b37ebb2a082da --- /dev/null +++ b/ports/stm32/octospi.c @@ -0,0 +1,343 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// This OCTOSPI driver is currently configured to run in 1-line (SPI) mode. +// It uses the mp_qspi_proto_t QSPI protocol and translates quad-commands +// into 1-line commands. + +#include "py/mperrno.h" +#include "py/mphal.h" +#include "octospi.h" +#include "pin_static_af.h" + +#if defined(MICROPY_HW_OSPIFLASH_SIZE_BITS_LOG2) + +#ifndef MICROPY_HW_OSPI_PRESCALER +#define MICROPY_HW_OSPI_PRESCALER (3) // F_CLK = F_AHB/3 +#endif + +#ifndef MICROPY_HW_OSPI_CS_HIGH_CYCLES +#define MICROPY_HW_OSPI_CS_HIGH_CYCLES (2) // nCS stays high for 2 cycles +#endif + +void octospi_init(void) { + // Configure OCTOSPI pins (allows 1, 2, 4 or 8 line configuration). + mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_CS, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPI1_NCS); + mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_SCK, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPI1_CLK); + mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_IO0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPI1_IO0); + #if defined(MICROPY_HW_OSPIFLASH_IO1) + mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_IO1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPI1_IO1); + #if defined(MICROPY_HW_OSPIFLASH_IO2) + mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_IO2, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPI1_IO2); + mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_IO3, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPI1_IO3); + #if defined(MICROPY_HW_OSPIFLASH_IO4) + mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_IO4, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPI1_IO4); + mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_IO5, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPI1_IO5); + mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_IO6, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPI1_IO6); + mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_IO7, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPI1_IO7); + #endif + #endif + #endif + + // Reset and turn on the OCTOSPI peripheral. + __HAL_RCC_OSPI1_CLK_ENABLE(); + __HAL_RCC_OSPI1_FORCE_RESET(); + __HAL_RCC_OSPI1_RELEASE_RESET(); + + // Configure the OCTOSPI peripheral. + + OCTOSPI1->CR = + 3 << OCTOSPI_CR_FTHRES_Pos // 4 bytes must be available to read/write + | 0 << OCTOSPI_CR_MSEL_Pos // FLASH 0 selected + | 0 << OCTOSPI_CR_DMM_Pos // dual-memory mode disabled + ; + + OCTOSPI1->DCR1 = + (MICROPY_HW_OSPIFLASH_SIZE_BITS_LOG2 - 3 - 1) << OCTOSPI_DCR1_DEVSIZE_Pos + | (MICROPY_HW_OSPI_CS_HIGH_CYCLES - 1) << OCTOSPI_DCR1_CSHT_Pos + | 0 << OCTOSPI_DCR1_CKMODE_Pos // CLK idles at low state + ; + + OCTOSPI1->DCR2 = + (MICROPY_HW_OSPI_PRESCALER - 1) << OCTOSPI_DCR2_PRESCALER_Pos + ; + + OCTOSPI1->DCR3 = 0; + OCTOSPI1->DCR4 = 0; + + // Enable the OCTOSPI peripheral. + OCTOSPI1->CR |= OCTOSPI_CR_EN; +} + +STATIC int octospi_ioctl(void *self_in, uint32_t cmd) { + (void)self_in; + switch (cmd) { + case MP_QSPI_IOCTL_INIT: + octospi_init(); + break; + case MP_QSPI_IOCTL_BUS_ACQUIRE: + // Abort any ongoing transfer if peripheral is busy. + if (OCTOSPI1->SR & OCTOSPI_SR_BUSY) { + OCTOSPI1->CR |= OCTOSPI_CR_ABORT; + while (OCTOSPI1->CR & OCTOSPI_CR_ABORT) { + } + } + break; + case MP_QSPI_IOCTL_BUS_RELEASE: + break; + } + return 0; // success +} + +STATIC int octospi_write_cmd_data(void *self_in, uint8_t cmd, size_t len, uint32_t data) { + (void)self_in; + + OCTOSPI1->FCR = OCTOSPI_FCR_CTCF; // clear TC flag + + OCTOSPI1->CR = (OCTOSPI1->CR & ~OCTOSPI_CR_FMODE_Msk) | 0 << OCTOSPI_CR_FMODE_Pos; // indirect write mode + + if (len == 0) { + OCTOSPI1->CCR = + 0 << OCTOSPI_CCR_DDTR_Pos // DD mode disabled + | 0 << OCTOSPI_CCR_SIOO_Pos // send instruction every transaction + | 0 << OCTOSPI_CCR_DMODE_Pos // no data + | 0 << OCTOSPI_CCR_ABMODE_Pos // no alternate byte + | 0 << OCTOSPI_CCR_ADMODE_Pos // no address + | 1 << OCTOSPI_CCR_IMODE_Pos // instruction on 1 line + ; + OCTOSPI1->TCR = 0 << OCTOSPI_TCR_DCYC_Pos; // 0 dummy cycles + + // This triggers the start of the operation. + OCTOSPI1->IR = cmd << OCTOSPI_IR_INSTRUCTION_Pos; // write opcode + } else { + OCTOSPI1->DLR = len - 1; + OCTOSPI1->CCR = + 0 << OCTOSPI_CCR_DDTR_Pos // DD mode disabled + | 0 << OCTOSPI_CCR_SIOO_Pos // send instruction every transaction + | 1 << OCTOSPI_CCR_DMODE_Pos // data on 1 line + | 0 << OCTOSPI_CCR_ABMODE_Pos // no alternate byte + | 0 << OCTOSPI_CCR_ADMODE_Pos // no address + | 1 << OCTOSPI_CCR_IMODE_Pos // instruction on 1 line + ; + OCTOSPI1->TCR = 0 << OCTOSPI_TCR_DCYC_Pos; // 0 dummy cycles + OCTOSPI1->IR = cmd << OCTOSPI_IR_INSTRUCTION_Pos; // write opcode + + // Wait for at least 1 free byte location in the FIFO. + while (!(OCTOSPI1->SR & OCTOSPI_SR_FTF)) { + } + + // This triggers the start of the operation. + // This assumes len==2 + *(uint16_t *)&OCTOSPI1->DR = data; + } + + // Wait for write to finish + while (!(OCTOSPI1->SR & OCTOSPI_SR_TCF)) { + if (OCTOSPI1->SR & OCTOSPI_SR_TEF) { + return -MP_EIO; + } + } + + OCTOSPI1->FCR = OCTOSPI_FCR_CTCF; // clear TC flag + + return 0; +} + +STATIC int octospi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src) { + (void)self_in; + + uint8_t adsize = MICROPY_HW_SPI_ADDR_IS_32BIT(addr) ? 3 : 2; + + OCTOSPI1->FCR = OCTOSPI_FCR_CTCF; // clear TC flag + + OCTOSPI1->CR = (OCTOSPI1->CR & ~OCTOSPI_CR_FMODE_Msk) | 0 << OCTOSPI_CR_FMODE_Pos; // indirect write mode + + if (len == 0) { + OCTOSPI1->CCR = + 0 << OCTOSPI_CCR_DDTR_Pos // DD mode disabled + | 0 << OCTOSPI_CCR_SIOO_Pos // send instruction every transaction + | 0 << OCTOSPI_CCR_DMODE_Pos // no data + | 0 << OCTOSPI_CCR_ABMODE_Pos // no alternate byte + | adsize << OCTOSPI_CCR_ADSIZE_Pos // 32/24-bit address size + | 1 << OCTOSPI_CCR_ADMODE_Pos // address on 1 line + | 1 << OCTOSPI_CCR_IMODE_Pos // instruction on 1 line + ; + OCTOSPI1->TCR = 0 << OCTOSPI_TCR_DCYC_Pos; // 0 dummy cycles + OCTOSPI1->IR = cmd << OCTOSPI_IR_INSTRUCTION_Pos; // write opcode + + // This triggers the start of the operation. + OCTOSPI1->AR = addr; + } else { + OCTOSPI1->DLR = len - 1; + + OCTOSPI1->CCR = + 0 << OCTOSPI_CCR_DDTR_Pos // DD mode disabled + | 0 << OCTOSPI_CCR_SIOO_Pos // send instruction every transaction + | 1 << OCTOSPI_CCR_DMODE_Pos // data on 1 line + | 0 << OCTOSPI_CCR_ABMODE_Pos // no alternate byte + | adsize << OCTOSPI_CCR_ADSIZE_Pos // 32/24-bit address size + | 1 << OCTOSPI_CCR_ADMODE_Pos // address on 1 line + | 1 << OCTOSPI_CCR_IMODE_Pos // instruction on 1 line + ; + OCTOSPI1->TCR = 0 << OCTOSPI_TCR_DCYC_Pos; // 0 dummy cycles + OCTOSPI1->IR = cmd << OCTOSPI_IR_INSTRUCTION_Pos; // write opcode + OCTOSPI1->AR = addr; + + // Write out the data 1 byte at a time + // This triggers the start of the operation. + while (len) { + while (!(OCTOSPI1->SR & OCTOSPI_SR_FTF)) { + if (OCTOSPI1->SR & OCTOSPI_SR_TEF) { + return -MP_EIO; + } + } + *(volatile uint8_t *)&OCTOSPI1->DR = *src++; + --len; + } + } + + // Wait for write to finish + while (!(OCTOSPI1->SR & OCTOSPI_SR_TCF)) { + if (OCTOSPI1->SR & OCTOSPI_SR_TEF) { + return -MP_EIO; + } + } + + OCTOSPI1->FCR = OCTOSPI_FCR_CTCF; // clear TC flag + + return 0; +} + +STATIC int octospi_read_cmd(void *self_in, uint8_t cmd, size_t len, uint32_t *dest) { + (void)self_in; + + OCTOSPI1->FCR = OCTOSPI_FCR_CTCF; // clear TC flag + + OCTOSPI1->DLR = len - 1; // number of bytes to read + + OCTOSPI1->CR = (OCTOSPI1->CR & ~OCTOSPI_CR_FMODE_Msk) | 1 << OCTOSPI_CR_FMODE_Pos; // indirect read mode + + OCTOSPI1->CCR = + 0 << OCTOSPI_CCR_DDTR_Pos // DD mode disabled + | 0 << OCTOSPI_CCR_SIOO_Pos // send instruction every transaction + | 1 << OCTOSPI_CCR_DMODE_Pos // data on 1 line + | 0 << OCTOSPI_CCR_ABMODE_Pos // no alternate byte + | 0 << OCTOSPI_CCR_ADMODE_Pos // no address + | 1 << OCTOSPI_CCR_IMODE_Pos // instruction on 1 line + ; + + OCTOSPI1->TCR = 0 << OCTOSPI_TCR_DCYC_Pos; // 0 dummy cycles + + // This triggers the start of the operation. + OCTOSPI1->IR = cmd << OCTOSPI_IR_INSTRUCTION_Pos; // read opcode + + // Wait for read to finish + while (!(OCTOSPI1->SR & OCTOSPI_SR_TCF)) { + if (OCTOSPI1->SR & OCTOSPI_SR_TEF) { + return -MP_EIO; + } + } + + OCTOSPI1->FCR = OCTOSPI_FCR_CTCF; // clear TC flag + + // Read result + *dest = OCTOSPI1->DR; + + return 0; +} + +STATIC int octospi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest) { + (void)self_in; + + uint32_t adsize = MICROPY_HW_SPI_ADDR_IS_32BIT(addr) ? 3 : 2; + uint32_t dmode = 1; // data on 1-line + uint32_t admode = 1; // address on 1-line + uint32_t dcyc = 0; // 0 dummy cycles + + if (cmd == 0xeb) { + // Convert to 1-line command. + cmd = MICROPY_HW_SPI_ADDR_IS_32BIT(addr) ? 0x13 : 0x03; + } + + OCTOSPI1->FCR = OCTOSPI_FCR_CTCF; // clear TC flag + + OCTOSPI1->DLR = len - 1; // number of bytes to read + OCTOSPI1->CR = (OCTOSPI1->CR & ~OCTOSPI_CR_FMODE_Msk) | 1 << OCTOSPI_CR_FMODE_Pos; // indirect read mode + OCTOSPI1->CCR = + 0 << OCTOSPI_CCR_DDTR_Pos // DD mode disabled + | 0 << OCTOSPI_CCR_SIOO_Pos // send instruction every transaction + | dmode << OCTOSPI_CCR_DMODE_Pos // data on n lines + | 0 << OCTOSPI_CCR_ABSIZE_Pos // 8-bit alternate byte + | 0 << OCTOSPI_CCR_ABMODE_Pos // no alternate byte + | adsize << OCTOSPI_CCR_ADSIZE_Pos // 32 or 24-bit address size + | admode << OCTOSPI_CCR_ADMODE_Pos // address on n lines + | 1 << OCTOSPI_CCR_IMODE_Pos // instruction on 1 line + ; + OCTOSPI1->TCR = dcyc << OCTOSPI_TCR_DCYC_Pos; // n dummy cycles + OCTOSPI1->IR = cmd << OCTOSPI_IR_INSTRUCTION_Pos; // quad read opcode + + // This triggers the start of the operation. + OCTOSPI1->AR = addr; // address to read from + + // Read in the data 4 bytes at a time if dest is aligned + if (((uintptr_t)dest & 3) == 0) { + while (len >= 4) { + while (!(OCTOSPI1->SR & OCTOSPI_SR_FTF)) { + if (OCTOSPI1->SR & OCTOSPI_SR_TEF) { + return -MP_EIO; + } + } + *(uint32_t *)dest = OCTOSPI1->DR; + dest += 4; + len -= 4; + } + } + + // Read in remaining data 1 byte at a time + while (len) { + while (!((OCTOSPI1->SR >> OCTOSPI_SR_FLEVEL_Pos) & 0x3f)) { + if (OCTOSPI1->SR & OCTOSPI_SR_TEF) { + return -MP_EIO; + } + } + *dest++ = *(volatile uint8_t *)&OCTOSPI1->DR; + --len; + } + + OCTOSPI1->FCR = OCTOSPI_FCR_CTCF; // clear TC flag + + return 0; +} + +const mp_qspi_proto_t octospi_proto = { + .ioctl = octospi_ioctl, + .write_cmd_data = octospi_write_cmd_data, + .write_cmd_addr_data = octospi_write_cmd_addr_data, + .read_cmd = octospi_read_cmd, + .read_cmd_qaddr_qdata = octospi_read_cmd_qaddr_qdata, +}; + +#endif // defined(MICROPY_HW_OSPIFLASH_SIZE_BITS_LOG2) diff --git a/ports/stm32/octospi.h b/ports/stm32/octospi.h new file mode 100644 index 0000000000000..3ef4b8206fa2a --- /dev/null +++ b/ports/stm32/octospi.h @@ -0,0 +1,33 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_STM32_OCTOSPI_H +#define MICROPY_INCLUDED_STM32_OCTOSPI_H + +#include "drivers/bus/qspi.h" + +extern const mp_qspi_proto_t octospi_proto; + +#endif // MICROPY_INCLUDED_STM32_OCTOSPI_H diff --git a/ports/stm32/powerctrl.c b/ports/stm32/powerctrl.c index d5fa9095d8c66..80195f04aeb38 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 @@ int powerctrl_set_sysclk(uint32_t sysclk, uint32_t ahb, uint32_t apb1, uint32_t // Determine the bus clock dividers // Note: AHB freq required to be >= 14.2MHz for USB operation RCC_ClkInitStruct.AHBCLKDivider = calc_ahb_div(sysclk / ahb); - #if !defined(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 e970b81a9fcc3..149c34ae63ec4 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 5d6ddf6d62c9a..236d79ea87952 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 92f64626a3ecb..3b05fb40ebfff 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 e61c837692b2c..11a9a74ea3bac 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 ae267a599596b..b9f70db73e0a1 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 78e7f15190eb6..84c05602b57b7 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 6c110f87ea6ea..b4fa1d6cf9b7e 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 6d1240cf8d5aa..e477c5c16ca14 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 c9c29cc50c1b5..94d62f7625a57 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 399411d8abbb8..f25dcc380a6ee 100644 --- a/ports/stm32/usbd_cdc_interface.c +++ b/ports/stm32/usbd_cdc_interface.c @@ -52,9 +52,9 @@ #if !MICROPY_HW_USB_IS_MULTI_OTG #define USE_USB_CNTR_SOFM (1) -#elif defined(STM32G0) -#define USE_USB_CNTR_SOFM (1) +#if defined(STM32G0) || defined(STM32H5) #define USB USB_DRD_FS +#endif #else #define USE_USB_CNTR_SOFM (0) #endif diff --git a/ports/stm32/usbd_conf.c b/ports/stm32/usbd_conf.c index 371558d77517d..9f187fc08b57a 100644 --- a/ports/stm32/usbd_conf.c +++ b/ports/stm32/usbd_conf.c @@ -44,15 +44,13 @@ PCD_HandleTypeDef pcd_fs_handle; PCD_HandleTypeDef pcd_hs_handle; #endif -#if !MICROPY_HW_USB_IS_MULTI_OTG +#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 #define USB_OTG_FS USB #endif -#if defined(STM32G0) -#define USB_OTG_FS USB_DRD_FS -#endif - /******************************************************************************* PCD BSP Routines *******************************************************************************/ @@ -87,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; @@ -110,23 +108,25 @@ 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 // Enable USB FS Clocks - #if !MICROPY_HW_USB_IS_MULTI_OTG || defined(STM32G0) + #if !MICROPY_HW_USB_IS_MULTI_OTG __HAL_RCC_USB_CLK_ENABLE(); #else __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(); @@ -140,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); @@ -262,11 +265,7 @@ void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd) { #if MICROPY_HW_USB_FS if (hpcd->Instance == USB_OTG_FS) { /* Disable USB FS Clocks */ - #if defined(STM32G0) - __HAL_RCC_USB_CLK_DISABLE(); - #else __USB_OTG_FS_CLK_DISABLE(); - #endif return; } #endif @@ -443,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 - #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; @@ -454,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; @@ -463,7 +466,7 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed, const HAL_PCD_Init(&pcd_fs_handle); // Set FIFO buffer sizes - #if !MICROPY_HW_USB_IS_MULTI_OTG || defined(STM32G0) + #if !MICROPY_HW_USB_IS_MULTI_OTG uint32_t fifo_offset = USBD_PMA_RESERVE; // need to reserve some data at start of FIFO for (size_t i = 0; i < USBD_PMA_NUM_FIFO; ++i) { uint16_t ep_addr = ((i & 1) * 0x80) | (i >> 1); diff --git a/py/mkrules.mk b/py/mkrules.mk index db81faa7ff2f6..a3ff85ef821b3 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -52,7 +52,7 @@ $(BUILD)/%.o: %.S vpath %.s . $(TOP) $(USER_C_MODULES) $(BUILD)/%.o: %.s $(ECHO) "AS $<" - $(Q)$(AS) -o $@ $< + $(Q)$(AS) $(AFLAGS) -o $@ $< define compile_c $(ECHO) "CC $<" diff --git a/tools/ci.sh b/tools/ci.sh index eac0d52ffccf2..986fe8f074de8 100755 --- a/tools/ci.sh +++ b/tools/ci.sh @@ -358,6 +358,7 @@ function ci_stm32_nucleo_build { # Test building various MCU families, some with additional options. make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_F091RC + make ${MAKEOPTS} -C ports/stm32 BOARD=STM32H573I_DK make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_H743ZI COPT=-O2 CFLAGS_EXTRA='-DMICROPY_PY_THREAD=1' make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_L073RZ make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_L476RG DEBUG=1 pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy