Skip to content

Commit bcb8e15

Browse files
committed
feat(esp_driver_uart): Add uart_write_bytes_with_timeout()
Avoids locking if the uart is blocked due to flow control.
1 parent a6e7046 commit bcb8e15

File tree

2 files changed

+59
-10
lines changed

2 files changed

+59
-10
lines changed

components/esp_driver_uart/include/driver/uart.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,26 @@ int uart_tx_chars(uart_port_t uart_num, const char* buffer, uint32_t len);
553553
*/
554554
int uart_write_bytes(uart_port_t uart_num, const void* src, size_t size);
555555

556+
/**
557+
* @brief Send data to the UART port from a given buffer and length,
558+
*
559+
* If the UART driver's parameter 'tx_buffer_size' is set to zero:
560+
* This function will return before all the data have been sent out, if it times out.
561+
*
562+
* Otherwise, if the 'tx_buffer_size' > 0, this function will return after copying all the data to tx ring buffer,
563+
* UART ISR will then move data from the ring buffer to TX FIFO gradually.
564+
*
565+
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
566+
* @param src data buffer address
567+
* @param size data length to send
568+
* @param ticks_to_wait Timeout, count in RTOS ticks
569+
*
570+
* @return
571+
* - (-1) Parameter error
572+
* - OTHERS (>=0) The number of bytes pushed to the TX FIFO
573+
*/
574+
int uart_write_bytes_with_timeout(uart_port_t uart_num, const void* src, size_t size, TickType_t ticks_to_wait);
575+
556576
/**
557577
* @brief Send data to the UART port from a given buffer and length,
558578
*

components/esp_driver_uart/src/uart.c

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1620,15 +1620,17 @@ int uart_tx_chars(uart_port_t uart_num, const char *buffer, uint32_t len)
16201620

16211621
// Per transaction in the ring buffer:
16221622
// A data description item, followed by one or more data chunk items
1623-
static int uart_tx_all(uart_port_t uart_num, const char *src, size_t size, bool brk_en, int brk_len)
1623+
static int uart_tx_all(uart_port_t uart_num, const char *src, size_t size, bool brk_en, int brk_len, TickType_t ticks_to_wait)
16241624
{
16251625
if (size == 0) {
16261626
return 0;
16271627
}
1628-
size_t original_size = size;
1628+
size_t bytes_transmitted = size;
16291629

16301630
//lock for uart_tx
1631-
xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (TickType_t)portMAX_DELAY);
1631+
if (xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (TickType_t)ticks_to_wait) != pdTRUE) {
1632+
return -1;
1633+
}
16321634
#if PROTECT_APB
16331635
esp_pm_lock_acquire(p_uart_obj[uart_num]->pm_lock);
16341636
#endif
@@ -1643,12 +1645,21 @@ static int uart_tx_all(uart_port_t uart_num, const char *src, size_t size, bool
16431645
} else {
16441646
evt.type = UART_DATA;
16451647
}
1646-
xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void *) &evt, sizeof(uart_tx_data_t), portMAX_DELAY);
1648+
UBaseType_t res = xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void *) &evt, sizeof(uart_tx_data_t), ticks_to_wait);
1649+
if (res != pdTRUE) {
1650+
bytes_transmitted = -1;
1651+
goto unlock_and_return;
1652+
1653+
}
16471654
while (size > 0) {
16481655
size_t free_size = xRingbufferGetCurFreeSize(p_uart_obj[uart_num]->tx_ring_buf);
16491656
size_t send_size = MIN(size, free_size);
16501657
if (send_size > 0) {
1651-
xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void *)(src + offset), send_size, portMAX_DELAY);
1658+
res = xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void *)(src + offset), send_size, ticks_to_wait);
1659+
if (res != pdTRUE) {
1660+
bytes_transmitted = -1;
1661+
goto unlock_and_return;
1662+
}
16521663
size -= send_size;
16531664
offset += send_size;
16541665
uart_enable_tx_intr(uart_num, 1, UART_THRESHOLD_NUM(uart_num, UART_EMPTY_THRESH_DEFAULT));
@@ -1657,14 +1668,17 @@ static int uart_tx_all(uart_port_t uart_num, const char *src, size_t size, bool
16571668
} else {
16581669
while (size) {
16591670
//semaphore for tx_fifo available
1660-
if (pdTRUE == xSemaphoreTake(p_uart_obj[uart_num]->tx_fifo_sem, (TickType_t)portMAX_DELAY)) {
1671+
if (pdTRUE == xSemaphoreTake(p_uart_obj[uart_num]->tx_fifo_sem, ticks_to_wait)) {
16611672
uint32_t sent = uart_enable_tx_write_fifo(uart_num, (const uint8_t *) src, size);
16621673
if (sent < size) {
16631674
p_uart_obj[uart_num]->tx_waiting_fifo = true;
16641675
uart_enable_tx_intr(uart_num, 1, UART_THRESHOLD_NUM(uart_num, UART_EMPTY_THRESH_DEFAULT));
16651676
}
16661677
size -= sent;
16671678
src += sent;
1679+
} else {
1680+
bytes_transmitted = -1;
1681+
goto unlock_and_return;
16681682
}
16691683
}
16701684
if (brk_en) {
@@ -1673,23 +1687,38 @@ static int uart_tx_all(uart_port_t uart_num, const char *src, size_t size, bool
16731687
uart_hal_tx_break(&(uart_context[uart_num].hal), brk_len);
16741688
uart_hal_ena_intr_mask(&(uart_context[uart_num].hal), UART_INTR_TX_BRK_DONE);
16751689
UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock));
1676-
xSemaphoreTake(p_uart_obj[uart_num]->tx_brk_sem, (TickType_t)portMAX_DELAY);
1690+
if (pdFALSE == xSemaphoreTake(p_uart_obj[uart_num]->tx_brk_sem, ticks_to_wait)) {
1691+
xSemaphoreGive(p_uart_obj[uart_num]->tx_fifo_sem);
1692+
uart_hal_disable_intr_mask(&(uart_context[uart_num].hal), UART_INTR_TX_BRK_DONE);
1693+
bytes_transmitted = -1;
1694+
goto unlock_and_return;
1695+
}
16771696
}
16781697
xSemaphoreGive(p_uart_obj[uart_num]->tx_fifo_sem);
16791698
}
1699+
1700+
unlock_and_return:
16801701
#if PROTECT_APB
16811702
esp_pm_lock_release(p_uart_obj[uart_num]->pm_lock);
16821703
#endif
16831704
xSemaphoreGive(p_uart_obj[uart_num]->tx_mux);
1684-
return original_size;
1705+
return bytes_transmitted;
16851706
}
16861707

16871708
int uart_write_bytes(uart_port_t uart_num, const void *src, size_t size)
16881709
{
16891710
ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), (-1), UART_TAG, "uart_num error");
16901711
ESP_RETURN_ON_FALSE((p_uart_obj[uart_num] != NULL), (-1), UART_TAG, "uart driver error");
16911712
ESP_RETURN_ON_FALSE(src, (-1), UART_TAG, "buffer null");
1692-
return uart_tx_all(uart_num, src, size, 0, 0);
1713+
return uart_tx_all(uart_num, src, size, 0, 0, portMAX_DELAY);
1714+
}
1715+
1716+
int uart_write_bytes_with_timeout(uart_port_t uart_num, const void *src, size_t size, TickType_t ticks_to_wait)
1717+
{
1718+
ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), (-1), UART_TAG, "uart_num error");
1719+
ESP_RETURN_ON_FALSE((p_uart_obj[uart_num] != NULL), (-1), UART_TAG, "uart driver error");
1720+
ESP_RETURN_ON_FALSE(src, (-1), UART_TAG, "buffer null");
1721+
return uart_tx_all(uart_num, src, size, 0, 0, ticks_to_wait);
16931722
}
16941723

16951724
int uart_write_bytes_with_break(uart_port_t uart_num, const void *src, size_t size, int brk_len)
@@ -1699,7 +1728,7 @@ int uart_write_bytes_with_break(uart_port_t uart_num, const void *src, size_t si
16991728
ESP_RETURN_ON_FALSE((size > 0), (-1), UART_TAG, "uart size error");
17001729
ESP_RETURN_ON_FALSE((src), (-1), UART_TAG, "uart data null");
17011730
ESP_RETURN_ON_FALSE((brk_len > 0 && brk_len < 256), (-1), UART_TAG, "break_num error");
1702-
return uart_tx_all(uart_num, src, size, 1, brk_len);
1731+
return uart_tx_all(uart_num, src, size, 1, brk_len, portMAX_DELAY);
17031732
}
17041733

17051734
static bool uart_check_buf_full(uart_port_t uart_num)

0 commit comments

Comments
 (0)