1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-27 15:31:17 +01:00

cpu/stm32: avoid deadlock on nonblocking write

If a write to a full tsrb is attempted with disabled interrupts
or in a interrupt then a deadlock will occure. To avoid this make
space in the ringbuffer by synchrnously writing to uart.
This commit is contained in:
Francisco Molina 2020-06-14 19:50:48 +02:00
parent f7d124e141
commit 09f0fd4526
No known key found for this signature in database
GPG Key ID: 3E94EAC3DBDEEDA8

View File

@ -322,22 +322,18 @@ static inline void uart_init_lpuart(uart_t uart, uint32_t baudrate)
#endif /* MODULE_PERIPH_LPUART */
#endif /* STM32L0 || STM32L4 || STM32WB */
#ifndef MODULE_PERIPH_UART_NONBLOCKING
static inline void send_byte(uart_t uart, uint8_t byte)
{
while (!(dev(uart)->ISR_REG & ISR_TXE)) {}
dev(uart)->TDR_REG = byte;
}
#endif
#ifndef MODULE_PERIPH_UART_NONBLOCKING
static inline void wait_for_tx_complete(uart_t uart)
{
#ifdef MODULE_PERIPH_UART_NONBLOCKING
(void) uart;
#else
while (!(dev(uart)->ISR_REG & ISR_TC)) {}
#endif
}
#endif
void uart_write(uart_t uart, const uint8_t *data, size_t len)
{
@ -387,17 +383,28 @@ void uart_write(uart_t uart, const uint8_t *data, size_t len)
return;
}
#endif
for (size_t i = 0; i < len; i++) {
#ifdef MODULE_PERIPH_UART_NONBLOCKING
for (size_t i = 0; i < len; i++) {
dev(uart)->CR1 |= (USART_CR1_TCIE);
while (tsrb_add_one(&uart_tx_rb[uart], data[i]) < 0) {}
if (irq_is_in() || __get_PRIMASK()) {
/* if ring buffer is full free up a spot */
if (tsrb_full(&uart_tx_rb[uart])) {
send_byte(uart, tsrb_get_one(&uart_tx_rb[uart]));
}
tsrb_add_one(&uart_tx_rb[uart], data[i]);
}
else {
while (tsrb_add_one(&uart_tx_rb[uart], data[i]) < 0) {}
}
}
#else
for (size_t i = 0; i < len; i++) {
send_byte(uart, data[i]);
#endif
}
/* make sure the function is synchronous by waiting for the transfer to
* finish */
wait_for_tx_complete(uart);
#endif
}
void uart_poweron(uart_t uart)