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 + * + *