From 9d674cf7ab8570637dfab23811800e3b98babad9 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Wed, 17 Feb 2021 11:07:34 +1100 Subject: [PATCH] stm32/uart: Add support for LPUART1 on L0, L4, H7 and WB MCUs. Add LPUART1 as a standard UART. No low power features are supported, yet. LPUART1 is enabled as the next available UART after the standard U(S)ARTs: STM32WB: LPUART1 = UART(2) STM32L0: LPUART1 = UART(6) STM32L4: LPUART1 = UART(6) STM32H7: LPUART1 = UART(9) On all ports: LPUART1 = machine.UART('LP1') LPUART1 is enabled by defining MICROPY_HW_LPUART1_TX and MICROPY_HW_LPUART1_RX in mpconfigboard.h. Signed-off-by: Chris Mason --- ports/stm32/boards/make-pins.py | 2 ++ ports/stm32/machine_uart.c | 29 ++++++++++++++++-- ports/stm32/mpconfigboard_common.h | 9 +++++- ports/stm32/mpconfigport.h | 2 +- ports/stm32/pin_defs_stm32.h | 5 ++++ ports/stm32/stm32_it.c | 18 ++++++++++++ ports/stm32/uart.c | 47 ++++++++++++++++++++++++++++-- ports/stm32/uart.h | 3 ++ 8 files changed, 108 insertions(+), 7 deletions(-) diff --git a/ports/stm32/boards/make-pins.py b/ports/stm32/boards/make-pins.py index a91ed8a2c9..a195323318 100755 --- a/ports/stm32/boards/make-pins.py +++ b/ports/stm32/boards/make-pins.py @@ -14,6 +14,7 @@ SUPPORTED_FN = { "I2S": ["CK", "MCK", "SD", "WS", "EXTSD"], "USART": ["RX", "TX", "CTS", "RTS", "CK"], "UART": ["RX", "TX", "CTS", "RTS"], + "LPUART": ["RX", "TX", "CTS", "RTS"], "SPI": ["NSS", "SCK", "MISO", "MOSI"], "SDMMC": ["CK", "CMD", "D0", "D1", "D2", "D3"], "CAN": ["TX", "RX"], @@ -24,6 +25,7 @@ CONDITIONAL_VAR = { "I2S": "MICROPY_HW_ENABLE_I2S{num}", "SPI": "MICROPY_HW_SPI{num}_SCK", "UART": "MICROPY_HW_UART{num}_TX", + "LPUART": "MICROPY_HW_LPUART{num}_TX", "USART": "MICROPY_HW_UART{num}_TX", "SDMMC": "MICROPY_HW_SDMMC{num}_CK", "CAN": "MICROPY_HW_CAN{num}_TX", diff --git a/ports/stm32/machine_uart.c b/ports/stm32/machine_uart.c index 31e6a1789e..eceb5b6e7a 100644 --- a/ports/stm32/machine_uart.c +++ b/ports/stm32/machine_uart.c @@ -76,7 +76,14 @@ STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); if (!self->is_enabled) { - mp_printf(print, "UART(%u)", self->uart_id); + #ifdef LPUART1 + if (self->uart_id == PYB_LPUART_1) { + mp_printf(print, "UART('LP1')"); + } else + #endif + { + mp_printf(print, "UART(%u)", self->uart_id); + } } else { mp_int_t bits; uint32_t cr1 = self->uartx->CR1; @@ -98,8 +105,16 @@ STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_k if (cr1 & USART_CR1_PCE) { bits -= 1; } - mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=", - self->uart_id, uart_get_baudrate(self), bits); + #ifdef LPUART1 + if (self->uart_id == PYB_LPUART_1) { + mp_printf(print, "UART('LP1', baudrate=%u, bits=%u, parity=", + uart_get_baudrate(self), bits); + } else + #endif + { + mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=", + self->uart_id, uart_get_baudrate(self), bits); + } if (!(cr1 & USART_CR1_PCE)) { mp_print_str(print, "None"); } else if (!(cr1 & USART_CR1_PS)) { @@ -335,6 +350,14 @@ STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, size_t n_args, size } else if (strcmp(port, MICROPY_HW_UART10_NAME) == 0) { uart_id = PYB_UART_10; #endif + #ifdef MICROPY_HW_LPUART1_NAME + } else if (strcmp(port, MICROPY_HW_LPUART1_NAME) == 0) { + uart_id = PYB_LPUART_1; + #endif + #ifdef LPUART1 + } else if (strcmp(port, "LP1") == 0 && uart_exists(PYB_LPUART_1)) { + uart_id = PYB_LPUART_1; + #endif } else { mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("UART(%s) doesn't exist"), port); } diff --git a/ports/stm32/mpconfigboard_common.h b/ports/stm32/mpconfigboard_common.h index 615310e51b..ed30d17bdc 100644 --- a/ports/stm32/mpconfigboard_common.h +++ b/ports/stm32/mpconfigboard_common.h @@ -181,6 +181,7 @@ #define MICROPY_HW_MAX_I2C (2) #define MICROPY_HW_MAX_TIMER (17) #define MICROPY_HW_MAX_UART (8) +#define MICROPY_HW_MAX_LPUART (0) // Configuration for STM32F4 series #elif defined(STM32F4) @@ -200,6 +201,7 @@ #else #define MICROPY_HW_MAX_UART (6) #endif +#define MICROPY_HW_MAX_LPUART (0) // Configuration for STM32F7 series #elif defined(STM32F7) @@ -214,6 +216,7 @@ #define MICROPY_HW_MAX_I2C (4) #define MICROPY_HW_MAX_TIMER (17) #define MICROPY_HW_MAX_UART (8) +#define MICROPY_HW_MAX_LPUART (0) // Configuration for STM32H7 series #elif defined(STM32H7) @@ -223,6 +226,7 @@ #define MICROPY_HW_MAX_I2C (4) #define MICROPY_HW_MAX_TIMER (17) #define MICROPY_HW_MAX_UART (8) +#define MICROPY_HW_MAX_LPUART (1) // Configuration for STM32L0 series #elif defined(STM32L0) @@ -232,6 +236,7 @@ #define MICROPY_HW_MAX_I2C (3) #define MICROPY_HW_MAX_TIMER (22) #define MICROPY_HW_MAX_UART (5) +#define MICROPY_HW_MAX_LPUART (1) // Configuration for STM32L4 series #elif defined(STM32L4) @@ -240,7 +245,8 @@ #define PYB_EXTI_NUM_VECTORS (23) #define MICROPY_HW_MAX_I2C (4) #define MICROPY_HW_MAX_TIMER (17) -#define MICROPY_HW_MAX_UART (6) +#define MICROPY_HW_MAX_UART (5) +#define MICROPY_HW_MAX_LPUART (1) // Configuration for STM32WB series #elif defined(STM32WB) @@ -250,6 +256,7 @@ #define MICROPY_HW_MAX_I2C (3) #define MICROPY_HW_MAX_TIMER (17) #define MICROPY_HW_MAX_UART (1) +#define MICROPY_HW_MAX_LPUART (1) #ifndef MICROPY_HW_STM32WB_FLASH_SYNCRONISATION #define MICROPY_HW_STM32WB_FLASH_SYNCRONISATION (1) diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index 407a3e6c6a..5998cd9085 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -375,7 +375,7 @@ struct _mp_bluetooth_btstack_root_pointers_t; struct _pyb_uart_obj_t *pyb_stdio_uart; \ \ /* pointers to all UART objects (if they have been created) */ \ - struct _pyb_uart_obj_t *pyb_uart_obj_all[MICROPY_HW_MAX_UART]; \ + struct _pyb_uart_obj_t *pyb_uart_obj_all[MICROPY_HW_MAX_UART + MICROPY_HW_MAX_LPUART]; \ \ /* pointers to all CAN objects (if they have been created) */ \ struct _pyb_can_obj_t *pyb_can_obj_all[MICROPY_HW_MAX_CAN]; \ diff --git a/ports/stm32/pin_defs_stm32.h b/ports/stm32/pin_defs_stm32.h index 33a1790807..9285c190a6 100644 --- a/ports/stm32/pin_defs_stm32.h +++ b/ports/stm32/pin_defs_stm32.h @@ -47,6 +47,7 @@ enum { AF_FN_I2C, AF_FN_USART, AF_FN_UART = AF_FN_USART, + AF_FN_LPUART, AF_FN_SPI, AF_FN_I2S, AF_FN_SDMMC, @@ -77,6 +78,10 @@ enum { AF_PIN_TYPE_UART_RX = AF_PIN_TYPE_USART_RX, AF_PIN_TYPE_UART_CTS = AF_PIN_TYPE_USART_CTS, AF_PIN_TYPE_UART_RTS = AF_PIN_TYPE_USART_RTS, + AF_PIN_TYPE_LPUART_TX = AF_PIN_TYPE_USART_TX, + AF_PIN_TYPE_LPUART_RX = AF_PIN_TYPE_USART_RX, + AF_PIN_TYPE_LPUART_CTS = AF_PIN_TYPE_USART_CTS, + AF_PIN_TYPE_LPUART_RTS = AF_PIN_TYPE_USART_RTS, AF_PIN_TYPE_SPI_MOSI = 0, AF_PIN_TYPE_SPI_MISO, diff --git a/ports/stm32/stm32_it.c b/ports/stm32/stm32_it.c index 8e96da177b..dc96e2dd6c 100644 --- a/ports/stm32/stm32_it.c +++ b/ports/stm32/stm32_it.c @@ -742,11 +742,13 @@ void USART1_IRQHandler(void) { IRQ_EXIT(USART1_IRQn); } +#if defined(USART2) void USART2_IRQHandler(void) { IRQ_ENTER(USART2_IRQn); uart_irq_handler(2); IRQ_EXIT(USART2_IRQn); } +#endif #if defined(STM32F0) @@ -772,29 +774,37 @@ void USART4_5_IRQHandler(void) { #else +#if defined(USART3) void USART3_IRQHandler(void) { IRQ_ENTER(USART3_IRQn); uart_irq_handler(3); IRQ_EXIT(USART3_IRQn); } +#endif +#if defined(UART4) void UART4_IRQHandler(void) { IRQ_ENTER(UART4_IRQn); uart_irq_handler(4); IRQ_EXIT(UART4_IRQn); } +#endif +#if defined(UART5) void UART5_IRQHandler(void) { IRQ_ENTER(UART5_IRQn); uart_irq_handler(5); IRQ_EXIT(UART5_IRQn); } +#endif +#if defined(USART6) void USART6_IRQHandler(void) { IRQ_ENTER(USART6_IRQn); uart_irq_handler(6); IRQ_EXIT(USART6_IRQn); } +#endif #if defined(UART7) void UART7_IRQHandler(void) { @@ -830,6 +840,14 @@ void UART10_IRQHandler(void) { #endif +#if defined(LPUART1) +void LPUART1_IRQHandler(void) { + IRQ_ENTER(LPUART1_IRQn); + uart_irq_handler(PYB_LPUART_1); + IRQ_EXIT(LPUART1_IRQn); +} +#endif + #if MICROPY_PY_PYB_LEGACY #if defined(MICROPY_HW_I2C1_SCL) diff --git a/ports/stm32/uart.c b/ports/stm32/uart.c index 8091ba05f9..d40a883c52 100644 --- a/ports/stm32/uart.c +++ b/ports/stm32/uart.c @@ -201,6 +201,11 @@ bool uart_exists(int uart_id) { return true; #endif + #if defined(MICROPY_HW_LPUART1_TX) && defined(MICROPY_HW_LPUART1_RX) + case PYB_LPUART_1: + return true; + #endif + default: return false; } @@ -211,6 +216,7 @@ bool uart_init(pyb_uart_obj_t *uart_obj, uint32_t baudrate, uint32_t bits, uint32_t parity, uint32_t stop, uint32_t flow) { USART_TypeDef *UARTx; IRQn_Type irqn; + uint8_t uart_fn = AF_FN_UART; int uart_unit; const pin_obj_t *pins[4] = {0}; @@ -406,6 +412,28 @@ bool uart_init(pyb_uart_obj_t *uart_obj, break; #endif + #if defined(MICROPY_HW_LPUART1_TX) && defined(MICROPY_HW_LPUART1_RX) + case PYB_LPUART_1: + uart_fn = AF_FN_LPUART; + uart_unit = 1; + UARTx = LPUART1; + irqn = LPUART1_IRQn; + pins[0] = MICROPY_HW_LPUART1_TX; + pins[1] = MICROPY_HW_LPUART1_RX; + #if defined(MICROPY_HW_LPUART1_RTS) + if (flow & UART_HWCONTROL_RTS) { + pins[2] = MICROPY_HW_LPUART1_RTS; + } + #endif + #if defined(MICROPY_HW_LPUART1_CTS) + if (flow & UART_HWCONTROL_CTS) { + pins[3] = MICROPY_HW_LPUART1_CTS; + } + #endif + __HAL_RCC_LPUART1_CLK_ENABLE(); + break; + #endif + default: // UART does not exist or is not configured for this board return false; @@ -416,7 +444,7 @@ bool uart_init(pyb_uart_obj_t *uart_obj, for (uint i = 0; i < 4; i++) { if (pins[i] != NULL) { - bool ret = mp_hal_pin_config_alt(pins[i], mode, pull, AF_FN_UART, uart_unit); + bool ret = mp_hal_pin_config_alt(pins[i], mode, pull, uart_fn, uart_unit); if (!ret) { return false; } @@ -596,6 +624,13 @@ void uart_deinit(pyb_uart_obj_t *self) { __HAL_RCC_UART10_RELEASE_RESET(); __HAL_RCC_UART10_CLK_DISABLE(); #endif + #if defined(LPUART1) + } else if (self->uart_id == PYB_LPUART_1) { + HAL_NVIC_DisableIRQ(LPUART1_IRQn); + __HAL_RCC_LPUART1_FORCE_RESET(); + __HAL_RCC_LPUART1_RELEASE_RESET(); + __HAL_RCC_LPUART1_CLK_DISABLE(); + #endif } } @@ -677,7 +712,15 @@ uint32_t uart_get_source_freq(pyb_uart_obj_t *self) { uint32_t uart_get_baudrate(pyb_uart_obj_t *self) { // This formula assumes UART_OVERSAMPLING_16 - return uart_get_source_freq(self) / self->uartx->BRR; + uint32_t source_freq = uart_get_source_freq(self); + #if defined(LPUART1) + if (self->uart_id == PYB_LPUART_1) { + return source_freq / (self->uartx->BRR >> 8); + } else + #endif + { + return source_freq / self->uartx->BRR; + } } void uart_set_baudrate(pyb_uart_obj_t *self, uint32_t baudrate) { diff --git a/ports/stm32/uart.h b/ports/stm32/uart.h index 570a79c932..0490a617f6 100644 --- a/ports/stm32/uart.h +++ b/ports/stm32/uart.h @@ -40,6 +40,9 @@ typedef enum { PYB_UART_8 = 8, PYB_UART_9 = 9, PYB_UART_10 = 10, + #ifdef LPUART1 + PYB_LPUART_1 = MICROPY_HW_MAX_UART + 1, + #endif } pyb_uart_t; #define CHAR_WIDTH_8BIT (0)