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 <c.mason@inchipdesign.com.au>
This commit is contained in:
Chris Mason 2021-02-17 11:07:34 +11:00 committed by Damien George
parent 1342debb9b
commit 9d674cf7ab
8 changed files with 108 additions and 7 deletions

View File

@ -14,6 +14,7 @@ SUPPORTED_FN = {
"I2S": ["CK", "MCK", "SD", "WS", "EXTSD"], "I2S": ["CK", "MCK", "SD", "WS", "EXTSD"],
"USART": ["RX", "TX", "CTS", "RTS", "CK"], "USART": ["RX", "TX", "CTS", "RTS", "CK"],
"UART": ["RX", "TX", "CTS", "RTS"], "UART": ["RX", "TX", "CTS", "RTS"],
"LPUART": ["RX", "TX", "CTS", "RTS"],
"SPI": ["NSS", "SCK", "MISO", "MOSI"], "SPI": ["NSS", "SCK", "MISO", "MOSI"],
"SDMMC": ["CK", "CMD", "D0", "D1", "D2", "D3"], "SDMMC": ["CK", "CMD", "D0", "D1", "D2", "D3"],
"CAN": ["TX", "RX"], "CAN": ["TX", "RX"],
@ -24,6 +25,7 @@ CONDITIONAL_VAR = {
"I2S": "MICROPY_HW_ENABLE_I2S{num}", "I2S": "MICROPY_HW_ENABLE_I2S{num}",
"SPI": "MICROPY_HW_SPI{num}_SCK", "SPI": "MICROPY_HW_SPI{num}_SCK",
"UART": "MICROPY_HW_UART{num}_TX", "UART": "MICROPY_HW_UART{num}_TX",
"LPUART": "MICROPY_HW_LPUART{num}_TX",
"USART": "MICROPY_HW_UART{num}_TX", "USART": "MICROPY_HW_UART{num}_TX",
"SDMMC": "MICROPY_HW_SDMMC{num}_CK", "SDMMC": "MICROPY_HW_SDMMC{num}_CK",
"CAN": "MICROPY_HW_CAN{num}_TX", "CAN": "MICROPY_HW_CAN{num}_TX",

View File

@ -76,7 +76,14 @@
STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { 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); pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (!self->is_enabled) { if (!self->is_enabled) {
#ifdef LPUART1
if (self->uart_id == PYB_LPUART_1) {
mp_printf(print, "UART('LP1')");
} else
#endif
{
mp_printf(print, "UART(%u)", self->uart_id); mp_printf(print, "UART(%u)", self->uart_id);
}
} else { } else {
mp_int_t bits; mp_int_t bits;
uint32_t cr1 = self->uartx->CR1; 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) { if (cr1 & USART_CR1_PCE) {
bits -= 1; bits -= 1;
} }
#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=", mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=",
self->uart_id, uart_get_baudrate(self), bits); self->uart_id, uart_get_baudrate(self), bits);
}
if (!(cr1 & USART_CR1_PCE)) { if (!(cr1 & USART_CR1_PCE)) {
mp_print_str(print, "None"); mp_print_str(print, "None");
} else if (!(cr1 & USART_CR1_PS)) { } 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) { } else if (strcmp(port, MICROPY_HW_UART10_NAME) == 0) {
uart_id = PYB_UART_10; uart_id = PYB_UART_10;
#endif #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 { } else {
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("UART(%s) doesn't exist"), port); mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("UART(%s) doesn't exist"), port);
} }

View File

