stm32: Add support for STM32L1 MCUs.

This change adds STM32L1 support to the STM32 port.
This commit is contained in:
yn386 2022-09-19 17:56:31 +09:00 committed by Damien George
parent ae0b0e7018
commit 427d72667f
25 changed files with 657 additions and 37 deletions

View File

@ -347,11 +347,18 @@ SRC_O += \
resethandler_m0.o \ resethandler_m0.o \
shared/runtime/gchelper_m0.o shared/runtime/gchelper_m0.o
else else
ifeq ($(MCU_SERIES),l1)
CFLAGS += -DUSE_HAL_DRIVER
SRC_O += \
resethandler_m3.o \
shared/runtime/gchelper_m3.o
else
SRC_O += \ SRC_O += \
system_stm32.o \ system_stm32.o \
resethandler.o \ resethandler.o \
shared/runtime/gchelper_m3.o shared/runtime/gchelper_m3.o
endif endif
endif
HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_,\ HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_,\
hal.c \ hal.c \

View File

@ -118,6 +118,14 @@
#define ADC_CAL2 ((uint16_t *)(0x1FF1E840)) #define ADC_CAL2 ((uint16_t *)(0x1FF1E840))
#define ADC_CAL_BITS (16) #define ADC_CAL_BITS (16)
#elif defined(STM32L1)
#define ADC_SCALE_V (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)
#elif defined(STM32L4) || defined(STM32WB) #elif defined(STM32L4) || defined(STM32WB)
#define ADC_SCALE_V (VREFINT_CAL_VREF / 1000.0f) #define ADC_SCALE_V (VREFINT_CAL_VREF / 1000.0f)
@ -163,6 +171,8 @@
defined(STM32L476xx) || defined(STM32L496xx) || \ defined(STM32L476xx) || defined(STM32L496xx) || \
defined(STM32WB55xx) defined(STM32WB55xx)
#define VBAT_DIV (3) #define VBAT_DIV (3)
#elif defined(STM32L152xE)
// STM32L152xE does not have vbat.
#else #else
#error Unsupported processor #error Unsupported processor
#endif #endif
@ -179,11 +189,17 @@
#define VREFIN_CAL ((uint16_t *)ADC_CAL_ADDRESS) #define VREFIN_CAL ((uint16_t *)ADC_CAL_ADDRESS)
#ifndef __HAL_ADC_IS_CHANNEL_INTERNAL #ifndef __HAL_ADC_IS_CHANNEL_INTERNAL
#if defined(STM32L1)
#define __HAL_ADC_IS_CHANNEL_INTERNAL(channel) \
(channel == ADC_CHANNEL_VREFINT \
|| channel == ADC_CHANNEL_TEMPSENSOR)
#else
#define __HAL_ADC_IS_CHANNEL_INTERNAL(channel) \ #define __HAL_ADC_IS_CHANNEL_INTERNAL(channel) \
(channel == ADC_CHANNEL_VBAT \ (channel == ADC_CHANNEL_VBAT \
|| channel == ADC_CHANNEL_VREFINT \ || channel == ADC_CHANNEL_VREFINT \
|| channel == ADC_CHANNEL_TEMPSENSOR) || channel == ADC_CHANNEL_TEMPSENSOR)
#endif #endif
#endif
typedef struct _pyb_obj_adc_t { typedef struct _pyb_obj_adc_t {
mp_obj_base_t base; mp_obj_base_t base;
@ -210,6 +226,10 @@ STATIC bool is_adcx_channel(int channel) {
return IS_ADC_CHANNEL(channel) || channel == ADC_CHANNEL_TEMPSENSOR; return IS_ADC_CHANNEL(channel) || channel == ADC_CHANNEL_TEMPSENSOR;
#elif defined(STM32F0) || defined(STM32F4) || defined(STM32F7) #elif defined(STM32F0) || defined(STM32F4) || defined(STM32F7)
return IS_ADC_CHANNEL(channel); return IS_ADC_CHANNEL(channel);
#elif defined(STM32L1)
// The HAL of STM32L1 defines some channels those may not be available on package
return __HAL_ADC_IS_CHANNEL_INTERNAL(channel)
|| (channel < MP_ARRAY_SIZE(pin_adcall_table) && pin_adcall_table[channel]);
#elif defined(STM32G0) || defined(STM32H7) #elif defined(STM32G0) || defined(STM32H7)
return __HAL_ADC_IS_CHANNEL_INTERNAL(channel) return __HAL_ADC_IS_CHANNEL_INTERNAL(channel)
|| IS_ADC_CHANNEL(__HAL_ADC_DECIMAL_NB_TO_CHANNEL(channel)); || IS_ADC_CHANNEL(__HAL_ADC_DECIMAL_NB_TO_CHANNEL(channel));
@ -225,7 +245,7 @@ STATIC bool is_adcx_channel(int channel) {
STATIC void adc_wait_for_eoc_or_timeout(ADC_HandleTypeDef *adcHandle, int32_t timeout) { STATIC void adc_wait_for_eoc_or_timeout(ADC_HandleTypeDef *adcHandle, int32_t timeout) {
uint32_t tickstart = HAL_GetTick(); uint32_t tickstart = HAL_GetTick();
#if defined(STM32F4) || defined(STM32F7) #if defined(STM32F4) || defined(STM32F7) || defined(STM32L1)
while ((adcHandle->Instance->SR & ADC_FLAG_EOC) != ADC_FLAG_EOC) { while ((adcHandle->Instance->SR & ADC_FLAG_EOC) != ADC_FLAG_EOC) {
#elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB)
while (READ_BIT(adcHandle->Instance->ISR, ADC_FLAG_EOC) != ADC_FLAG_EOC) { while (READ_BIT(adcHandle->Instance->ISR, ADC_FLAG_EOC) != ADC_FLAG_EOC) {
@ -239,7 +259,7 @@ STATIC void adc_wait_for_eoc_or_timeout(ADC_HandleTypeDef *adcHandle, int32_t ti
} }
STATIC void adcx_clock_enable(ADC_HandleTypeDef *adch) { STATIC void adcx_clock_enable(ADC_HandleTypeDef *adch) {
#if defined(STM32F0) || defined(STM32F4) || defined(STM32F7) #if defined(STM32F0) || defined(STM32F4) || defined(STM32F7) || defined(STM32L1)
ADCx_CLK_ENABLE(); ADCx_CLK_ENABLE();
#elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ) #elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ)
__HAL_RCC_ADC12_CLK_ENABLE(); __HAL_RCC_ADC12_CLK_ENABLE();
@ -299,6 +319,12 @@ STATIC void adcx_init_periph(ADC_HandleTypeDef *adch, uint32_t resolution) {
adch->Init.OversamplingMode = DISABLE; adch->Init.OversamplingMode = DISABLE;
adch->Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE; adch->Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
adch->Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR; adch->Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR;
#elif defined(STM32L1)
adch->Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
adch->Init.ScanConvMode = ADC_SCAN_DISABLE;
adch->Init.LowPowerAutoWait = DISABLE;
adch->Init.DataAlign = ADC_DATAALIGN_RIGHT;
adch->Init.DMAContinuousRequests = DISABLE;
#elif defined(STM32G0) || defined(STM32G4) || defined(STM32L4) || defined(STM32WB) #elif defined(STM32G0) || defined(STM32G4) || defined(STM32L4) || defined(STM32WB)
adch->Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1; adch->Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
adch->Init.ScanConvMode = ADC_SCAN_DISABLE; adch->Init.ScanConvMode = ADC_SCAN_DISABLE;
@ -367,6 +393,12 @@ STATIC void adc_config_channel(ADC_HandleTypeDef *adc_handle, uint32_t channel)
sConfig.OffsetNumber = ADC_OFFSET_NONE; sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.OffsetRightShift = DISABLE; sConfig.OffsetRightShift = DISABLE;
sConfig.OffsetSignedSaturation = DISABLE; sConfig.OffsetSignedSaturation = DISABLE;
#elif defined(STM32L1)
if (__HAL_ADC_IS_CHANNEL_INTERNAL(channel)) {
sConfig.SamplingTime = ADC_SAMPLETIME_384CYCLES;
} else {
sConfig.SamplingTime = ADC_SAMPLETIME_384CYCLES;
}
#elif defined(STM32G0) #elif defined(STM32G0)
if (__HAL_ADC_IS_CHANNEL_INTERNAL(channel)) { if (__HAL_ADC_IS_CHANNEL_INTERNAL(channel)) {
sConfig.SamplingTime = ADC_SAMPLETIME_160CYCLES_5; sConfig.SamplingTime = ADC_SAMPLETIME_160CYCLES_5;
@ -555,7 +587,7 @@ STATIC mp_obj_t adc_read_timed(mp_obj_t self_in, mp_obj_t buf_in, mp_obj_t freq_
HAL_ADC_Start(&self->handle); HAL_ADC_Start(&self->handle);
} else { } else {
// for subsequent samples we can just set the "start sample" bit // for subsequent samples we can just set the "start sample" bit
#if defined(STM32F4) || defined(STM32F7) #if defined(STM32F4) || defined(STM32F7) || defined(STM32L1)
self->handle.Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART; self->handle.Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART;
#elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB)
SET_BIT(self->handle.Instance->CR, ADC_CR_ADSTART); SET_BIT(self->handle.Instance->CR, ADC_CR_ADSTART);
@ -665,7 +697,7 @@ STATIC mp_obj_t adc_read_timed_multi(mp_obj_t adc_array_in, mp_obj_t buf_array_i
adc_config_channel(&adc->handle, adc->channel); adc_config_channel(&adc->handle, adc->channel);
// for the first sample we need to turn the ADC on // for the first sample we need to turn the ADC on
// ADC is started: set the "start sample" bit // ADC is started: set the "start sample" bit
#if defined(STM32F4) || defined(STM32F7) #if defined(STM32F4) || defined(STM32F7) || defined(STM32L1)
adc->handle.Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART; adc->handle.Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART;
#elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB)
SET_BIT(adc->handle.Instance->CR, ADC_CR_ADSTART); SET_BIT(adc->handle.Instance->CR, ADC_CR_ADSTART);
@ -720,6 +752,8 @@ typedef struct _pyb_adc_all_obj_t {
ADC_HandleTypeDef handle; ADC_HandleTypeDef handle;
} pyb_adc_all_obj_t; } pyb_adc_all_obj_t;
float adc_read_core_vref(ADC_HandleTypeDef *adcHandle);
void adc_init_all(pyb_adc_all_obj_t *adc_all, uint32_t resolution, uint32_t en_mask) { void adc_init_all(pyb_adc_all_obj_t *adc_all, uint32_t resolution, uint32_t en_mask) {
switch (resolution) { switch (resolution) {
@ -762,7 +796,11 @@ void adc_init_all(pyb_adc_all_obj_t *adc_all, uint32_t resolution, uint32_t en_m
} }
int adc_get_resolution(ADC_HandleTypeDef *adcHandle) { int adc_get_resolution(ADC_HandleTypeDef *adcHandle) {
#if defined(STM32L1)
uint32_t res_reg = adcHandle->Instance->CR1 & ADC_CR1_RES_Msk;
#else
uint32_t res_reg = ADC_GET_RESOLUTION(adcHandle); uint32_t res_reg = ADC_GET_RESOLUTION(adcHandle);
#endif
switch (res_reg) { switch (res_reg) {
#if !defined(STM32H7) #if !defined(STM32H7)
@ -814,6 +852,11 @@ float adc_read_core_temp_float(ADC_HandleTypeDef *adcHandle) {
return 0; return 0;
} }
#else #else
#if defined(STM32L1)
// Update the reference correction factor before reading tempsensor
// because TS_CAL1 and TS_CAL2 of STM32L1 are at VDDA=3.0V
adc_read_core_vref(adcHandle);
#endif
int32_t raw_value = adc_config_and_read_ref(adcHandle, ADC_CHANNEL_TEMPSENSOR); int32_t raw_value = adc_config_and_read_ref(adcHandle, ADC_CHANNEL_TEMPSENSOR);
#endif #endif
float core_temp_avg_slope = (*ADC_CAL2 - *ADC_CAL1) / 80.0f; float core_temp_avg_slope = (*ADC_CAL2 - *ADC_CAL1) / 80.0f;
@ -821,8 +864,12 @@ float adc_read_core_temp_float(ADC_HandleTypeDef *adcHandle) {
} }
float adc_read_core_vbat(ADC_HandleTypeDef *adcHandle) { float adc_read_core_vbat(ADC_HandleTypeDef *adcHandle) {
#if defined(STM32L152xE)
mp_raise_NotImplementedError(MP_ERROR_TEXT("read_core_vbat not supported"));
#else
uint32_t raw_value = adc_config_and_read_ref(adcHandle, ADC_CHANNEL_VBAT); uint32_t raw_value = adc_config_and_read_ref(adcHandle, ADC_CHANNEL_VBAT);
return raw_value * VBAT_DIV * ADC_SCALE * adc_refcor; return raw_value * VBAT_DIV * ADC_SCALE * adc_refcor;
#endif
} }
float adc_read_core_vref(ADC_HandleTypeDef *adcHandle) { float adc_read_core_vref(ADC_HandleTypeDef *adcHandle) {

View File

@ -0,0 +1,117 @@
Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15,
,,SYS_AF,TIM2,TIM3/TIM4/TIM5,TIM9/TIM10/TIM11,I2C1/I2C2,SPI1/SPI2,SPI3,USART1/USART2/USART3,UART4/UART5,,,,,,,,ADC
PortA,PA0,,TIM2_CH1_ETR,TIM5_CH1,,,,,USART2_CTS,,,,,,,,EVENTOUT,ADC1_IN0
PortA,PA1,,TIM2_CH2,TIM5_CH2,,,,,USART2_RTS,,,,,,,,EVENTOUT,ADC1_IN1
PortA,PA2,,TIM2_CH3,TIM5_CH3,TIM9_CH1,,,,USART2_TX,,,,,,,,EVENTOUT,ADC1_IN2
PortA,PA3,,TIM2_CH4,TIM5_CH4,TIM9_CH2,,,,USART2_RX,,,,,,,,EVENTOUT,ADC1_IN3
PortA,PA4,,,,,,SPI1_NSS,SPI3_NSS/I2S3_WS,USART2_CK,,,,,,,,EVENTOUT,ADC1_IN4
PortA,PA5,,TIM2_CH1_ETR,,,,SPI1_SCK,,,,,,,,,,EVENTOUT,ADC1_IN5
PortA,PA6,,,TIM3_CH1,TIM10_CH1,,SPI1_MISO,,,,,,,,,,EVENTOUT,ADC1_IN6
PortA,PA7,,,TIM3_CH2,TIM11_CH1,,SPI1_MOSI,,,,,,,,,,EVENTOUT,ADC1_IN7
PortA,PA8,MCO,,,,,,,USART1_CK,,,,,,,,EVENTOUT,
PortA,PA9,,,,,,,,USART1_TX,,,,,,,,EVENTOUT,
PortA,PA10,,,,,,,,USART1_RX,,,,,,,,EVENTOUT,
PortA,PA11,,,,,,SPI1_MISO,,USART1_CTS,,,,,,,,EVENTOUT,
PortA,PA12,,,,,,SPI1_MOSI,,USART1_RTS,,,,,,,,EVENTOUT,
PortA,PA13,JTMS/SWDIO,,,,,,,,,,,,,,,EVENTOUT,
PortA,PA14,JTCK/SWCLK,,,,,,,,,,,,,,,EVENTOUT,
PortA,PA15,JTDI,TIM2_CH1_ETR,,,,SPI1_NSS,SPI3_NSS/I2S3_WS,,,,,,,,,EVENTOUT,
PortB,PB0,,,TIM3_CH3,,,,,,,,,,,,,EVENTOUT,ADC1_IN8
PortB,PB1,,,TIM3_CH4,,,,,,,,,,,,,EVENTOUT,ADC1_IN9
PortB,PB2,BOOT1,,,,,,,,,,,,,,,EVENTOUT,
PortB,PB3,JTDO,TIM2_CH2,,,,SPI1_SCK,SPI3_SCK/I2S3_CK,,,,,,,,,EVENTOUT,
PortB,PB4,NJTRST,,TIM3_CH1,,,SPI1_MISO,SPI3_MISO,,,,,,,,,EVENTOUT,
PortB,PB5,,,TIM3_CH2,,I2C1_SMBA,SPI1_MOSI,SPI3_MOSI/I2S3_SD,,,,,,,,,EVENTOUT,
PortB,PB6,,,TIM4_CH1,,I2C1_SCL,,,USART1_TX,,,,,,,,EVENTOUT,
PortB,PB7,,,TIM4_CH2,,I2C1_SDA,,,USART1_RX,,,,,,,,EVENTOUT,
PortB,PB8,,,TIM4_CH3,TIM10_CH1,I2C1_SCL,,,,,,,,,,,EVENTOUT,
PortB,PB9,,,TIM4_CH4,TIM11_CH1,I2C1_SDA,,,,,,,,,,,EVENTOUT,
PortB,PB10,,TIM2_CH3,,,I2C2_SCL,,,USART3_TX,,,,,,,,EVENTOUT,
PortB,PB11,,TIM2_CH4,,,I2C2_SDA,,,USART3_RX,,,,,,,,EVENTOUT,
PortB,PB12,,,,TIM10_CH1,I2C2_SMBA,SPI2_NSS/I2S2_WS,,USART3_CK,,,,,,,,EVENTOUT,ADC1_IN18
PortB,PB13,,,,TIM9_CH1,,SPI2_SCK/I2S2_CK,,USART3_CTS,,,,,,,,EVENTOUT,ADC1_IN19
PortB,PB14,,,,TIM9_CH2,,SPI2_MISO,,USART3_RTS,,,,,,,,EVENTOUT,ADC1_IN20
PortB,PB15,,,,TIM11_CH1,,SPI2_MOSI/I2S2_SD,,,,,,,,,,EVENTOUT,ADC1_IN21
PortC,PC0,,,,,,,,,,,,,,,,EVENTOUT,ADC1_IN10
PortC,PC1,,,,,,,,,,,,,,,,EVENTOUT,ADC1_IN11
PortC,PC2,,,,,,,,,,,,,,,,EVENTOUT,ADC1_IN12
PortC,PC3,,,,,,,,,,,,,,,,EVENTOUT,ADC1_IN13
PortC,PC4,,,,,,,,,,,,,,,,EVENTOUT,ADC1_IN14
PortC,PC5,,,,,,,,,,,,,,,,EVENTOUT,ADC1_IN15
PortC,PC6,,,TIM3_CH1,,,I2S2_MCK,,,,,,,,,,EVENTOUT,
PortC,PC7,,,TIM3_CH2,,,,I2S3_MCK,,,,,,,,,EVENTOUT,
PortC,PC8,,,TIM3_CH3,,,,,,,,,,,,,EVENTOUT,
PortC,PC9,,,TIM3_CH4,,,,,,,,,,,,,EVENTOUT,
PortC,PC10,,,,,,,SPI3_SCK/I2S3_CK,USART3_TX,UART4_TX,,,,,,,EVENTOUT,
PortC,PC11,,,,,,,SPI3_MISO,USART3_RX,UART4_RX,,,,,,,EVENTOUT,
PortC,PC12,,,,,,,SPI3_MOSI/I2S3_SD,USART3_CK,UART5_TX,,,,,,,EVENTOUT,
PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT,
PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT,
PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT,
PortD,PD0,,,,TIM9_CH1,,SPI2_NSS/I2S2_WS,,,,,,,,,,EVENTOUT,
PortD,PD1,,,,,,SPI2_SCK/I2S2_CK,,,,,,,,,,EVENTOUT,
PortD,PD2,,,TIM3_ETR,,,,,,UART5_RX,,,,,,,EVENTOUT,
PortD,PD3,,,,,,SPI2_MISO,,USART2_CTS,,,,,,,,EVENTOUT,
PortD,PD4,,,,,,SPI2_MOSI/I2S2_SD,,USART2_RTS,,,,,,,,EVENTOUT,
PortD,PD5,,,,,,,,USART2_TX,,,,,,,,EVENTOUT,
PortD,PD6,,,,,,,,USART2_RX,,,,,,,,EVENTOUT,
PortD,PD7,,,,TIM9_CH2,,,,USART2_CK,,,,,,,,EVENTOUT,
PortD,PD8,,,,,,,,USART3_TX,,,,,,,,EVENTOUT,
PortD,PD9,,,,,,,,USART3_RX,,,,,,,,EVENTOUT,
PortD,PD10,,,,,,,,USART3_CK,,,,,,,,EVENTOUT,
PortD,PD11,,,,,,,,USART3_CTS,,,,,,,,EVENTOUT,
PortD,PD12,,,TIM4_CH1,,,,,USART3_RTS,,,,,,,,EVENTOUT,
PortD,PD13,,,TIM4_CH2,,,,,,,,,,,,,EVENTOUT,
PortD,PD14,,,TIM4_CH3,,,,,,,,,,,,,EVENTOUT,
PortD,PD15,,,TIM4_CH4,,,,,,,,,,,,,EVENTOUT,
PortE,PE0,,,TIM4_ETR,TIM10_CH1,,,,,,,,,,,,EVENTOUT,
PortE,PE1,,,,TIM11_CH1,,,,,,,,,,,,EVENTOUT,
PortE,PE2,TRACECK,,TIM3_ETR,,,,,,,,,,,,,EVENTOUT,
PortE,PE3,TRACED0,,TIM3_CH1,,,,,,,,,,,,,EVENTOUT,
PortE,PE4,TRACED1,,TIM3_CH2,,,,,,,,,,,,,EVENTOUT,
PortE,PE5,TRACED2,,,TIM9_CH1,,,,,,,,,,,,EVENTOUT,
PortE,PE6,TRACED3,,,TIM9_CH2,,,,,,,,,,,,EVENTOUT,
PortE,PE7,,,,,,,,,,,,,,,,EVENTOUT,
PortE,PE8,,,,,,,,,,,,,,,,EVENTOUT,
PortE,PE9,,TIM2_CH1_ETR,,,,,,,,,,,,,,EVENTOUT,
PortE,PE10,,TIM2_CH2,,,,,,,,,,,,,,EVENTOUT,
PortE,PE11,,TIM2_CH3,,,,,,,,,,,,,,EVENTOUT,
PortE,PE12,,TIM2_CH4,,,,SPI1_NSS,,,,,,,,,,EVENTOUT,
PortE,PE13,,,,,,SPI1_SCK,,,,,,,,,,EVENTOUT,
PortE,PE14,,,,,,SPI1_MISO,,,,,,,,,,EVENTOUT,
PortE,PE15,,,,,,SPI1_MOSI,,,,,,,,,,EVENTOUT,
PortF,PF0,,,,,,,,,,,,,,,,EVENTOUT,
PortF,PF1,,,,,,,,,,,,,,,,EVENTOUT,
PortF,PF2,,,,,,,,,,,,,,,,EVENTOUT,
PortF,PF3,,,,,,,,,,,,,,,,EVENTOUT,
PortF,PF4,,,,,,,,,,,,,,,,EVENTOUT,
PortF,PF5,,,,,,,,,,,,,,,,EVENTOUT,
PortF,PF6,,,TIM5_ETR,,,,,,,,,,,,,EVENTOUT,
PortF,PF7,,,TIM5_CH2,,,,,,,,,,,,,EVENTOUT,
PortF,PF8,,,TIM5_CH3,,,,,,,,,,,,,EVENTOUT,
PortF,PF9,,,TIM5_CH4,,,,,,,,,,,,,EVENTOUT,
PortF,PF10,,,,,,,,,,,,,,,,EVENTOUT,
PortF,PF11,,,,,,,,,,,,,,,,EVENTOUT,
PortF,PF12,,,,,,,,,,,,,,,,EVENTOUT,
PortF,PF13,,,,,,,,,,,,,,,,EVENTOUT,
PortF,PF14,,,,,,,,,,,,,,,,EVENTOUT,
PortF,PF15,,,,,,,,,,,,,,,,EVENTOUT,
PortG,PG0,,,,,,,,,,,,,,,,EVENTOUT,
PortG,PG1,,,,,,,,,,,,,,,,EVENTOUT,
PortG,PG2,,,,,,,,,,,,,,,,EVENTOUT,
PortG,PG3,,,,,,,,,,,,,,,,EVENTOUT,
PortG,PG4,,,,,,,,,,,,,,,,EVENTOUT,
PortG,PG5,,,,,,,,,,,,,,,,EVENTOUT,
PortG,PG6,,,,,,,,,,,,,,,,EVENTOUT,
PortG,PG7,,,,,,,,,,,,,,,,EVENTOUT,
PortG,PG8,,,,,,,,,,,,,,,,EVENTOUT,
PortG,PG9,,,,,,,,,,,,,,,,EVENTOUT,
PortG,PG10,,,,,,,,,,,,,,,,EVENTOUT,
PortG,PG11,,,,,,,,,,,,,,,,EVENTOUT,
PortG,PG12,,,,,,,,,,,,,,,,EVENTOUT,
PortG,PG13,,,,,,,,,,,,,,,,EVENTOUT,
PortG,PG14,,,,,,,,,,,,,,,,EVENTOUT,
PortG,PG15,,,,,,,,,,,,,,,,EVENTOUT,
PortH,PH0,,,,,,,,,,,,,,,,,
PortH,PH1,,,,,,,,,,,,,,,,,
PortH,PH2,,,,,,,,,,,,,,,,,
1 Port AF0 AF1 AF2 AF3 AF4 AF5 AF6 AF7 AF8 AF9 AF10 AF11 AF12 AF13 AF14 AF15
2 SYS_AF TIM2 TIM3/TIM4/TIM5 TIM9/TIM10/TIM11 I2C1/I2C2 SPI1/SPI2 SPI3 USART1/USART2/USART3 UART4/UART5 ADC
3 PortA PA0 TIM2_CH1_ETR TIM5_CH1 USART2_CTS EVENTOUT ADC1_IN0
4 PortA PA1 TIM2_CH2 TIM5_CH2 USART2_RTS EVENTOUT ADC1_IN1
5 PortA PA2 TIM2_CH3 TIM5_CH3 TIM9_CH1 USART2_TX EVENTOUT ADC1_IN2
6 PortA PA3 TIM2_CH4 TIM5_CH4 TIM9_CH2 USART2_RX EVENTOUT ADC1_IN3
7 PortA PA4 SPI1_NSS SPI3_NSS/I2S3_WS USART2_CK EVENTOUT ADC1_IN4
8 PortA PA5 TIM2_CH1_ETR SPI1_SCK EVENTOUT ADC1_IN5
9 PortA PA6 TIM3_CH1 TIM10_CH1 SPI1_MISO EVENTOUT ADC1_IN6
10 PortA PA7 TIM3_CH2 TIM11_CH1 SPI1_MOSI EVENTOUT ADC1_IN7
11 PortA PA8 MCO USART1_CK EVENTOUT
12 PortA PA9 USART1_TX EVENTOUT
13 PortA PA10 USART1_RX EVENTOUT
14 PortA PA11 SPI1_MISO USART1_CTS EVENTOUT
15 PortA PA12 SPI1_MOSI USART1_RTS EVENTOUT
16 PortA PA13 JTMS/SWDIO EVENTOUT
17 PortA PA14 JTCK/SWCLK EVENTOUT
18 PortA PA15 JTDI TIM2_CH1_ETR SPI1_NSS SPI3_NSS/I2S3_WS EVENTOUT
19 PortB PB0 TIM3_CH3 EVENTOUT ADC1_IN8
20 PortB PB1 TIM3_CH4 EVENTOUT ADC1_IN9
21 PortB PB2 BOOT1 EVENTOUT
22 PortB PB3 JTDO TIM2_CH2 SPI1_SCK SPI3_SCK/I2S3_CK EVENTOUT
23 PortB PB4 NJTRST TIM3_CH1 SPI1_MISO SPI3_MISO EVENTOUT
24 PortB PB5 TIM3_CH2 I2C1_SMBA SPI1_MOSI SPI3_MOSI/I2S3_SD EVENTOUT
25 PortB PB6 TIM4_CH1 I2C1_SCL USART1_TX EVENTOUT
26 PortB PB7 TIM4_CH2 I2C1_SDA USART1_RX EVENTOUT
27 PortB PB8 TIM4_CH3 TIM10_CH1 I2C1_SCL EVENTOUT
28 PortB PB9 TIM4_CH4 TIM11_CH1 I2C1_SDA EVENTOUT
29 PortB PB10 TIM2_CH3 I2C2_SCL USART3_TX EVENTOUT
30 PortB PB11 TIM2_CH4 I2C2_SDA USART3_RX EVENTOUT
31 PortB PB12 TIM10_CH1 I2C2_SMBA SPI2_NSS/I2S2_WS USART3_CK EVENTOUT ADC1_IN18
32 PortB PB13 TIM9_CH1 SPI2_SCK/I2S2_CK USART3_CTS EVENTOUT ADC1_IN19
33 PortB PB14 TIM9_CH2 SPI2_MISO USART3_RTS EVENTOUT ADC1_IN20
34 PortB PB15 TIM11_CH1 SPI2_MOSI/I2S2_SD EVENTOUT ADC1_IN21
35 PortC PC0 EVENTOUT ADC1_IN10
36 PortC PC1 EVENTOUT ADC1_IN11
37 PortC PC2 EVENTOUT ADC1_IN12
38 PortC PC3 EVENTOUT ADC1_IN13
39 PortC PC4 EVENTOUT ADC1_IN14
40 PortC PC5 EVENTOUT ADC1_IN15
41 PortC PC6 TIM3_CH1 I2S2_MCK EVENTOUT
42 PortC PC7 TIM3_CH2 I2S3_MCK EVENTOUT
43 PortC PC8 TIM3_CH3 EVENTOUT
44 PortC PC9 TIM3_CH4 EVENTOUT
45 PortC PC10 SPI3_SCK/I2S3_CK USART3_TX UART4_TX EVENTOUT
46 PortC PC11 SPI3_MISO USART3_RX UART4_RX EVENTOUT
47 PortC PC12 SPI3_MOSI/I2S3_SD USART3_CK UART5_TX EVENTOUT
48 PortC PC13 EVENTOUT
49 PortC PC14 EVENTOUT
50 PortC PC15 EVENTOUT
51 PortD PD0 TIM9_CH1 SPI2_NSS/I2S2_WS EVENTOUT
52 PortD PD1 SPI2_SCK/I2S2_CK EVENTOUT
53 PortD PD2 TIM3_ETR UART5_RX EVENTOUT
54 PortD PD3 SPI2_MISO USART2_CTS EVENTOUT
55 PortD PD4 SPI2_MOSI/I2S2_SD USART2_RTS EVENTOUT
56 PortD PD5 USART2_TX EVENTOUT
57 PortD PD6 USART2_RX EVENTOUT
58 PortD PD7 TIM9_CH2 USART2_CK EVENTOUT
59 PortD PD8 USART3_TX EVENTOUT
60 PortD PD9 USART3_RX EVENTOUT
61 PortD PD10 USART3_CK EVENTOUT
62 PortD PD11 USART3_CTS EVENTOUT
63 PortD PD12 TIM4_CH1 USART3_RTS EVENTOUT
64 PortD PD13 TIM4_CH2 EVENTOUT
65 PortD PD14 TIM4_CH3 EVENTOUT
66 PortD PD15 TIM4_CH4 EVENTOUT
67 PortE PE0 TIM4_ETR TIM10_CH1 EVENTOUT
68 PortE PE1 TIM11_CH1 EVENTOUT
69 PortE PE2 TRACECK TIM3_ETR EVENTOUT
70 PortE PE3 TRACED0 TIM3_CH1 EVENTOUT
71 PortE PE4 TRACED1 TIM3_CH2 EVENTOUT
72 PortE PE5 TRACED2 TIM9_CH1 EVENTOUT
73 PortE PE6 TRACED3 TIM9_CH2 EVENTOUT
74 PortE PE7 EVENTOUT
75 PortE PE8 EVENTOUT
76 PortE PE9 TIM2_CH1_ETR EVENTOUT
77 PortE PE10 TIM2_CH2 EVENTOUT
78 PortE PE11 TIM2_CH3 EVENTOUT
79 PortE PE12 TIM2_CH4 SPI1_NSS EVENTOUT
80 PortE PE13 SPI1_SCK EVENTOUT
81 PortE PE14 SPI1_MISO EVENTOUT
82 PortE PE15 SPI1_MOSI EVENTOUT
83 PortF PF0 EVENTOUT
84 PortF PF1 EVENTOUT
85 PortF PF2 EVENTOUT
86 PortF PF3 EVENTOUT
87 PortF PF4 EVENTOUT
88 PortF PF5 EVENTOUT
89 PortF PF6 TIM5_ETR EVENTOUT
90 PortF PF7 TIM5_CH2 EVENTOUT
91 PortF PF8 TIM5_CH3 EVENTOUT
92 PortF PF9 TIM5_CH4 EVENTOUT
93 PortF PF10 EVENTOUT
94 PortF PF11 EVENTOUT
95 PortF PF12 EVENTOUT
96 PortF PF13 EVENTOUT
97 PortF PF14 EVENTOUT
98 PortF PF15 EVENTOUT
99 PortG PG0 EVENTOUT
100 PortG PG1 EVENTOUT
101 PortG PG2 EVENTOUT
102 PortG PG3 EVENTOUT
103 PortG PG4 EVENTOUT
104 PortG PG5 EVENTOUT
105 PortG PG6 EVENTOUT
106 PortG PG7 EVENTOUT
107 PortG PG8 EVENTOUT
108 PortG PG9 EVENTOUT
109 PortG PG10 EVENTOUT
110 PortG PG11 EVENTOUT
111 PortG PG12 EVENTOUT
112 PortG PG13 EVENTOUT
113 PortG PG14 EVENTOUT
114 PortG PG15 EVENTOUT
115 PortH PH0
116 PortH PH1
117 PortH PH2

View File

@ -0,0 +1,37 @@
/*
GNU linker script for STM32L152xE
*/
/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K /* entire flash */
FLASH_FS (rx) : ORIGIN = 0x08064000, LENGTH = 112K /* sectors 100-127 */
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 81408
FS_CACHE (xrw) : ORIGIN = 0x20013e00, LENGTH = 512
}
/* produce a link error if there is not this amount of RAM for these sections */
_minimum_stack_size = 2K;
_minimum_heap_size = 16K;
/* RAM extents for the garbage collector */
_ram_start = ORIGIN(RAM);
_ram_end = ORIGIN(RAM) + LENGTH(RAM);
/* Define the stack. The stack is full descending so begins just above last byte
of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */
_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve;
_sstack = _estack - 16K; /* tunable */
/* RAM extents for the garbage collector */
_ram_start = ORIGIN(RAM);
_ram_end = ORIGIN(RAM) + LENGTH(RAM);
_heap_start = _ebss; /* heap starts just after statically allocated memory */
_heap_end = _sstack;
/* Filesystem cache in RAM, and storage in flash */
_micropy_hw_internal_flash_storage_ram_cache_start = ORIGIN(FS_CACHE);
_micropy_hw_internal_flash_storage_ram_cache_end = ORIGIN(FS_CACHE) + LENGTH(FS_CACHE);
_micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS);
_micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS);

View File

@ -0,0 +1,99 @@
/*
* 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_STM32L1XX_HAL_CONF_BASE_H
#define MICROPY_INCLUDED_STM32L1XX_HAL_CONF_BASE_H
// Include various HAL modules for convenience
#include "stm32l1xx_hal_rcc.h"
#include "stm32l1xx_hal_gpio.h"
#include "stm32l1xx_hal_dma.h"
#include "stm32l1xx_hal_cortex.h"
#include "stm32l1xx_hal_adc.h"
#include "stm32l1xx_hal_comp.h"
#include "stm32l1xx_hal_crc.h"
#include "stm32l1xx_hal_dac.h"
#include "stm32l1xx_hal_flash.h"
#include "stm32l1xx_hal_i2c.h"
#include "stm32l1xx_hal_iwdg.h"
#include "stm32l1xx_hal_pwr.h"
#include "stm32l1xx_hal_rtc.h"
#include "stm32l1xx_hal_spi.h"
#include "stm32l1xx_hal_tim.h"
#include "stm32l1xx_hal_uart.h"
#include "stm32l1xx_hal_usart.h"
#include "stm32l1xx_hal_wwdg.h"
#include "stm32l1xx_hal_exti.h"
#include "stm32l1xx_ll_adc.h"
#include "stm32l1xx_ll_pwr.h"
#include "stm32l1xx_ll_rtc.h"
#include "stm32l1xx_ll_usart.h"
// Enable various HAL modules
#define HAL_MODULE_ENABLED
#define HAL_ADC_MODULE_ENABLED
#define HAL_CORTEX_MODULE_ENABLED
#define HAL_CRC_MODULE_ENABLED
#define HAL_DAC_MODULE_ENABLED
#define HAL_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
#define HAL_WWDG_MODULE_ENABLED
// Oscillator values in Hz
#define HSE_VALUE (8000000)
#define HSI_VALUE (16000000)
#define HSI48_VALUE (48000000)
#define LSI_VALUE (37000)
#define LSE_VALUE (32768)
#define MSI_VALUE (2097000)
// Oscillator timeouts in ms
#define HSE_STARTUP_TIMEOUT (100)
#define LSE_STARTUP_TIMEOUT (5000)
// SysTick has the highest priority
#define TICK_INT_PRIORITY (0x00)
// Miscellaneous HAL settings
#define DATA_CACHE_ENABLE 1
#define INSTRUCTION_CACHE_ENABLE 1
#define PREFETCH_ENABLE 1
#define USE_SPI_CRC 0
#define USE_RTOS 0
// HAL parameter assertions are disabled
#define assert_param(expr) ((void)0)
#endif // MICROPY_INCLUDED_STM32L1XX_HAL_CONF_BASE_H

View File

@ -261,6 +261,8 @@ STATIC mp_obj_t pyb_dac_init_helper(pyb_dac_obj_t *self, size_t n_args, const mp
__HAL_RCC_DAC12_CLK_ENABLE(); __HAL_RCC_DAC12_CLK_ENABLE();
#elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32L4) #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32L4)
__HAL_RCC_DAC1_CLK_ENABLE(); __HAL_RCC_DAC1_CLK_ENABLE();
#elif defined(STM32L1)
__HAL_RCC_DAC_CLK_ENABLE();
#else #else
#error Unsupported Processor #error Unsupported Processor
#endif #endif

View File

@ -80,7 +80,7 @@ typedef union {
struct _dma_descr_t { struct _dma_descr_t {
#if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) #if defined(STM32F4) || defined(STM32F7) || defined(STM32H7)
DMA_Stream_TypeDef *instance; DMA_Stream_TypeDef *instance;
#elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL)
DMA_Channel_TypeDef *instance; DMA_Channel_TypeDef *instance;
#else #else
#error "Unsupported Processor" #error "Unsupported Processor"
@ -398,6 +398,57 @@ static const uint8_t dma_irqn[NSTREAM] = {
DMA1_Channel4_5_6_7_IRQn, DMA1_Channel4_5_6_7_IRQn,
}; };
#elif defined(STM32L1)
#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
#define DMA2_ENABLE_MASK (0x0f80) // Bits in dma_enable_mask corresponding to DMA2
// 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, 2, dma_id_1, &dma_init_struct_spi_i2c };
#if MICROPY_HW_ENABLE_DAC
const dma_descr_t dma_DAC_1_TX = { DMA1_Channel2, 2, dma_id_1, &dma_init_struct_dac };
#endif
const dma_descr_t dma_SPI_1_TX = { DMA1_Channel3, 3, dma_id_2, &dma_init_struct_spi_i2c };
#if MICROPY_HW_ENABLE_DAC
const dma_descr_t dma_DAC_2_TX = { DMA1_Channel3, 3, dma_id_2, &dma_init_struct_dac };
#endif
const dma_descr_t dma_SPI_2_RX = { DMA1_Channel4, 4, dma_id_3, &dma_init_struct_spi_i2c };
const dma_descr_t dma_I2C_2_TX = { DMA1_Channel4, 4, dma_id_3, &dma_init_struct_spi_i2c };
const dma_descr_t dma_SPI_2_TX = { DMA1_Channel5, 5, dma_id_4, &dma_init_struct_spi_i2c };
const dma_descr_t dma_I2C_2_RX = { DMA1_Channel5, 5, dma_id_4, &dma_init_struct_spi_i2c };
const dma_descr_t dma_I2C_1_TX = { DMA1_Channel6, 6, dma_id_5, &dma_init_struct_spi_i2c };
const dma_descr_t dma_I2C_1_RX = { DMA1_Channel7, 7, dma_id_6, &dma_init_struct_spi_i2c };
// DMA2 streams
const dma_descr_t dma_SPI_3_RX = { DMA2_Channel1, 3, dma_id_7, &dma_init_struct_spi_i2c };
const dma_descr_t dma_SPI_3_TX = { DMA2_Channel2, 3, dma_id_8, &dma_init_struct_spi_i2c };
static const uint8_t dma_irqn[NSTREAM] = {
DMA1_Channel1_IRQn,
DMA1_Channel2_IRQn,
DMA1_Channel3_IRQn,
DMA1_Channel4_IRQn,
DMA1_Channel5_IRQn,
DMA1_Channel6_IRQn,
DMA1_Channel7_IRQn,
DMA2_Channel1_IRQn,
DMA2_Channel2_IRQn,
DMA2_Channel3_IRQn,
DMA2_Channel4_IRQn,
DMA2_Channel5_IRQn,
0,
0
};
#elif defined(STM32L4) #elif defined(STM32L4)
#define NCONTROLLERS (2) #define NCONTROLLERS (2)
@ -705,7 +756,7 @@ volatile dma_idle_count_t dma_idle;
#define DMA_INVALID_CHANNEL 0xff // Value stored in dma_last_channel which means invalid #define DMA_INVALID_CHANNEL 0xff // Value stored in dma_last_channel which means invalid
#if defined(STM32F0) || defined(STM32G0) || defined(STM32L0) #if defined(STM32F0) || defined(STM32G0) || defined(STM32L0) || defined(STM32L1)
#define DMA1_IS_CLK_ENABLED() ((RCC->AHBENR & RCC_AHBENR_DMA1EN) != 0) #define DMA1_IS_CLK_ENABLED() ((RCC->AHBENR & RCC_AHBENR_DMA1EN) != 0)
#if defined(DMA2) #if defined(DMA2)
#define DMA2_IS_CLK_ENABLED() ((RCC->AHBENR & RCC_AHBENR_DMA2EN) != 0) #define DMA2_IS_CLK_ENABLED() ((RCC->AHBENR & RCC_AHBENR_DMA2EN) != 0)
@ -1080,7 +1131,7 @@ void DMA1_Channel4_5_6_7_IRQHandler(void) {
IRQ_EXIT(DMA1_Channel4_5_6_7_IRQn); IRQ_EXIT(DMA1_Channel4_5_6_7_IRQn);
} }
#elif defined(STM32L4) || defined(STM32WB) #elif defined(STM32L1) || defined(STM32L4) || defined(STM32WB)
void DMA1_Channel1_IRQHandler(void) { void DMA1_Channel1_IRQHandler(void) {
IRQ_ENTER(DMA1_Channel1_IRQn); IRQ_ENTER(DMA1_Channel1_IRQn);
@ -1166,6 +1217,7 @@ void DMA2_Channel5_IRQHandler(void) {
} }
IRQ_EXIT(DMA2_Channel5_IRQn); IRQ_EXIT(DMA2_Channel5_IRQn);
} }
#if !defined(STM32L1)
void DMA2_Channel6_IRQHandler(void) { void DMA2_Channel6_IRQHandler(void) {
IRQ_ENTER(DMA2_Channel6_IRQn); IRQ_ENTER(DMA2_Channel6_IRQn);
if (dma_handle[dma_id_12] != NULL) { if (dma_handle[dma_id_12] != NULL) {
@ -1180,6 +1232,7 @@ void DMA2_Channel7_IRQHandler(void) {
} }
IRQ_EXIT(DMA2_Channel7_IRQn); IRQ_EXIT(DMA2_Channel7_IRQn);
} }
#endif
#endif #endif
@ -1260,7 +1313,7 @@ void dma_init_handle(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint3
#if defined(STM32G0) || 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; dma->Init.Request = dma_descr->sub_instance;
#else #else
#if !defined(STM32F0) #if !defined(STM32F0) && !defined(STM32L1)
dma->Init.Channel = dma_descr->sub_instance; dma->Init.Channel = dma_descr->sub_instance;
#endif #endif
#endif #endif
@ -1284,7 +1337,7 @@ void dma_init(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint32_t dir
dma_enable_clock(dma_id); dma_enable_clock(dma_id);
#if defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) #if defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL)
// Always reset and configure the H7 and G0/G4/H7/L0/L4/WB/WL DMA peripheral // 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) // (dma->State is set to HAL_DMA_STATE_RESET by memset above)
// TODO: understand how L0/L4 DMA works so this is not needed // TODO: understand how L0/L4 DMA works so this is not needed
@ -1410,7 +1463,7 @@ static void dma_idle_handler(uint32_t tick) {
} }
#endif #endif
#if defined(STM32F0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L4) #if defined(STM32F0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L1) || defined(STM32L4)
void dma_nohal_init(const dma_descr_t *descr, uint32_t config) { void dma_nohal_init(const dma_descr_t *descr, uint32_t config) {
DMA_Channel_TypeDef *dma = descr->instance; DMA_Channel_TypeDef *dma = descr->instance;
@ -1436,6 +1489,7 @@ void dma_nohal_init(const dma_descr_t *descr, uint32_t config) {
#elif defined(STM32G4) #elif defined(STM32G4)
uint32_t *dmamux_ctrl = (void *)(DMAMUX1_Channel0_BASE + 0x04 * descr->id); uint32_t *dmamux_ctrl = (void *)(DMAMUX1_Channel0_BASE + 0x04 * descr->id);
*dmamux_ctrl = (*dmamux_ctrl & ~(0x7f)) | descr->sub_instance; *dmamux_ctrl = (*dmamux_ctrl & ~(0x7f)) | descr->sub_instance;
#elif defined(STM32L1)
#else #else
DMA_Request_TypeDef *dma_ctrl = (void *)(((uint32_t)dma & ~0xff) + (DMA1_CSELR_BASE - DMA1_BASE)); // DMA1_CSELR or DMA2_CSELR DMA_Request_TypeDef *dma_ctrl = (void *)(((uint32_t)dma & ~0xff) + (DMA1_CSELR_BASE - DMA1_BASE)); // DMA1_CSELR or DMA2_CSELR
uint32_t channel_number = (((uint32_t)dma & 0xff) - 0x08) / 20; // 0 through 6 uint32_t channel_number = (((uint32_t)dma & 0xff) - 0x08) / 20; // 0 through 6

View File

@ -100,6 +100,20 @@ 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_TX;
extern const dma_descr_t dma_I2C_1_RX; extern const dma_descr_t dma_I2C_1_RX;
#elif defined(STM32L1)
extern const dma_descr_t dma_SPI_1_RX;
extern const dma_descr_t dma_SPI_3_TX;
extern const dma_descr_t dma_SPI_1_TX;
extern const dma_descr_t dma_SPI_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) || defined(STM32WB) || defined(STM32WL) #elif defined(STM32L4) || defined(STM32WB) || defined(STM32WL)
extern const dma_descr_t dma_ADC_1_RX; extern const dma_descr_t dma_ADC_1_RX;

View File

@ -210,7 +210,11 @@ STATIC const uint8_t nvic_irq_channel[EXTI_NUM_VECTORS] = {
#endif #endif
ETH_WKUP_IRQn, ETH_WKUP_IRQn,
OTG_HS_WKUP_IRQn, OTG_HS_WKUP_IRQn,
#if defined(STM32L1)
TAMPER_STAMP_IRQn,
#else
TAMP_STAMP_IRQn, TAMP_STAMP_IRQn,
#endif
RTC_WKUP_IRQn, RTC_WKUP_IRQn,
#endif #endif

View File

@ -43,7 +43,7 @@
#endif #endif
#define EXTI_ETH_WAKEUP (19) #define EXTI_ETH_WAKEUP (19)
#define EXTI_USB_OTG_HS_WAKEUP (20) #define EXTI_USB_OTG_HS_WAKEUP (20)
#if defined(STM32F0) || defined(STM32G4) || defined(STM32L4) || defined(STM32WL) #if defined(STM32F0) || defined(STM32G4) || defined(STM32L1) || defined(STM32L4) || defined(STM32WL)
#define EXTI_RTC_TIMESTAMP (19) #define EXTI_RTC_TIMESTAMP (19)
#define EXTI_RTC_WAKEUP (20) #define EXTI_RTC_WAKEUP (20)
#elif defined(STM32H7) || defined(STM32WB) #elif defined(STM32H7) || defined(STM32WB)

View File

@ -117,6 +117,12 @@ static const flash_layout_t flash_layout[] = {
{ (uint32_t)FLASH_BASE, (uint32_t)FLASH_PAGE_SIZE, 512 }, { (uint32_t)FLASH_BASE, (uint32_t)FLASH_PAGE_SIZE, 512 },
}; };
#elif defined(STM32L1)
static const flash_layout_t flash_layout[] = {
{ (uint32_t)FLASH_BASE, 0x200, 1024 },
};
#elif defined(STM32H7) #elif defined(STM32H7)
static const flash_layout_t flash_layout[] = { static const flash_layout_t flash_layout[] = {
@ -264,7 +270,7 @@ int flash_erase(uint32_t flash_dest, uint32_t num_word32) {
EraseInitStruct.Page = get_page(flash_dest); EraseInitStruct.Page = get_page(flash_dest);
EraseInitStruct.Banks = get_bank(flash_dest); EraseInitStruct.Banks = get_bank(flash_dest);
EraseInitStruct.NbPages = (4 * num_word32 + FLASH_PAGE_SIZE - 4) / FLASH_PAGE_SIZE; EraseInitStruct.NbPages = (4 * num_word32 + FLASH_PAGE_SIZE - 4) / FLASH_PAGE_SIZE;
#elif defined(STM32L0) #elif defined(STM32L0) || defined(STM32L1)
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR); __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR);
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
EraseInitStruct.PageAddress = flash_dest; EraseInitStruct.PageAddress = flash_dest;
@ -286,6 +292,8 @@ int flash_erase(uint32_t flash_dest, uint32_t num_word32) {
#if defined(STM32H7) #if defined(STM32H7)
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS_BANK1 | FLASH_FLAG_ALL_ERRORS_BANK2); __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS_BANK1 | FLASH_FLAG_ALL_ERRORS_BANK2);
#elif defined(STM32L1)
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR);
#else #else
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR |
FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);

View File

@ -42,7 +42,7 @@
#define ADCx_COMMON __LL_ADC_COMMON_INSTANCE(0) #define ADCx_COMMON __LL_ADC_COMMON_INSTANCE(0)
#endif #endif
#if defined(STM32F0) || defined(STM32G0) || defined(STM32L0) || defined(STM32WL) #if defined(STM32F0) || defined(STM32G0) || defined(STM32L0) || defined(STM32L1) || defined(STM32WL)
#define ADC_STAB_DELAY_US (1) #define ADC_STAB_DELAY_US (1)
#define ADC_TEMPSENSOR_DELAY_US (10) #define ADC_TEMPSENSOR_DELAY_US (10)
#elif defined(STM32G4) #elif defined(STM32G4)
@ -68,6 +68,9 @@
#elif defined(STM32G0) || defined(STM32L0) || defined(STM32WL) #elif defined(STM32G0) || defined(STM32L0) || defined(STM32WL)
#define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_12CYCLES_5 #define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_12CYCLES_5
#define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_160CYCLES_5 #define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_160CYCLES_5
#elif defined(STM32L1)
#define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_384CYCLES
#define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_384CYCLES
#elif defined(STM32L4) || defined(STM32WB) #elif defined(STM32L4) || defined(STM32WB)
#define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_12CYCLES_5 #define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_12CYCLES_5
#define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_247CYCLES_5 #define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_247CYCLES_5
@ -239,7 +242,7 @@ void adc_config(ADC_TypeDef *adc, uint32_t bits) {
STATIC int adc_get_bits(ADC_TypeDef *adc) { STATIC int adc_get_bits(ADC_TypeDef *adc) {
#if defined(STM32F0) || defined(STM32G0) || 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; uint32_t res = (adc->CFGR1 & ADC_CFGR1_RES) >> ADC_CFGR1_RES_Pos;
#elif defined(STM32F4) || defined(STM32F7) #elif defined(STM32F4) || defined(STM32F7) || defined(STM32L1)
uint32_t res = (adc->CR1 & ADC_CR1_RES) >> ADC_CR1_RES_Pos; uint32_t res = (adc->CR1 & ADC_CR1_RES) >> ADC_CR1_RES_Pos;
#elif defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) #elif defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB)
uint32_t res = (adc->CFGR & ADC_CFGR_RES) >> ADC_CFGR_RES_Pos; uint32_t res = (adc->CFGR & ADC_CFGR_RES) >> ADC_CFGR_RES_Pos;

View File

@ -138,7 +138,7 @@ void machine_init(void) {
if (state & RCC_SR_IWDGRSTF || state & RCC_SR_WWDGRSTF) { if (state & RCC_SR_IWDGRSTF || state & RCC_SR_WWDGRSTF) {
reset_cause = PYB_RESET_WDT; reset_cause = PYB_RESET_WDT;
} else if (state & RCC_SR_PORRSTF } else if (state & RCC_SR_PORRSTF
#if !defined(STM32F0) && !defined(STM32F412Zx) #if !defined(STM32F0) && !defined(STM32F412Zx) && !defined(STM32L1)
|| state & RCC_SR_BORRSTF || state & RCC_SR_BORRSTF
#endif #endif
) { ) {
@ -309,7 +309,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); return mp_obj_new_tuple(MP_ARRAY_SIZE(tuple), tuple);
} else { } else {
// set // set
#if defined(STM32F0) || defined(STM32L0) || defined(STM32L4) || defined(STM32G0) #if defined(STM32F0) || defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32G0)
mp_raise_NotImplementedError(MP_ERROR_TEXT("machine.freq set not supported yet")); mp_raise_NotImplementedError(MP_ERROR_TEXT("machine.freq set not supported yet"));
#else #else
mp_int_t sysclk = mp_obj_get_int(args[0]); mp_int_t sysclk = mp_obj_get_int(args[0]);

View File

@ -370,6 +370,16 @@
#define MICROPY_HW_MAX_UART (5) #define MICROPY_HW_MAX_UART (5)
#define MICROPY_HW_MAX_LPUART (1) #define MICROPY_HW_MAX_LPUART (1)
// Configuration for STM32L1 series
#elif defined(STM32L1)
#define MP_HAL_UNIQUE_ID_ADDRESS (UID_BASE)
#define PYB_EXTI_NUM_VECTORS (23)
#define MICROPY_HW_MAX_I2C (2)
// TODO: L1 has 9 timers but tim0 and tim1 don't exist.
#define MICROPY_HW_MAX_TIMER (11)
#define MICROPY_HW_MAX_UART (5)
#define MICROPY_HW_MAX_LPUART (0)
// Configuration for STM32L4 series // Configuration for STM32L4 series
#elif defined(STM32L4) #elif defined(STM32L4)

View File

@ -87,7 +87,7 @@ 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 // This logic assumes that all the GPIOx_EN bits are adjacent and ordered in one register
#if defined(STM32F0) #if defined(STM32F0) || defined(STM32L1)
#define AHBxENR AHBENR #define AHBxENR AHBENR
#define AHBxENR_GPIOAEN_Pos RCC_AHBENR_GPIOAEN_Pos #define AHBxENR_GPIOAEN_Pos RCC_AHBENR_GPIOAEN_Pos
#elif defined(STM32F4) || defined(STM32F7) #elif defined(STM32F4) || defined(STM32F7)

View File

@ -17,6 +17,8 @@
#define MICROPY_PLATFORM_VERSION "HAL1.6.0" #define MICROPY_PLATFORM_VERSION "HAL1.6.0"
#elif defined(STM32L0) #elif defined(STM32L0)
#define MICROPY_PLATFORM_VERSION "HAL1.11.2" #define MICROPY_PLATFORM_VERSION "HAL1.11.2"
#elif defined(STM32L1)
#define MICROPY_PLATFORM_VERSION "HAL1.10.3"
#elif defined(STM32L4) #elif defined(STM32L4)
#define MICROPY_PLATFORM_VERSION "HAL1.17.0" #define MICROPY_PLATFORM_VERSION "HAL1.17.0"
#elif defined(STM32WB) #elif defined(STM32WB)

View File

@ -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)) { 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 // Reset by NVIC_SystemReset with bootloader data set -> branch to bootloader
RCC->RCC_SR = RCC_SR_RMVF; RCC->RCC_SR = RCC_SR_RMVF;
#if defined(STM32F0) || defined(STM32F4) || defined(STM32G0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) #if defined(STM32F0) || defined(STM32F4) || defined(STM32G0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32WB)
__HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH(); __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();
#endif #endif
branch_to_bootloader(BL_STATE_GET_REG(bl_state), BL_STATE_GET_ADDR(bl_state)); 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 #endif
#if !defined(STM32F0) && !defined(STM32G0) && !defined(STM32L0) && !defined(STM32L4) #if !defined(STM32F0) && !defined(STM32G0) && !defined(STM32L0) && !defined(STM32L1) && !defined(STM32L4)
STATIC uint32_t calc_ahb_div(uint32_t wanted_div) { STATIC uint32_t calc_ahb_div(uint32_t wanted_div) {
#if defined(STM32H7) #if defined(STM32H7)
@ -708,7 +708,7 @@ void powerctrl_enter_stop_mode(void) {
__HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_MSI); __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_MSI);
#endif #endif
#if !defined(STM32F0) && !defined(STM32G0) && !defined(STM32G4) && !defined(STM32L0) && !defined(STM32L4) && !defined(STM32WB) && !defined(STM32WL) #if !defined(STM32F0) && !defined(STM32G0) && !defined(STM32G4) && !defined(STM32L0) && !defined(STM32L1) && !defined(STM32L4) && !defined(STM32WB) && !defined(STM32WL)
// takes longer to wake but reduces stop current // takes longer to wake but reduces stop current
HAL_PWREx_EnableFlashPowerDown(); HAL_PWREx_EnableFlashPowerDown();
#endif #endif

View File

@ -228,6 +228,74 @@ void SystemClock_Config(void) {
#endif #endif
} }
#elif defined(STM32L1)
void SystemClock_Config(void) {
// Enable power control peripheral
__HAL_RCC_PWR_CLK_ENABLE();
// Set power voltage scaling
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
// Enable the FLASH 64-bit access
FLASH->ACR = FLASH_ACR_ACC64;
// Set flash latency to 1 because SYSCLK > 16MHz
FLASH->ACR |= MICROPY_HW_FLASH_LATENCY;
#if MICROPY_HW_CLK_USE_HSI
// Enable the 16MHz internal oscillator
RCC->CR |= RCC_CR_HSION;
while (!(RCC->CR & RCC_CR_HSIRDY)) {
}
RCC->CFGR = RCC_CFGR_PLLSRC_HSI;
#else
// Enable the 8MHz external oscillator
RCC->CR |= RCC_CR_HSEBYP;
RCC->CR |= RCC_CR_HSEON;
while (!(RCC->CR & RCC_CR_HSERDY)) {
}
RCC->CFGR = RCC_CFGR_PLLSRC_HSE;
#endif
// Use HSI16 and the PLL to get a 32MHz SYSCLK
RCC->CFGR |= MICROPY_HW_CLK_PLLMUL | MICROPY_HW_CLK_PLLDIV;
RCC->CR |= RCC_CR_PLLON;
while (!(RCC->CR & RCC_CR_PLLRDY)) {
// Wait for PLL to lock
}
RCC->CFGR |= RCC_CFGR_SW_PLL;
while ((RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_PLL) {
// Wait for SYSCLK source to change
}
SystemCoreClockUpdate();
powerctrl_config_systick();
#if 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;
// 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
// Disable the Debug Module in low-power mode due to prevent
// unexpected HardFault after __WFI().
#if !defined(NDEBUG)
DBGMCU->CR &= ~(DBGMCU_CR_DBG_SLEEP | DBGMCU_CR_DBG_STOP | DBGMCU_CR_DBG_STANDBY);
#endif
}
#elif defined(STM32WB) #elif defined(STM32WB)
#include "stm32wbxx_ll_hsem.h" #include "stm32wbxx_ll_hsem.h"

View File

@ -0,0 +1,75 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 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.
*/
.syntax unified
.cpu cortex-m3
.fpu softvfp
.thumb
.section .text.Reset_Handler
.global Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
/* Save the first argument to pass through to stm32_main */
mov r4, r0
/* Load the stack pointer */
ldr r0, =_estack
mov sp, r0
/* Initialise the data section */
ldr r1, =_sidata
ldr r2, =_sdata
ldr r3, =_edata
b .data_copy_entry
.data_copy_loop:
ldr r0, [r1]
adds r1, #4
str r0, [r2]
adds r2, #4
.data_copy_entry:
cmp r2, r3
bcc .data_copy_loop
/* Zero out the BSS section */
movs r0, #0
ldr r1, =_sbss
ldr r2, =_ebss
b .bss_zero_entry
.bss_zero_loop:
str r0, [r1]
adds r1, #4
.bss_zero_entry:
cmp r1, r2
bcc .bss_zero_loop
/* Initialise the system and jump to the main code */
bl SystemInit
mov r0, r4
bl stm32_main
.size Reset_Handler, .-Reset_Handler

View File

@ -91,6 +91,15 @@ STATIC bool rtc_need_init_finalise = false;
#define RCC_BDCR_LSEON RCC_CSR_LSEON #define RCC_BDCR_LSEON RCC_CSR_LSEON
#define RCC_BDCR_LSERDY RCC_CSR_LSERDY #define RCC_BDCR_LSERDY RCC_CSR_LSERDY
#define RCC_BDCR_LSEBYP RCC_CSR_LSEBYP #define RCC_BDCR_LSEBYP RCC_CSR_LSEBYP
#elif defined(STM32L1)
#define BDCR CR
#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 #endif
void rtc_init_start(bool force_init) { void rtc_init_start(bool force_init) {
@ -664,7 +673,15 @@ mp_obj_t pyb_rtc_wakeup(size_t n_args, const mp_obj_t *args) {
wucksel -= 1; wucksel -= 1;
} }
if (div <= 16) { if (div <= 16) {
#if defined(STM32L1)
if (rtc_use_lse) {
wut = LSE_VALUE / div * ms / 1000;
} else {
wut = LSI_VALUE / div * ms / 1000;
}
#else
wut = 32768 / div * ms / 1000; wut = 32768 / div * ms / 1000;
#endif
} else { } else {
// use 1Hz clock // use 1Hz clock
wucksel = 4; wucksel = 4;

View File

@ -48,7 +48,7 @@ CFLAGS_CORTEX_M += -mfpu=fpv5-d16 -mfloat-abi=hard
SUPPORTS_HARDWARE_FP_SINGLE = 1 SUPPORTS_HARDWARE_FP_SINGLE = 1
SUPPORTS_HARDWARE_FP_DOUBLE = 1 SUPPORTS_HARDWARE_FP_DOUBLE = 1
else else
ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 g0 l0 wl)) ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 g0 l0 l1 wl))
CFLAGS_CORTEX_M += -msoft-float CFLAGS_CORTEX_M += -msoft-float
else else
CFLAGS_CORTEX_M += -mfpu=fpv4-sp-d16 -mfloat-abi=hard CFLAGS_CORTEX_M += -mfpu=fpv4-sp-d16 -mfloat-abi=hard
@ -64,6 +64,7 @@ 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_g0 = $(CFLAGS_CORTEX_M) -mtune=cortex-m0plus -mcpu=cortex-m0plus
CFLAGS_MCU_g4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 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_l0 = $(CFLAGS_CORTEX_M) -mtune=cortex-m0plus -mcpu=cortex-m0plus
CFLAGS_MCU_l1 = $(CFLAGS_CORTEX_M) -mtune=cortex-m3 -mcpu=cortex-m3
CFLAGS_MCU_l4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 CFLAGS_MCU_l4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4
CFLAGS_MCU_h7 = $(CFLAGS_CORTEX_M) -mtune=cortex-m7 -mcpu=cortex-m7 CFLAGS_MCU_h7 = $(CFLAGS_CORTEX_M) -mtune=cortex-m7 -mcpu=cortex-m7
CFLAGS_MCU_wb = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 CFLAGS_MCU_wb = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4

View File

@ -520,11 +520,19 @@ void ETH_WKUP_IRQHandler(void) {
} }
#endif #endif
#if defined(STM32L1)
void TAMPER_STAMP_IRQHandler(void) {
IRQ_ENTER(TAMPER_STAMP_IRQn);
Handle_EXTI_Irq(EXTI_RTC_TIMESTAMP);
IRQ_EXIT(TAMPER_STAMP_IRQn);
}
#else
void TAMP_STAMP_IRQHandler(void) { void TAMP_STAMP_IRQHandler(void) {
IRQ_ENTER(TAMP_STAMP_IRQn); IRQ_ENTER(TAMP_STAMP_IRQn);
Handle_EXTI_Irq(EXTI_RTC_TIMESTAMP); Handle_EXTI_Irq(EXTI_RTC_TIMESTAMP);
IRQ_EXIT(TAMP_STAMP_IRQn); IRQ_EXIT(TAMP_STAMP_IRQn);
} }
#endif
void RTC_WKUP_IRQHandler(void) { void RTC_WKUP_IRQHandler(void) {
IRQ_ENTER(RTC_WKUP_IRQn); IRQ_ENTER(RTC_WKUP_IRQn);
@ -698,6 +706,12 @@ void TIM6_DAC_LPTIM1_IRQHandler(void) {
timer_irq_handler(6); timer_irq_handler(6);
IRQ_EXIT(TIM6_DAC_LPTIM1_IRQn); IRQ_EXIT(TIM6_DAC_LPTIM1_IRQn);
} }
#elif defined(STM32L1)
void TIM6_IRQHandler(void) {
IRQ_ENTER(TIM6_IRQn);
timer_irq_handler(6);
IRQ_EXIT(TIM6_IRQn);
}
#else #else
void TIM6_DAC_IRQHandler(void) { void TIM6_DAC_IRQHandler(void) {
IRQ_ENTER(TIM6_DAC_IRQn); IRQ_ENTER(TIM6_DAC_IRQn);
@ -764,6 +778,26 @@ void TIM8_TRG_COM_TIM14_IRQHandler(void) {
} }
#endif #endif
#if defined(STM32L1)
void TIM9_IRQHandler(void) {
IRQ_ENTER(TIM9_IRQn);
timer_irq_handler(9);
IRQ_EXIT(TIM9_IRQn);
}
void TIM10_IRQHandler(void) {
IRQ_ENTER(TIM9_IRQn);
timer_irq_handler(10);
IRQ_EXIT(TIM9_IRQn);
}
void TIM11_IRQHandler(void) {
IRQ_ENTER(TIM9_IRQn);
timer_irq_handler(11);
IRQ_EXIT(TIM9_IRQn);
}
#endif
#if defined(STM32G0) #if defined(STM32G0)
void TIM14_IRQHandler(void) { void TIM14_IRQHandler(void) {
IRQ_ENTER(TIM14_IRQn); IRQ_ENTER(TIM14_IRQn);

View File

@ -431,7 +431,7 @@ STATIC mp_obj_t compute_percent_from_pwm_value(uint32_t period, uint32_t cmp) {
#endif #endif
} }
#if !defined(STM32L0) #if !defined(STM32L0) && !defined(STM32L1)
// Computes the 8-bit value for the DTG field in the BDTR register. // Computes the 8-bit value for the DTG field in the BDTR register.
// //
@ -522,7 +522,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_DIV4 ? 4 :
self->tim.Init.ClockDivision == TIM_CLOCKDIVISION_DIV2 ? 2 : 1); self->tim.Init.ClockDivision == TIM_CLOCKDIVISION_DIV2 ? 2 : 1);
#if !defined(STM32L0) #if !defined(STM32L0) && !defined(STM32L1)
#if defined(IS_TIM_ADVANCED_INSTANCE) #if defined(IS_TIM_ADVANCED_INSTANCE)
if (IS_TIM_ADVANCED_INSTANCE(self->tim.Instance)) if (IS_TIM_ADVANCED_INSTANCE(self->tim.Instance))
#elif defined(IS_TIM_BREAK_INSTANCE) #elif defined(IS_TIM_BREAK_INSTANCE)
@ -640,7 +640,7 @@ 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 : args[ARG_div].u_int == 4 ? TIM_CLOCKDIVISION_DIV4 :
TIM_CLOCKDIVISION_DIV1; TIM_CLOCKDIVISION_DIV1;
#if !defined(STM32L0) #if !defined(STM32L0) && !defined(STM32L1)
init->RepetitionCounter = 0; init->RepetitionCounter = 0;
#endif #endif
@ -772,7 +772,7 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *self, size_t n_args, cons
// init TIM // init TIM
HAL_TIM_Base_Init(&self->tim); HAL_TIM_Base_Init(&self->tim);
#if !defined(STM32L0) #if !defined(STM32L0) && !defined(STM32L1)
#if defined(IS_TIM_ADVANCED_INSTANCE) #if defined(IS_TIM_ADVANCED_INSTANCE)
if (IS_TIM_ADVANCED_INSTANCE(self->tim.Instance)) if (IS_TIM_ADVANCED_INSTANCE(self->tim.Instance))
#elif defined(IS_TIM_BREAK_INSTANCE) #elif defined(IS_TIM_BREAK_INSTANCE)
@ -833,7 +833,7 @@ STATIC const uint32_t tim_instance_table[MICROPY_HW_MAX_TIMER] = {
TIM_ENTRY(5, TIM5_IRQn), TIM_ENTRY(5, TIM5_IRQn),
#endif #endif
#if defined(TIM6) #if defined(TIM6)
#if defined(STM32F412Zx) #if defined(STM32F412Zx) || defined(STM32L1)
TIM_ENTRY(6, TIM6_IRQn), TIM_ENTRY(6, TIM6_IRQn),
#elif defined(STM32G0) #elif defined(STM32G0)
TIM_ENTRY(6, TIM6_DAC_LPTIM1_IRQn), TIM_ENTRY(6, TIM6_DAC_LPTIM1_IRQn),
@ -858,14 +858,26 @@ STATIC const uint32_t tim_instance_table[MICROPY_HW_MAX_TIMER] = {
#endif #endif
#endif #endif
#if defined(TIM9) #if defined(TIM9)
#if defined(STM32L1)
TIM_ENTRY(9, TIM9_IRQn),
#else
TIM_ENTRY(9, TIM1_BRK_TIM9_IRQn), TIM_ENTRY(9, TIM1_BRK_TIM9_IRQn),
#endif #endif
#endif
#if defined(TIM10) #if defined(TIM10)
#if defined(STM32L1)
TIM_ENTRY(10, TIM10_IRQn),
#else
TIM_ENTRY(10, TIM1_UP_TIM10_IRQn), TIM_ENTRY(10, TIM1_UP_TIM10_IRQn),
#endif #endif
#endif
#if defined(TIM11) #if defined(TIM11)
#if defined(STM32L1)
TIM_ENTRY(11, TIM11_IRQn),
#else
TIM_ENTRY(11, TIM1_TRG_COM_TIM11_IRQn), TIM_ENTRY(11, TIM1_TRG_COM_TIM11_IRQn),
#endif #endif
#endif
#if defined(TIM12) #if defined(TIM12)
TIM_ENTRY(12, TIM8_BRK_TIM12_IRQn), TIM_ENTRY(12, TIM8_BRK_TIM12_IRQn),
#endif #endif
@ -936,7 +948,11 @@ STATIC mp_obj_t pyb_timer_make_new(const mp_obj_type_t *type, size_t n_args, siz
memset(tim, 0, sizeof(*tim)); memset(tim, 0, sizeof(*tim));
tim->base.type = &pyb_timer_type; tim->base.type = &pyb_timer_type;
tim->tim_id = tim_id; tim->tim_id = tim_id;
#if defined(STM32L1)
tim->is_32bit = tim_id == 5;
#else
tim->is_32bit = tim_id == 2 || tim_id == 5; tim->is_32bit = tim_id == 2 || tim_id == 5;
#endif
tim->callback = mp_const_none; tim->callback = mp_const_none;
uint32_t ti = tim_instance_table[tim_id - 1]; uint32_t ti = tim_instance_table[tim_id - 1];
tim->tim.Instance = (TIM_TypeDef *)(ti & 0xffffff00); tim->tim.Instance = (TIM_TypeDef *)(ti & 0xffffff00);
@ -1168,7 +1184,7 @@ STATIC mp_obj_t pyb_timer_channel(size_t n_args, const mp_obj_t *pos_args, mp_ma
} }
oc_config.OCPolarity = TIM_OCPOLARITY_HIGH; oc_config.OCPolarity = TIM_OCPOLARITY_HIGH;
oc_config.OCFastMode = TIM_OCFAST_DISABLE; oc_config.OCFastMode = TIM_OCFAST_DISABLE;
#if !defined(STM32L0) #if !defined(STM32L0) && !defined(STM32L1)
oc_config.OCNPolarity = TIM_OCNPOLARITY_HIGH; oc_config.OCNPolarity = TIM_OCNPOLARITY_HIGH;
oc_config.OCIdleState = TIM_OCIDLESTATE_SET; oc_config.OCIdleState = TIM_OCIDLESTATE_SET;
oc_config.OCNIdleState = TIM_OCNIDLESTATE_SET; oc_config.OCNIdleState = TIM_OCNIDLESTATE_SET;
@ -1180,7 +1196,7 @@ STATIC mp_obj_t pyb_timer_channel(size_t n_args, const mp_obj_t *pos_args, mp_ma
} else { } else {
pyb_timer_channel_callback(MP_OBJ_FROM_PTR(chan), chan->callback); pyb_timer_channel_callback(MP_OBJ_FROM_PTR(chan), chan->callback);
} }
#if !defined(STM32L0) #if !defined(STM32L0) && !defined(STM32L1)
// Start the complimentary channel too (if its supported) // Start the complimentary channel too (if its supported)
if (IS_TIM_CCXN_INSTANCE(self->tim.Instance, TIMER_CHANNEL(chan))) { if (IS_TIM_CCXN_INSTANCE(self->tim.Instance, TIMER_CHANNEL(chan))) {
HAL_TIMEx_PWMN_Start(&self->tim, TIMER_CHANNEL(chan)); HAL_TIMEx_PWMN_Start(&self->tim, TIMER_CHANNEL(chan));
@ -1203,7 +1219,7 @@ STATIC mp_obj_t pyb_timer_channel(size_t n_args, const mp_obj_t *pos_args, mp_ma
oc_config.OCPolarity = TIM_OCPOLARITY_HIGH; oc_config.OCPolarity = TIM_OCPOLARITY_HIGH;
} }
oc_config.OCFastMode = TIM_OCFAST_DISABLE; oc_config.OCFastMode = TIM_OCFAST_DISABLE;
#if !defined(STM32L0) #if !defined(STM32L0) && !defined(STM32L1)
if (oc_config.OCPolarity == TIM_OCPOLARITY_HIGH) { if (oc_config.OCPolarity == TIM_OCPOLARITY_HIGH) {
oc_config.OCNPolarity = TIM_OCNPOLARITY_HIGH; oc_config.OCNPolarity = TIM_OCNPOLARITY_HIGH;
} else { } else {
@ -1222,7 +1238,7 @@ STATIC mp_obj_t pyb_timer_channel(size_t n_args, const mp_obj_t *pos_args, mp_ma
} else { } else {
pyb_timer_channel_callback(MP_OBJ_FROM_PTR(chan), chan->callback); pyb_timer_channel_callback(MP_OBJ_FROM_PTR(chan), chan->callback);
} }
#if !defined(STM32L0) #if !defined(STM32L0) && !defined(STM32L1)
// Start the complimentary channel too (if its supported) // Start the complimentary channel too (if its supported)
if (IS_TIM_CCXN_INSTANCE(self->tim.Instance, TIMER_CHANNEL(chan))) { if (IS_TIM_CCXN_INSTANCE(self->tim.Instance, TIMER_CHANNEL(chan))) {
HAL_TIMEx_OCN_Start(&self->tim, TIMER_CHANNEL(chan)); HAL_TIMEx_OCN_Start(&self->tim, TIMER_CHANNEL(chan));

View File

@ -38,7 +38,7 @@
#include "irq.h" #include "irq.h"
#include "pendsv.h" #include "pendsv.h"
#if defined(STM32F4) #if defined(STM32F4) || defined(STM32L1)
#define UART_RXNE_IS_SET(uart) ((uart)->SR & USART_SR_RXNE) #define UART_RXNE_IS_SET(uart) ((uart)->SR & USART_SR_RXNE)
#else #else
#if defined(STM32G0) || defined(STM32H7) || defined(STM32WL) #if defined(STM32G0) || defined(STM32H7) || defined(STM32WL)
@ -101,6 +101,11 @@
#define USART_CR2_IE_ALL (USART_CR2_IE_BASE) #define USART_CR2_IE_ALL (USART_CR2_IE_BASE)
#define USART_CR3_IE_ALL (USART_CR3_IE_BASE | USART_CR3_WUFIE) #define USART_CR3_IE_ALL (USART_CR3_IE_BASE | USART_CR3_WUFIE)
#elif defined(STM32L1)
#define USART_CR1_IE_ALL (USART_CR1_IE_BASE)
#define USART_CR2_IE_ALL (USART_CR2_IE_BASE)
#define USART_CR3_IE_ALL (USART_CR3_IE_BASE)
#elif defined(STM32L4) || defined(STM32WB) || defined(STM32WL) #elif defined(STM32L4) || defined(STM32WB) || defined(STM32WL)
#define USART_CR1_IE_ALL (USART_CR1_IE_BASE | USART_CR1_EOBIE | USART_CR1_RTOIE | USART_CR1_CMIE) #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_CR2_IE_ALL (USART_CR2_IE_BASE)
@ -580,7 +585,7 @@ bool uart_init(pyb_uart_obj_t *uart_obj,
huart.FifoMode = UART_FIFOMODE_ENABLE; huart.FifoMode = UART_FIFOMODE_ENABLE;
#endif #endif
#if !defined(STM32F4) #if !defined(STM32F4) && !defined(STM32L1)
huart.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; huart.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
#endif #endif
@ -1016,7 +1021,7 @@ STATIC bool uart_wait_flag_set(pyb_uart_obj_t *self, uint32_t flag, uint32_t tim
// an interrupt and the flag can be set quickly if the baudrate is large. // an interrupt and the flag can be set quickly if the baudrate is large.
uint32_t start = HAL_GetTick(); uint32_t start = HAL_GetTick();
for (;;) { for (;;) {
#if defined(STM32F4) #if defined(STM32F4) || defined(STM32L1)
if (self->uartx->SR & flag) { if (self->uartx->SR & flag) {
return true; return true;
} }
@ -1071,7 +1076,7 @@ size_t uart_tx_data(pyb_uart_obj_t *self, const void *src_in, size_t num_chars,
} else { } else {
data = *src++; data = *src++;
} }
#if defined(STM32F4) #if defined(STM32F4) || defined(STM32L1)
uart->DR = data; uart->DR = data;
#else #else
uart->TDR = data; uart->TDR = data;
@ -1109,7 +1114,7 @@ void uart_irq_handler(mp_uint_t uart_id) {
} }
// Capture IRQ status flags. // Capture IRQ status flags.
#if defined(STM32F4) #if defined(STM32F4) || defined(STM32L1)
self->mp_irq_flags = self->uartx->SR; self->mp_irq_flags = self->uartx->SR;
bool rxne_is_set = self->mp_irq_flags & USART_SR_RXNE; bool rxne_is_set = self->mp_irq_flags & USART_SR_RXNE;
bool did_clear_sr = false; bool did_clear_sr = false;
@ -1153,7 +1158,7 @@ void uart_irq_handler(mp_uint_t uart_id) {
} }
// Clear other interrupt flags that can trigger this IRQ handler. // Clear other interrupt flags that can trigger this IRQ handler.
#if defined(STM32F4) #if defined(STM32F4) || defined(STM32L1)
if (did_clear_sr) { if (did_clear_sr) {
// SR was cleared above. Re-enable IDLE if it should be enabled. // SR was cleared above. Re-enable IDLE if it should be enabled.
if (self->mp_irq_trigger & UART_FLAG_IDLE) { if (self->mp_irq_trigger & UART_FLAG_IDLE) {

View File

@ -103,7 +103,7 @@ size_t uart_tx_data(pyb_uart_obj_t *self, const void *src_in, size_t num_chars,
void uart_tx_strn(pyb_uart_obj_t *uart_obj, const char *str, uint len); 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) { static inline bool uart_tx_avail(pyb_uart_obj_t *self) {
#if defined(STM32F4) #if defined(STM32F4) || defined(STM32L1)
return self->uartx->SR & USART_SR_TXE; return self->uartx->SR & USART_SR_TXE;
#elif defined(STM32G0) || defined(STM32H7) || defined(STM32WL) #elif defined(STM32G0) || defined(STM32H7) || defined(STM32WL)
return self->uartx->ISR & USART_ISR_TXE_TXFNF; return self->uartx->ISR & USART_ISR_TXE_TXFNF;