From ae635d5cd4a51267262248f8eac8631a1d357ea9 Mon Sep 17 00:00:00 2001 From: Filip Jagodzinski Date: Tue, 28 Jan 2020 14:09:01 +0100 Subject: [PATCH 1/2] STM32L4: Fix the UART RX & TX data reg bitmasks The existing logic was insufficient to properly handle odd and even parity setting, e.g. serial_getc() returned 9-bit data for 8O1 transmission format. --- .../TARGET_STM/TARGET_STM32L4/serial_device.c | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/targets/TARGET_STM/TARGET_STM32L4/serial_device.c b/targets/TARGET_STM/TARGET_STM32L4/serial_device.c index 102bdd98ed..74637246a8 100644 --- a/targets/TARGET_STM/TARGET_STM32L4/serial_device.c +++ b/targets/TARGET_STM/TARGET_STM32L4/serial_device.c @@ -215,12 +215,15 @@ int serial_getc(serial_t *obj) struct serial_s *obj_s = SERIAL_S(obj); UART_HandleTypeDef *huart = &uart_handlers[obj_s->index]; + /* Computation of UART mask to apply to RDR register */ + UART_MASK_COMPUTATION(huart); + uint16_t uhMask = huart->Mask; + while (!serial_readable(obj)); - if (obj_s->databits == UART_WORDLENGTH_8B) { - return (int)(huart->Instance->RDR & (uint8_t)0xFF); - } else { - return (int)(huart->Instance->RDR & (uint16_t)0x1FF); - } + /* When receiving with the parity enabled, the value read in the MSB bit + * is the received parity bit. + */ + return (int)(huart->Instance->RDR & uhMask); } void serial_putc(serial_t *obj, int c) @@ -229,11 +232,12 @@ void serial_putc(serial_t *obj, int c) UART_HandleTypeDef *huart = &uart_handlers[obj_s->index]; while (!serial_writable(obj)); - if (obj_s->databits == UART_WORDLENGTH_8B) { - huart->Instance->TDR = (uint8_t)(c & (uint8_t)0xFF); - } else { - huart->Instance->TDR = (uint16_t)(c & (uint16_t)0x1FF); - } + /* When transmitting with the parity enabled (PCE bit set to 1 in the + * USART_CR1 register), the value written in the MSB (bit 7 or bit 8 + * depending on the data length) has no effect because it is replaced + * by the parity. + */ + huart->Instance->TDR = (uint16_t)(c & 0x1FFU); } void serial_clear(serial_t *obj) From 2368a072443c25d31aacb3a61b2e92b25d41335a Mon Sep 17 00:00:00 2001 From: jeromecoutant Date: Thu, 6 Feb 2020 15:04:11 +0100 Subject: [PATCH 2/2] STM32: Fix the UART RX & TX data reg bitmasks --- .../TARGET_STM/TARGET_STM32F0/serial_device.c | 16 +++++++++++-- .../TARGET_STM/TARGET_STM32F3/serial_device.c | 24 +++++++++++-------- .../TARGET_STM/TARGET_STM32F7/serial_device.c | 16 +++++++++++-- .../TARGET_STM/TARGET_STM32G0/serial_device.c | 16 +++++++++++-- .../TARGET_STM/TARGET_STM32H7/serial_device.c | 16 +++++++++++-- .../TARGET_STM/TARGET_STM32L0/serial_device.c | 16 +++++++++++-- .../TARGET_STM/TARGET_STM32WB/serial_device.c | 24 +++++++++++-------- 7 files changed, 98 insertions(+), 30 deletions(-) diff --git a/targets/TARGET_STM/TARGET_STM32F0/serial_device.c b/targets/TARGET_STM/TARGET_STM32F0/serial_device.c index 65d56f65a9..c9ba29b217 100644 --- a/targets/TARGET_STM/TARGET_STM32F0/serial_device.c +++ b/targets/TARGET_STM/TARGET_STM32F0/serial_device.c @@ -263,8 +263,15 @@ int serial_getc(serial_t *obj) struct serial_s *obj_s = SERIAL_S(obj); UART_HandleTypeDef *huart = &uart_handlers[obj_s->index]; + /* Computation of UART mask to apply to RDR register */ + UART_MASK_COMPUTATION(huart); + uint16_t uhMask = huart->Mask; + while (!serial_readable(obj)); - return (int)(huart->Instance->RDR & (uint16_t)0xFF); + /* When receiving with the parity enabled, the value read in the MSB bit + * is the received parity bit. + */ + return (int)(huart->Instance->RDR & uhMask); } void serial_putc(serial_t *obj, int c) @@ -273,7 +280,12 @@ void serial_putc(serial_t *obj, int c) UART_HandleTypeDef *huart = &uart_handlers[obj_s->index]; while (!serial_writable(obj)); - huart->Instance->TDR = (uint32_t)(c & (uint16_t)0xFF); + /* When transmitting with the parity enabled (PCE bit set to 1 in the + * USART_CR1 register), the value written in the MSB (bit 7 or bit 8 + * depending on the data length) has no effect because it is replaced + * by the parity. + */ + huart->Instance->TDR = (uint16_t)(c & 0x1FFU); } void serial_clear(serial_t *obj) diff --git a/targets/TARGET_STM/TARGET_STM32F3/serial_device.c b/targets/TARGET_STM/TARGET_STM32F3/serial_device.c index ab7c011016..362411f4ff 100644 --- a/targets/TARGET_STM/TARGET_STM32F3/serial_device.c +++ b/targets/TARGET_STM/TARGET_STM32F3/serial_device.c @@ -202,12 +202,15 @@ int serial_getc(serial_t *obj) struct serial_s *obj_s = SERIAL_S(obj); UART_HandleTypeDef *huart = &uart_handlers[obj_s->index]; + /* Computation of UART mask to apply to RDR register */ + UART_MASK_COMPUTATION(huart); + uint16_t uhMask = huart->Mask; + while (!serial_readable(obj)); - if (obj_s->databits == UART_WORDLENGTH_8B) { - return (int)(huart->Instance->RDR & (uint8_t)0xFF); - } else { - return (int)(huart->Instance->RDR & (uint16_t)0x1FF); - } + /* When receiving with the parity enabled, the value read in the MSB bit + * is the received parity bit. + */ + return (int)(huart->Instance->RDR & uhMask); } void serial_putc(serial_t *obj, int c) @@ -216,11 +219,12 @@ void serial_putc(serial_t *obj, int c) UART_HandleTypeDef *huart = &uart_handlers[obj_s->index]; while (!serial_writable(obj)); - if (obj_s->databits == UART_WORDLENGTH_8B) { - huart->Instance->TDR = (uint8_t)(c & (uint8_t)0xFF); - } else { - huart->Instance->TDR = (uint16_t)(c & (uint16_t)0x1FF); - } + /* When transmitting with the parity enabled (PCE bit set to 1 in the + * USART_CR1 register), the value written in the MSB (bit 7 or bit 8 + * depending on the data length) has no effect because it is replaced + * by the parity. + */ + huart->Instance->TDR = (uint16_t)(c & 0x1FFU); } void serial_clear(serial_t *obj) diff --git a/targets/TARGET_STM/TARGET_STM32F7/serial_device.c b/targets/TARGET_STM/TARGET_STM32F7/serial_device.c index a2a9f9327a..45e40dff38 100644 --- a/targets/TARGET_STM/TARGET_STM32F7/serial_device.c +++ b/targets/TARGET_STM/TARGET_STM32F7/serial_device.c @@ -234,8 +234,15 @@ int serial_getc(serial_t *obj) struct serial_s *obj_s = SERIAL_S(obj); UART_HandleTypeDef *huart = &uart_handlers[obj_s->index]; + /* Computation of UART mask to apply to RDR register */ + UART_MASK_COMPUTATION(huart); + uint16_t uhMask = huart->Mask; + while (!serial_readable(obj)); - return (int)(huart->Instance->RDR & 0x1FF); + /* When receiving with the parity enabled, the value read in the MSB bit + * is the received parity bit. + */ + return (int)(huart->Instance->RDR & uhMask); } void serial_putc(serial_t *obj, int c) @@ -244,7 +251,12 @@ void serial_putc(serial_t *obj, int c) UART_HandleTypeDef *huart = &uart_handlers[obj_s->index]; while (!serial_writable(obj)); - huart->Instance->TDR = (uint32_t)(c & 0x1FF); + /* When transmitting with the parity enabled (PCE bit set to 1 in the + * USART_CR1 register), the value written in the MSB (bit 7 or bit 8 + * depending on the data length) has no effect because it is replaced + * by the parity. + */ + huart->Instance->TDR = (uint16_t)(c & 0x1FFU); } void serial_clear(serial_t *obj) diff --git a/targets/TARGET_STM/TARGET_STM32G0/serial_device.c b/targets/TARGET_STM/TARGET_STM32G0/serial_device.c index d14cefcd69..b94924bd7b 100644 --- a/targets/TARGET_STM/TARGET_STM32G0/serial_device.c +++ b/targets/TARGET_STM/TARGET_STM32G0/serial_device.c @@ -190,8 +190,15 @@ int serial_getc(serial_t *obj) struct serial_s *obj_s = SERIAL_S(obj); UART_HandleTypeDef *huart = &uart_handlers[obj_s->index]; + /* Computation of UART mask to apply to RDR register */ + UART_MASK_COMPUTATION(huart); + uint16_t uhMask = huart->Mask; + while (!serial_readable(obj)); - return (int)(huart->Instance->RDR & (uint16_t)0xFF); + /* When receiving with the parity enabled, the value read in the MSB bit + * is the received parity bit. + */ + return (int)(huart->Instance->RDR & uhMask); } void serial_putc(serial_t *obj, int c) @@ -200,7 +207,12 @@ void serial_putc(serial_t *obj, int c) UART_HandleTypeDef *huart = &uart_handlers[obj_s->index]; while (!serial_writable(obj)); - huart->Instance->TDR = (uint32_t)(c & (uint16_t)0xFF); + /* When transmitting with the parity enabled (PCE bit set to 1 in the + * USART_CR1 register), the value written in the MSB (bit 7 or bit 8 + * depending on the data length) has no effect because it is replaced + * by the parity. + */ + huart->Instance->TDR = (uint16_t)(c & 0x1FFU); } void serial_clear(serial_t *obj) diff --git a/targets/TARGET_STM/TARGET_STM32H7/serial_device.c b/targets/TARGET_STM/TARGET_STM32H7/serial_device.c index 7acdfc8f64..1a8ee627fb 100644 --- a/targets/TARGET_STM/TARGET_STM32H7/serial_device.c +++ b/targets/TARGET_STM/TARGET_STM32H7/serial_device.c @@ -247,8 +247,15 @@ int serial_getc(serial_t *obj) struct serial_s *obj_s = SERIAL_S(obj); UART_HandleTypeDef *huart = &uart_handlers[obj_s->index]; + /* Computation of UART mask to apply to RDR register */ + UART_MASK_COMPUTATION(huart); + uint16_t uhMask = huart->Mask; + while (!serial_readable(obj)); - return (int)(huart->Instance->RDR & 0x1FF); + /* When receiving with the parity enabled, the value read in the MSB bit + * is the received parity bit. + */ + return (int)(huart->Instance->RDR & uhMask); } void serial_putc(serial_t *obj, int c) @@ -257,7 +264,12 @@ void serial_putc(serial_t *obj, int c) UART_HandleTypeDef *huart = &uart_handlers[obj_s->index]; while (!serial_writable(obj)); - huart->Instance->TDR = (uint32_t)(c & 0x1FF); + /* When transmitting with the parity enabled (PCE bit set to 1 in the + * USART_CR1 register), the value written in the MSB (bit 7 or bit 8 + * depending on the data length) has no effect because it is replaced + * by the parity. + */ + huart->Instance->TDR = (uint16_t)(c & 0x1FFU); } void serial_clear(serial_t *obj) diff --git a/targets/TARGET_STM/TARGET_STM32L0/serial_device.c b/targets/TARGET_STM/TARGET_STM32L0/serial_device.c index 73cbc3e250..52db647bfd 100644 --- a/targets/TARGET_STM/TARGET_STM32L0/serial_device.c +++ b/targets/TARGET_STM/TARGET_STM32L0/serial_device.c @@ -204,8 +204,15 @@ int serial_getc(serial_t *obj) struct serial_s *obj_s = SERIAL_S(obj); UART_HandleTypeDef *huart = &uart_handlers[obj_s->index]; + /* Computation of UART mask to apply to RDR register */ + UART_MASK_COMPUTATION(huart); + uint16_t uhMask = huart->Mask; + while (!serial_readable(obj)); - return (int)(huart->Instance->RDR & (uint16_t)0xFF); + /* When receiving with the parity enabled, the value read in the MSB bit + * is the received parity bit. + */ + return (int)(huart->Instance->RDR & uhMask); } void serial_putc(serial_t *obj, int c) @@ -214,7 +221,12 @@ void serial_putc(serial_t *obj, int c) UART_HandleTypeDef *huart = &uart_handlers[obj_s->index]; while (!serial_writable(obj)); - huart->Instance->TDR = (uint32_t)(c & (uint16_t)0xFF); + /* When transmitting with the parity enabled (PCE bit set to 1 in the + * USART_CR1 register), the value written in the MSB (bit 7 or bit 8 + * depending on the data length) has no effect because it is replaced + * by the parity. + */ + huart->Instance->TDR = (uint16_t)(c & 0x1FFU); } void serial_clear(serial_t *obj) diff --git a/targets/TARGET_STM/TARGET_STM32WB/serial_device.c b/targets/TARGET_STM/TARGET_STM32WB/serial_device.c index 7128c8e9f8..9e02554db2 100644 --- a/targets/TARGET_STM/TARGET_STM32WB/serial_device.c +++ b/targets/TARGET_STM/TARGET_STM32WB/serial_device.c @@ -160,12 +160,15 @@ int serial_getc(serial_t *obj) struct serial_s *obj_s = SERIAL_S(obj); UART_HandleTypeDef *huart = &uart_handlers[obj_s->index]; + /* Computation of UART mask to apply to RDR register */ + UART_MASK_COMPUTATION(huart); + uint16_t uhMask = huart->Mask; + while (!serial_readable(obj)); - if (obj_s->databits == UART_WORDLENGTH_8B) { - return (int)(huart->Instance->RDR & (uint8_t)0xFF); - } else { - return (int)(huart->Instance->RDR & (uint16_t)0x1FF); - } + /* When receiving with the parity enabled, the value read in the MSB bit + * is the received parity bit. + */ + return (int)(huart->Instance->RDR & uhMask); } void serial_putc(serial_t *obj, int c) @@ -174,11 +177,12 @@ void serial_putc(serial_t *obj, int c) UART_HandleTypeDef *huart = &uart_handlers[obj_s->index]; while (!serial_writable(obj)); - if (obj_s->databits == UART_WORDLENGTH_8B) { - huart->Instance->TDR = (uint8_t)(c & (uint8_t)0xFF); - } else { - huart->Instance->TDR = (uint16_t)(c & (uint16_t)0x1FF); - } + /* When transmitting with the parity enabled (PCE bit set to 1 in the + * USART_CR1 register), the value written in the MSB (bit 7 or bit 8 + * depending on the data length) has no effect because it is replaced + * by the parity. + */ + huart->Instance->TDR = (uint16_t)(c & 0x1FFU); } void serial_clear(serial_t *obj)