@ -181,6 +181,7 @@
#define MICROPY_HW_MAX_I2C (2) #define MICROPY_HW_MAX_I2C (2)
#define MICROPY_HW_MAX_TIMER (17) #define MICROPY_HW_MAX_TIMER (17)
#define MICROPY_HW_MAX_UART (8) #define MICROPY_HW_MAX_UART (8)
#define MICROPY_HW_MAX_LPUART (0)
// Configuration for STM32F4 series // Configuration for STM32F4 series
#elif defined(STM32F4) #elif defined(STM32F4)
@ -200,6 +201,7 @@
#else #else
#define MICROPY_HW_MAX_UART (6) #define MICROPY_HW_MAX_UART (6)
#endif #endif
#define MICROPY_HW_MAX_LPUART (0)
// Configuration for STM32F7 series // Configuration for STM32F7 series
#elif defined(STM32F7) #elif defined(STM32F7)
@ -214,6 +216,7 @@
#define MICROPY_HW_MAX_I2C (4) #define MICROPY_HW_MAX_I2C (4)
#define MICROPY_HW_MAX_TIMER (17) #define MICROPY_HW_MAX_TIMER (17)
#define MICROPY_HW_MAX_UART (8) #define MICROPY_HW_MAX_UART (8)
#define MICROPY_HW_MAX_LPUART (0)
// Configuration for STM32H7 series // Configuration for STM32H7 series
#elif defined(STM32H7) #elif defined(STM32H7)
@ -223,6 +226,7 @@
#define MICROPY_HW_MAX_I2C (4) #define MICROPY_HW_MAX_I2C (4)
#define MICROPY_HW_MAX_TIMER (17) #define MICROPY_HW_MAX_TIMER (17)
#define MICROPY_HW_MAX_UART (8) #define MICROPY_HW_MAX_UART (8)
#define MICROPY_HW_MAX_LPUART (1)
// Configuration for STM32L0 series // Configuration for STM32L0 series
#elif defined(STM32L0) #elif defined(STM32L0)
@ -232,6 +236,7 @@
#define MICROPY_HW_MAX_I2C (3) #define MICROPY_HW_MAX_I2C (3)
#define MICROPY_HW_MAX_TIMER (22) #define MICROPY_HW_MAX_TIMER (22)
#define MICROPY_HW_MAX_UART (5) #define MICROPY_HW_MAX_UART (5)
#define MICROPY_HW_MAX_LPUART (1)
// Configuration for STM32L4 series // Configuration for STM32L4 series
#elif defined(STM32L4) #elif defined(STM32L4)
@ -240,7 +245,8 @@
#define PYB_EXTI_NUM_VECTORS (23) #define PYB_EXTI_NUM_VECTORS (23)
#define MICROPY_HW_MAX_I2C (4) #define MICROPY_HW_MAX_I2C (4)
#define MICROPY_HW_MAX_TIMER (17) #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 // Configuration for STM32WB series
#elif defined(STM32WB) #elif defined(STM32WB)
@ -250,6 +256,7 @@
#define MICROPY_HW_MAX_I2C (3) #define MICROPY_HW_MAX_I2C (3)
#define MICROPY_HW_MAX_TIMER (17) #define MICROPY_HW_MAX_TIMER (17)
#define MICROPY_HW_MAX_UART (1) #define MICROPY_HW_MAX_UART (1)
#define MICROPY_HW_MAX_LPUART (1)
#ifndef MICROPY_HW_STM32WB_FLASH_SYNCRONISATION #ifndef MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
#define MICROPY_HW_STM32WB_FLASH_SYNCRONISATION (1) #define MICROPY_HW_STM32WB_FLASH_SYNCRONISATION (1)

View File

@ -375,7 +375,7 @@ struct _mp_bluetooth_btstack_root_pointers_t;
struct _pyb_uart_obj_t *pyb_stdio_uart; \ struct _pyb_uart_obj_t *pyb_stdio_uart; \
\ \
/* pointers to all UART objects (if they have been created) */ \ /* 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) */ \ /* pointers to all CAN objects (if they have been created) */ \
struct _pyb_can_obj_t *pyb_can_obj_all[MICROPY_HW_MAX_CAN]; \ struct _pyb_can_obj_t *pyb_can_obj_all[MICROPY_HW_MAX_CAN]; \

View File

