diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index cbfd8baa1a..afb21b048c 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -57,10 +57,15 @@ CFLAGS_CORTEX_M = -mthumb ifeq ($(CMSIS_MCU),$(filter $(CMSIS_MCU),STM32F767xx STM32F769xx STM32H743xx)) CFLAGS_CORTEX_M += -mfpu=fpv5-d16 -mfloat-abi=hard else +ifeq ($(MCU_SERIES),f0) +CFLAGS_CORTEX_M += -msoft-float +else CFLAGS_CORTEX_M += -mfpu=fpv4-sp-d16 -mfloat-abi=hard endif +endif # Options for particular MCU series +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_l4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 @@ -155,7 +160,6 @@ SRC_LIBM = $(addprefix lib/libm_dbl/,\ else SRC_LIBM = $(addprefix lib/libm/,\ math.c \ - thumb_vfp_sqrtf.c \ acoshf.c \ asinfacosf.c \ asinhf.c \ @@ -181,6 +185,11 @@ SRC_LIBM = $(addprefix lib/libm/,\ wf_lgamma.c \ wf_tgamma.c \ ) +ifeq ($(MCU_SERIES),f0) +SRC_LIBM += lib/libm/ef_sqrt.c +else +SRC_LIBM += lib/libm/thumb_vfp_sqrtf.c +endif endif EXTMOD_SRC_C = $(addprefix extmod/,\ @@ -197,7 +206,6 @@ DRIVERS_SRC_C = $(addprefix drivers/,\ SRC_C = \ main.c \ - system_stm32.c \ stm32_it.c \ usbd_conf.c \ usbd_desc.c \ @@ -252,10 +260,19 @@ SRC_C = \ adc.c \ $(wildcard boards/$(BOARD)/*.c) +ifeq ($(MCU_SERIES),f0) SRC_O = \ $(STARTUP_FILE) \ + system_stm32f0.o \ + resethandler_m0.o \ + gchelper_m0.o +else +SRC_O = \ + $(STARTUP_FILE) \ + system_stm32.o \ resethandler.o \ - gchelper.o \ + gchelper.o +endif SRC_HAL = $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\ hal.c \ @@ -277,14 +294,19 @@ SRC_HAL = $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\ hal_rcc_ex.c \ hal_rtc.c \ hal_rtc_ex.c \ - hal_sd.c \ hal_spi.c \ hal_tim.c \ hal_tim_ex.c \ hal_uart.c \ + ) + +ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 h7 l4)) +SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\ + hal_sd.c \ ll_sdmmc.c \ ll_usb.c \ ) +endif ifeq ($(CMSIS_MCU),$(filter $(CMSIS_MCU),STM32H743xx)) SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_, hal_fdcan.c) diff --git a/ports/stm32/adc.c b/ports/stm32/adc.c index 773cccd40e..f439503e61 100644 --- a/ports/stm32/adc.c +++ b/ports/stm32/adc.c @@ -59,7 +59,15 @@ #define ADCx_CLK_ENABLE __HAL_RCC_ADC1_CLK_ENABLE #define ADC_NUM_CHANNELS (19) -#if defined(STM32F4) +#if defined(STM32F0) + +#define ADC_FIRST_GPIO_CHANNEL (0) +#define ADC_LAST_GPIO_CHANNEL (15) +#define ADC_CAL_ADDRESS (0x1ffff7ba) +#define ADC_CAL1 ((uint16_t*)0x1ffff7b8) +#define ADC_CAL2 ((uint16_t*)0x1ffff7c2) + +#elif defined(STM32F4) #define ADC_FIRST_GPIO_CHANNEL (0) #define ADC_LAST_GPIO_CHANNEL (15) @@ -104,7 +112,9 @@ #endif -#if defined(STM32F405xx) || defined(STM32F415xx) || \ +#if defined(STM32F091xC) +#define VBAT_DIV (2) +#elif defined(STM32F405xx) || defined(STM32F415xx) || \ defined(STM32F407xx) || defined(STM32F417xx) || \ defined(STM32F401xC) || defined(STM32F401xE) || \ defined(STM32F411xE) @@ -159,7 +169,7 @@ STATIC bool is_adcx_channel(int channel) { #if defined(STM32F411xE) // The HAL has an incorrect IS_ADC_CHANNEL macro for the F411 so we check for temp return IS_ADC_CHANNEL(channel) || channel == ADC_CHANNEL_TEMPSENSOR; -#elif defined(STM32F4) || defined(STM32F7) || defined(STM32H7) +#elif defined(STM32F0) || defined(STM32F4) || defined(STM32F7) || defined(STM32H7) return IS_ADC_CHANNEL(channel); #elif defined(STM32L4) ADC_HandleTypeDef handle; @@ -174,7 +184,7 @@ STATIC void adc_wait_for_eoc_or_timeout(int32_t timeout) { uint32_t tickstart = HAL_GetTick(); #if defined(STM32F4) || defined(STM32F7) while ((ADCx->SR & ADC_FLAG_EOC) != ADC_FLAG_EOC) { -#elif defined(STM32H7) || defined(STM32L4) +#elif defined(STM32F0) || defined(STM32H7) || defined(STM32L4) while (READ_BIT(ADCx->ISR, ADC_FLAG_EOC) != ADC_FLAG_EOC) { #else #error Unsupported processor @@ -186,7 +196,7 @@ STATIC void adc_wait_for_eoc_or_timeout(int32_t timeout) { } STATIC void adcx_clock_enable(void) { -#if defined(STM32F4) || defined(STM32F7) +#if defined(STM32F0) || defined(STM32F4) || defined(STM32F7) ADCx_CLK_ENABLE(); #elif defined(STM32H7) __HAL_RCC_ADC3_CLK_ENABLE(); @@ -205,12 +215,14 @@ 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) adch->Init.NbrOfDiscConversion = 0; adch->Init.NbrOfConversion = 1; + #endif adch->Init.EOCSelection = ADC_EOC_SINGLE_CONV; adch->Init.ExternalTrigConv = ADC_SOFTWARE_START; adch->Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; - #if defined(STM32F4) || defined(STM32F7) + #if defined(STM32F0) || defined(STM32F4) || defined(STM32F7) adch->Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; adch->Init.ScanConvMode = DISABLE; adch->Init.DataAlign = ADC_DATAALIGN_RIGHT; @@ -271,7 +283,9 @@ STATIC void adc_config_channel(ADC_HandleTypeDef *adc_handle, uint32_t channel) sConfig.Channel = channel; sConfig.Rank = 1; -#if defined(STM32F4) || defined(STM32F7) +#if defined(STM32F0) + sConfig.SamplingTime = ADC_SAMPLETIME_28CYCLES_5; +#elif defined(STM32F4) || defined(STM32F7) sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES; #elif defined(STM32H7) sConfig.SamplingTime = ADC_SAMPLETIME_8CYCLES_5; @@ -283,10 +297,10 @@ STATIC void adc_config_channel(ADC_HandleTypeDef *adc_handle, uint32_t channel) sConfig.SamplingTime = ADC_SAMPLETIME_12CYCLES_5; sConfig.SingleDiff = ADC_SINGLE_ENDED; sConfig.OffsetNumber = ADC_OFFSET_NONE; + sConfig.Offset = 0; #else #error Unsupported processor #endif - sConfig.Offset = 0; HAL_ADC_ConfigChannel(adc_handle, &sConfig); } @@ -443,7 +457,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) ADCx->CR2 |= (uint32_t)ADC_CR2_SWSTART; -#elif defined(STM32H7) || defined(STM32L4) +#elif defined(STM32F0) || defined(STM32H7) || defined(STM32L4) SET_BIT(ADCx->CR, ADC_CR_ADSTART); #else #error Unsupported processor @@ -553,7 +567,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) ADCx->CR2 |= (uint32_t)ADC_CR2_SWSTART; - #elif defined(STM32H7) || defined(STM32L4) + #elif defined(STM32F0) || defined(STM32H7) || defined(STM32L4) SET_BIT(ADCx->CR, ADC_CR_ADSTART); #else #error Unsupported processor diff --git a/ports/stm32/dac.c b/ports/stm32/dac.c index 0c9e0ae0cf..559bb0b0d0 100644 --- a/ports/stm32/dac.c +++ b/ports/stm32/dac.c @@ -177,7 +177,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(STM32L4) + #elif defined(STM32F0) || defined(STM32L4) __HAL_RCC_DAC1_CLK_ENABLE(); #else #error Unsupported Processor diff --git a/ports/stm32/dma.c b/ports/stm32/dma.c index 499649b36d..dc1ad6c1cd 100644 --- a/ports/stm32/dma.c +++ b/ports/stm32/dma.c @@ -55,7 +55,7 @@ typedef enum { struct _dma_descr_t { #if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) DMA_Stream_TypeDef *instance; - #elif defined(STM32L4) + #elif defined(STM32F0) || defined(STM32L4) DMA_Channel_TypeDef *instance; #else #error "Unsupported Processor" @@ -141,7 +141,46 @@ static const DMA_InitTypeDef dma_init_struct_dac = { }; #endif -#if defined(STM32F4) || defined(STM32F7) +#if defined(STM32F0) + +#define NCONTROLLERS (2) +#define NSTREAMS_PER_CONTROLLER (7) +#define NSTREAM (NCONTROLLERS * NSTREAMS_PER_CONTROLLER) + +#define DMA_SUB_INSTANCE_AS_UINT8(dma_channel) (dma_channel) + +#define DMA1_ENABLE_MASK (0x007f) // Bits in dma_enable_mask corresponfing 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, HAL_DMA1_CH3_DAC_CH1, DMA_MEMORY_TO_PERIPH, dma_id_3, &dma_init_struct_dac }; +const dma_descr_t dma_DAC_2_TX = { DMA1_Channel4, HAL_DMA1_CH4_DAC_CH2, DMA_MEMORY_TO_PERIPH, dma_id_4, &dma_init_struct_dac }; +#endif +const dma_descr_t dma_SPI_2_TX = { DMA1_Channel5, HAL_DMA1_CH5_SPI2_TX, DMA_MEMORY_TO_PERIPH, dma_id_5, &dma_init_struct_spi_i2c}; +const dma_descr_t dma_SPI_2_RX = { DMA1_Channel6, HAL_DMA1_CH6_SPI2_RX, DMA_PERIPH_TO_MEMORY, dma_id_6, &dma_init_struct_spi_i2c}; +const dma_descr_t dma_SPI_1_RX = { DMA2_Channel3, HAL_DMA2_CH3_SPI1_RX, DMA_PERIPH_TO_MEMORY, dma_id_3, &dma_init_struct_spi_i2c}; +const dma_descr_t dma_SPI_1_TX = { DMA2_Channel4, HAL_DMA2_CH4_SPI1_TX, DMA_MEMORY_TO_PERIPH, dma_id_4, &dma_init_struct_spi_i2c}; + +static const uint8_t dma_irqn[NSTREAM] = { + DMA1_Ch1_IRQn, + DMA1_Ch2_3_DMA2_Ch1_2_IRQn, + DMA1_Ch2_3_DMA2_Ch1_2_IRQn, + DMA1_Ch4_7_DMA2_Ch3_5_IRQn, + DMA1_Ch4_7_DMA2_Ch3_5_IRQn, + DMA1_Ch4_7_DMA2_Ch3_5_IRQn, + DMA1_Ch4_7_DMA2_Ch3_5_IRQn, + + DMA1_Ch2_3_DMA2_Ch1_2_IRQn, + DMA1_Ch2_3_DMA2_Ch1_2_IRQn, + DMA1_Ch4_7_DMA2_Ch3_5_IRQn, + DMA1_Ch4_7_DMA2_Ch3_5_IRQn, + DMA1_Ch4_7_DMA2_Ch3_5_IRQn, + 0, + 0, +}; + +#elif defined(STM32F4) || defined(STM32F7) #define NCONTROLLERS (2) #define NSTREAMS_PER_CONTROLLER (8) @@ -381,8 +420,13 @@ volatile dma_idle_count_t dma_idle; #define DMA_INVALID_CHANNEL 0xff // Value stored in dma_last_channel which means invalid +#if defined(STM32F0) +#define DMA1_IS_CLK_ENABLED() ((RCC->AHBENR & RCC_AHBENR_DMA1EN) != 0) +#define DMA2_IS_CLK_ENABLED() ((RCC->AHBENR & RCC_AHBENR_DMA2EN) != 0) +#else #define DMA1_IS_CLK_ENABLED() ((RCC->AHB1ENR & RCC_AHB1ENR_DMA1EN) != 0) #define DMA2_IS_CLK_ENABLED() ((RCC->AHB1ENR & RCC_AHB1ENR_DMA2EN) != 0) +#endif #if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) @@ -476,8 +520,10 @@ void dma_init_handle(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, void #if defined(STM32L4) || defined(STM32H7) dma->Init.Request = dma_descr->sub_instance; #else + #if !defined(STM32F0) dma->Init.Channel = dma_descr->sub_instance; #endif + #endif // half of __HAL_LINKDMA(data, xxx, *dma) // caller must implement other half by doing: data->xxx = dma dma->Parent = data; @@ -517,6 +563,13 @@ void dma_init(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, void *data){ HAL_DMA_DeInit(dma); HAL_DMA_Init(dma); NVIC_SetPriority(IRQn_NONNEG(dma_irqn[dma_id]), IRQ_PRI_DMA); + #if defined(STM32F0) + if (dma->Instance < DMA2_Channel1) { + __HAL_DMA1_REMAP(dma_descr->sub_instance); + } else { + __HAL_DMA2_REMAP(dma_descr->sub_instance); + } + #endif } else { // only necessary initialization dma->State = HAL_DMA_STATE_READY; diff --git a/ports/stm32/dma.h b/ports/stm32/dma.h index f265d60357..cacabe9253 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(STM32F4) || defined(STM32F7) || defined(STM32H7) +#if defined(STM32F0) || defined(STM32F4) || defined(STM32F7) || 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 844cfb0622..70bf7eae7e 100644 --- a/ports/stm32/extint.c +++ b/ports/stm32/extint.c @@ -133,6 +133,12 @@ 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) + EXTI0_1_IRQn, EXTI0_1_IRQn, EXTI2_3_IRQn, EXTI2_3_IRQn, + EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, + EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, + EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, + #else EXTI0_IRQn, EXTI1_IRQn, EXTI2_IRQn, EXTI3_IRQn, EXTI4_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, @@ -148,6 +154,7 @@ STATIC const uint8_t nvic_irq_channel[EXTI_NUM_VECTORS] = { OTG_HS_WKUP_IRQn, TAMP_STAMP_IRQn, RTC_WKUP_IRQn, + #endif }; // Set override_callback_obj to true if you want to unconditionally set the @@ -282,7 +289,7 @@ void extint_enable(uint line) { if (line >= EXTI_NUM_VECTORS) { return; } - #if defined(STM32F7) || defined(STM32H7) + #if defined(STM32F0) || defined(STM32F7) || defined(STM32H7) // The Cortex-M7 doesn't have bitband support. mp_uint_t irq_state = disable_irq(); if (pyb_extint_mode[line] == EXTI_Mode_Interrupt) { @@ -312,7 +319,7 @@ void extint_disable(uint line) { return; } - #if defined(STM32F7) || defined(STM32H7) + #if defined(STM32F0) || defined(STM32F7) || defined(STM32H7) // The Cortex-M7 doesn't have bitband support. mp_uint_t irq_state = disable_irq(); #if defined(STM32H7) diff --git a/ports/stm32/flash.c b/ports/stm32/flash.c index bc5b3c60c2..d3a568858c 100644 --- a/ports/stm32/flash.c +++ b/ports/stm32/flash.c @@ -34,7 +34,13 @@ typedef struct { uint32_t sector_count; } flash_layout_t; -#if defined(STM32F4) +#if defined(STM32F0) + +static const flash_layout_t flash_layout[] = { + { FLASH_BASE, FLASH_PAGE_SIZE, (FLASH_BANK1_END + 1 - FLASH_BASE) / FLASH_PAGE_SIZE }, +}; + +#elif defined(STM32F4) static const flash_layout_t flash_layout[] = { { 0x08000000, 0x04000, 4 }, @@ -153,7 +159,12 @@ void flash_erase(uint32_t flash_dest, uint32_t num_word32) { FLASH_EraseInitTypeDef EraseInitStruct; - #if defined(STM32L4) + #if defined(STM32F0) + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR); + EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; + EraseInitStruct.PageAddress = flash_dest; + EraseInitStruct.NbPages = (4 * num_word32 + FLASH_PAGE_SIZE - 4) / FLASH_PAGE_SIZE; + #elif defined(STM32L4) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); // erase the sector(s) diff --git a/ports/stm32/i2c.c b/ports/stm32/i2c.c index a717ca7b39..e0eea90ab7 100644 --- a/ports/stm32/i2c.c +++ b/ports/stm32/i2c.c @@ -262,7 +262,7 @@ int i2c_write(i2c_t *i2c, const uint8_t *src, size_t len, size_t next_len) { return num_acks; } -#elif defined(STM32F7) +#elif defined(STM32F0) || defined(STM32F7) int i2c_init(i2c_t *i2c, mp_hal_pin_obj_t scl, mp_hal_pin_obj_t sda, uint32_t freq) { uint32_t i2c_id = ((uint32_t)i2c - I2C1_BASE) / (I2C2_BASE - I2C1_BASE); @@ -446,7 +446,7 @@ int i2c_write(i2c_t *i2c, const uint8_t *src, size_t len, size_t next_len) { #endif -#if defined(STM32F4) || defined(STM32F7) +#if defined(STM32F0) || defined(STM32F4) || defined(STM32F7) int i2c_readfrom(i2c_t *i2c, uint16_t addr, uint8_t *dest, size_t len, bool stop) { int ret; diff --git a/ports/stm32/machine_i2c.c b/ports/stm32/machine_i2c.c index 4cb1dc97d6..b7a9ea69bf 100644 --- a/ports/stm32/machine_i2c.c +++ b/ports/stm32/machine_i2c.c @@ -37,7 +37,7 @@ STATIC const mp_obj_type_t machine_hard_i2c_type; -#if defined(STM32F4) || defined(STM32F7) +#if defined(STM32F0) || defined(STM32F4) || defined(STM32F7) typedef struct _machine_hard_i2c_obj_t { mp_obj_base_t base; diff --git a/ports/stm32/modmachine.c b/ports/stm32/modmachine.c index d8054c3f25..158f5f2b34 100644 --- a/ports/stm32/modmachine.c +++ b/ports/stm32/modmachine.c @@ -110,7 +110,11 @@ 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 || state & RCC_SR_BORRSTF) { + } else if (state & RCC_SR_PORRSTF + #if !defined(STM32F0) + || state & RCC_SR_BORRSTF + #endif + ) { reset_cause = PYB_RESET_POWER_ON; } else if (state & RCC_SR_PINRSTF) { reset_cause = PYB_RESET_HARD; @@ -140,11 +144,18 @@ 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) + printf("S=%u\nH=%u\nP1=%u\n", + (unsigned int)HAL_RCC_GetSysClockFreq(), + (unsigned int)HAL_RCC_GetHCLKFreq(), + (unsigned int)HAL_RCC_GetPCLK1Freq()); + #else printf("S=%u\nH=%u\nP1=%u\nP2=%u\n", (unsigned int)HAL_RCC_GetSysClockFreq(), (unsigned int)HAL_RCC_GetHCLKFreq(), (unsigned int)HAL_RCC_GetPCLK1Freq(), (unsigned int)HAL_RCC_GetPCLK2Freq()); + #endif } // to print info about memory @@ -267,6 +278,7 @@ STATIC NORETURN mp_obj_t machine_bootloader(void) { } MP_DEFINE_CONST_FUN_OBJ_0(machine_bootloader_obj, machine_bootloader); +#if !(defined(STM32F0) || defined(STM32L4)) // get or set the MCU frequencies STATIC mp_uint_t machine_freq_calc_ahb_div(mp_uint_t wanted_div) { if (wanted_div <= 1) { return RCC_SYSCLK_DIV1; } @@ -286,23 +298,28 @@ STATIC mp_uint_t machine_freq_calc_apb_div(mp_uint_t wanted_div) { else if (wanted_div <= 8) { return RCC_HCLK_DIV8; } else { return RCC_SYSCLK_DIV16; } } +#endif + STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) { if (n_args == 0) { // get - mp_obj_t tuple[4] = { + mp_obj_t tuple[] = { mp_obj_new_int(HAL_RCC_GetSysClockFreq()), mp_obj_new_int(HAL_RCC_GetHCLKFreq()), mp_obj_new_int(HAL_RCC_GetPCLK1Freq()), + #if !defined(STM32F0) mp_obj_new_int(HAL_RCC_GetPCLK2Freq()), + #endif }; - return mp_obj_new_tuple(4, tuple); + return mp_obj_new_tuple(MP_ARRAY_SIZE(tuple), tuple); } else { // set - mp_int_t wanted_sysclk = mp_obj_get_int(args[0]) / 1000000; - #if defined(STM32L4) + #if defined(STM32F0) || defined(STM32L4) mp_raise_NotImplementedError("machine.freq set not supported yet"); - #endif + #else + + mp_int_t wanted_sysclk = mp_obj_get_int(args[0]) / 1000000; // default PLL parameters that give 48MHz on PLL48CK uint32_t m = HSE_VALUE / 1000000, n = 336, p = 2, q = 7; @@ -458,6 +475,8 @@ STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) { fail:; void NORETURN __fatal_error(const char *msg); __fatal_error("can't change freq"); + + #endif } } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_freq_obj, 0, 4, machine_freq); @@ -492,8 +511,10 @@ STATIC mp_obj_t machine_sleep(void) { #else + #if !defined(STM32F0) // takes longer to wake but reduces stop current HAL_PWREx_EnableFlashPowerDown(); + #endif # if defined(STM32F7) HAL_PWR_EnterSTOPMode((PWR_CR1_LPDS | PWR_CR1_LPUDS | PWR_CR1_FPDS | PWR_CR1_UDEN), PWR_STOPENTRY_WFI); @@ -542,16 +563,22 @@ STATIC mp_obj_t machine_deepsleep(void) { // Note: we only support RTC ALRA, ALRB, WUT and TS. // TODO support TAMP and WKUP (PA0 external pin). - uint32_t irq_bits = RTC_CR_ALRAIE | RTC_CR_ALRBIE | RTC_CR_WUTIE | RTC_CR_TSIE; + #if defined(STM32F0) + #define CR_BITS (RTC_CR_ALRAIE | RTC_CR_WUTIE | RTC_CR_TSIE) + #define ISR_BITS (RTC_ISR_ALRAF | RTC_ISR_WUTF | RTC_ISR_TSF) + #else + #define CR_BITS (RTC_CR_ALRAIE | RTC_CR_ALRBIE | RTC_CR_WUTIE | RTC_CR_TSIE) + #define ISR_BITS (RTC_ISR_ALRAF | RTC_ISR_ALRBF | RTC_ISR_WUTF | RTC_ISR_TSF) + #endif // save RTC interrupts - uint32_t save_irq_bits = RTC->CR & irq_bits; + uint32_t save_irq_bits = RTC->CR & CR_BITS; // disable RTC interrupts - RTC->CR &= ~irq_bits; + RTC->CR &= ~CR_BITS; // clear RTC wake-up flags - RTC->ISR &= ~(RTC_ISR_ALRAF | RTC_ISR_ALRBF | RTC_ISR_WUTF | RTC_ISR_TSF); + RTC->ISR &= ~ISR_BITS; #if defined(STM32F7) // disable wake-up flags diff --git a/ports/stm32/mpconfigboard_common.h b/ports/stm32/mpconfigboard_common.h index 919598de44..2cc02b77cf 100644 --- a/ports/stm32/mpconfigboard_common.h +++ b/ports/stm32/mpconfigboard_common.h @@ -110,8 +110,16 @@ /*****************************************************************************/ // General configuration +// Configuration for STM32F0 series +#if defined(STM32F0) + +#define MP_HAL_UNIQUE_ID_ADDRESS (0x1ffff7ac) +#define PYB_EXTI_NUM_VECTORS (23) +#define MICROPY_HW_MAX_TIMER (17) +#define MICROPY_HW_MAX_UART (8) + // Configuration for STM32F4 series -#if defined(STM32F4) +#elif defined(STM32F4) #define MP_HAL_UNIQUE_ID_ADDRESS (0x1fff7a10) #define PYB_EXTI_NUM_VECTORS (23) diff --git a/ports/stm32/mphalport.c b/ports/stm32/mphalport.c index 2bf10ad479..a2f8e412ee 100644 --- a/ports/stm32/mphalport.c +++ b/ports/stm32/mphalport.c @@ -111,7 +111,10 @@ void mp_hal_gpio_clock_enable(GPIO_TypeDef *gpio) { // This logic assumes that all the GPIOx_EN bits are adjacent and ordered in one register - #if defined(STM32F4) || defined(STM32F7) + #if defined(STM32F0) + #define AHBxENR AHBENR + #define AHBxENR_GPIOAEN_Pos RCC_AHBENR_GPIOAEN_Pos + #elif defined(STM32F4) || defined(STM32F7) #define AHBxENR AHB1ENR #define AHBxENR_GPIOAEN_Pos RCC_AHB1ENR_GPIOAEN_Pos #elif defined(STM32H7) diff --git a/ports/stm32/rtc.c b/ports/stm32/rtc.c index 4134037124..c51dfab119 100644 --- a/ports/stm32/rtc.c +++ b/ports/stm32/rtc.c @@ -539,6 +539,10 @@ 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) +#define RTC_WKUP_IRQn RTC_IRQn +#endif + // wakeup(None) // wakeup(ms, callback=None) // wakeup(wucksel, wut, callback) diff --git a/ports/stm32/spi.c b/ports/stm32/spi.c index a6e7143171..c578ac7da2 100644 --- a/ports/stm32/spi.c +++ b/ports/stm32/spi.c @@ -203,6 +203,9 @@ STATIC void spi_set_params(const spi_t *spi_obj, uint32_t prescale, int32_t baud if (prescale == 0xffffffff) { // prescaler not given, so select one that yields at most the requested baudrate mp_uint_t spi_clock; + #if defined(STM32F0) + spi_clock = HAL_RCC_GetPCLK1Freq(); + #else if (spi->Instance == SPI2 || spi->Instance == SPI3) { // SPI2 and SPI3 are on APB1 spi_clock = HAL_RCC_GetPCLK1Freq(); @@ -210,6 +213,7 @@ STATIC void spi_set_params(const spi_t *spi_obj, uint32_t prescale, int32_t baud // SPI1, SPI4, SPI5 and SPI6 are on APB2 spi_clock = HAL_RCC_GetPCLK2Freq(); } + #endif prescale = spi_clock / baudrate; } if (prescale <= 2) { init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; } @@ -500,7 +504,9 @@ STATIC void spi_print(const mp_print_t *print, const spi_t *spi_obj, bool legacy uint spi_num = 1; // default to SPI1 if (spi->Instance == SPI2) { spi_num = 2; } + #if defined(SPI3) else if (spi->Instance == SPI3) { spi_num = 3; } + #endif #if defined(SPI4) else if (spi->Instance == SPI4) { spi_num = 4; } #endif @@ -516,6 +522,9 @@ STATIC void spi_print(const mp_print_t *print, const spi_t *spi_obj, bool legacy if (spi->Init.Mode == SPI_MODE_MASTER) { // compute baudrate uint spi_clock; + #if defined(STM32F0) + spi_clock = HAL_RCC_GetPCLK1Freq(); + #else if (spi->Instance == SPI2 || spi->Instance == SPI3) { // SPI2 and SPI3 are on APB1 spi_clock = HAL_RCC_GetPCLK1Freq(); @@ -523,6 +532,7 @@ STATIC void spi_print(const mp_print_t *print, const spi_t *spi_obj, bool legacy // SPI1, SPI4, SPI5 and SPI6 are on APB2 spi_clock = HAL_RCC_GetPCLK2Freq(); } + #endif uint log_prescaler = (spi->Init.BaudRatePrescaler >> 3) + 1; uint baudrate = spi_clock >> log_prescaler; if (legacy) { diff --git a/ports/stm32/stm32_it.c b/ports/stm32/stm32_it.c index 8202209775..c09ffce767 100644 --- a/ports/stm32/stm32_it.c +++ b/ports/stm32/stm32_it.c @@ -579,6 +579,39 @@ void RTC_WKUP_IRQHandler(void) { IRQ_EXIT(RTC_WKUP_IRQn); } +#if defined(STM32F0) + +void RTC_IRQHandler(void) { + IRQ_ENTER(RTC_IRQn); + RTC->ISR &= ~(1 << 10); // clear wakeup interrupt flag + Handle_EXTI_Irq(EXTI_RTC_WAKEUP); // clear EXTI flag and execute optional callback + IRQ_EXIT(RTC_IRQn); +} + +void EXTI0_1_IRQHandler(void) { + IRQ_ENTER(EXTI0_1_IRQn); + Handle_EXTI_Irq(0); + Handle_EXTI_Irq(1); + IRQ_EXIT(EXTI0_1_IRQn); +} + +void EXTI2_3_IRQHandler(void) { + IRQ_ENTER(EXTI2_3_IRQn); + Handle_EXTI_Irq(2); + Handle_EXTI_Irq(3); + IRQ_EXIT(EXTI2_3_IRQn); +} + +void EXTI4_15_IRQHandler(void) { + IRQ_ENTER(EXTI4_15_IRQn); + for (int i = 4; i <= 15; ++i) { + Handle_EXTI_Irq(i); + } + IRQ_EXIT(EXTI4_15_IRQn); +} + +#endif + void TIM1_BRK_TIM9_IRQHandler(void) { IRQ_ENTER(TIM1_BRK_TIM9_IRQn); timer_irq_handler(9); @@ -718,6 +751,21 @@ void USART2_IRQHandler(void) { IRQ_EXIT(USART2_IRQn); } +#if defined(STM32F0) + +void USART3_8_IRQHandler(void) { + IRQ_ENTER(USART3_8_IRQn); + uart_irq_handler(3); + uart_irq_handler(4); + uart_irq_handler(5); + uart_irq_handler(6); + uart_irq_handler(7); + uart_irq_handler(8); + IRQ_EXIT(USART3_8_IRQn); +} + +#else + void USART3_IRQHandler(void) { IRQ_ENTER(USART3_IRQn); uart_irq_handler(3); @@ -758,6 +806,8 @@ void UART8_IRQHandler(void) { } #endif +#endif + #if defined(MICROPY_HW_CAN1_TX) void CAN1_RX0_IRQHandler(void) { IRQ_ENTER(CAN1_RX0_IRQn); diff --git a/ports/stm32/system_stm32f0.c b/ports/stm32/system_stm32f0.c new file mode 100644 index 0000000000..9d4b06e568 --- /dev/null +++ b/ports/stm32/system_stm32f0.c @@ -0,0 +1,203 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * Taken from ST Cube library and modified. See below for original header. + */ + +/** + ****************************************************************************** + * @file system_stm32f0xx.c + * @author MCD Application Team + * @brief CMSIS Cortex-M0 Device Peripheral Access Layer System Source File. + * + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2016 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +#include STM32_HAL_H + +#ifndef HSE_VALUE +#define HSE_VALUE (8000000) +#endif + +#ifndef HSI_VALUE +#define HSI_VALUE (8000000) +#endif + +#ifndef HSI48_VALUE +#define HSI48_VALUE (48000000) +#endif + +/* This variable is updated in three ways: + 1) by calling CMSIS function SystemCoreClockUpdate() + 2) by calling HAL API function HAL_RCC_GetHCLKFreq() + 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency + Note: If you use this function to configure the system clock there is no need to + call the 2 first functions listed above, since SystemCoreClock variable is + updated automatically. +*/ +uint32_t SystemCoreClock = 8000000; + +const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; +const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; + +void SystemInit(void) { + // Set HSION bit + RCC->CR |= (uint32_t)0x00000001U; + + #if defined(STM32F051x8) || defined(STM32F058x8) + // Reset SW[1:0], HPRE[3:0], PPRE[2:0], ADCPRE and MCOSEL[2:0] bits + RCC->CFGR &= (uint32_t)0xF8FFB80CU; + #else + // Reset SW[1:0], HPRE[3:0], PPRE[2:0], ADCPRE, MCOSEL[2:0], MCOPRE[2:0] and PLLNODIV bits + RCC->CFGR &= (uint32_t)0x08FFB80CU; + #endif + + // Reset HSEON, CSSON and PLLON bits + RCC->CR &= (uint32_t)0xFEF6FFFFU; + + // Reset HSEBYP bit + RCC->CR &= (uint32_t)0xFFFBFFFFU; + + // Reset PLLSRC, PLLXTPRE and PLLMUL[3:0] bits + RCC->CFGR &= (uint32_t)0xFFC0FFFFU; + + // Reset PREDIV[3:0] bits + RCC->CFGR2 &= (uint32_t)0xFFFFFFF0U; + + #if defined(STM32F072xB) || defined(STM32F078xx) + // Reset USART2SW[1:0], USART1SW[1:0], I2C1SW, CECSW, USBSW and ADCSW bits + RCC->CFGR3 &= (uint32_t)0xFFFCFE2CU; + #elif defined(STM32F071xB) + // Reset USART2SW[1:0], USART1SW[1:0], I2C1SW, CECSW and ADCSW bits + RCC->CFGR3 &= (uint32_t)0xFFFFCEACU; + #elif defined(STM32F091xC) || defined(STM32F098xx) + // Reset USART3SW[1:0], USART2SW[1:0], USART1SW[1:0], I2C1SW, CECSW and ADCSW bits + RCC->CFGR3 &= (uint32_t)0xFFF0FEACU; + #elif defined(STM32F030x6) || defined(STM32F030x8) || defined(STM32F031x6) || defined(STM32F038xx) || defined(STM32F030xC) + // Reset USART1SW[1:0], I2C1SW and ADCSW bits + RCC->CFGR3 &= (uint32_t)0xFFFFFEECU; + #elif defined(STM32F051x8) || defined(STM32F058xx) + // Reset USART1SW[1:0], I2C1SW, CECSW and ADCSW bits + RCC->CFGR3 &= (uint32_t)0xFFFFFEACU; + #elif defined(STM32F042x6) || defined(STM32F048xx) + // Reset USART1SW[1:0], I2C1SW, CECSW, USBSW and ADCSW bits + RCC->CFGR3 &= (uint32_t)0xFFFFFE2CU; + #elif defined(STM32F070x6) || defined(STM32F070xB) + // Reset USART1SW[1:0], I2C1SW, USBSW and ADCSW bits + RCC->CFGR3 &= (uint32_t)0xFFFFFE6CU; + // Set default USB clock to PLLCLK, since there is no HSI48 + RCC->CFGR3 |= (uint32_t)0x00000080U; + #else + #warning "No target selected" + #endif + + // Reset HSI14 bit + RCC->CR2 &= (uint32_t)0xFFFFFFFEU; + + // Disable all interrupts + RCC->CIR = 0x00000000U; + + // dpgeorge: enable 8-byte stack alignment for IRQ handlers, in accord with EABI + SCB->CCR |= SCB_CCR_STKALIGN_Msk; +} + +void SystemClock_Config(void) { + // Set flash latency to 1 because SYSCLK > 24MHz + FLASH->ACR = (FLASH->ACR & ~0x7) | 0x1; + + // Use the 48MHz internal oscillator + RCC->CR2 |= RCC_CR2_HSI48ON; + while ((RCC->CR2 & RCC_CR2_HSI48RDY) == 0) { + } + RCC->CFGR |= 3 << RCC_CFGR_SW_Pos; + while (((RCC->CFGR >> RCC_CFGR_SWS_Pos) & 0x3) != 0x03) { + // Wait for SYSCLK source to change + } + + SystemCoreClockUpdate(); + + HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000); + HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); +} + +void SystemCoreClockUpdate(void) { + // Get SYSCLK source + uint32_t tmp = RCC->CFGR & RCC_CFGR_SWS; + + switch (tmp) { + case RCC_CFGR_SWS_HSI: + SystemCoreClock = HSI_VALUE; + break; + case RCC_CFGR_SWS_HSE: + SystemCoreClock = HSE_VALUE; + break; + case RCC_CFGR_SWS_PLL: { + /* Get PLL clock source and multiplication factor */ + uint32_t pllmull = RCC->CFGR & RCC_CFGR_PLLMUL; + uint32_t pllsource = RCC->CFGR & RCC_CFGR_PLLSRC; + pllmull = (pllmull >> 18) + 2; + uint32_t predivfactor = (RCC->CFGR2 & RCC_CFGR2_PREDIV) + 1; + + if (pllsource == RCC_CFGR_PLLSRC_HSE_PREDIV) { + /* HSE used as PLL clock source : SystemCoreClock = HSE/PREDIV * PLLMUL */ + SystemCoreClock = (HSE_VALUE/predivfactor) * pllmull; + #if defined(STM32F042x6) || defined(STM32F048xx) || defined(STM32F072xB) \ + || defined(STM32F078xx) || defined(STM32F091xC) || defined(STM32F098xx) + } else if (pllsource == RCC_CFGR_PLLSRC_HSI48_PREDIV) { + /* HSI48 used as PLL clock source : SystemCoreClock = HSI48/PREDIV * PLLMUL */ + SystemCoreClock = (HSI48_VALUE/predivfactor) * pllmull; + #endif + } else { + #if defined(STM32F042x6) || defined(STM32F048xx) || defined(STM32F070x6) \ + || defined(STM32F078xx) || defined(STM32F071xB) || defined(STM32F072xB) \ + || defined(STM32F070xB) || defined(STM32F091xC) || defined(STM32F098xx) || defined(STM32F030xC) + /* HSI used as PLL clock source : SystemCoreClock = HSI/PREDIV * PLLMUL */ + SystemCoreClock = (HSI_VALUE / predivfactor) * pllmull; + #else + /* HSI used as PLL clock source : SystemCoreClock = HSI/2 * PLLMUL */ + SystemCoreClock = (HSI_VALUE >> 1) * pllmull; + #endif + } + break; + } + case RCC_CFGR_SWS_HSI48: + SystemCoreClock = HSI48_VALUE; + break; + default: + SystemCoreClock = HSI_VALUE; + break; + } + + // Compute HCLK clock frequency + tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; + SystemCoreClock >>= tmp; +} + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/timer.c b/ports/stm32/timer.c index fd719b2f2c..cc00f7a887 100644 --- a/ports/stm32/timer.c +++ b/ports/stm32/timer.c @@ -231,16 +231,22 @@ 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) + source = HAL_RCC_GetPCLK1Freq(); + clk_div = RCC->CFGR & RCC_CFGR_PPRE; + #elif defined(STM32H7) source = HAL_RCC_GetPCLK2Freq(); - #if defined(STM32H7) clk_div = RCC->D2CFGR & RCC_D2CFGR_D2PPRE2; #else + source = HAL_RCC_GetPCLK2Freq(); clk_div = RCC->CFGR & RCC_CFGR_PPRE2; #endif } else { // TIM{2,3,4,5,6,7,12,13,14} are on APB1 source = HAL_RCC_GetPCLK1Freq(); - #if defined(STM32H7) + #if defined(STM32F0) + clk_div = RCC->CFGR & RCC_CFGR_PPRE; + #elif defined(STM32H7) clk_div = RCC->D2CFGR & RCC_D2CFGR_D2PPRE1; #else clk_div = RCC->CFGR & RCC_CFGR_PPRE1; @@ -694,25 +700,27 @@ STATIC const uint32_t tim_instance_table[MICROPY_HW_MAX_TIMER] = { #if defined(TIM13) TIM_ENTRY(13, TIM8_UP_TIM13_IRQn), #endif - #if defined(TIM14) + #if defined(STM32F0) + TIM_ENTRY(14, TIM14_IRQn), + #elif defined(TIM14) TIM_ENTRY(14, TIM8_TRG_COM_TIM14_IRQn), #endif #if defined(TIM15) - #if defined(STM32H7) + #if defined(STM32F0) || defined(STM32H7) TIM_ENTRY(15, TIM15_IRQn), #else TIM_ENTRY(15, TIM1_BRK_TIM15_IRQn), #endif #endif #if defined(TIM16) - #if defined(STM32H7) + #if defined(STM32F0) || defined(STM32H7) TIM_ENTRY(16, TIM16_IRQn), #else TIM_ENTRY(16, TIM1_UP_TIM16_IRQn), #endif #endif #if defined(TIM17) - #if defined(STM32H7) + #if defined(STM32F0) || defined(STM32H7) 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 54dcc05728..1622c505c1 100644 --- a/ports/stm32/uart.c +++ b/ports/stm32/uart.c @@ -289,11 +289,17 @@ STATIC bool uart_init2(pyb_uart_obj_t *uart_obj) { #if defined(MICROPY_HW_UART8_TX) && defined(MICROPY_HW_UART8_RX) case PYB_UART_8: uart_unit = 8; + #if defined(STM32F0) + UARTx = USART8; + irqn = USART3_8_IRQn; + __HAL_RCC_USART8_CLK_ENABLE(); + #else UARTx = UART8; irqn = UART8_IRQn; + __HAL_RCC_UART8_CLK_ENABLE(); + #endif pins[0] = MICROPY_HW_UART8_TX; pins[1] = MICROPY_HW_UART8_RX; - __HAL_RCC_UART8_CLK_ENABLE(); break; #endif @@ -390,7 +396,7 @@ int uart_rx_char(pyb_uart_obj_t *self) { return data; } else { // no buffering - #if defined(STM32F7) || defined(STM32L4) || defined(STM32H7) + #if defined(STM32F0) || defined(STM32F7) || defined(STM32L4) || defined(STM32H7) return self->uart.Instance->RDR & self->char_mask; #else return self->uart.Instance->DR & self->char_mask; @@ -508,7 +514,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(STM32F7) || defined(STM32L4) || defined(STM32H7) + #if defined(STM32F0) || defined(STM32F7) || defined(STM32L4) || defined(STM32H7) int data = self->uart.Instance->RDR; // clears UART_FLAG_RXNE #else int data = self->uart.Instance->DR; // clears UART_FLAG_RXNE @@ -698,7 +704,9 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, size_t n_args, const // compute actual baudrate that was configured // (this formula assumes UART_OVERSAMPLING_16) uint32_t actual_baudrate = 0; - #if defined(STM32F7) || defined(STM32H7) + #if defined(STM32F0) + actual_baudrate = HAL_RCC_GetPCLK1Freq(); + #elif defined(STM32F7) || defined(STM32H7) UART_ClockSourceTypeDef clocksource = UART_CLOCKSOURCE_UNDEFINED; UART_GETCLOCKSOURCE(&self->uart, clocksource); switch (clocksource) { @@ -854,7 +862,9 @@ STATIC mp_obj_t pyb_uart_deinit(mp_obj_t self_in) { __HAL_RCC_USART2_CLK_DISABLE(); #if defined(USART3) } else if (uart->Instance == USART3) { + #if !defined(STM32F0) HAL_NVIC_DisableIRQ(USART3_IRQn); + #endif __HAL_RCC_USART3_FORCE_RESET(); __HAL_RCC_USART3_RELEASE_RESET(); __HAL_RCC_USART3_CLK_DISABLE(); @@ -949,7 +959,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 = self_in; - #if defined(STM32F7) || defined(STM32L4) || defined(STM32H7) + #if defined(STM32F0) || defined(STM32F7) || defined(STM32L4) || defined(STM32H7) self->uart.Instance->RQR = USART_RQR_SBKRQ; // write-only register #else self->uart.Instance->CR1 |= USART_CR1_SBK;