Skip to content

Commit 9914847

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 ff97953 commit 9914847

File tree

2 files changed

+49
-8
lines changed

2 files changed

+49
-8
lines changed

components/esp_driver_uart/include/driver/uart.h

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

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

components/esp_driver_uart/src/uart.c

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1593,15 +1593,17 @@ int uart_tx_chars(uart_port_t uart_num, const char *buffer, uint32_t len)
15931593

15941594
// Per transaction in the ring buffer:
15951595
// A data description item, followed by one or more data chunk items
1596-
static int uart_tx_all(uart_port_t uart_num, const char *src, size_t size, bool brk_en, int brk_len)
1596+
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)
15971597
{
15981598
if (size == 0) {
15991599
return 0;
16001600
}
16011601
size_t original_size = size;
16021602

16031603
//lock for uart_tx
1604-
xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (TickType_t)portMAX_DELAY);
1604+
if (xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (TickType_t)ticks_to_wait) != pdTRUE) {
1605+
return -1;
1606+
}
16051607
#if PROTECT_APB
16061608
esp_pm_lock_acquire(p_uart_obj[uart_num]->pm_lock);
16071609
#endif
@@ -1616,25 +1618,36 @@ static int uart_tx_all(uart_port_t uart_num, const char *src, size_t size, bool
16161618
} else {
16171619
evt.type = UART_DATA;
16181620
}
1619-
xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void *) &evt, sizeof(uart_tx_data_t), portMAX_DELAY);
1621+
UBaseType_t res = xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void *) &evt, sizeof(uart_tx_data_t), ticks_to_wait);
1622+
if (res != pdTRUE) {
1623+
xSemaphoreGive(p_uart_obj[uart_num]->tx_mux);
1624+
return -1;
1625+
}
16201626
while (size > 0) {
16211627
size_t send_size = MIN(size, xRingbufferGetCurFreeSize(p_uart_obj[uart_num]->tx_ring_buf));
1622-
xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void *)(src + offset), send_size, portMAX_DELAY);
1628+
res = xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void *)(src + offset), send_size, ticks_to_wait);
1629+
if (res != pdTRUE) {
1630+
xSemaphoreGive(p_uart_obj[uart_num]->tx_mux);
1631+
return -1;
1632+
}
16231633
size -= send_size;
16241634
offset += send_size;
16251635
uart_enable_tx_intr(uart_num, 1, UART_THRESHOLD_NUM(uart_num, UART_EMPTY_THRESH_DEFAULT));
16261636
}
16271637
} else {
16281638
while (size) {
16291639
//semaphore for tx_fifo available
1630-
if (pdTRUE == xSemaphoreTake(p_uart_obj[uart_num]->tx_fifo_sem, (TickType_t)portMAX_DELAY)) {
1640+
if (pdTRUE == xSemaphoreTake(p_uart_obj[uart_num]->tx_fifo_sem, ticks_to_wait)) {
16311641
uint32_t sent = uart_enable_tx_write_fifo(uart_num, (const uint8_t *) src, size);
16321642
if (sent < size) {
16331643
p_uart_obj[uart_num]->tx_waiting_fifo = true;
16341644
uart_enable_tx_intr(uart_num, 1, UART_THRESHOLD_NUM(uart_num, UART_EMPTY_THRESH_DEFAULT));
16351645
}
16361646
size -= sent;
16371647
src += sent;
1648+
} else {
1649+
xSemaphoreGive(p_uart_obj[uart_num]->tx_mux);
1650+
return -1;
16381651
}
16391652
}
16401653
if (brk_en) {
@@ -1643,7 +1656,7 @@ static int uart_tx_all(uart_port_t uart_num, const char *src, size_t size, bool
16431656
uart_hal_tx_break(&(uart_context[uart_num].hal), brk_len);
16441657
uart_hal_ena_intr_mask(&(uart_context[uart_num].hal), UART_INTR_TX_BRK_DONE);
16451658
UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock));
1646-
xSemaphoreTake(p_uart_obj[uart_num]->tx_brk_sem, (TickType_t)portMAX_DELAY);
1659+
xSemaphoreTake(p_uart_obj[uart_num]->tx_brk_sem, ticks_to_wait);
16471660
}
16481661
xSemaphoreGive(p_uart_obj[uart_num]->tx_fifo_sem);
16491662
}
@@ -1659,7 +1672,15 @@ int uart_write_bytes(uart_port_t uart_num, const void *src, size_t size)
16591672
ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), (-1), UART_TAG, "uart_num error");
16601673
ESP_RETURN_ON_FALSE((p_uart_obj[uart_num] != NULL), (-1), UART_TAG, "uart driver error");
16611674
ESP_RETURN_ON_FALSE(src, (-1), UART_TAG, "buffer null");
1662-
return uart_tx_all(uart_num, src, size, 0, 0);
1675+
return uart_tx_all(uart_num, src, size, 0, 0, portMAX_DELAY);
1676+
}
1677+
1678+
int uart_write_bytes_with_timeout(uart_port_t uart_num, const void *src, size_t size, TickType_t ticks_to_wait)
1679+
{
1680+
ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), (-1), UART_TAG, "uart_num error");
1681+
ESP_RETURN_ON_FALSE((p_uart_obj[uart_num] != NULL), (-1), UART_TAG, "uart driver error");
1682+
ESP_RETURN_ON_FALSE(src, (-1), UART_TAG, "buffer null");
1683+
return uart_tx_all(uart_num, src, size, 0, 0, ticks_to_wait);
16631684
}
16641685

16651686
int uart_write_bytes_with_break(uart_port_t uart_num, const void *src, size_t size, int brk_len)
@@ -1669,7 +1690,7 @@ int uart_write_bytes_with_break(uart_port_t uart_num, const void *src, size_t si
16691690
ESP_RETURN_ON_FALSE((size > 0), (-1), UART_TAG, "uart size error");
16701691
ESP_RETURN_ON_FALSE((src), (-1), UART_TAG, "uart data null");
16711692
ESP_RETURN_ON_FALSE((brk_len > 0 && brk_len < 256), (-1), UART_TAG, "break_num error");
1672-
return uart_tx_all(uart_num, src, size, 1, brk_len);
1693+
return uart_tx_all(uart_num, src, size, 1, brk_len, portMAX_DELAY);
16731694
}
16741695

16751696
static bool uart_check_buf_full(uart_port_t uart_num)

0 commit comments

Comments
 (0)