@ -47,6 +47,7 @@ enum {
AF_FN_I2C, AF_FN_I2C,
AF_FN_USART, AF_FN_USART,
AF_FN_UART = AF_FN_USART, AF_FN_UART = AF_FN_USART,
AF_FN_LPUART,
AF_FN_SPI, AF_FN_SPI,
AF_FN_I2S, AF_FN_I2S,
AF_FN_SDMMC, AF_FN_SDMMC,
@ -77,6 +78,10 @@ enum {
AF_PIN_TYPE_UART_RX = AF_PIN_TYPE_USART_RX, AF_PIN_TYPE_UART_RX = AF_PIN_TYPE_USART_RX,
AF_PIN_TYPE_UART_CTS = AF_PIN_TYPE_USART_CTS, AF_PIN_TYPE_UART_CTS = AF_PIN_TYPE_USART_CTS,
AF_PIN_TYPE_UART_RTS = AF_PIN_TYPE_USART_RTS, 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_MOSI = 0,
AF_PIN_TYPE_SPI_MISO, AF_PIN_TYPE_SPI_MISO,

View File

@ -742,11 +742,13 @@ void USART1_IRQHandler(void) {
IRQ_EXIT(USART1_IRQn); IRQ_EXIT(USART1_IRQn);
} }
#if defined(USART2)
void USART2_IRQHandler(void) { void USART2_IRQHandler(void) {
IRQ_ENTER(USART2_IRQn); IRQ_ENTER(USART2_IRQn);
uart_irq_handler(2); uart_irq_handler(2);
IRQ_EXIT(USART2_IRQn); IRQ_EXIT(USART2_IRQn);
} }
#endif
#if defined(STM32F0) #if defined(STM32F0)
@ -772,29 +774,37 @@ void USART4_5_IRQHandler(void) {
#else #else
#if defined(USART3)
void USART3_IRQHandler(void) { void USART3_IRQHandler(void) {
IRQ_ENTER(USART3_IRQn); IRQ_ENTER(USART3_IRQn);
uart_irq_handler(3); uart_irq_handler(3);
IRQ_EXIT(USART3_IRQn); IRQ_EXIT(USART3_IRQn);
} }
#endif
#if defined(UART4)
void UART4_IRQHandler(void) { void UART4_IRQHandler(void) {
IRQ_ENTER(UART4_IRQn); IRQ_ENTER(UART4_IRQn);
uart_irq_handler(4); uart_irq_handler(4);
IRQ_EXIT(UART4_IRQn); IRQ_EXIT(UART4_IRQn);
} }
#endif
#if defined(UART5)
void UART5_IRQHandler(void) { void UART5_IRQHandler(void) {
IRQ_ENTER(UART5_IRQn); IRQ_ENTER(UART5_IRQn);
uart_irq_handler(5); uart_irq_handler(5);
IRQ_EXIT(UART5_IRQn); IRQ_EXIT(UART5_IRQn);
} }
#endif
#if defined(USART6)
void USART6_IRQHandler(void) { void USART6_IRQHandler(void) {
IRQ_ENTER(USART6_IRQn); IRQ_ENTER(USART6_IRQn);
uart_irq_handler(6); uart_irq_handler(6);
IRQ_EXIT(USART6_IRQn); IRQ_EXIT(USART6_IRQn);
} }
#endif
#if defined(UART7) #if defined(UART7)
void UART7_IRQHandler(void) { void UART7_IRQHandler(void) {
@ -830,6 +840,14 @@ void UART10_IRQHandler(void) {
#endif #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 MICROPY_PY_PYB_LEGACY
#if defined(MICROPY_HW_I2C1_SCL) #if defined(MICROPY_HW_I2C1_SCL)

View File

@ -201,6 +201,11 @@ bool uart_exists(int uart_id) {
return true; return true;
#endif #endif
#if defined(MICROPY_HW_LPUART1_TX) && defined(MICROPY_HW_LPUART1_RX)
case PYB_LPUART_1:
return true;
#endif
default: default:
return false; 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) { uint32_t baudrate, uint32_t bits, uint32_t parity, uint32_t stop, uint32_t flow) {
USART_TypeDef *UARTx; USART_TypeDef *UARTx;
IRQn_Type irqn; IRQn_Type irqn;
uint8_t uart_fn = AF_FN_UART;
int uart_unit; int uart_unit;
const pin_obj_t *pins[4] = {0}; const pin_obj_t *pins[4] = {0};
@ -406,6 +412,28 @@ bool uart_init(pyb_uart_obj_t *uart_obj,
break; break;
#endif #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: default:
// UART does not exist or is not configured for this board // UART does not exist or is not configured for this board
return false; return false;
@ -416,7 +444,7 @@ bool uart_init(pyb_uart_obj_t *uart_obj,
for (uint i = 0; i < 4; i++) { for (uint i = 0; i < 4; i++) {
if (pins[i] != NULL) { 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) { if (!ret) {
return false; return false;
} }
@ -596,6 +624,13 @@ void uart_deinit(pyb_uart_obj_t *self) {
__HAL_RCC_UART10_RELEASE_RESET(); __HAL_RCC_UART10_RELEASE_RESET();
__HAL_RCC_UART10_CLK_DISABLE(); __HAL_RCC_UART10_CLK_DISABLE();
#endif #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) { uint32_t uart_get_baudrate(pyb_uart_obj_t *self) {
// This formula assumes UART_OVERSAMPLING_16 // 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) { void uart_set_baudrate(pyb_uart_obj_t *self, uint32_t baudrate) {

View File

@ -40,6 +40,9 @@ typedef enum {
PYB_UART_8 = 8, PYB_UART_8 = 8,
PYB_UART_9 = 9, PYB_UART_9 = 9,
PYB_UART_10 = 10, PYB_UART_10 = 10,
#ifdef LPUART1
PYB_LPUART_1 = MICROPY_HW_MAX_UART + 1,
#endif
} pyb_uart_t; } pyb_uart_t;
#define CHAR_WIDTH_8BIT (0) #define CHAR_WIDTH_8BIT (0)