From 0b81b966d4da5bebd426ce9275306a83213c688c Mon Sep 17 00:00:00 2001 From: Ben Iofel Date: Tue, 9 Apr 2019 16:47:07 -0400 Subject: [PATCH 1/3] Disable uart interrupt in uart_debug_write --- cores/arduino/stm32/uart.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cores/arduino/stm32/uart.c b/cores/arduino/stm32/uart.c index 91c9c66d7e..9ac04904c4 100644 --- a/cores/arduino/stm32/uart.c +++ b/cores/arduino/stm32/uart.c @@ -607,12 +607,16 @@ size_t uart_debug_write(uint8_t *data, uint32_t size) index = serial_debug.index; } + HAL_NVIC_DisableIRQ(serial_debug.irq); + while (HAL_UART_Transmit(uart_handlers[index], data, size, TX_TIMEOUT) != HAL_OK) { if ((HAL_GetTick() - tickstart) >= TX_TIMEOUT) { + HAL_NVIC_EnableIRQ(serial_debug.irq); return 0; } } + HAL_NVIC_EnableIRQ(serial_debug.irq); return size; } From 7ef9fa95b38cb352989897510af6f5d4ff4377ec Mon Sep 17 00:00:00 2001 From: ppescher Date: Wed, 10 Apr 2019 15:25:25 -0400 Subject: [PATCH 2/3] Fix serial port full-duplex bug When a receive IT fires while the HAL handle is locked, the receive callback fails to re-enable the IT and the serial port stops receiving anymore. This can happen when transmit IT is enabled outside the IRQ in HardwareSerial::write(), following a buffer full condition that disables transmit IT in HAL_UART_TxCpltCallback(). Solution is to temporarily disable the IRQ while the interrupt enable flags are modified. --- cores/arduino/stm32/uart.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/cores/arduino/stm32/uart.c b/cores/arduino/stm32/uart.c index 9ac04904c4..a771d61292 100644 --- a/cores/arduino/stm32/uart.c +++ b/cores/arduino/stm32/uart.c @@ -686,12 +686,14 @@ void uart_attach_rx_callback(serial_t *obj, void (*callback)(serial_t *)) rx_callback[obj->index] = callback; rx_callback_obj[obj->index] = obj; + /* Must disable interrupt to prevent handle lock contention */ + HAL_NVIC_DisableIRQ(obj->irq); + + HAL_UART_Receive_IT(uart_handlers[obj->index], &(obj->recv), 1); + + /* Enable interrupt */ HAL_NVIC_SetPriority(obj->irq, 0, 1); HAL_NVIC_EnableIRQ(obj->irq); - - if (HAL_UART_Receive_IT(uart_handlers[obj->index], &(obj->recv), 1) != HAL_OK) { - return; - } } /** @@ -710,14 +712,15 @@ void uart_attach_tx_callback(serial_t *obj, int (*callback)(serial_t *)) tx_callback[obj->index] = callback; tx_callback_obj[obj->index] = obj; + /* Must disable interrupt to prevent handle lock contention */ + HAL_NVIC_DisableIRQ(obj->irq); + + /* The following function will enable UART_IT_TXE and error interrupts */ + HAL_UART_Transmit_IT(uart_handlers[obj->index], &obj->tx_buff[obj->tx_tail], 1); + /* Enable interrupt */ HAL_NVIC_SetPriority(obj->irq, 0, 2); HAL_NVIC_EnableIRQ(obj->irq); - - /* The following function will enable UART_IT_TXE and error interrupts */ - if (HAL_UART_Transmit_IT(uart_handlers[obj->index], &obj->tx_buff[obj->tx_tail], 1) != HAL_OK) { - return; - } } /** From 896d988242803d7aaad3be370fb6b4268e56420e Mon Sep 17 00:00:00 2001 From: ppescher Date: Thu, 7 Mar 2019 13:53:36 +0100 Subject: [PATCH 3/3] Fix UART error callback (clear flags and restart receive IT) --- cores/arduino/stm32/uart.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/cores/arduino/stm32/uart.c b/cores/arduino/stm32/uart.c index a771d61292..bc246c10c3 100644 --- a/cores/arduino/stm32/uart.c +++ b/cores/arduino/stm32/uart.c @@ -797,16 +797,23 @@ void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) } #else if (__HAL_UART_GET_FLAG(huart, UART_FLAG_PE) != RESET) { - tmpval = huart->Instance->RDR; /* Clear PE flag */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_PEF); /* Clear PE flag */ } else if (__HAL_UART_GET_FLAG(huart, UART_FLAG_FE) != RESET) { - tmpval = huart->Instance->RDR; /* Clear FE flag */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_FEF); /* Clear FE flag */ } else if (__HAL_UART_GET_FLAG(huart, UART_FLAG_NE) != RESET) { - tmpval = huart->Instance->RDR; /* Clear NE flag */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_NEF); /* Clear NE flag */ } else if (__HAL_UART_GET_FLAG(huart, UART_FLAG_ORE) != RESET) { - tmpval = huart->Instance->RDR; /* Clear ORE flag */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF); /* Clear ORE flag */ } #endif - + /* Restart receive interrupt after any error */ + uint8_t index = uart_index(huart); + if (index < UART_NUM) { + serial_t *obj = rx_callback_obj[index]; + if (!serial_rx_active(obj)) { + HAL_UART_Receive_IT(uart_handlers[obj->index], &(obj->recv), 1); + } + } UNUSED(tmpval); }