stm32: Add initial support for STM32L0xx MCUs.

This commit is contained in:
Damien George 2019-07-05 17:24:59 +10:00
parent fa5c0b819c
commit 23d9c6a0fd
13 changed files with 264 additions and 35 deletions

View File

@ -64,7 +64,7 @@ CFLAGS_CORTEX_M = -mthumb
ifeq ($(CMSIS_MCU),$(filter $(CMSIS_MCU),STM32F765xx STM32F767xx STM32F769xx STM32H743xx))
CFLAGS_CORTEX_M += -mfpu=fpv5-d16 -mfloat-abi=hard
else
ifeq ($(MCU_SERIES),f0)
ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 l0))
CFLAGS_CORTEX_M += -msoft-float
else
CFLAGS_CORTEX_M += -mfpu=fpv4-sp-d16 -mfloat-abi=hard
@ -75,6 +75,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_l0 = $(CFLAGS_CORTEX_M) -mtune=cortex-m0plus -mcpu=cortex-m0plus
CFLAGS_MCU_l4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4
CFLAGS_MCU_h7 = $(CFLAGS_CORTEX_M) -mtune=cortex-m7 -mcpu=cortex-m7
@ -200,7 +201,7 @@ SRC_LIBM = $(addprefix lib/libm/,\
wf_lgamma.c \
wf_tgamma.c \
)
ifeq ($(MCU_SERIES),f0)
ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 l0))
SRC_LIBM += lib/libm/ef_sqrt.c
else
SRC_LIBM += lib/libm/thumb_vfp_sqrtf.c
@ -289,12 +290,21 @@ SRC_O = \
resethandler_m0.o \
lib/utils/gchelper_m0.o
else
ifeq ($(MCU_SERIES),l0)
CSUPEROPT = -Os # save some code space
SRC_O = \
$(STARTUP_FILE) \
lib/stm32lib/CMSIS/STM32$(MCU_SERIES_UPPER)xx/Source/Templates/system_stm32$(MCU_SERIES)xx.o \
resethandler_m0.o \
lib/utils/gchelper_m0.o
else
SRC_O = \
$(STARTUP_FILE) \
system_stm32.o \
resethandler.o \
lib/utils/gchelper_m3.o
endif
endif
SRC_HAL = $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\
hal.c \
@ -341,8 +351,10 @@ endif
ifeq ($(CMSIS_MCU),$(filter $(CMSIS_MCU),STM32H743xx))
SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_, hal_fdcan.c)
else
ifneq ($(MCU_SERIES),$(filter $(MCU_SERIES),l0))
SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_, hal_can.c)
endif
endif
SRC_USBDEV = $(addprefix $(USBDEV_DIR)/,\
core/src/usbd_core.c \

View File

@ -70,7 +70,7 @@ typedef union {
struct _dma_descr_t {
#if defined(STM32F4) || defined(STM32F7) || defined(STM32H7)
DMA_Stream_TypeDef *instance;
#elif defined(STM32F0) || defined(STM32L4)
#elif defined(STM32F0) || defined(STM32L0) || defined(STM32L4)
DMA_Channel_TypeDef *instance;
#else
#error "Unsupported Processor"
@ -310,6 +310,47 @@ static const uint8_t dma_irqn[NSTREAM] = {
DMA2_Stream7_IRQn,
};
#elif defined(STM32L0)
#define NCONTROLLERS (1)
#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
// These descriptors are ordered by DMAx_Channel number, and within a channel by request
// number. The duplicate streams are ok as long as they aren't used at the same time.
// DMA1 streams
const dma_descr_t dma_SPI_1_RX = { DMA1_Channel2, DMA_REQUEST_1, dma_id_1, &dma_init_struct_spi_i2c };
const dma_descr_t dma_I2C_3_TX = { DMA1_Channel2, DMA_REQUEST_3, dma_id_1, &dma_init_struct_spi_i2c };
const dma_descr_t dma_SPI_1_TX = { DMA1_Channel3, DMA_REQUEST_1, dma_id_2, &dma_init_struct_spi_i2c };
const dma_descr_t dma_I2C_3_RX = { DMA1_Channel3, DMA_REQUEST_3, dma_id_2, &dma_init_struct_spi_i2c };
#if MICROPY_HW_ENABLE_DAC
const dma_descr_t dma_DAC_1_TX = { DMA1_Channel3, DMA_REQUEST_6, dma_id_2, &dma_init_struct_dac };
#endif
const dma_descr_t dma_SPI_2_RX = { DMA1_Channel4, DMA_REQUEST_1, dma_id_3, &dma_init_struct_spi_i2c };
const dma_descr_t dma_I2C_2_TX = { DMA1_Channel4, DMA_REQUEST_3, dma_id_3, &dma_init_struct_spi_i2c };
#if MICROPY_HW_ENABLE_DAC
const dma_descr_t dma_DAC_2_TX = { DMA1_Channel4, DMA_REQUEST_5, dma_id_3, &dma_init_struct_dac };
#endif
const dma_descr_t dma_SPI_2_TX = { DMA1_Channel5, DMA_REQUEST_1, dma_id_4, &dma_init_struct_spi_i2c };
const dma_descr_t dma_I2C_2_RX = { DMA1_Channel5, DMA_REQUEST_3, dma_id_4, &dma_init_struct_spi_i2c };
const dma_descr_t dma_I2C_1_TX = { DMA1_Channel6, DMA_REQUEST_3, dma_id_5, &dma_init_struct_spi_i2c };
const dma_descr_t dma_I2C_1_RX = { DMA1_Channel7, DMA_REQUEST_3, dma_id_6, &dma_init_struct_spi_i2c };
static const uint8_t dma_irqn[NSTREAM] = {
DMA1_Channel1_IRQn,
DMA1_Channel2_3_IRQn,
DMA1_Channel4_5_6_7_IRQn,
0,
0,
0,
0,
};
#elif defined(STM32L4)
#define NCONTROLLERS (2)
@ -459,9 +500,11 @@ volatile dma_idle_count_t dma_idle;
#define DMA_INVALID_CHANNEL 0xff // Value stored in dma_last_channel which means invalid
#if defined(STM32F0)
#if defined(STM32F0) || 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)
#endif
#else
#define DMA1_IS_CLK_ENABLED() ((RCC->AHB1ENR & RCC_AHB1ENR_DMA1EN) != 0)
#define DMA2_IS_CLK_ENABLED() ((RCC->AHB1ENR & RCC_AHB1ENR_DMA2EN) != 0)
@ -526,6 +569,44 @@ void DMA2_Stream5_IRQHandler(void) { IRQ_ENTER(DMA2_Stream5_IRQn); if (dma_handl
void DMA2_Stream6_IRQHandler(void) { IRQ_ENTER(DMA2_Stream6_IRQn); if (dma_handle[dma_id_14] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_14]); } IRQ_EXIT(DMA2_Stream6_IRQn); }
void DMA2_Stream7_IRQHandler(void) { IRQ_ENTER(DMA2_Stream7_IRQn); if (dma_handle[dma_id_15] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_15]); } IRQ_EXIT(DMA2_Stream7_IRQn); }
#elif defined(STM32L0)
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_Channel4_5_6_7_IRQHandler(void) {
IRQ_ENTER(DMA1_Channel4_5_6_7_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]);
}
IRQ_EXIT(DMA1_Channel4_5_6_7_IRQn);
}
#elif defined(STM32L4)
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); }
@ -572,18 +653,21 @@ static void dma_enable_clock(dma_id_t dma_id) {
dma_last_sub_instance[channel] = DMA_INVALID_CHANNEL;
}
}
} else {
}
#if defined(DMA2)
else {
if (((old_enable_mask & DMA2_ENABLE_MASK) == 0) && !DMA2_IS_CLK_ENABLED()) {
__HAL_RCC_DMA2_CLK_ENABLE();
// We just turned on the clock. This means that anything stored
// in dma_last_channel (for DMA1) needs to be invalidated.
// in dma_last_channel (for DMA2) needs to be invalidated.
for (int channel = NSTREAMS_PER_CONTROLLER; channel < NSTREAM; channel++) {
dma_last_sub_instance[channel] = DMA_INVALID_CHANNEL;
}
}
}
#endif
}
static void dma_disable_clock(dma_id_t dma_id) {
@ -599,7 +683,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(STM32L4) || defined(STM32H7)
#if defined(STM32L0) || defined(STM32L4) || defined(STM32H7)
dma->Init.Request = dma_descr->sub_instance;
#else
#if !defined(STM32F0)
@ -705,7 +789,10 @@ static void dma_idle_handler(uint32_t tick) {
}
static const uint32_t controller_mask[] = {
DMA1_ENABLE_MASK, DMA2_ENABLE_MASK
DMA1_ENABLE_MASK,
#if defined(DMA2)
DMA2_ENABLE_MASK,
#endif
};
{
int controller = (tick >> DMA_SYSTICK_LOG2) & 1;
@ -719,9 +806,12 @@ static void dma_idle_handler(uint32_t tick) {
dma_idle.counter[controller] = 0;
if (controller == 0) {
__HAL_RCC_DMA1_CLK_DISABLE();
} else {
}
#if defined(DMA2)
else {
__HAL_RCC_DMA2_CLK_DISABLE();
}
#endif
} else {
// Something is still active, but the counter never got
// reset, so we'll reset the counter here.
@ -731,7 +821,7 @@ static void dma_idle_handler(uint32_t tick) {
}
}
#if defined(STM32F0) || defined(STM32L4)
#if defined(STM32F0) || defined(STM32L0) || defined(STM32L4)
void dma_nohal_init(const dma_descr_t *descr, uint32_t config) {
DMA_Channel_TypeDef *dma = descr->instance;

View File

@ -58,6 +58,21 @@ extern const dma_descr_t dma_SPI_6_RX;
extern const dma_descr_t dma_SDIO_0;
extern const dma_descr_t dma_DCMI_0;
#elif defined(STM32L0)
extern const dma_descr_t dma_SPI_1_RX;
extern const dma_descr_t dma_I2C_3_TX;
extern const dma_descr_t dma_SPI_1_TX;
extern const dma_descr_t dma_I2C_3_RX;
extern const dma_descr_t dma_DAC_1_TX;
extern const dma_descr_t dma_SPI_2_RX;
extern const dma_descr_t dma_I2C_2_TX;
extern const dma_descr_t dma_DAC_2_TX;
extern const dma_descr_t dma_SPI_2_TX;
extern const dma_descr_t dma_I2C_2_RX;
extern const dma_descr_t dma_I2C_1_TX;
extern const dma_descr_t dma_I2C_1_RX;
#elif defined(STM32L4)
extern const dma_descr_t dma_ADC_1_RX;

View File

@ -139,12 +139,16 @@ 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)
#if defined(STM32F0) || defined(STM32L0)
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,
#if defined(STM32L0)
PVD_IRQn,
#else
PVD_VDDIO2_IRQn,
#endif
RTC_IRQn,
0, // internal USB wakeup event
RTC_IRQn,

View File

@ -68,7 +68,7 @@ static const flash_layout_t flash_layout[] = {
{ 0x08040000, 0x40000, 3 },
};
#elif defined(STM32L4)
#elif defined(STM32L0) || defined(STM32L4)
static const flash_layout_t flash_layout[] = {
{ (uint32_t)FLASH_BASE, (uint32_t)FLASH_PAGE_SIZE, 512 },
@ -170,7 +170,12 @@ void 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(STM32L4) && !defined(SYSCFG_MEMRMP_FB_MODE))
#elif defined(STM32L0)
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR);
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
EraseInitStruct.PageAddress = flash_dest;
EraseInitStruct.NbPages = (4 * num_word32 + FLASH_PAGE_SIZE - 4) / FLASH_PAGE_SIZE;
#elif defined(STM32L4) && !defined(SYSCFG_MEMRMP_FB_MODE)
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
EraseInitStruct.Page = get_page(flash_dest);

View File

@ -489,7 +489,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(STM32L4) || defined(STM32H7)
#if defined(STM32F0) || defined(STM32F7) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7)
self->uartx->RQR = USART_RQR_SBKRQ; // write-only register
#else
self->uartx->CR1 |= USART_CR1_SBK;

View File

@ -56,6 +56,11 @@
#include "uart.h"
#include "wdt.h"
#if defined(STM32L0)
// L0 does not have a BOR, so use POR instead
#define RCC_CSR_BORRSTF RCC_CSR_PORRSTF
#endif
#if defined(STM32L4)
// L4 does not have a POR, so use BOR instead
#define RCC_CSR_PORRSTF RCC_CSR_BORRSTF
@ -300,7 +305,7 @@ STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) {
return mp_obj_new_tuple(MP_ARRAY_SIZE(tuple), tuple);
} else {
// set
#if defined(STM32F0) || defined(STM32L4)
#if defined(STM32F0) || defined(STM32L0) || defined(STM32L4)
mp_raise_NotImplementedError("machine.freq set not supported yet");
#else
mp_int_t sysclk = mp_obj_get_int(args[0]);

View File

@ -184,6 +184,15 @@
#define MICROPY_HW_MAX_TIMER (17)
#define MICROPY_HW_MAX_UART (8)
// Configuration for STM32L0 series
#elif defined(STM32L0)
#define MP_HAL_UNIQUE_ID_ADDRESS (0x1FF80050)
#define PYB_EXTI_NUM_VECTORS (30) // TODO (22 configurable, 7 direct)
#define MICROPY_HW_MAX_I2C (3)
#define MICROPY_HW_MAX_TIMER (22)
#define MICROPY_HW_MAX_UART (4)
// Configuration for STM32L4 series
#elif defined(STM32L4)

View File

@ -119,6 +119,9 @@ void mp_hal_gpio_clock_enable(GPIO_TypeDef *gpio) {
#elif defined(STM32H7)
#define AHBxENR AHB4ENR
#define AHBxENR_GPIOAEN_Pos RCC_AHB4ENR_GPIOAEN_Pos
#elif defined(STM32L0)
#define AHBxENR IOPENR
#define AHBxENR_GPIOAEN_Pos RCC_IOPENR_GPIOAEN
#elif defined(STM32L4)
#define AHBxENR AHB2ENR
#define AHBxENR_GPIOAEN_Pos RCC_AHB2ENR_GPIOAEN_Pos

View File

@ -84,7 +84,31 @@ void powerctrl_check_enter_bootloader(void) {
}
}
#if !defined(STM32F0)
#if defined(STM32L0)
void SystemClock_Config(void) {
// Enable power control peripheral
__HAL_RCC_PWR_CLK_ENABLE();
// Use the 16MHz internal oscillator
RCC->CR |= RCC_CR_HSION;
while (!(RCC->CR & RCC_CR_HSIRDY)) {
}
const uint32_t sysclk_src = 1;
// Select SYSCLK source
RCC->CFGR |= sysclk_src << RCC_CFGR_SW_Pos;
while (((RCC->CFGR >> RCC_CFGR_SWS_Pos) & 0x3) != sysclk_src) {
// Wait for SYSCLK source to change
}
SystemCoreClockUpdate();
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
}
#endif
#if !defined(STM32F0) && !defined(STM32L0)
// Assumes that PLL is used as the SYSCLK source
int powerctrl_rcc_clock_config_pll(RCC_ClkInitTypeDef *rcc_init, uint32_t sysclk_mhz, bool need_pllsai) {
@ -158,7 +182,7 @@ int powerctrl_rcc_clock_config_pll(RCC_ClkInitTypeDef *rcc_init, uint32_t sysclk
#endif
#if !(defined(STM32F0) || defined(STM32L4))
#if !defined(STM32F0) && !defined(STM32L0) && !defined(STM32L4)
STATIC uint32_t calc_ahb_div(uint32_t wanted_div) {
if (wanted_div <= 1) { return RCC_SYSCLK_DIV1; }
@ -333,7 +357,7 @@ void powerctrl_enter_stop_mode(void) {
__HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_MSI);
#endif
#if !defined(STM32F0) && !defined(STM32L4)
#if !defined(STM32F0) && !defined(STM32L0) && !defined(STM32L4)
// takes longer to wake but reduces stop current
HAL_PWREx_EnableFlashPowerDown();
#endif
@ -426,7 +450,7 @@ void powerctrl_enter_standby_mode(void) {
// Note: we only support RTC ALRA, ALRB, WUT and TS.
// TODO support TAMP and WKUP (PA0 external pin).
#if defined(STM32F0)
#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)
#else

View File

@ -73,6 +73,17 @@ STATIC bool rtc_use_lse = false;
STATIC uint32_t rtc_startup_tick;
STATIC bool rtc_need_init_finalise = false;
#if defined(STM32L0)
#define BDCR CSR
#define RCC_BDCR_RTCEN RCC_CSR_RTCEN
#define RCC_BDCR_RTCSEL RCC_CSR_RTCSEL
#define RCC_BDCR_RTCSEL_0 RCC_CSR_RTCSEL_0
#define RCC_BDCR_RTCSEL_1 RCC_CSR_RTCSEL_1
#define RCC_BDCR_LSEON RCC_CSR_LSEON
#define RCC_BDCR_LSERDY RCC_CSR_LSERDY
#define RCC_BDCR_LSEBYP RCC_CSR_LSEBYP
#endif
void rtc_init_start(bool force_init) {
RTCHandle.Instance = RTC;
@ -287,7 +298,7 @@ STATIC HAL_StatusTypeDef PYB_RTC_Init(RTC_HandleTypeDef *hrtc) {
// Exit Initialization mode
hrtc->Instance->ISR &= (uint32_t)~RTC_ISR_INIT;
#if defined(STM32L4) || defined(STM32H7)
#if defined(STM32L0) || defined(STM32L4) || defined(STM32H7)
hrtc->Instance->OR &= (uint32_t)~RTC_OR_ALARMOUTTYPE;
hrtc->Instance->OR |= (uint32_t)(hrtc->Init.OutPutType);
#elif defined(STM32F7)
@ -539,7 +550,7 @@ mp_obj_t pyb_rtc_datetime(size_t n_args, const mp_obj_t *args) {
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_datetime_obj, 1, 2, pyb_rtc_datetime);
#if defined(STM32F0)
#if defined(STM32F0) || defined(STM32L0)
#define RTC_WKUP_IRQn RTC_IRQn
#endif

View File

@ -427,6 +427,8 @@ STATIC mp_obj_t compute_percent_from_pwm_value(uint32_t period, uint32_t cmp) {
#endif
}
#if !defined(STM32L0)
// Computes the 8-bit value for the DTG field in the BDTR register.
//
// 1 tick = 1 count of the timer's clock (source_freq) divided by div.
@ -486,6 +488,8 @@ STATIC void config_deadtime(pyb_timer_obj_t *self, mp_int_t ticks, mp_int_t brk)
HAL_TIMEx_ConfigBreakDeadTime(&self->tim, &deadTimeConfig);
}
#endif
TIM_HandleTypeDef *pyb_timer_get_handle(mp_obj_t timer) {
if (mp_obj_get_type(timer) != &pyb_timer_type) {
mp_raise_ValueError("need a Timer object");
@ -514,6 +518,7 @@ STATIC void pyb_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_
self->tim.Init.ClockDivision == TIM_CLOCKDIVISION_DIV4 ? 4 :
self->tim.Init.ClockDivision == TIM_CLOCKDIVISION_DIV2 ? 2 : 1);
#if !defined(STM32L0)
#if defined(IS_TIM_ADVANCED_INSTANCE)
if (IS_TIM_ADVANCED_INSTANCE(self->tim.Instance))
#elif defined(IS_TIM_BREAK_INSTANCE)
@ -531,6 +536,7 @@ STATIC void pyb_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_
mp_printf(print, ", brk=BRK_OFF");
}
}
#endif
mp_print_str(print, ")");
}
}
@ -630,11 +636,15 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *self, size_t n_args, cons
args[ARG_div].u_int == 4 ? TIM_CLOCKDIVISION_DIV4 :
TIM_CLOCKDIVISION_DIV1;
#if !defined(STM32L0)
init->RepetitionCounter = 0;
#endif
// enable TIM clock
switch (self->tim_id) {
#if defined(TIM1)
case 1: __HAL_RCC_TIM1_CLK_ENABLE(); break;
#endif
case 2: __HAL_RCC_TIM2_CLK_ENABLE(); break;
#if defined(TIM3)
case 3: __HAL_RCC_TIM3_CLK_ENABLE(); break;
@ -681,15 +691,32 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *self, size_t n_args, cons
#if defined(TIM17)
case 17: __HAL_RCC_TIM17_CLK_ENABLE(); break;
#endif
#if defined(TIM18)
case 18: __HAL_RCC_TIM18_CLK_ENABLE(); break;
#endif
#if defined(TIM19)
case 19: __HAL_RCC_TIM19_CLK_ENABLE(); break;
#endif
#if defined(TIM20)
case 20: __HAL_RCC_TIM20_CLK_ENABLE(); break;
#endif
#if defined(TIM21)
case 21: __HAL_RCC_TIM21_CLK_ENABLE(); break;
#endif
#if defined(TIM22)
case 22: __HAL_RCC_TIM22_CLK_ENABLE(); break;
#endif
}
// set IRQ priority (if not a special timer)
if (self->tim_id != 5) {
NVIC_SetPriority(IRQn_NONNEG(self->irqn), IRQ_PRI_TIMX);
if (self->tim_id == 1) {
#if defined(TIM1)
NVIC_SetPriority(TIM1_CC_IRQn, IRQ_PRI_TIMX);
#if defined(TIM8)
#endif
} else if (self->tim_id == 8) {
#if defined(TIM8)
NVIC_SetPriority(TIM8_CC_IRQn, IRQ_PRI_TIMX);
#endif
}
@ -697,6 +724,7 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *self, size_t n_args, cons
// init TIM
HAL_TIM_Base_Init(&self->tim);
#if !defined(STM32L0)
#if defined(IS_TIM_ADVANCED_INSTANCE)
if (IS_TIM_ADVANCED_INSTANCE(self->tim.Instance)) {
#elif defined(IS_TIM_BREAK_INSTANCE)
@ -707,6 +735,7 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *self, size_t n_args, cons
config_deadtime(self, args[ARG_deadtime].u_int, args[ARG_brk].u_int);
}
#endif
// Enable ARPE so that the auto-reload register is buffered.
// This allows to smoothly change the frequency of the timer.
@ -726,6 +755,7 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *self, size_t n_args, cons
// It assumes that timer instance pointer has the lower 8 bits cleared.
#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)
TIM_ENTRY(1, TIM1_BRK_UP_TRG_COM_IRQn),
#elif defined(STM32F4) || defined(STM32F7)
@ -733,6 +763,7 @@ STATIC const uint32_t tim_instance_table[MICROPY_HW_MAX_TIMER] = {
#elif defined(STM32L4)
TIM_ENTRY(1, TIM1_UP_TIM16_IRQn),
#endif
#endif
TIM_ENTRY(2, TIM2_IRQn),
#if defined(TIM3)
TIM_ENTRY(3, TIM3_IRQn),
@ -1054,10 +1085,12 @@ STATIC mp_obj_t pyb_timer_channel(size_t n_args, const mp_obj_t *pos_args, mp_ma
oc_config.Pulse = args[3].u_int;
}
oc_config.OCPolarity = TIM_OCPOLARITY_HIGH;
oc_config.OCNPolarity = TIM_OCNPOLARITY_HIGH;
oc_config.OCFastMode = TIM_OCFAST_DISABLE;
#if !defined(STM32L0)
oc_config.OCNPolarity = TIM_OCNPOLARITY_HIGH;
oc_config.OCIdleState = TIM_OCIDLESTATE_SET;
oc_config.OCNIdleState = TIM_OCNIDLESTATE_SET;
#endif
HAL_TIM_PWM_ConfigChannel(&self->tim, &oc_config, TIMER_CHANNEL(chan));
if (chan->callback == mp_const_none) {
@ -1065,10 +1098,12 @@ STATIC mp_obj_t pyb_timer_channel(size_t n_args, const mp_obj_t *pos_args, mp_ma
} else {
pyb_timer_channel_callback(MP_OBJ_FROM_PTR(chan), chan->callback);
}
#if !defined(STM32L0)
// Start the complimentary channel too (if its supported)
if (IS_TIM_CCXN_INSTANCE(self->tim.Instance, TIMER_CHANNEL(chan))) {
HAL_TIMEx_PWMN_Start(&self->tim, TIMER_CHANNEL(chan));
}
#endif
break;
}
@ -1085,14 +1120,16 @@ STATIC mp_obj_t pyb_timer_channel(size_t n_args, const mp_obj_t *pos_args, mp_ma
if (oc_config.OCPolarity == 0xffffffff) {
oc_config.OCPolarity = TIM_OCPOLARITY_HIGH;
}
oc_config.OCFastMode = TIM_OCFAST_DISABLE;
#if !defined(STM32L0)
if (oc_config.OCPolarity == TIM_OCPOLARITY_HIGH) {
oc_config.OCNPolarity = TIM_OCNPOLARITY_HIGH;
} else {
oc_config.OCNPolarity = TIM_OCNPOLARITY_LOW;
}
oc_config.OCFastMode = TIM_OCFAST_DISABLE;
oc_config.OCIdleState = TIM_OCIDLESTATE_SET;
oc_config.OCNIdleState = TIM_OCNIDLESTATE_SET;
#endif
if (!IS_TIM_OC_POLARITY(oc_config.OCPolarity)) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid polarity (%d)", oc_config.OCPolarity));
@ -1103,10 +1140,12 @@ STATIC mp_obj_t pyb_timer_channel(size_t n_args, const mp_obj_t *pos_args, mp_ma
} else {
pyb_timer_channel_callback(MP_OBJ_FROM_PTR(chan), chan->callback);
}
#if !defined(STM32L0)
// Start the complimentary channel too (if its supported)
if (IS_TIM_CCXN_INSTANCE(self->tim.Instance, TIMER_CHANNEL(chan))) {
HAL_TIMEx_OCN_Start(&self->tim, TIMER_CHANNEL(chan));
}
#endif
break;
}
@ -1155,8 +1194,12 @@ STATIC mp_obj_t pyb_timer_channel(size_t n_args, const mp_obj_t *pos_args, mp_ma
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid polarity (%d)", enc_config.IC1Polarity));
}
// Only Timers 1, 2, 3, 4, 5, and 8 support encoder mode
if (self->tim.Instance != TIM1
&& self->tim.Instance != TIM2
if (
#if defined(TIM1)
self->tim.Instance != TIM1
&&
#endif
self->tim.Instance != TIM2
#if defined(TIM3)
&& self->tim.Instance != TIM3
#endif
@ -1426,15 +1469,18 @@ STATIC mp_obj_t pyb_timer_channel_callback(mp_obj_t self_in, mp_obj_t callback)
self->callback = mp_const_none;
} else if (mp_obj_is_callable(callback)) {
self->callback = callback;
uint8_t tim_id = self->timer->tim_id;
__HAL_TIM_CLEAR_IT(&self->timer->tim, TIMER_IRQ_MASK(self->channel));
if (tim_id == 1) {
#if defined(TIM1)
if (self->timer->tim_id == 1) {
HAL_NVIC_EnableIRQ(TIM1_CC_IRQn);
#if defined(TIM8) // STM32F401 doesn't have a TIM8
} else if (tim_id == 8) {
HAL_NVIC_EnableIRQ(TIM8_CC_IRQn);
} else
#endif
} else {
#if defined(TIM8) // STM32F401 doesn't have a TIM8
if (self->timer->tim_id == 8) {
HAL_NVIC_EnableIRQ(TIM8_CC_IRQn);
} else
#endif
{
HAL_NVIC_EnableIRQ(self->timer->irqn);
}
// start timer, so that it interrupts on overflow

View File

@ -76,6 +76,11 @@
#define USART_CR2_IE_ALL (USART_CR2_IE_BASE)
#define USART_CR3_IE_ALL (USART_CR3_IE_BASE | USART_CR3_RXFTIE | USART_CR3_TCBGTIE | USART_CR3_TXFTIE | USART_CR3_WUFIE)
#elif defined(STM32L0)
#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)
#define USART_CR3_IE_ALL (USART_CR3_IE_BASE | USART_CR3_WUFIE)
#elif defined(STM32L4)
#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)
@ -648,7 +653,7 @@ int uart_rx_char(pyb_uart_obj_t *self) {
return data;
} else {
// no buffering
#if defined(STM32F0) || defined(STM32F7) || defined(STM32L4) || defined(STM32H7)
#if defined(STM32F0) || defined(STM32F7) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7)
int data = self->uartx->RDR & self->char_mask;
self->uartx->ICR = USART_ICR_ORECF; // clear ORE if it was set
return data;
@ -774,7 +779,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(STM32L4) || defined(STM32H7)
#if defined(STM32F0) || defined(STM32F7) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7)
int data = self->uartx->RDR; // clears UART_FLAG_RXNE
self->uartx->ICR = USART_ICR_ORECF; // clear ORE if it was set
#else