From 010012c7c3af76ca47cf28eb156e0fe5ac3d87a5 Mon Sep 17 00:00:00 2001 From: Asensio Lorenzo Sempere Date: Sat, 12 Feb 2022 14:36:58 -0600 Subject: [PATCH] stm32: Add support for G0 MCUs. This commit adds support for the STM32G0 series of MCUs. Signed-off-by: Asensio Lorenzo Sempere --- ports/stm32/Makefile | 24 ++-- ports/stm32/adc.c | 34 ++++-- ports/stm32/adc.h | 2 +- ports/stm32/boards/stm32g0xx_hal_conf_base.h | 106 +++++++++++++++++ ports/stm32/dac.c | 6 +- ports/stm32/dma.c | 115 +++++++++++++++++-- ports/stm32/dma.h | 2 +- ports/stm32/extint.c | 41 +++++-- ports/stm32/extint.h | 3 + ports/stm32/flash.c | 24 +++- ports/stm32/machine_adc.c | 18 +-- ports/stm32/machine_uart.c | 24 +++- ports/stm32/modmachine.c | 12 +- ports/stm32/mpconfigboard_common.h | 12 +- ports/stm32/mphalport.c | 3 + ports/stm32/mphalport.h | 4 +- ports/stm32/powerctrl.c | 27 +++-- ports/stm32/powerctrlboot.c | 71 ++++++++++++ ports/stm32/pyb_i2c.c | 12 +- ports/stm32/rtc.c | 18 ++- ports/stm32/spi.c | 18 ++- ports/stm32/stm32.mk | 3 +- ports/stm32/stm32_it.c | 113 +++++++++++++++++- ports/stm32/timer.c | 34 ++++-- ports/stm32/uart.c | 98 +++++++++++++--- ports/stm32/uart.h | 5 +- 26 files changed, 719 insertions(+), 110 deletions(-) create mode 100644 ports/stm32/boards/stm32g0xx_hal_conf_base.h diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 34d586674..10e4e15d9 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -324,14 +324,12 @@ SRC_CXX += \ SRC_O += \ $(STARTUP_FILE) \ $(SYSTEM_FILE) - -ifeq ($(MCU_SERIES),f0) -SRC_O += \ - resethandler_m0.o \ - shared/runtime/gchelper_m0.o -else + ifeq ($(MCU_SERIES),l0) CSUPEROPT = -Os # save some code space +endif + +ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 g0 l0)) SRC_O += \ resethandler_m0.o \ shared/runtime/gchelper_m0.o @@ -341,7 +339,6 @@ SRC_O += \ resethandler.o \ shared/runtime/gchelper_m3.o endif -endif HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_,\ hal.c \ @@ -366,7 +363,7 @@ HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_,\ ll_utils.c \ ) -ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 g4 h7 l0 l4 wb)) +ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 g0 g4 h7 l0 l4 wb)) HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_,\ hal_pcd.c \ hal_pcd_ex.c \ @@ -386,7 +383,6 @@ ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 h7)) HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_,\ hal_mmc.c \ hal_sdram.c \ - hal_dma_ex.c \ hal_dcmi.c \ ) ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4)) @@ -396,7 +392,13 @@ $(BUILD)/$(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_hal_mmc.o: CFLAGS += -Wno endif endif -ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),g4)) +ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 g0 g4 h7)) +HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_,\ + hal_dma_ex.c \ + ) +endif + +ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),g0 g4)) HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_, hal_fdcan.c) endif @@ -413,7 +415,7 @@ endif endif endif -ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 f4 f7 l0)) +ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 f4 f7 g0 l0)) HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_,\ hal_i2s.c \ ) diff --git a/ports/stm32/adc.c b/ports/stm32/adc.c index c5ca6306e..3b5a8b364 100644 --- a/ports/stm32/adc.c +++ b/ports/stm32/adc.c @@ -102,13 +102,13 @@ #define ADC_CAL2 ((uint16_t *)(ADC_CAL_ADDRESS + 4)) #define ADC_CAL_BITS (12) -#elif defined(STM32G4) +#elif defined(STM32G0) || defined(STM32G4) #define ADC_SCALE_V (((float)VREFINT_CAL_VREF) / 1000.0f) #define ADC_CAL_ADDRESS VREFINT_CAL_ADDR #define ADC_CAL1 TEMPSENSOR_CAL1_ADDR #define ADC_CAL2 TEMPSENSOR_CAL2_ADDR -#define ADC_CAL_BITS (12) // UM2570, __HAL_ADC_CALC_TEMPERATURE: 'corresponds to a resolution of 12 bits' +#define ADC_CAL_BITS (12) // UM2319/UM2570, __HAL_ADC_CALC_TEMPERATURE: 'corresponds to a resolution of 12 bits' #elif defined(STM32H7) @@ -150,7 +150,7 @@ defined(STM32F746xx) || defined(STM32F765xx) || \ defined(STM32F767xx) || defined(STM32F769xx) #define VBAT_DIV (4) -#elif defined(STM32G4) +#elif defined(STM32G0) || defined(STM32G4) #define VBAT_DIV (3) #elif defined(STM32H743xx) || defined(STM32H747xx) || \ defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || \ @@ -210,7 +210,7 @@ STATIC bool is_adcx_channel(int channel) { return IS_ADC_CHANNEL(channel) || channel == ADC_CHANNEL_TEMPSENSOR; #elif defined(STM32F0) || defined(STM32F4) || defined(STM32F7) return IS_ADC_CHANNEL(channel); - #elif defined(STM32H7) + #elif defined(STM32G0) || defined(STM32H7) return __HAL_ADC_IS_CHANNEL_INTERNAL(channel) || IS_ADC_CHANNEL(__HAL_ADC_DECIMAL_NB_TO_CHANNEL(channel)); #elif defined(STM32G4) || defined(STM32L4) || defined(STM32WB) @@ -227,7 +227,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) while ((adcHandle->Instance->SR & ADC_FLAG_EOC) != ADC_FLAG_EOC) { - #elif defined(STM32F0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) + #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) while (READ_BIT(adcHandle->Instance->ISR, ADC_FLAG_EOC) != ADC_FLAG_EOC) { #else #error Unsupported processor @@ -244,6 +244,8 @@ STATIC void adcx_clock_enable(ADC_HandleTypeDef *adch) { #elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ) __HAL_RCC_ADC12_CLK_ENABLE(); __HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_CLKP); + #elif defined(STM32G0) + __HAL_RCC_ADC_CLK_ENABLE(); #elif defined(STM32G4) __HAL_RCC_ADC12_CLK_ENABLE(); #elif defined(STM32H7) @@ -269,8 +271,10 @@ STATIC void adcx_init_periph(ADC_HandleTypeDef *adch, uint32_t resolution) { adch->Init.Resolution = resolution; adch->Init.ContinuousConvMode = DISABLE; adch->Init.DiscontinuousConvMode = DISABLE; - #if !defined(STM32F0) + #if !defined(STM32F0) && !defined(STM32G0) adch->Init.NbrOfDiscConversion = 0; + #endif + #if !defined(STM32F0) adch->Init.NbrOfConversion = 1; #endif adch->Init.EOCSelection = ADC_EOC_SINGLE_CONV; @@ -295,7 +299,7 @@ STATIC void adcx_init_periph(ADC_HandleTypeDef *adch, uint32_t resolution) { adch->Init.OversamplingMode = DISABLE; adch->Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE; adch->Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR; - #elif defined(STM32G4) || defined(STM32L4) || defined(STM32WB) + #elif defined(STM32G0) || defined(STM32G4) || defined(STM32L4) || defined(STM32WB) adch->Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1; adch->Init.ScanConvMode = ADC_SCAN_DISABLE; adch->Init.LowPowerAutoWait = DISABLE; @@ -312,7 +316,9 @@ STATIC void adcx_init_periph(ADC_HandleTypeDef *adch, uint32_t resolution) { #if defined(STM32H7) HAL_ADCEx_Calibration_Start(adch, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED); #endif - #if defined(STM32G4) || defined(STM32L4) || defined(STM32WB) + #if defined(STM32G0) + HAL_ADCEx_Calibration_Start(adch); + #elif defined(STM32G4) || defined(STM32L4) || defined(STM32WB) HAL_ADCEx_Calibration_Start(adch, ADC_SINGLE_ENDED); #endif } @@ -333,7 +339,7 @@ STATIC void adc_init_single(pyb_obj_adc_t *adc_obj) { STATIC void adc_config_channel(ADC_HandleTypeDef *adc_handle, uint32_t channel) { ADC_ChannelConfTypeDef sConfig; - #if defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) sConfig.Rank = ADC_REGULAR_RANK_1; if (__HAL_ADC_IS_CHANNEL_INTERNAL(channel) == 0) { channel = __HAL_ADC_DECIMAL_NB_TO_CHANNEL(channel); @@ -361,6 +367,12 @@ STATIC void adc_config_channel(ADC_HandleTypeDef *adc_handle, uint32_t channel) sConfig.OffsetNumber = ADC_OFFSET_NONE; sConfig.OffsetRightShift = DISABLE; sConfig.OffsetSignedSaturation = DISABLE; + #elif defined(STM32G0) + if (__HAL_ADC_IS_CHANNEL_INTERNAL(channel)) { + sConfig.SamplingTime = ADC_SAMPLETIME_160CYCLES_5; + } else { + sConfig.SamplingTime = ADC_SAMPLETIME_12CYCLES_5; + } #elif defined(STM32G4) || defined(STM32L4) || defined(STM32WB) if (__HAL_ADC_IS_CHANNEL_INTERNAL(channel)) { sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5; @@ -545,7 +557,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) self->handle.Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART; - #elif defined(STM32F0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) + #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) SET_BIT(self->handle.Instance->CR, ADC_CR_ADSTART); #else #error Unsupported processor @@ -655,7 +667,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) adc->handle.Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART; - #elif defined(STM32F0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) + #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || 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 3b79dc01f..c61bad459 100644 --- a/ports/stm32/adc.h +++ b/ports/stm32/adc.h @@ -42,7 +42,7 @@ static inline void adc_deselect_vbat(ADC_TypeDef *adc, uint32_t channel) { if (channel == ADC_CHANNEL_VBAT) { ADC_Common_TypeDef *adc_common; - #if defined(STM32F0) || defined(STM32WB) + #if defined(STM32F0) || defined(STM32G0) || defined(STM32WB) adc_common = ADC1_COMMON; #elif defined(STM32F4) adc_common = ADC_COMMON_REGISTER(0); diff --git a/ports/stm32/boards/stm32g0xx_hal_conf_base.h b/ports/stm32/boards/stm32g0xx_hal_conf_base.h new file mode 100644 index 000000000..fc49ca945 --- /dev/null +++ b/ports/stm32/boards/stm32g0xx_hal_conf_base.h @@ -0,0 +1,106 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 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_STM32G0XX_HAL_CONF_BASE_H +#define MICROPY_INCLUDED_STM32G0XX_HAL_CONF_BASE_H + +// Oscillator values in Hz +// These must come before the HAL headers because stm32g0xx_ll_rcc.h will define HSI_VALUE unless already defined +#define HSI_VALUE (16000000) +#define LSI_VALUE (32000) +#if defined(STM32G0C1xx) || defined(STM32G0B1xx) || defined(STM32G0B0xx) +#define HSI48_VALUE 48000000 +#endif + +// Include various HAL modules for convenience + +#include "stm32g0xx_hal_rcc.h" +#include "stm32g0xx_hal_gpio.h" +#include "stm32g0xx_hal_dma.h" +#include "stm32g0xx_hal_cortex.h" +#include "stm32g0xx_hal_adc.h" +#include "stm32g0xx_hal_adc_ex.h" +#include "stm32g0xx_hal_cec.h" +#include "stm32g0xx_hal_comp.h" +#include "stm32g0xx_hal_crc.h" +#include "stm32g0xx_hal_cryp.h" +#include "stm32g0xx_hal_dac.h" +#include "stm32g0xx_hal_exti.h" +#include "stm32g0xx_hal_fdcan.h" +#include "stm32g0xx_hal_flash.h" +#include "stm32g0xx_hal_i2c.h" +#include "stm32g0xx_hal_i2s.h" +#include "stm32g0xx_hal_irda.h" +#include "stm32g0xx_hal_iwdg.h" +#include "stm32g0xx_hal_lptim.h" +#include "stm32g0xx_hal_pcd.h" +#include "stm32g0xx_hal_hcd.h" +#include "stm32g0xx_hal_pwr.h" +#include "stm32g0xx_hal_rng.h" +#include "stm32g0xx_hal_rtc.h" +#include "stm32g0xx_hal_smartcard.h" +#include "stm32g0xx_hal_smbus.h" +#include "stm32g0xx_hal_spi.h" +#include "stm32g0xx_hal_tim.h" +#include "stm32g0xx_hal_uart.h" +#include "stm32g0xx_hal_usart.h" +#include "stm32g0xx_hal_wwdg.h" + +#include "stm32g0xx_ll_lpuart.h" +#include "stm32g0xx_ll_rtc.h" +#include "stm32g0xx_ll_usart.h" + +// Enable various HAL modules +#define HAL_MODULE_ENABLED +#define HAL_ADC_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_EXTI_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_RTC_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_TIM_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +#define HAL_USART_MODULE_ENABLED + +// SysTick has the highest priority +#define TICK_INT_PRIORITY (0x00) + +// Miscellaneous HAL settings +#define USE_RTOS 0 +#define PREFETCH_ENABLE 1 +#define INSTRUCTION_CACHE_ENABLE 1 +#define USE_SPI_CRC 1 +#define USE_HAL_CRYP_SUSPEND_RESUME 1 + +// HAL parameter assertions are disabled +#define assert_param(expr) ((void)0) + +#endif // MICROPY_INCLUDED_STM32G0XX_HAL_CONF_BASE_H diff --git a/ports/stm32/dac.c b/ports/stm32/dac.c index b7fb0cbd7..c41bf858a 100644 --- a/ports/stm32/dac.c +++ b/ports/stm32/dac.c @@ -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(STM32G4) || defined(STM32H7) || defined(STM32L4) + #if defined(STM32G0) || defined(STM32G4) || 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(STM32G4) || defined(STM32H7) || defined(STM32L4) + #if defined(STM32G0) || defined(STM32G4) || 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(STM32G4) || defined(STM32L4) + #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32L4) __HAL_RCC_DAC1_CLK_ENABLE(); #else #error Unsupported Processor diff --git a/ports/stm32/dma.c b/ports/stm32/dma.c index cb8e555df..2dc6e8e8b 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(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) DMA_Channel_TypeDef *instance; #else #error "Unsupported Processor" @@ -95,7 +95,7 @@ struct _dma_descr_t { static const DMA_InitTypeDef dma_init_struct_spi_i2c = { #if defined(STM32F4) || defined(STM32F7) .Channel = 0, - #elif defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #elif defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) .Request = 0, #endif .Direction = 0, @@ -119,7 +119,7 @@ static const DMA_InitTypeDef dma_init_struct_spi_i2c = { static const DMA_InitTypeDef dma_init_struct_i2s = { #if defined(STM32F4) || defined(STM32F7) .Channel = 0, - #elif defined(STM32H7) || defined(STM32L0) || defined(STM32L4) + #elif defined(STM32G0) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) .Request = 0, #endif .Direction = DMA_MEMORY_TO_PERIPH, @@ -143,7 +143,7 @@ static const DMA_InitTypeDef dma_init_struct_i2s = { static const DMA_InitTypeDef dma_init_struct_sdio = { #if defined(STM32F4) || defined(STM32F7) .Channel = 0, - #elif defined(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) + #elif defined(STM32G0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) .Request = 0, #endif .Direction = 0, @@ -153,7 +153,7 @@ static const DMA_InitTypeDef dma_init_struct_sdio = { .MemDataAlignment = DMA_MDATAALIGN_WORD, #if defined(STM32F4) || defined(STM32F7) .Mode = DMA_PFCTRL, - #elif defined(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) + #elif defined(STM32G0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) .Mode = DMA_NORMAL, #endif .Priority = DMA_PRIORITY_VERY_HIGH, @@ -171,7 +171,7 @@ static const DMA_InitTypeDef dma_init_struct_sdio = { static const DMA_InitTypeDef dma_init_struct_dac = { #if defined(STM32F4) || defined(STM32F7) .Channel = 0, - #elif defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) + #elif defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) .Request = 0, #endif .Direction = 0, @@ -507,6 +507,46 @@ static const uint8_t dma_irqn[NSTREAM] = { DMA2_Channel7_IRQn, }; +#elif defined(STM32G0) + +#define NCONTROLLERS (2) +#define NSTREAMS_PER_CONTROLLER (7) +#define NSTREAM (NCONTROLLERS * NSTREAMS_PER_CONTROLLER) + +#define DMA_SUB_INSTANCE_AS_UINT8(dma_request) (dma_request) + +#define DMA1_ENABLE_MASK (0x007f) // Bits in dma_enable_mask corresponding to DMA1 (7 channels) +#define DMA2_ENABLE_MASK (0x0f80) // Bits in dma_enable_mask corresponding to DMA2 (only 5 channels) + +// DMA1 streams +#if MICROPY_HW_ENABLE_DAC +const dma_descr_t dma_DAC_1_TX = { DMA1_Channel3, DMA_REQUEST_DAC1_CH1, dma_id_2, &dma_init_struct_dac }; +const dma_descr_t dma_DAC_2_TX = { DMA1_Channel4, DMA_REQUEST_DAC1_CH2, dma_id_3, &dma_init_struct_dac }; +#endif +const dma_descr_t dma_SPI_3_TX = { DMA1_Channel7, DMA_REQUEST_SPI3_TX, dma_id_6, &dma_init_struct_spi_i2c}; +const dma_descr_t dma_SPI_3_RX = { DMA2_Channel1, DMA_REQUEST_SPI3_RX, dma_id_7, &dma_init_struct_spi_i2c}; +const dma_descr_t dma_SPI_2_TX = { DMA1_Channel5, DMA_REQUEST_SPI2_TX, dma_id_4, &dma_init_struct_spi_i2c}; +const dma_descr_t dma_SPI_2_RX = { DMA1_Channel6, DMA_REQUEST_SPI2_RX, dma_id_5, &dma_init_struct_spi_i2c}; +const dma_descr_t dma_SPI_1_RX = { DMA2_Channel3, DMA_REQUEST_SPI1_RX, dma_id_9, &dma_init_struct_spi_i2c}; +const dma_descr_t dma_SPI_1_TX = { DMA2_Channel4, DMA_REQUEST_SPI1_TX, dma_id_10, &dma_init_struct_spi_i2c}; + +static const uint8_t dma_irqn[NSTREAM] = { + DMA1_Channel1_IRQn, + DMA1_Channel2_3_IRQn, + DMA1_Channel2_3_IRQn, + DMA1_Ch4_7_DMA2_Ch1_5_DMAMUX1_OVR_IRQn, + DMA1_Ch4_7_DMA2_Ch1_5_DMAMUX1_OVR_IRQn, + DMA1_Ch4_7_DMA2_Ch1_5_DMAMUX1_OVR_IRQn, + DMA1_Ch4_7_DMA2_Ch1_5_DMAMUX1_OVR_IRQn, + DMA1_Ch4_7_DMA2_Ch1_5_DMAMUX1_OVR_IRQn, + DMA1_Ch4_7_DMA2_Ch1_5_DMAMUX1_OVR_IRQn, + DMA1_Ch4_7_DMA2_Ch1_5_DMAMUX1_OVR_IRQn, + DMA1_Ch4_7_DMA2_Ch1_5_DMAMUX1_OVR_IRQn, + DMA1_Ch4_7_DMA2_Ch1_5_DMAMUX1_OVR_IRQn, + 0, + 0, +}; + #elif defined(STM32G4) #define NCONTROLLERS (2) @@ -665,7 +705,7 @@ volatile dma_idle_count_t dma_idle; #define DMA_INVALID_CHANNEL 0xff // Value stored in dma_last_channel which means invalid -#if defined(STM32F0) || defined(STM32L0) +#if defined(STM32F0) || defined(STM32G0) || defined(STM32L0) #define DMA1_IS_CLK_ENABLED() ((RCC->AHBENR & RCC_AHBENR_DMA1EN) != 0) #if defined(DMA2) #define DMA2_IS_CLK_ENABLED() ((RCC->AHBENR & RCC_AHBENR_DMA2EN) != 0) @@ -830,6 +870,59 @@ void DMA2_Stream7_IRQHandler(void) { IRQ_EXIT(DMA2_Stream7_IRQn); } +#elif defined(STM32G0) + +void DMA1_Channel1_IRQHandler(void) { + IRQ_ENTER(DMA1_Channel1_IRQn); + if (dma_handle[dma_id_0] != NULL) { + HAL_DMA_IRQHandler(dma_handle[dma_id_0]); + } + IRQ_EXIT(DMA1_Channel1_IRQn); +} + +void DMA1_Channel2_3_IRQHandler(void) { + IRQ_ENTER(DMA1_Channel2_3_IRQn); + if (dma_handle[dma_id_1] != NULL) { + HAL_DMA_IRQHandler(dma_handle[dma_id_1]); + } + if (dma_handle[dma_id_2] != NULL) { + HAL_DMA_IRQHandler(dma_handle[dma_id_2]); + } + IRQ_EXIT(DMA1_Channel2_3_IRQn); +} + +void DMA1_Ch4_7_DMA2_Ch1_5_DMAMUX1_OVR_IRQHandler(void) { + IRQ_ENTER(DMA1_Ch4_7_DMA2_Ch1_5_DMAMUX1_OVR_IRQn); + if (dma_handle[dma_id_3] != NULL) { + HAL_DMA_IRQHandler(dma_handle[dma_id_3]); + } + if (dma_handle[dma_id_4] != NULL) { + HAL_DMA_IRQHandler(dma_handle[dma_id_4]); + } + if (dma_handle[dma_id_5] != NULL) { + HAL_DMA_IRQHandler(dma_handle[dma_id_5]); + } + if (dma_handle[dma_id_6] != NULL) { + HAL_DMA_IRQHandler(dma_handle[dma_id_6]); + } + if (dma_handle[dma_id_7] != NULL) { + HAL_DMA_IRQHandler(dma_handle[dma_id_7]); + } + if (dma_handle[dma_id_8] != NULL) { + HAL_DMA_IRQHandler(dma_handle[dma_id_8]); + } + if (dma_handle[dma_id_9] != NULL) { + HAL_DMA_IRQHandler(dma_handle[dma_id_9]); + } + if (dma_handle[dma_id_10] != NULL) { + HAL_DMA_IRQHandler(dma_handle[dma_id_10]); + } + if (dma_handle[dma_id_11] != NULL) { + HAL_DMA_IRQHandler(dma_handle[dma_id_11]); + } + IRQ_EXIT(DMA1_Ch4_7_DMA2_Ch1_5_DMAMUX1_OVR_IRQn); +} + #elif defined(STM32G4) void DMA1_Channel1_IRQHandler(void) { @@ -1164,7 +1257,7 @@ void dma_init_handle(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint3 dma->Instance = dma_descr->instance; dma->Init = *dma_descr->init; dma->Init.Direction = dir; - #if defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) dma->Init.Request = dma_descr->sub_instance; #else #if !defined(STM32F0) @@ -1191,8 +1284,8 @@ void dma_init(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint32_t dir dma_enable_clock(dma_id); - #if defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) - // Always reset and configure the H7 and L0/L4 DMA peripheral + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || 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); @@ -1367,7 +1460,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(STM32WB) || defined(STM32WL) +#elif defined(STM32G0) || 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 9b0b4c77a..70c7e6a00 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(STM32H7) +#if defined(STM32F0) || defined(STM32F4) || defined(STM32F7) || defined(STM32G0) || 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 55c9095f1..2fc68e195 100644 --- a/ports/stm32/extint.c +++ b/ports/stm32/extint.c @@ -91,7 +91,7 @@ #define EXTI_SWIER_BB(line) (*(__IO uint32_t *)(PERIPH_BB_BASE + ((EXTI_OFFSET + offsetof(EXTI_TypeDef, SWIER)) * 32) + ((line) * 4))) #endif -#if defined(STM32G4) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) +#if defined(STM32G0) || defined(STM32G4) || 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. @@ -143,7 +143,7 @@ STATIC mp_obj_t pyb_extint_callback_arg[EXTI_NUM_VECTORS]; #endif STATIC const uint8_t nvic_irq_channel[EXTI_NUM_VECTORS] = { - #if defined(STM32F0) || defined(STM32L0) + #if defined(STM32F0) || defined(STM32L0) || defined(STM32G0) EXTI0_1_IRQn, EXTI0_1_IRQn, EXTI2_3_IRQn, EXTI2_3_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, @@ -154,12 +154,20 @@ STATIC const uint8_t nvic_irq_channel[EXTI_NUM_VECTORS] = { #else PVD_VDDIO2_IRQn, #endif + #if defined(STM32G0) + ADC1_COMP_IRQn, + ADC1_COMP_IRQn, + RTC_TAMP_IRQn, + 0, // COMP3 + RTC_TAMP_IRQn,// 21 + #else RTC_IRQn, 0, // internal USB wakeup event RTC_IRQn, RTC_IRQn, ADC1_COMP_IRQn, ADC1_COMP_IRQn, + #endif #else @@ -317,9 +325,15 @@ void extint_register_pin(const pin_obj_t *pin, uint32_t mode, bool hard_irq, mp_ #if !defined(STM32WB) && !defined(STM32WL) __HAL_RCC_SYSCFG_CLK_ENABLE(); #endif + #if defined(STM32G0) + EXTI->EXTICR[line >> 2] = + (EXTI->EXTICR[line >> 2] & ~(0x0f << (4 * (line & 0x03)))) + | ((uint32_t)(GPIO_GET_INDEX(pin->gpio)) << (4 * (line & 0x03))); + #else SYSCFG->EXTICR[line >> 2] = (SYSCFG->EXTICR[line >> 2] & ~(0x0f << (4 * (line & 0x03)))) | ((uint32_t)(GPIO_GET_INDEX(pin->gpio)) << (4 * (line & 0x03))); + #endif extint_trigger_mode(line, mode); @@ -354,9 +368,15 @@ void extint_set(const pin_obj_t *pin, uint32_t mode) { #if !defined(STM32WB) && !defined(STM32WL) __HAL_RCC_SYSCFG_CLK_ENABLE(); #endif + #if defined(STM32G0) + EXTI->EXTICR[line >> 2] = + (EXTI->EXTICR[line >> 2] & ~(0x0f << (4 * (line & 0x03)))) + | ((uint32_t)(GPIO_GET_INDEX(pin->gpio)) << (4 * (line & 0x03))); + #else SYSCFG->EXTICR[line >> 2] = (SYSCFG->EXTICR[line >> 2] & ~(0x0f << (4 * (line & 0x03)))) | ((uint32_t)(GPIO_GET_INDEX(pin->gpio)) << (4 * (line & 0x03))); + #endif // Enable or disable the rising detector if ((mode & GPIO_MODE_IT_RISING) == GPIO_MODE_IT_RISING) { @@ -391,7 +411,7 @@ void extint_enable(uint line) { if (pyb_extint_mode[line] == EXTI_Mode_Interrupt) { #if defined(STM32H7) EXTI_D1->IMR1 |= (1 << line); - #elif defined(STM32G4) || defined(STM32WB) || defined(STM32WL) + #elif defined(STM32G0) || defined(STM32G4) || defined(STM32WB) || defined(STM32WL) EXTI->IMR1 |= (1 << line); #else EXTI->IMR |= (1 << line); @@ -399,7 +419,7 @@ void extint_enable(uint line) { } else { #if defined(STM32H7) EXTI_D1->EMR1 |= (1 << line); - #elif defined(STM32G4) || defined(STM32WB) || defined(STM32WL) + #elif defined(STM32G0) || defined(STM32G4) || defined(STM32WB) || defined(STM32WL) EXTI->EMR1 |= (1 << line); #else EXTI->EMR |= (1 << line); @@ -425,7 +445,7 @@ void extint_disable(uint line) { #if defined(STM32H7) EXTI_D1->IMR1 &= ~(1 << line); EXTI_D1->EMR1 &= ~(1 << line); - #elif defined(STM32G4) || defined(STM32WB) || defined(STM32WL) + #elif defined(STM32G0) || defined(STM32G4) || defined(STM32WB) || defined(STM32WL) EXTI->IMR1 &= ~(1 << line); EXTI->EMR1 &= ~(1 << line); #else @@ -447,7 +467,7 @@ void extint_swint(uint line) { return; } // we need 0 to 1 transition to trigger the interrupt - #if defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) EXTI->SWIER1 &= ~(1 << line); EXTI->SWIER1 |= (1 << line); #else @@ -525,7 +545,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_swint_obj, extint_obj_swint); /// \classmethod regs() /// Dump the values of the EXTI registers. STATIC mp_obj_t extint_regs(void) { - #if defined(STM32G4) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) printf("EXTI_IMR1 %08x\n", (unsigned int)EXTI->IMR1); printf("EXTI_IMR2 %08x\n", (unsigned int)EXTI->IMR2); printf("EXTI_EMR1 %08x\n", (unsigned int)EXTI->EMR1); @@ -536,8 +556,15 @@ STATIC mp_obj_t extint_regs(void) { printf("EXTI_FTSR2 %08x\n", (unsigned int)EXTI->FTSR2); printf("EXTI_SWIER1 %08x\n", (unsigned int)EXTI->SWIER1); printf("EXTI_SWIER2 %08x\n", (unsigned int)EXTI->SWIER2); + #if defined(STM32G0) + printf("EXTI_RPR1 %08x\n", (unsigned int)EXTI->RPR1); + printf("EXTI_FPR1 %08x\n", (unsigned int)EXTI->FPR1); + printf("EXTI_RPR2 %08x\n", (unsigned int)EXTI->RPR2); + printf("EXTI_FPR2 %08x\n", (unsigned int)EXTI->FPR2); + #else printf("EXTI_PR1 %08x\n", (unsigned int)EXTI->PR1); printf("EXTI_PR2 %08x\n", (unsigned int)EXTI->PR2); + #endif #elif defined(STM32H7) printf("EXTI_IMR1 %08x\n", (unsigned int)EXTI_D1->IMR1); printf("EXTI_IMR2 %08x\n", (unsigned int)EXTI_D1->IMR2); diff --git a/ports/stm32/extint.h b/ports/stm32/extint.h index 247852fa1..95e29c97f 100644 --- a/ports/stm32/extint.h +++ b/ports/stm32/extint.h @@ -49,6 +49,9 @@ #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) #else #define EXTI_RTC_TIMESTAMP (21) #define EXTI_RTC_WAKEUP (22) diff --git a/ports/stm32/flash.c b/ports/stm32/flash.c index 0c4d2cf5b..2644e0f58 100644 --- a/ports/stm32/flash.c +++ b/ports/stm32/flash.c @@ -29,6 +29,20 @@ #include "py/mphal.h" #include "flash.h" +#if defined(STM32G0) +// These are not defined on the CMSIS header +#define FLASH_FLAG_SR_ERRORS (FLASH_FLAG_OPERR | FLASH_FLAG_PROGERR | FLASH_FLAG_WRPERR | \ + FLASH_FLAG_PGAERR | FLASH_FLAG_SIZERR | FLASH_FLAG_PGSERR | \ + FLASH_FLAG_MISERR | FLASH_FLAG_FASTERR | FLASH_FLAG_RDERR | \ + FLASH_FLAG_OPTVERR) +#if defined(FLASH_OPTR_DBANK) +#define FLASH_FLAG_ECCR_ERRORS (FLASH_FLAG_ECCC | FLASH_FLAG_ECCD | FLASH_FLAG_ECCC2 | FLASH_FLAG_ECCD2) +#else +#define FLASH_FLAG_ECCR_ERRORS (FLASH_FLAG_ECCC | FLASH_FLAG_ECCD) +#endif +#define FLASH_FLAG_ALL_ERRORS (FLASH_FLAG_SR_ERRORS | FLASH_FLAG_ECCR_ERRORS) +#endif + #if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION // See WB55 specific documentation in AN5289 Rev 3, and in particular, Figure 10. @@ -97,7 +111,7 @@ static const flash_layout_t flash_layout[] = { }; #endif -#elif defined(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) +#elif defined(STM32G0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) static const flash_layout_t flash_layout[] = { { (uint32_t)FLASH_BASE, (uint32_t)FLASH_PAGE_SIZE, 512 }, @@ -165,7 +179,7 @@ static uint32_t get_page(uint32_t addr) { return (addr - FLASH_BASE) / FLASH_PAGE_SIZE; } -#elif defined(STM32G4) +#elif defined(STM32G0) || defined(STM32G4) static uint32_t get_page(uint32_t addr) { return (addr - FLASH_BASE) / FLASH_PAGE_SIZE; @@ -252,7 +266,7 @@ int flash_erase(uint32_t flash_dest, uint32_t num_word32) { EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; EraseInitStruct.PageAddress = flash_dest; EraseInitStruct.NbPages = (4 * num_word32 + FLASH_PAGE_SIZE - 4) / FLASH_PAGE_SIZE; - #elif defined(STM32G4) + #elif defined(STM32G0) || defined(STM32G4) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; EraseInitStruct.Page = get_page(flash_dest); @@ -291,7 +305,7 @@ int flash_erase(uint32_t flash_dest, uint32_t num_word32) { #else EraseInitStruct.VoltageRange = 0; // unused parameter on STM32H7A3/B3 #endif - #if defined(STM32G4) || defined(STM32H7) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H7) EraseInitStruct.Banks = get_bank(flash_dest); #endif EraseInitStruct.Sector = flash_get_sector_info(flash_dest, NULL, NULL); @@ -370,7 +384,7 @@ int flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) { HAL_StatusTypeDef status = HAL_OK; - #if defined(STM32G4) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) // program the flash uint64 by uint64 for (int i = 0; i < num_word32 / 2; i++) { diff --git a/ports/stm32/machine_adc.c b/ports/stm32/machine_adc.c index 819fd3414..ca40acf0d 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(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) +#if defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) #define ADC_V2 (1) #else #define ADC_V2 (0) @@ -42,7 +42,7 @@ #define ADCx_COMMON __LL_ADC_COMMON_INSTANCE(0) #endif -#if defined(STM32F0) || defined(STM32L0) || defined(STM32WL) +#if defined(STM32F0) || defined(STM32G0) || defined(STM32L0) || defined(STM32WL) #define ADC_STAB_DELAY_US (1) #define ADC_TEMPSENSOR_DELAY_US (10) #elif defined(STM32G4) @@ -65,7 +65,7 @@ #elif defined(STM32H7) #define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_8CYCLES_5 #define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_387CYCLES_5 -#elif defined(STM32L0) || defined(STM32WL) +#elif defined(STM32G0) || defined(STM32L0) || defined(STM32WL) #define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_12CYCLES_5 #define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_160CYCLES_5 #elif defined(STM32L4) || defined(STM32WB) @@ -105,7 +105,7 @@ STATIC const uint8_t adc_cr_to_bits_table[] = {12, 10, 8, 6}; void adc_config(ADC_TypeDef *adc, uint32_t bits) { // Configure ADC clock source and enable ADC clock - #if defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) __HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_SYSCLK); __HAL_RCC_ADC_CLK_ENABLE(); #else @@ -174,7 +174,7 @@ void adc_config(ADC_TypeDef *adc, uint32_t bits) { #if ADC_V2 if (!(adc->CR & ADC_CR_ADEN)) { // ADC isn't enabled so calibrate it now - #if defined(STM32F0) || defined(STM32L0) || defined(STM32WL) + #if defined(STM32F0) || defined(STM32G0) || defined(STM32L0) || defined(STM32WL) LL_ADC_StartCalibration(adc); #elif defined(STM32G4) || defined(STM32L4) || defined(STM32WB) LL_ADC_StartCalibration(adc, LL_ADC_SINGLE_ENDED); @@ -237,7 +237,7 @@ void adc_config(ADC_TypeDef *adc, uint32_t bits) { } STATIC int adc_get_bits(ADC_TypeDef *adc) { - #if defined(STM32F0) || defined(STM32L0) || defined(STM32WL) + #if defined(STM32F0) || defined(STM32G0) || defined(STM32L0) || defined(STM32WL) uint32_t res = (adc->CFGR1 & ADC_CFGR1_RES) >> ADC_CFGR1_RES_Pos; #elif defined(STM32F4) || defined(STM32F7) uint32_t res = (adc->CR1 & ADC_CR1_RES) >> ADC_CR1_RES_Pos; @@ -267,7 +267,7 @@ STATIC void adc_config_channel(ADC_TypeDef *adc, uint32_t channel, uint32_t samp } #endif - #if defined(STM32F0) || defined(STM32L0) + #if defined(STM32F0) || defined(STM32G0) || defined(STM32L0) if (channel == ADC_CHANNEL_VREFINT) { ADC1_COMMON->CCR |= ADC_CCR_VREFEN; @@ -279,7 +279,11 @@ STATIC void adc_config_channel(ADC_TypeDef *adc, uint32_t channel, uint32_t samp ADC1_COMMON->CCR |= ADC_CCR_VBATEN; #endif } + #if defined(STM32G0) + adc->SMPR = sample_time << ADC_SMPR_SMP1_Pos; // select sample time from SMP1 (default) + #else adc->SMPR = sample_time << ADC_SMPR_SMP_Pos; // select sample time + #endif adc->CHSELR = 1 << channel; // select channel for conversion #elif defined(STM32F4) || defined(STM32F7) diff --git a/ports/stm32/machine_uart.c b/ports/stm32/machine_uart.c index 681939094..bf7bcfb9c 100644 --- a/ports/stm32/machine_uart.c +++ b/ports/stm32/machine_uart.c @@ -76,10 +76,14 @@ STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); if (!self->is_enabled) { - #ifdef LPUART1 + #if defined(LPUART1) if (self->uart_id == PYB_LPUART_1) { mp_printf(print, "UART('LP1')"); } else + #elif defined(LPUART2) + if (self->uart_id == PYB_LPUART_2) { + mp_printf(print, "UART('LP2')"); + } else #endif { mp_printf(print, "UART(%u)", self->uart_id); @@ -105,12 +109,18 @@ STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_k if (cr1 & USART_CR1_PCE) { bits -= 1; } - #ifdef LPUART1 + #if defined(LPUART1) if (self->uart_id == PYB_LPUART_1) { mp_printf(print, "UART('LP1', baudrate=%u, bits=%u, parity=", uart_get_baudrate(self), bits); } else #endif + #if defined(LPUART2) + if (self->uart_id == PYB_LPUART_2) { + mp_printf(print, "UART('LP2', baudrate=%u, bits=%u, parity=", + uart_get_baudrate(self), bits); + } else + #endif { mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=", self->uart_id, uart_get_baudrate(self), bits); @@ -354,10 +364,18 @@ STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, size_t n_args, size } else if (strcmp(port, MICROPY_HW_LPUART1_NAME) == 0) { uart_id = PYB_LPUART_1; #endif + #ifdef MICROPY_HW_LPUART2_NAME + } else if (strcmp(port, MICROPY_HW_LPUART2_NAME) == 0) { + uart_id = PYB_LPUART_2; + #endif #ifdef LPUART1 } else if (strcmp(port, "LP1") == 0 && uart_exists(PYB_LPUART_1)) { uart_id = PYB_LPUART_1; #endif + #ifdef LPUART2 + } else if (strcmp(port, "LP2") == 0 && uart_exists(PYB_LPUART_2)) { + uart_id = PYB_LPUART_2; + #endif } else { mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("UART(%s) doesn't exist"), port); } @@ -459,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(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32F0) || defined(STM32F7) || defined(STM32G0) || defined(STM32G4) || 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/modmachine.c b/ports/stm32/modmachine.c index 0239ea64c..3a24e08f4 100644 --- a/ports/stm32/modmachine.c +++ b/ports/stm32/modmachine.c @@ -68,6 +68,12 @@ #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) #define RCC_SR RSR #define RCC_SR_IWDGRSTF RCC_RSR_IWDG1RSTF @@ -167,7 +173,7 @@ STATIC mp_obj_t machine_info(size_t n_args, const mp_obj_t *args) { // get and print clock speeds // SYSCLK=168MHz, HCLK=168MHz, PCLK1=42MHz, PCLK2=84MHz { - #if defined(STM32F0) + #if defined(STM32F0) || defined(STM32G0) printf("S=%u\nH=%u\nP1=%u\n", (unsigned int)HAL_RCC_GetSysClockFreq(), (unsigned int)HAL_RCC_GetHCLKFreq(), @@ -310,14 +316,14 @@ STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) { mp_obj_new_int(HAL_RCC_GetSysClockFreq()), mp_obj_new_int(HAL_RCC_GetHCLKFreq()), mp_obj_new_int(HAL_RCC_GetPCLK1Freq()), - #if !defined(STM32F0) + #if !defined(STM32F0) && !defined(STM32G0) mp_obj_new_int(HAL_RCC_GetPCLK2Freq()), #endif }; return mp_obj_new_tuple(MP_ARRAY_SIZE(tuple), tuple); } else { // set - #if defined(STM32F0) || defined(STM32L0) || defined(STM32L4) + #if defined(STM32F0) || defined(STM32L0) || defined(STM32L4) || defined(STM32G0) mp_raise_NotImplementedError(MP_ERROR_TEXT("machine.freq set not supported yet")); #else mp_int_t sysclk = mp_obj_get_int(args[0]); diff --git a/ports/stm32/mpconfigboard_common.h b/ports/stm32/mpconfigboard_common.h index 7c8662318..51bad18dd 100644 --- a/ports/stm32/mpconfigboard_common.h +++ b/ports/stm32/mpconfigboard_common.h @@ -319,6 +319,16 @@ #define MICROPY_HW_MAX_UART (8) #define MICROPY_HW_MAX_LPUART (0) +// Configuration for STM32G0 series +#elif defined(STM32G0) + +#define MP_HAL_UNIQUE_ID_ADDRESS (UID_BASE) +#define PYB_EXTI_NUM_VECTORS (22) // previously 23 +#define MICROPY_HW_MAX_I2C (3) +#define MICROPY_HW_MAX_TIMER (17) +#define MICROPY_HW_MAX_UART (6) +#define MICROPY_HW_MAX_LPUART (2) + // Configuration for STM32G4 series #elif defined(STM32G4) @@ -505,7 +515,7 @@ // Enable CAN if there are any peripherals defined #if defined(MICROPY_HW_CAN1_TX) || defined(MICROPY_HW_CAN2_TX) || defined(MICROPY_HW_CAN3_TX) #define MICROPY_HW_ENABLE_CAN (1) -#if defined(STM32G4) || defined(STM32H7) +#if defined(STM32G0) || defined(STM32G4) || defined(STM32H7) #define MICROPY_HW_ENABLE_FDCAN (1) // define for MCUs with FDCAN #endif #else diff --git a/ports/stm32/mphalport.c b/ports/stm32/mphalport.c index 9961c3d99..477192330 100644 --- a/ports/stm32/mphalport.c +++ b/ports/stm32/mphalport.c @@ -99,6 +99,9 @@ void mp_hal_gpio_clock_enable(GPIO_TypeDef *gpio) { #elif defined(STM32L0) #define AHBxENR IOPENR #define AHBxENR_GPIOAEN_Pos RCC_IOPENR_IOPAEN_Pos + #elif defined(STM32G0) + #define AHBxENR IOPENR + #define AHBxENR_GPIOAEN_Pos RCC_IOPENR_GPIOAEN_Pos #elif defined(STM32G4) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) #define AHBxENR AHB2ENR #define AHBxENR_GPIOAEN_Pos RCC_AHB2ENR_GPIOAEN_Pos diff --git a/ports/stm32/mphalport.h b/ports/stm32/mphalport.h index 6cfa9b927..47bb1f8c8 100644 --- a/ports/stm32/mphalport.h +++ b/ports/stm32/mphalport.h @@ -2,13 +2,15 @@ #include STM32_HAL_H #include "pin.h" -// F0-1.9.0+F4-1.16.0+F7-1.7.0+G4-1.3.0+H7-1.6.0+L0-1.11.2+L4-1.17.0+WB-1.10.0+WL-1.1.0 +// 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" #elif defined(STM32F4) #define MICROPY_PLATFORM_VERSION "HAL1.16.0" #elif defined(STM32F7) #define MICROPY_PLATFORM_VERSION "HAL1.7.0" +#elif defined(STM32G0) +#define MICROPY_PLATFORM_VERSION "HAL1.5.1" #elif defined(STM32G4) #define MICROPY_PLATFORM_VERSION "HAL1.3.0" #elif defined(STM32H7) diff --git a/ports/stm32/powerctrl.c b/ports/stm32/powerctrl.c index a2e3b5c71..cf06f3e18 100644 --- a/ports/stm32/powerctrl.c +++ b/ports/stm32/powerctrl.c @@ -143,7 +143,7 @@ void powerctrl_check_enter_bootloader(void) { if (BL_STATE_GET_KEY(bl_state) == BL_STATE_KEY && (RCC->RCC_SR & RCC_SR_SFTRSTF)) { // Reset by NVIC_SystemReset with bootloader data set -> branch to bootloader RCC->RCC_SR = RCC_SR_RMVF; - #if defined(STM32F0) || defined(STM32F4) || defined(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) + #if defined(STM32F0) || defined(STM32F4) || defined(STM32G0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH(); #endif branch_to_bootloader(BL_STATE_GET_REG(bl_state), BL_STATE_GET_ADDR(bl_state)); @@ -286,7 +286,7 @@ int powerctrl_rcc_clock_config_pll(RCC_ClkInitTypeDef *rcc_init, uint32_t sysclk #endif -#if !defined(STM32F0) && !defined(STM32L0) && !defined(STM32L4) +#if !defined(STM32F0) && !defined(STM32G0) && !defined(STM32L0) && !defined(STM32L4) STATIC uint32_t calc_ahb_div(uint32_t wanted_div) { #if defined(STM32H7) @@ -378,14 +378,17 @@ STATIC uint32_t calc_apb2_div(uint32_t wanted_div) { #endif } -#if defined(STM32F4) || defined(STM32F7) || defined(STM32G4) || defined(STM32H7) +#if defined(STM32F4) || defined(STM32F7) || defined(STM32G0) || defined(STM32G4) || defined(STM32H7) int powerctrl_set_sysclk(uint32_t sysclk, uint32_t ahb, uint32_t apb1, uint32_t apb2) { // Return straightaway if the clocks are already at the desired frequency if (sysclk == HAL_RCC_GetSysClockFreq() && ahb == HAL_RCC_GetHCLKFreq() && apb1 == HAL_RCC_GetPCLK1Freq() - && apb2 == HAL_RCC_GetPCLK2Freq()) { + #if !defined(STM32G0) + && apb2 == HAL_RCC_GetPCLK2Freq() + #endif + ) { return 0; } @@ -428,7 +431,11 @@ set_clk: // Desired system clock source is in sysclk_source RCC_ClkInitTypeDef RCC_ClkInitStruct; + #if defined(STM32G0) || defined(STM32G4) + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_ALL; + #else RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); + #endif if (sysclk_source == RCC_SYSCLKSOURCE_PLLCLK) { // Set HSE as system clock source to allow modification of the PLL configuration // We then change to PLL after re-configuring PLL @@ -449,7 +456,9 @@ set_clk: 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(STM32H7) RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB3CLKDivider = MICROPY_HW_CLK_APB3_DIV; @@ -692,7 +701,7 @@ void powerctrl_enter_stop_mode(void) { __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_MSI); #endif - #if !defined(STM32F0) && !defined(STM32G4) && !defined(STM32L0) && !defined(STM32L4) && !defined(STM32WB) && !defined(STM32WL) + #if !defined(STM32F0) && !defined(STM32G0) && !defined(STM32G4) && !defined(STM32L0) && !defined(STM32L4) && !defined(STM32WB) && !defined(STM32WL) // takes longer to wake but reduces stop current HAL_PWREx_EnableFlashPowerDown(); #endif @@ -771,7 +780,7 @@ void powerctrl_enter_stop_mode(void) { #if defined(STM32H7) while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL1) { } - #elif defined(STM32WB) || defined(STM32WL) + #elif defined(STM32G0) || defined(STM32WB) || defined(STM32WL) while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_SYSCLKSOURCE_STATUS_PLLCLK) { } #else @@ -867,7 +876,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(STM32G4) || defined(STM32WL) + #elif defined(STM32G0) || defined(STM32G4) || 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) @@ -891,7 +900,7 @@ void powerctrl_enter_standby_mode(void) { // clear RTC wake-up flags #if defined(SR_BITS) RTC->SR &= ~SR_BITS; - #elif defined(STM32G4) || defined(STM32WL) + #elif defined(STM32G0) || defined(STM32G4) || defined(STM32WL) RTC->MISR &= ~ISR_BITS; #else RTC->ISR &= ~ISR_BITS; @@ -909,7 +918,7 @@ void powerctrl_enter_standby_mode(void) { #elif defined(STM32H7) EXTI_D1->PR1 = 0x3fffff; PWR->WKUPCR |= PWR_WAKEUP_FLAG1 | PWR_WAKEUP_FLAG2 | PWR_WAKEUP_FLAG3 | PWR_WAKEUP_FLAG4 | PWR_WAKEUP_FLAG5 | PWR_WAKEUP_FLAG6; - #elif defined(STM32G4) || defined(STM32L4) || defined(STM32WB) + #elif defined(STM32G0) || defined(STM32G4) || defined(STM32L4) || defined(STM32WB) // clear all wake-up flags PWR->SCR |= PWR_SCR_CWUF5 | PWR_SCR_CWUF4 | PWR_SCR_CWUF3 | PWR_SCR_CWUF2 | PWR_SCR_CWUF1; // TODO diff --git a/ports/stm32/powerctrlboot.c b/ports/stm32/powerctrlboot.c index 4ecd83e2c..555457c58 100644 --- a/ports/stm32/powerctrlboot.c +++ b/ports/stm32/powerctrlboot.c @@ -104,6 +104,77 @@ void SystemClock_Config(void) { powerctrl_config_systick(); } +#elif defined(STM32G0) + +void SystemClock_Config(void) { + // Enable power control peripheral + __HAL_RCC_PWR_CLK_ENABLE(); + + // Set flash latency to 2 because SYSCLK > 48MHz + FLASH->ACR = (FLASH->ACR & ~0x7) | 0x2; + + #if MICROPY_HW_CLK_USE_HSI + // Enable the 16MHz internal oscillator and the PLL to get a 64MHz SYSCLK + RCC->CR |= RCC_CR_HSION; + while ((RCC->CR & RCC_CR_HSIRDY) == 0) { + // Wait for HSI to be ready + } + + // Use the PLL to get a 64MHz SYSCLK + #define PLLM (HSI_VALUE / 16000000) // input is 8MHz + #define PLLN (8) // 8*16MHz = 128MHz + #define PLLP (2) // f_P = 64MHz + #define PLLQ (2) // f_Q = 64MHz + #define PLLR (2) // f_R = 64MHz + RCC->PLLCFGR = + (PLLP - 1) << RCC_PLLCFGR_PLLP_Pos | RCC_PLLCFGR_PLLPEN + | (PLLQ - 1) << RCC_PLLCFGR_PLLQ_Pos | RCC_PLLCFGR_PLLQEN + | (PLLR - 1) << RCC_PLLCFGR_PLLR_Pos | RCC_PLLCFGR_PLLREN + | PLLN << RCC_PLLCFGR_PLLN_Pos + | (PLLM - 1) << RCC_PLLCFGR_PLLM_Pos + | RCC_PLLCFGR_PLLSRC_HSI; + + #else + #error System clock not specified + #endif + + RCC->CR |= RCC_CR_PLLON; // Turn PLL on + while ((RCC->CR & RCC_CR_PLLRDY) == 0) { + // Wait for PLL to lock + } + const uint32_t sysclk_src = 2; // 2 = PLLRCLK + + // Select SYSCLK source + RCC->CFGR |= sysclk_src << RCC_CFGR_SW_Pos; + while (((RCC->CFGR >> RCC_CFGR_SWS_Pos) & 0x7) != sysclk_src) { + // Wait for SYSCLK source to change + } + + SystemCoreClockUpdate(); + powerctrl_config_systick(); + + #if MICROPY_HW_ENABLE_RNG || MICROPY_HW_ENABLE_USB + // Enable the 48MHz internal oscillator + RCC->CRRCR |= RCC_CRRCR_HSI48ON; + RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; + SYSCFG->CFGR3 |= SYSCFG_CFGR3_ENREF_HSI48; + while (!(RCC->CRRCR & RCC_CRRCR_HSI48RDY)) { + // Wait for HSI48 to be ready + } + + // Select RC48 as HSI48 for USB and RNG + RCC->CCIPR |= RCC_CCIPR_HSI48SEL; + + #if MICROPY_HW_ENABLE_USB + // Synchronise HSI48 with 1kHz USB SoF + __HAL_RCC_CRS_CLK_ENABLE(); + CRS->CR = 0x20 << CRS_CR_TRIM_Pos; + CRS->CFGR = 2 << CRS_CFGR_SYNCSRC_Pos | 0x22 << CRS_CFGR_FELIM_Pos + | __HAL_RCC_CRS_RELOADVALUE_CALCULATE(48000000, 1000) << CRS_CFGR_RELOAD_Pos; + #endif + #endif +} + #elif defined(STM32L0) void SystemClock_Config(void) { diff --git a/ports/stm32/pyb_i2c.c b/ports/stm32/pyb_i2c.c index 5cd7c0c8b..9dfa27656 100644 --- a/ports/stm32/pyb_i2c.c +++ b/ports/stm32/pyb_i2c.c @@ -130,7 +130,7 @@ const pyb_i2c_obj_t pyb_i2c_obj[] = { #endif }; -#if defined(STM32F7) || defined(STM32G4) || defined(STM32L4) || defined(STM32H7) +#if defined(STM32F7) || defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) // The STM32F0, F3, F7, H7 and L4 use a TIMINGR register rather than ClockSpeed and // DutyCycle. @@ -163,6 +163,16 @@ const pyb_i2c_obj_t pyb_i2c_obj[] = { #define MICROPY_HW_I2C_BAUDRATE_DEFAULT (PYB_I2C_SPEED_FULL) #define MICROPY_HW_I2C_BAUDRATE_MAX (PYB_I2C_SPEED_FAST) +#elif defined(STM32G0) +// generated using CubeMX +#define MICROPY_HW_I2C_BAUDRATE_TIMING { \ + {PYB_I2C_SPEED_STANDARD, 0x10707DBC}, \ + {PYB_I2C_SPEED_FULL, 0x00602173}, \ + {PYB_I2C_SPEED_FAST, 0x00300B29}, \ +} +#define MICROPY_HW_I2C_BAUDRATE_DEFAULT (PYB_I2C_SPEED_FULL) +#define MICROPY_HW_I2C_BAUDRATE_MAX (PYB_I2C_SPEED_FAST) + #elif defined(STM32G4) // timing input depends on PLL // for now: 170MHz sysclock, PCLK 10.625 MHz diff --git a/ports/stm32/rtc.c b/ports/stm32/rtc.c index e776f67bb..55977791b 100644 --- a/ports/stm32/rtc.c +++ b/ports/stm32/rtc.c @@ -225,7 +225,9 @@ void rtc_init_finalise() { // fresh reset; configure RTC Calendar RTC_CalendarConfig(); - #if defined(STM32G4) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) + if (__HAL_RCC_GET_FLAG(RCC_FLAG_PWRRST) != RESET) { + #elif defined(STM32G4) || 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 +268,7 @@ STATIC HAL_StatusTypeDef PYB_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct HAL_PWR_EnableBkUpAccess(); uint32_t tickstart = HAL_GetTick(); - #if defined(STM32F7) || defined(STM32G4) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32F7) || defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) // __HAL_RCC_PWR_CLK_ENABLE(); // Enable write access to Backup domain // PWR->CR1 |= PWR_CR1_DBP; @@ -354,7 +356,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(STM32G4) || defined(STM32WL) + #elif defined(STM32G0) || defined(STM32G4) || defined(STM32WL) hrtc->Instance->CR &= (uint32_t) ~RTC_CR_TAMPALRM_TYPE_Msk; hrtc->Instance->CR |= (uint32_t)(hrtc->Init.OutPutType); #else @@ -622,6 +624,8 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_datetime_obj, 1, 2, pyb_rtc_datetime #if defined(STM32F0) || defined(STM32L0) #define RTC_WKUP_IRQn RTC_IRQn +#elif defined(STM32G0) +#define RTC_WKUP_IRQn RTC_TAMP_IRQn #endif // wakeup(None) @@ -719,7 +723,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(STM32G4) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) EXTI->IMR1 |= 1 << EXTI_RTC_WAKEUP; EXTI->RTSR1 |= 1 << EXTI_RTC_WAKEUP; #elif defined(STM32H7) @@ -731,7 +735,7 @@ mp_obj_t pyb_rtc_wakeup(size_t n_args, const mp_obj_t *args) { #endif // clear interrupt flags - #if defined(STM32G4) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32WL) RTC->ICSR &= ~RTC_ICSR_WUTWF; #elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ) RTC->SR &= ~RTC_SR_WUTF; @@ -742,6 +746,8 @@ 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) + // Do nothing #else EXTI->PR = 1 << EXTI_RTC_WAKEUP; #endif @@ -758,7 +764,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(STM32G4) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || 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 0ce6b5abc..188376ec0 100644 --- a/ports/stm32/spi.c +++ b/ports/stm32/spi.c @@ -216,7 +216,7 @@ int spi_find_index(mp_obj_t id) { } STATIC uint32_t spi_get_source_freq(SPI_HandleTypeDef *spi) { - #if defined(STM32F0) + #if defined(STM32F0) || defined(STM32G0) return HAL_RCC_GetPCLK1Freq(); #elif defined(STM32H7) if (spi->Instance == SPI1 || spi->Instance == SPI2 || spi->Instance == SPI3) { @@ -317,7 +317,11 @@ void spi_init(const spi_t *self, bool enable_nss_pin) { #endif #if defined(MICROPY_HW_SPI2_SCK) } else if (spi->Instance == SPI2) { + #if defined(STM32G0) + irqn = SPI2_3_IRQn; + #else irqn = SPI2_IRQn; + #endif #if defined(MICROPY_HW_SPI2_NSS) pins[0] = MICROPY_HW_SPI2_NSS; #endif @@ -331,7 +335,11 @@ void spi_init(const spi_t *self, bool enable_nss_pin) { #endif #if defined(MICROPY_HW_SPI3_SCK) } else if (spi->Instance == SPI3) { + #if defined(STM32G0) + irqn = SPI2_3_IRQn; + #else irqn = SPI3_IRQn; + #endif #if defined(MICROPY_HW_SPI3_NSS) pins[0] = MICROPY_HW_SPI3_NSS; #endif @@ -439,14 +447,22 @@ void spi_deinit(const spi_t *spi_obj) { __HAL_RCC_SPI2_FORCE_RESET(); __HAL_RCC_SPI2_RELEASE_RESET(); __HAL_RCC_SPI2_CLK_DISABLE(); + #if defined(STM32G0) + HAL_NVIC_DisableIRQ(SPI2_3_IRQn); + #else HAL_NVIC_DisableIRQ(SPI2_IRQn); + #endif #endif #if defined(MICROPY_HW_SPI3_SCK) } else if (spi->Instance == SPI3) { __HAL_RCC_SPI3_FORCE_RESET(); __HAL_RCC_SPI3_RELEASE_RESET(); __HAL_RCC_SPI3_CLK_DISABLE(); + #if defined(STM32G0) + HAL_NVIC_DisableIRQ(SPI2_3_IRQn); + #else HAL_NVIC_DisableIRQ(SPI3_IRQn); + #endif #endif #if defined(MICROPY_HW_SPI4_SCK) } else if (spi->Instance == SPI4) { diff --git a/ports/stm32/stm32.mk b/ports/stm32/stm32.mk index ed3298824..c55b243fe 100644 --- a/ports/stm32/stm32.mk +++ b/ports/stm32/stm32.mk @@ -48,7 +48,7 @@ CFLAGS_CORTEX_M += -mfpu=fpv5-d16 -mfloat-abi=hard SUPPORTS_HARDWARE_FP_SINGLE = 1 SUPPORTS_HARDWARE_FP_DOUBLE = 1 else -ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 l0 wl)) +ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 g0 l0 wl)) CFLAGS_CORTEX_M += -msoft-float else CFLAGS_CORTEX_M += -mfpu=fpv4-sp-d16 -mfloat-abi=hard @@ -61,6 +61,7 @@ endif CFLAGS_MCU_f0 = $(CFLAGS_CORTEX_M) -mtune=cortex-m0 -mcpu=cortex-m0 CFLAGS_MCU_f4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 CFLAGS_MCU_f7 = $(CFLAGS_CORTEX_M) -mtune=cortex-m7 -mcpu=cortex-m7 +CFLAGS_MCU_g0 = $(CFLAGS_CORTEX_M) -mtune=cortex-m0plus -mcpu=cortex-m0plus 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_l4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 diff --git a/ports/stm32/stm32_it.c b/ports/stm32/stm32_it.c index 39229a143..55c772efb 100644 --- a/ports/stm32/stm32_it.c +++ b/ports/stm32/stm32_it.c @@ -529,7 +529,7 @@ void TAMP_STAMP_IRQHandler(void) { void RTC_WKUP_IRQHandler(void) { IRQ_ENTER(RTC_WKUP_IRQn); - #if defined(STM32G4) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32WL) RTC->MISR &= ~RTC_MISR_WUTMF; // clear wakeup interrupt flag #elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ) RTC->SR &= ~RTC_SR_WUTF; // clear wakeup interrupt flag @@ -540,8 +540,17 @@ void RTC_WKUP_IRQHandler(void) { IRQ_EXIT(RTC_WKUP_IRQn); } -#if defined(STM32F0) || defined(STM32L0) +#if defined(STM32F0) || defined(STM32G0) || defined(STM32L0) +#if defined(STM32G0) +void RTC_TAMP_IRQHandler(void) { + IRQ_ENTER(RTC_TAMP_IRQn); + RTC->MISR &= ~RTC_MISR_WUTMF; // clear wakeup interrupt flag + Handle_EXTI_Irq(EXTI_RTC_WAKEUP); // clear EXTI flag and execute optional callback + Handle_EXTI_Irq(EXTI_RTC_TIMESTAMP); // clear EXTI flag and execute optional callback + IRQ_EXIT(RTC_TAMP_IRQn); +} +#else void RTC_IRQHandler(void) { IRQ_ENTER(RTC_IRQn); if (RTC->ISR & RTC_ISR_WUTF) { @@ -558,6 +567,7 @@ void RTC_IRQHandler(void) { } IRQ_EXIT(RTC_IRQn); } +#endif void EXTI0_1_IRQHandler(void) { IRQ_ENTER(EXTI0_1_IRQn); @@ -653,6 +663,15 @@ void TIM2_IRQHandler(void) { IRQ_EXIT(TIM2_IRQn); } +#if defined(STM32G0) +void TIM3_TIM4_IRQHandler(void) { + IRQ_ENTER(TIM3_TIM4_IRQn); + timer_irq_handler(3); + timer_irq_handler(4); + IRQ_EXIT(TIM3_TIM4_IRQn); +} + +#else void TIM3_IRQHandler(void) { IRQ_ENTER(TIM3_IRQn); timer_irq_handler(3); @@ -664,6 +683,7 @@ void TIM4_IRQHandler(void) { timer_irq_handler(4); IRQ_EXIT(TIM4_IRQn); } +#endif void TIM5_IRQHandler(void) { IRQ_ENTER(TIM5_IRQn); @@ -673,15 +693,29 @@ void TIM5_IRQHandler(void) { } #if defined(TIM6) // STM32F401 doesn't have TIM6 +#if defined(STM32G0) +void TIM6_DAC_LPTIM1_IRQHandler(void) { + IRQ_ENTER(TIM6_DAC_LPTIM1_IRQn); + timer_irq_handler(6); + IRQ_EXIT(TIM6_DAC_LPTIM1_IRQn); +} +#else void TIM6_DAC_IRQHandler(void) { IRQ_ENTER(TIM6_DAC_IRQn); timer_irq_handler(6); IRQ_EXIT(TIM6_DAC_IRQn); } #endif +#endif #if defined(TIM7) // STM32F401 doesn't have TIM7 -#if defined(STM32G4) +#if defined(STM32G0) +void TIM7_LPTIM2_IRQHandler(void) { + IRQ_ENTER(TIM7_LPTIM2_IRQn); + timer_irq_handler(7); + IRQ_EXIT(TIM7_LPTIM2_IRQn); +} +#elif defined(STM32G4) void TIM7_DAC_IRQHandler(void) { IRQ_ENTER(TIM7_DAC_IRQn); timer_irq_handler(7); @@ -731,6 +765,32 @@ void TIM8_TRG_COM_TIM14_IRQHandler(void) { } #endif +#if defined(STM32G0) +void TIM14_IRQHandler(void) { + IRQ_ENTER(TIM14_IRQn); + timer_irq_handler(14); + IRQ_EXIT(TIM14_IRQn); +} + +void TIM15_IRQHandler(void) { + IRQ_ENTER(TIM15_IRQn); + timer_irq_handler(15); + IRQ_EXIT(TIM15_IRQn); +} + +void TIM16_FDCAN_IT0_IRQHandler(void) { + IRQ_ENTER(TIM16_FDCAN_IT0_IRQn); + timer_irq_handler(16); + IRQ_EXIT(TIM16_FDCAN_IT0_IRQn); +} + +void TIM17_FDCAN_IT1_IRQHandler(void) { + IRQ_ENTER(TIM17_FDCAN_IT1_IRQn); + timer_irq_handler(17); + IRQ_EXIT(TIM17_FDCAN_IT1_IRQn); +} +#endif + #if defined(STM32H7) void TIM15_IRQHandler(void) { IRQ_ENTER(TIM15_IRQn); @@ -779,6 +839,29 @@ void USART3_8_IRQHandler(void) { IRQ_EXIT(USART3_8_IRQn); } +#elif defined(STM32G0) + +#if defined(STM32G0B1xx) || defined(STM32G0C1xx) +void USART2_LPUART2_IRQHandler(void) { + IRQ_ENTER(USART2_LPUART2_IRQn); + uart_irq_handler(2); + uart_irq_handler(PYB_LPUART_2); + IRQ_EXIT(USART2_LPUART2_IRQn); +} + +void USART3_4_5_6_LPUART1_IRQHandler(void) { + IRQ_ENTER(USART3_4_5_6_LPUART1_IRQn); + uart_irq_handler(3); + uart_irq_handler(4); + uart_irq_handler(5); + uart_irq_handler(6); + uart_irq_handler(PYB_LPUART_1); + IRQ_EXIT(USART3_4_5_6_LPUART1_IRQn); +} +#else +#error Unsupported processor +#endif + #elif defined(STM32L0) void USART4_5_IRQHandler(void) { @@ -798,6 +881,14 @@ void USART3_IRQHandler(void) { } #endif +#if defined(USART4) +void USART4_IRQHandler(void) { + IRQ_ENTER(USART4_IRQn); + uart_irq_handler(4); + IRQ_EXIT(USART4_IRQn); +} +#endif + #if defined(UART4) void UART4_IRQHandler(void) { IRQ_ENTER(UART4_IRQn); @@ -806,6 +897,14 @@ void UART4_IRQHandler(void) { } #endif +#if defined(USART5) +void USART5_IRQHandler(void) { + IRQ_ENTER(USART5_IRQn); + uart_irq_handler(5); + IRQ_EXIT(USART5_IRQn); +} +#endif + #if defined(UART5) void UART5_IRQHandler(void) { IRQ_ENTER(UART5_IRQn); @@ -864,6 +963,14 @@ void LPUART1_IRQHandler(void) { } #endif +#if defined(LPUART2) +void LPUART2_IRQHandler(void) { + IRQ_ENTER(LPUART2_IRQn); + uart_irq_handler(PYB_LPUART_2); + IRQ_EXIT(LPUART2_IRQn); +} +#endif + #if MICROPY_PY_PYB_LEGACY #if defined(MICROPY_HW_I2C1_SCL) diff --git a/ports/stm32/timer.c b/ports/stm32/timer.c index 12f0515d4..8181885e2 100644 --- a/ports/stm32/timer.c +++ b/ports/stm32/timer.c @@ -236,7 +236,7 @@ uint32_t timer_get_source_freq(uint32_t tim_id) { uint32_t source, clk_div; if (tim_id == 1 || (8 <= tim_id && tim_id <= 11)) { // TIM{1,8,9,10,11} are on APB2 - #if defined(STM32F0) + #if defined(STM32F0) || defined(STM32G0) source = HAL_RCC_GetPCLK1Freq(); clk_div = RCC->CFGR & RCC_CFGR_PPRE; #elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ) @@ -252,7 +252,7 @@ uint32_t timer_get_source_freq(uint32_t tim_id) { } else { // TIM{2,3,4,5,6,7,12,13,14} are on APB1 source = HAL_RCC_GetPCLK1Freq(); - #if defined(STM32F0) + #if defined(STM32F0) || defined(STM32G0) clk_div = RCC->CFGR & RCC_CFGR_PPRE; #elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ) clk_div = RCC->CDCFGR1 & RCC_CDCFGR2_CDPPRE1; @@ -482,7 +482,7 @@ STATIC void config_deadtime(pyb_timer_obj_t *self, mp_int_t ticks, mp_int_t brk) deadTimeConfig.DeadTime = compute_dtg_from_ticks(ticks); deadTimeConfig.BreakState = brk == BRK_OFF ? TIM_BREAK_DISABLE : TIM_BREAK_ENABLE; deadTimeConfig.BreakPolarity = brk == BRK_LOW ? TIM_BREAKPOLARITY_LOW : TIM_BREAKPOLARITY_HIGH; - #if defined(STM32F7) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) + #if defined(STM32F7) || defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) deadTimeConfig.BreakFilter = 0; deadTimeConfig.Break2State = TIM_BREAK_DISABLE; deadTimeConfig.Break2Polarity = TIM_BREAKPOLARITY_LOW; @@ -804,7 +804,7 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *self, size_t n_args, cons #define TIM_ENTRY(id, irq) [id - 1] = (uint32_t)TIM##id | irq STATIC const uint32_t tim_instance_table[MICROPY_HW_MAX_TIMER] = { #if defined(TIM1) - #if defined(STM32F0) + #if defined(STM32F0) || defined(STM32G0) TIM_ENTRY(1, TIM1_BRK_UP_TRG_COM_IRQn), #elif defined(STM32F4) || defined(STM32F7) TIM_ENTRY(1, TIM1_UP_TIM10_IRQn), @@ -816,23 +816,35 @@ STATIC const uint32_t tim_instance_table[MICROPY_HW_MAX_TIMER] = { #endif TIM_ENTRY(2, TIM2_IRQn), #if defined(TIM3) + #if defined(STM32G0B1xx) || defined(STM32G0C1xx) + TIM_ENTRY(3, TIM3_TIM4_IRQn), + #else TIM_ENTRY(3, TIM3_IRQn), #endif + #endif #if defined(TIM4) + #if defined(STM32G0B1xx) || defined(STM32G0C1xx) + TIM_ENTRY(3, TIM3_TIM4_IRQn), + #else TIM_ENTRY(4, TIM4_IRQn), #endif + #endif #if defined(TIM5) TIM_ENTRY(5, TIM5_IRQn), #endif #if defined(TIM6) #if defined(STM32F412Zx) TIM_ENTRY(6, TIM6_IRQn), + #elif defined(STM32G0) + TIM_ENTRY(6, TIM6_DAC_LPTIM1_IRQn), #else TIM_ENTRY(6, TIM6_DAC_IRQn), #endif #endif #if defined(TIM7) - #if defined(STM32G4) + #if defined(STM32G0) + TIM_ENTRY(7, TIM7_LPTIM2_IRQn), + #elif defined(STM32G4) TIM_ENTRY(7, TIM7_DAC_IRQn), #else TIM_ENTRY(7, TIM7_IRQn), @@ -860,27 +872,31 @@ STATIC const uint32_t tim_instance_table[MICROPY_HW_MAX_TIMER] = { #if defined(TIM13) TIM_ENTRY(13, TIM8_UP_TIM13_IRQn), #endif - #if defined(STM32F0) + #if defined(STM32F0) || defined(STM32G0) TIM_ENTRY(14, TIM14_IRQn), #elif defined(TIM14) TIM_ENTRY(14, TIM8_TRG_COM_TIM14_IRQn), #endif #if defined(TIM15) - #if defined(STM32F0) || defined(STM32H7) + #if defined(STM32F0) || defined(STM32G0) || defined(STM32H7) TIM_ENTRY(15, TIM15_IRQn), #else TIM_ENTRY(15, TIM1_BRK_TIM15_IRQn), #endif #endif #if defined(TIM16) - #if defined(STM32F0) || defined(STM32H7) || defined(STM32WL) + #if defined(STM32G0B1xx) || defined(STM32G0C1xx) + TIM_ENTRY(16, TIM16_FDCAN_IT0_IRQn), + #elif defined(STM32F0) || defined(STM32G0) || defined(STM32H7) || defined(STM32WL) TIM_ENTRY(16, TIM16_IRQn), #else TIM_ENTRY(16, TIM1_UP_TIM16_IRQn), #endif #endif #if defined(TIM17) - #if defined(STM32F0) || defined(STM32H7) || defined(STM32WL) + #if defined(STM32G0B1xx) || defined(STM32G0C1xx) + TIM_ENTRY(17, TIM17_FDCAN_IT1_IRQn), + #elif defined(STM32F0) || defined(STM32G0) || defined(STM32H7) || defined(STM32WL) TIM_ENTRY(17, TIM17_IRQn), #else TIM_ENTRY(17, TIM1_TRG_COM_TIM17_IRQn), diff --git a/ports/stm32/uart.c b/ports/stm32/uart.c index 13e1667d2..adcbe8836 100644 --- a/ports/stm32/uart.c +++ b/ports/stm32/uart.c @@ -41,13 +41,13 @@ #if defined(STM32F4) #define UART_RXNE_IS_SET(uart) ((uart)->SR & USART_SR_RXNE) #else -#if defined(STM32H7) || defined(STM32WL) +#if defined(STM32G0) || defined(STM32H7) || defined(STM32WL) #define USART_ISR_RXNE USART_ISR_RXNE_RXFNE #endif #define UART_RXNE_IS_SET(uart) ((uart)->ISR & USART_ISR_RXNE) #endif -#if defined(STM32WL) +#if defined(STM32G0) || defined(STM32WL) #define UART_RXNE_IT_EN(uart) do { (uart)->CR1 |= USART_CR1_RXNEIE_RXFNEIE; } while (0) #define UART_RXNE_IT_DIS(uart) do { (uart)->CR1 &= ~USART_CR1_RXNEIE_RXFNEIE; } while (0) #else @@ -55,7 +55,7 @@ #define UART_RXNE_IT_DIS(uart) do { (uart)->CR1 &= ~USART_CR1_RXNEIE; } while (0) #endif -#if defined(STM32WL) +#if defined(STM32G0) || defined(STM32WL) #define USART_CR1_IE_BASE (USART_CR1_PEIE | USART_CR1_TXEIE_TXFNFIE | USART_CR1_TCIE | USART_CR1_RXNEIE_RXFNEIE | USART_CR1_IDLEIE) #else #define USART_CR1_IE_BASE (USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE | USART_CR1_RXNEIE | USART_CR1_IDLEIE) @@ -82,7 +82,7 @@ #define USART_CR3_IE_ALL (USART_CR3_IE_BASE) #endif -#elif defined(STM32G4) +#elif defined(STM32G0) || defined(STM32G4) #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) @@ -122,13 +122,13 @@ typedef struct _pyb_uart_irq_map_t { STATIC const pyb_uart_irq_map_t mp_uart_irq_map[] = { { USART_CR1_IDLEIE, UART_FLAG_IDLE}, // RX idle { USART_CR1_PEIE, UART_FLAG_PE}, // parity error - #if defined(STM32WL) + #if defined(STM32G0) || defined(STM32WL) { USART_CR1_TXEIE_TXFNFIE, UART_FLAG_TXE}, // TX register empty #else { USART_CR1_TXEIE, UART_FLAG_TXE}, // TX register empty #endif { USART_CR1_TCIE, UART_FLAG_TC}, // TX complete - #if defined(STM32WL) + #if defined(STM32G0) || defined(STM32WL) { USART_CR1_RXNEIE_RXFNEIE, UART_FLAG_RXNE}, // RX register not empty #else { USART_CR1_RXNEIE, UART_FLAG_RXNE}, // RX register not empty @@ -229,6 +229,11 @@ bool uart_exists(int uart_id) { return true; #endif + #if defined(MICROPY_HW_LPUART2_TX) && defined(MICROPY_HW_LPUART2_RX) + case PYB_LPUART_2: + return true; + #endif + default: return false; } @@ -270,7 +275,11 @@ bool uart_init(pyb_uart_obj_t *uart_obj, case PYB_UART_2: uart_unit = 2; UARTx = USART2; + #if defined(STM32G0) + irqn = USART2_LPUART2_IRQn; + #else irqn = USART2_IRQn; + #endif pins[0] = MICROPY_HW_UART2_TX; pins[1] = MICROPY_HW_UART2_RX; #if defined(MICROPY_HW_UART2_RTS) @@ -293,6 +302,8 @@ bool uart_init(pyb_uart_obj_t *uart_obj, UARTx = USART3; #if defined(STM32F0) irqn = USART3_8_IRQn; + #elif defined(STM32G0) + irqn = USART3_4_5_6_LPUART1_IRQn; #else irqn = USART3_IRQn; #endif @@ -323,6 +334,10 @@ bool uart_init(pyb_uart_obj_t *uart_obj, UARTx = USART4; irqn = USART4_5_IRQn; __HAL_RCC_USART4_CLK_ENABLE(); + #elif defined(STM32G0) + UARTx = USART4; + irqn = USART3_4_5_6_LPUART1_IRQn; + __HAL_RCC_USART4_CLK_ENABLE(); #else UARTx = UART4; irqn = UART4_IRQn; @@ -354,6 +369,10 @@ bool uart_init(pyb_uart_obj_t *uart_obj, UARTx = USART5; irqn = USART4_5_IRQn; __HAL_RCC_USART5_CLK_ENABLE(); + #elif defined(STM32G0) + UARTx = USART5; + irqn = USART3_4_5_6_LPUART1_IRQn; + __HAL_RCC_USART5_CLK_ENABLE(); #else UARTx = UART5; irqn = UART5_IRQn; @@ -380,6 +399,8 @@ bool uart_init(pyb_uart_obj_t *uart_obj, UARTx = USART6; #if defined(STM32F0) irqn = USART3_8_IRQn; + #elif defined(STM32G0) + irqn = USART3_4_5_6_LPUART1_IRQn; #else irqn = USART6_IRQn; #endif @@ -480,7 +501,11 @@ bool uart_init(pyb_uart_obj_t *uart_obj, uart_fn = AF_FN_LPUART; uart_unit = 1; UARTx = LPUART1; + #if defined(STM32G0) + irqn = USART3_4_5_6_LPUART1_IRQn; + #else irqn = LPUART1_IRQn; + #endif pins[0] = MICROPY_HW_LPUART1_TX; pins[1] = MICROPY_HW_LPUART1_RX; #if defined(MICROPY_HW_LPUART1_RTS) @@ -497,6 +522,30 @@ bool uart_init(pyb_uart_obj_t *uart_obj, break; #endif + #if defined(MICROPY_HW_LPUART2_TX) && defined(MICROPY_HW_LPUART2_RX) + case PYB_LPUART_2: + uart_fn = AF_FN_LPUART; + uart_unit = 2; + UARTx = LPUART2; + #if defined(STM32G0) + irqn = USART2_LPUART2_IRQn; + #endif + pins[0] = MICROPY_HW_LPUART2_TX; + pins[1] = MICROPY_HW_LPUART2_RX; + #if defined(MICROPY_HW_LPUART2_RTS) + if (flow & UART_HWCONTROL_RTS) { + pins[2] = MICROPY_HW_LPUART2_RTS; + } + #endif + #if defined(MICROPY_HW_LPUART2_CTS) + if (flow & UART_HWCONTROL_CTS) { + pins[3] = MICROPY_HW_LPUART2_CTS; + } + #endif + __HAL_RCC_LPUART2_CLK_ENABLE(); + break; + #endif + default: // UART does not exist or is not configured for this board return false; @@ -626,14 +675,20 @@ void uart_deinit(pyb_uart_obj_t *self) { __HAL_RCC_USART1_CLK_DISABLE(); #if defined(USART2) } else if (self->uart_id == 2) { + #if defined(STM32G0) + HAL_NVIC_DisableIRQ(USART2_LPUART2_IRQn); + #else HAL_NVIC_DisableIRQ(USART2_IRQn); + #endif __HAL_RCC_USART2_FORCE_RESET(); __HAL_RCC_USART2_RELEASE_RESET(); __HAL_RCC_USART2_CLK_DISABLE(); #endif #if defined(USART3) } else if (self->uart_id == 3) { - #if !defined(STM32F0) + #if defined(STM32G0) + HAL_NVIC_DisableIRQ(USART3_4_5_6_LPUART1_IRQn); + #elif !defined(STM32F0) HAL_NVIC_DisableIRQ(USART3_IRQn); #endif __HAL_RCC_USART3_FORCE_RESET(); @@ -715,11 +770,26 @@ void uart_deinit(pyb_uart_obj_t *self) { #endif #if defined(LPUART1) } else if (self->uart_id == PYB_LPUART_1) { + #if defined(STM32G0) + HAL_NVIC_DisableIRQ(USART3_4_5_6_LPUART1_IRQn); + #else HAL_NVIC_DisableIRQ(LPUART1_IRQn); + #endif __HAL_RCC_LPUART1_FORCE_RESET(); __HAL_RCC_LPUART1_RELEASE_RESET(); __HAL_RCC_LPUART1_CLK_DISABLE(); #endif + #if defined(LPUART2) + } else if (self->uart_id == PYB_LPUART_2) { + #if defined(STM32G0) + HAL_NVIC_DisableIRQ(USART2_LPUART2_IRQn); + #else + HAL_NVIC_DisableIRQ(LPUART2_IRQn); + #endif + __HAL_RCC_LPUART2_FORCE_RESET(); + __HAL_RCC_LPUART2_RELEASE_RESET(); + __HAL_RCC_LPUART2_CLK_DISABLE(); + #endif } } @@ -730,7 +800,7 @@ void uart_attach_to_repl(pyb_uart_obj_t *self, bool attached) { uint32_t uart_get_source_freq(pyb_uart_obj_t *self) { uint32_t uart_clk = 0; - #if defined(STM32F0) + #if defined(STM32F0) || defined(STM32G0) uart_clk = HAL_RCC_GetPCLK1Freq(); #elif defined(STM32F7) switch ((RCC->DCKCFGR2 >> ((self->uart_id - 1) * 2)) & 3) { @@ -830,14 +900,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(STM32G4) || defined(STM32H7) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32WB) || defined(STM32WL) , self->uartx->PRESC #endif ); } #endif return LL_USART_GetBaudRate(self->uartx, uart_get_source_freq(self), - #if defined(STM32G4) || defined(STM32H7) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32WB) || defined(STM32WL) self->uartx->PRESC, #endif LL_USART_OVERSAMPLING_16); @@ -847,7 +917,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(STM32G4) || defined(STM32H7) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32WB) || defined(STM32WL) LL_LPUART_PRESCALER_DIV1, #endif baudrate); @@ -855,7 +925,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(STM32G4) || defined(STM32H7) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32WB) || defined(STM32WL) LL_USART_PRESCALER_DIV1, #endif LL_USART_OVERSAMPLING_16, baudrate); @@ -906,7 +976,7 @@ int uart_rx_char(pyb_uart_obj_t *self) { return data; } else { // no buffering - #if defined(STM32F0) || defined(STM32F7) || defined(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32F0) || defined(STM32F7) || defined(STM32G0) || defined(STM32G4) || 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; @@ -1056,7 +1126,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(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32F0) || defined(STM32F7) || defined(STM32G0) || defined(STM32G4) || 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/uart.h b/ports/stm32/uart.h index 5fee841f8..ec8a27591 100644 --- a/ports/stm32/uart.h +++ b/ports/stm32/uart.h @@ -43,6 +43,9 @@ typedef enum { #ifdef LPUART1 PYB_LPUART_1 = MICROPY_HW_MAX_UART + 1, #endif + #ifdef LPUART2 + PYB_LPUART_2 = MICROPY_HW_MAX_UART + 2, + #endif } pyb_uart_t; #define CHAR_WIDTH_8BIT (0) @@ -102,7 +105,7 @@ void uart_tx_strn(pyb_uart_obj_t *uart_obj, const char *str, uint len); static inline bool uart_tx_avail(pyb_uart_obj_t *self) { #if defined(STM32F4) return self->uartx->SR & USART_SR_TXE; - #elif defined(STM32H7) || defined(STM32WL) + #elif defined(STM32G0) || defined(STM32H7) || defined(STM32WL) return self->uartx->ISR & USART_ISR_TXE_TXFNF; #else return self->uartx->ISR & USART_ISR_TXE;