Merge branch 'bugfix/fix_uart_set_rx_timeout_feature_v41' into 'release/v4.1'

Bugfix/fix uart set rx timeout feature (backport v4.1)

See merge request espressif/esp-idf!11538
This commit is contained in:
Jiang Jiang Jian
2021-05-10 03:41:08 +00:00
9 changed files with 273 additions and 80 deletions

View File

@ -70,6 +70,8 @@ typedef enum {
typedef struct {
uart_event_type_t type; /*!< UART event type */
size_t size; /*!< UART data size for UART_DATA event*/
bool timeout_flag; /*!< UART data read timeout flag for UART_DATA event (no new data received during configured RX TOUT)*/
/*!< If the event is caused by FIFO-full interrupt, then there will be no event with the timeout flag before the next byte coming.*/
} uart_event_t;
typedef intr_handle_t uart_isr_handle_t;
@ -845,6 +847,20 @@ esp_err_t uart_wait_tx_idle_polling(uart_port_t uart_num);
*/
esp_err_t uart_set_loop_back(uart_port_t uart_num, bool loop_back_en);
/**
* @brief Configure behavior of UART RX timeout interrupt.
*
* When always_rx_timeout is true, timeout interrupt is triggered even if FIFO is full.
* This function can cause extra timeout interrupts triggered only to send the timeout event.
* Call this function only if you want to ensure timeout interrupt will always happen after a byte stream.
*
* @param uart_num UART number
* @param always_rx_timeout_en Set to false enable the default behavior of timeout interrupt,
* set it to true to always trigger timeout interrupt.
*
*/
void uart_set_always_rx_timeout(uart_port_t uart_num, bool always_rx_timeout_en);
#ifdef __cplusplus
}
#endif

View File

@ -52,13 +52,13 @@ static const char* UART_TAG = "uart";
return (ret_val); \
}
#define UART_EMPTY_THRESH_DEFAULT (10)
#define UART_FULL_THRESH_DEFAULT (120)
#define UART_TOUT_THRESH_DEFAULT (10)
#define UART_CLKDIV_FRAG_BIT_WIDTH (3)
#define UART_TX_IDLE_NUM_DEFAULT (0)
#define UART_PATTERN_DET_QLEN_DEFAULT (10)
#define UART_MIN_WAKEUP_THRESH (SOC_UART_MIN_WAKEUP_THRESH)
#define UART_EMPTY_THRESH_DEFAULT (10)
#define UART_FULL_THRESH_DEFAULT (120)
#define UART_TOUT_THRESH_DEFAULT (10)
#define UART_CLKDIV_FRAG_BIT_WIDTH (3)
#define UART_TX_IDLE_NUM_DEFAULT (0)
#define UART_PATTERN_DET_QLEN_DEFAULT (10)
#define UART_MIN_WAKEUP_THRESH (SOC_UART_MIN_WAKEUP_THRESH)
#define UART_INTR_CONFIG_FLAG ((UART_INTR_RXFIFO_FULL) \
| (UART_INTR_RXFIFO_TOUT) \
@ -104,6 +104,7 @@ typedef struct {
intr_handle_t intr_handle; /*!< UART interrupt handle*/
uart_mode_t uart_mode; /*!< UART controller actual mode set by uart_set_mode() */
bool coll_det_flg; /*!< UART collision detection flag */
bool rx_always_timeout_flg; /*!< UART always detect rx timeout flag */
//rx parameters
int rx_buffered_len; /*!< UART cached data length */
@ -805,6 +806,10 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param)
pat_flg = 0;
}
if (p_uart->rx_buffer_full_flg == false) {
rx_fifo_len = uart_hal_get_rxfifo_len(&(uart_context[uart_num].hal));
if ((p_uart_obj[uart_num]->rx_always_timeout_flg) && !(uart_intr_status & UART_INTR_RXFIFO_TOUT)) {
rx_fifo_len--; // leave one byte in the fifo in order to trigger uart_intr_rxfifo_tout
}
uart_hal_read_rxfifo(&(uart_context[uart_num].hal), p_uart->rx_data_buf, &rx_fifo_len);
uint8_t pat_chr = 0;
uint8_t pat_num = 0;
@ -822,6 +827,7 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param)
uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_RXFIFO_TOUT | UART_INTR_RXFIFO_FULL);
uart_event.type = UART_DATA;
uart_event.size = rx_fifo_len;
uart_event.timeout_flag = (uart_intr_status & UART_INTR_RXFIFO_TOUT) ? true : false;
UART_ENTER_CRITICAL_ISR(&uart_selectlock);
if (p_uart->uart_select_notif_callback) {
p_uart->uart_select_notif_callback(uart_num, UART_SELECT_READ_NOTIF, &HPTaskAwoken);
@ -1294,6 +1300,7 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b
p_uart_obj[uart_num]->uart_num = uart_num;
p_uart_obj[uart_num]->uart_mode = UART_MODE_UART;
p_uart_obj[uart_num]->coll_det_flg = false;
p_uart_obj[uart_num]->rx_always_timeout_flg = false;
p_uart_obj[uart_num]->tx_fifo_sem = xSemaphoreCreateBinary();
xSemaphoreGive(p_uart_obj[uart_num]->tx_fifo_sem);
p_uart_obj[uart_num]->tx_done_sem = xSemaphoreCreateBinary();
@ -1490,8 +1497,12 @@ esp_err_t uart_set_tx_empty_threshold(uart_port_t uart_num, int threshold)
esp_err_t uart_set_rx_timeout(uart_port_t uart_num, const uint8_t tout_thresh)
{
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG);
UART_CHECK((tout_thresh < 127), "tout_thresh max value is 126", ESP_ERR_INVALID_ARG);
// get maximum timeout threshold
uint16_t tout_max_thresh = uart_hal_get_max_rx_timeout_thrd(&(uart_context[uart_num].hal));
if (tout_thresh > tout_max_thresh) {
ESP_LOGE(UART_TAG, "tout_thresh = %d > maximum value = %d", tout_thresh, tout_max_thresh);
return ESP_ERR_INVALID_ARG;
}
UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock));
uart_hal_set_rx_timeout(&(uart_context[uart_num].hal), tout_thresh);
UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock));
@ -1543,3 +1554,13 @@ esp_err_t uart_set_loop_back(uart_port_t uart_num, bool loop_back_en)
uart_hal_set_loop_back(&(uart_context[uart_num].hal), loop_back_en);
return ESP_OK;
}
void uart_set_always_rx_timeout(uart_port_t uart_num, bool always_rx_timeout)
{
uint16_t rx_tout = uart_hal_get_rx_tout_thr(&(uart_context[uart_num].hal));
if (rx_tout) {
p_uart_obj[uart_num]->rx_always_timeout_flg = always_rx_timeout;
} else {
p_uart_obj[uart_num]->rx_always_timeout_flg = false;
}
}

View File

@ -103,7 +103,7 @@ void vMBPortSerialEnable(BOOL bRxEnable, BOOL bTxEnable)
}
}
static void vMBPortSerialRxPoll(size_t xEventSize)
static USHORT usMBPortSerialRxPoll(size_t xEventSize)
{
BOOL xReadStatus = TRUE;
USHORT usCnt = 0;
@ -114,17 +114,18 @@ static void vMBPortSerialRxPoll(size_t xEventSize)
// Get received packet into Rx buffer
for(usCnt = 0; xReadStatus && (usCnt < xEventSize); usCnt++ ) {
// Call the Modbus stack callback function and let it fill the buffers.
xReadStatus = pxMBFrameCBByteReceived(); // callback to execute receive FSM state machine
xReadStatus = pxMBFrameCBByteReceived(); // callback to execute receive FSM
}
uart_flush_input(ucUartNumber);
// Send event EV_FRAME_RECEIVED to allow stack process packet
#ifndef MB_TIMER_PORT_ENABLED
#if !CONFIG_FMB_TIMER_PORT_ENABLED
// Let the stack know that T3.5 time is expired and data is received
(void)pxMBPortCBTimerExpired(); // calls callback xMBRTUTimerT35Expired();
#endif
ESP_LOGD(TAG, "RX: %d bytes\n", usCnt);
}
}
return usCnt;
}
BOOL xMBPortSerialTxPoll(void)
@ -136,7 +137,7 @@ BOOL xMBPortSerialTxPoll(void)
// Continue while all response bytes put in buffer or out of buffer
while((bNeedPoll) && (usCount++ < MB_SERIAL_BUF_SIZE)) {
// Calls the modbus stack callback function to let it fill the UART transmit buffer.
bNeedPoll = pxMBFrameCBTransmitterEmpty( ); // callback to transmit FSM state machine
bNeedPoll = pxMBFrameCBTransmitterEmpty( ); // callback to transmit FSM
}
ESP_LOGD(TAG, "MB_TX_buffer send: (%d) bytes\n", (uint16_t)usCount);
// Waits while UART sending the packet
@ -151,15 +152,23 @@ BOOL xMBPortSerialTxPoll(void)
static void vUartTask(void *pvParameters)
{
uart_event_t xEvent;
USHORT usResult = 0;
for(;;) {
if (xQueueReceive(xMbUartQueue, (void*)&xEvent, portMAX_DELAY) == pdTRUE) {
ESP_LOGD(TAG, "MB_uart[%d] event:", ucUartNumber);
switch(xEvent.type) {
//Event of UART receving data
case UART_DATA:
ESP_LOGD(TAG,"Receive data, len: %d", xEvent.size);
// Read received data and send it to modbus stack
vMBPortSerialRxPoll(xEvent.size);
ESP_LOGD(TAG,"Data event, length: %d", xEvent.size);
// This flag set in the event means that no more
// data received during configured timeout and UART TOUT feature is triggered
if (xEvent.timeout_flag) {
// Get buffered data length
ESP_ERROR_CHECK(uart_get_buffered_data_len(ucUartNumber, &xEvent.size));
// Read received data and send it to modbus stack
usResult = usMBPortSerialRxPoll(xEvent.size);
ESP_LOGD(TAG,"Timeout occured, processed: %d bytes", usResult);
}
break;
//Event of HW FIFO overflow detected
case UART_FIFO_OVF:
@ -251,12 +260,14 @@ BOOL xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate,
MB_QUEUE_LENGTH, &xMbUartQueue, MB_PORT_SERIAL_ISR_FLAG);
MB_PORT_CHECK((xErr == ESP_OK), FALSE,
"mb serial driver failure, uart_driver_install() returned (0x%x).", xErr);
#ifndef MB_TIMER_PORT_ENABLED
#if !CONFIG_FMB_TIMER_PORT_ENABLED
// Set timeout for TOUT interrupt (T3.5 modbus time)
xErr = uart_set_rx_timeout(ucUartNumber, MB_SERIAL_TOUT);
MB_PORT_CHECK((xErr == ESP_OK), FALSE,
"mb serial set rx timeout failure, uart_set_rx_timeout() returned (0x%x).", xErr);
#endif
// Set always timeout flag to trigger timeout interrupt even after rx fifo full
uart_set_always_rx_timeout(ucUartNumber, true);
// Create a task to handle UART events
BaseType_t xStatus = xTaskCreate(vUartTask, "uart_queue_task", MB_SERIAL_TASK_STACK_SIZE,
NULL, MB_SERIAL_TASK_PRIO, &xMbTaskHandle);

View File

@ -96,7 +96,7 @@ void vMBMasterPortSerialEnable(BOOL bRxEnable, BOOL bTxEnable)
}
}
static void vMBMasterPortSerialRxPoll(size_t xEventSize)
static USHORT usMBMasterPortSerialRxPoll(size_t xEventSize)
{
BOOL xReadStatus = TRUE;
USHORT usCnt = 0;
@ -109,8 +109,11 @@ static void vMBMasterPortSerialRxPoll(size_t xEventSize)
uiRxBufferPos = 0;
for(usCnt = 0; xReadStatus && (usCnt < usLength); usCnt++ ) {
// Call the Modbus stack callback function and let it fill the stack buffers.
xReadStatus = pxMBMasterFrameCBByteReceived(); // callback to receive FSM state machine
xReadStatus = pxMBMasterFrameCBByteReceived(); // callback to receive FSM
}
#if !CONFIG_FMB_TIMER_PORT_ENABLED
pxMBMasterPortCBTimerExpired();
#endif
// The buffer is transferred into Modbus stack and is not needed here any more
uart_flush_input(ucUartNumber);
ESP_LOGD(TAG, "Received data: %d(bytes in buffer)\n", (uint32_t)usCnt);
@ -118,6 +121,7 @@ static void vMBMasterPortSerialRxPoll(size_t xEventSize)
} else {
ESP_LOGE(TAG, "%s: bRxState disabled but junk data (%d bytes) received. ", __func__, xEventSize);
}
return usCnt;
}
BOOL xMBMasterPortSerialTxPoll(void)
@ -145,15 +149,25 @@ BOOL xMBMasterPortSerialTxPoll(void)
static void vUartTask(void* pvParameters)
{
uart_event_t xEvent;
USHORT usResult = 0;
for(;;) {
if (xQueueReceive(xMbUartQueue, (void*)&xEvent, portMAX_DELAY) == pdTRUE) {
ESP_LOGD(TAG, "MB_uart[%d] event:", ucUartNumber);
switch(xEvent.type) {
//Event of UART receiving data
case UART_DATA:
ESP_LOGD(TAG,"Receive data, len: %d.", xEvent.size);
// Read received data and send it to modbus stack
vMBMasterPortSerialRxPoll(xEvent.size);
ESP_LOGD(TAG,"Data event, len: %d.", xEvent.size);
// This flag set in the event means that no more
// data received during configured timeout and UART TOUT feature is triggered
if (xEvent.timeout_flag) {
// Get buffered data length
ESP_ERROR_CHECK(uart_get_buffered_data_len(ucUartNumber, &xEvent.size));
// Read received data and send it to modbus stack
usResult = usMBMasterPortSerialRxPoll(xEvent.size);
ESP_LOGD(TAG,"Timeout occurred, processed: %d bytes", usResult);
// Block receiver task until data is not processed
vTaskSuspend(NULL);
}
break;
//Event of HW FIFO overflow detected
case UART_FIFO_OVF:
@ -249,6 +263,8 @@ BOOL xMBMasterPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
xErr = uart_set_rx_timeout(ucUartNumber, MB_SERIAL_TOUT);
MB_PORT_CHECK((xErr == ESP_OK), FALSE,
"mb serial set rx timeout failure, uart_set_rx_timeout() returned (0x%x).", xErr);
// Set always timeout flag to trigger timeout interrupt even after rx fifo full
uart_set_always_rx_timeout(ucUartNumber, true);
// Create a task to handle UART events
BaseType_t xStatus = xTaskCreate(vUartTask, "uart_queue_task", MB_SERIAL_TASK_STACK_SIZE,
NULL, MB_SERIAL_TASK_PRIO, &xMbTaskHandle);

View File

@ -395,31 +395,6 @@ static inline void uart_ll_set_tx_idle_num(uart_dev_t *hw, uint32_t idle_num)
hw->idle_conf.tx_idle_num = idle_num;
}
/**
* @brief Configure the timeout value for receiver receiving a byte, and enable rx timeout function.
*
* @param hw Beginning address of the peripheral registers.
* @param tout_thr The timeout value. The rx timeout function will be disabled if `tout_thr == 0`.
*
* @return None.
*/
static inline void uart_ll_set_rx_tout(uart_dev_t *hw, uint8_t tout_thr)
{
// The tout_thresh = 1, defines TOUT interrupt timeout equal to
// transmission time of one symbol (~11 bit) on current baudrate
if (hw->conf0.tick_ref_always_on == 0) {
//Hardware issue workaround: when using ref_tick, the rx timeout threshold needs increase to 10 times.
//T_ref = T_apb * APB_CLK/(REF_TICK << CLKDIV_FRAG_BIT_WIDTH)
tout_thr = tout_thr * UART_LL_TOUT_REF_FACTOR_DEFAULT;
}
if(tout_thr > 0) {
hw->conf1.rx_tout_thrhd = tout_thr;
hw->conf1.rx_tout_en = 1;
} else {
hw->conf1.rx_tout_en = 0;
}
}
/**
* @brief Configure the transmiter to send break chars.
*
@ -822,4 +797,66 @@ static inline void uart_ll_inverse_signal(uart_dev_t *hw, uint32_t inv_mask)
hw->conf0.val = conf0_reg.val;
}
/**
* @brief Configure the timeout value for receiver receiving a byte, and enable rx timeout function.
*
* @param hw Beginning address of the peripheral registers.
* @param tout_thr The timeout value as a bit time. The rx timeout function will be disabled if `tout_thr == 0`.
*
* @return None.
*/
static inline void uart_ll_set_rx_tout(uart_dev_t *hw, uint16_t tout_thr)
{
if (hw->conf0.tick_ref_always_on == 0) {
//Hardware issue workaround: when using ref_tick, the rx timeout threshold needs increase to 10 times.
//T_ref = T_apb * APB_CLK/(REF_TICK << CLKDIV_FRAG_BIT_WIDTH)
tout_thr = tout_thr * UART_LL_TOUT_REF_FACTOR_DEFAULT;
} else {
//If APB_CLK is used: counting rate is BAUD tick rate / 8
tout_thr = (tout_thr + 7) / 8;
}
if (tout_thr > 0) {
hw->conf1.rx_tout_thrhd = tout_thr;
hw->conf1.rx_tout_en = 1;
} else {
hw->conf1.rx_tout_en = 0;
}
}
/**
* @brief Get the timeout value for receiver receiving a byte.
*
* @param hw Beginning address of the peripheral registers.
*
* @return tout_thr The timeout threshold value. If timeout feature is disabled returns 0.
*/
static inline uint16_t uart_ll_get_rx_tout_thr(uart_dev_t *hw)
{
uint16_t tout_thrd = 0;
if (hw->conf1.rx_tout_en > 0) {
if (hw->conf0.tick_ref_always_on == 0) {
tout_thrd = (uint16_t)(hw->conf1.rx_tout_thrhd / UART_LL_TOUT_REF_FACTOR_DEFAULT);
} else {
tout_thrd = (uint16_t)(hw->conf1.rx_tout_thrhd << 3);
}
}
return tout_thrd;
}
/**
* @brief Get UART maximum timeout threshold.
*
* @param hw Beginning address of the peripheral registers.
*
* @return maximum timeout threshold.
*/
static inline uint16_t uart_ll_max_tout_thrd(uart_dev_t *hw)
{
uint16_t tout_thrd = 0;
if (hw->conf0.tick_ref_always_on == 0) {
tout_thrd = (uint16_t)(UART_RX_TOUT_THRHD_V / UART_LL_TOUT_REF_FACTOR_DEFAULT);
} else {
tout_thrd = (uint16_t)(UART_RX_TOUT_THRHD_V << 3);
}
return tout_thrd;
}
#undef UART_LL_TOUT_REF_FACTOR_DEFAULT

View File

@ -349,24 +349,6 @@ static inline void uart_ll_set_tx_idle_num(uart_dev_t *hw, uint32_t idle_num)
hw->idle_conf.tx_idle_num = idle_num;
}
/**
* @brief Configure the timeout value for receiver receiving a byte, and enable rx timeout function.
*
* @param hw Beginning address of the peripheral registers.
* @param tout_thr The timeout value. The rx timeout function will be disabled if `tout_thr == 0`.
*
* @return None.
*/
static inline void uart_ll_set_rx_tout(uart_dev_t *hw, uint8_t tout_thr)
{
if(tout_thr > 0) {
hw->mem_conf.rx_tout_thrhd = tout_thr;
hw->conf1.rx_tout_en = 1;
} else {
hw->conf1.rx_tout_en = 0;
}
}
/**
* @brief Configure the transmiter to send break chars.
*
@ -767,3 +749,50 @@ static inline void uart_ll_inverse_signal(uart_dev_t *hw, uint32_t inv_mask)
conf0_reg.dtr_inv |= (inv_mask & UART_SIGNAL_DTR_INV) ? 1 : 0;
hw->conf0.val = conf0_reg.val;
}
/**
* @brief Configure the timeout value for receiver receiving a byte, and enable rx timeout function.
*
* @param hw Beginning address of the peripheral registers.
* @param tout_thrd The timeout value as UART bit time. The rx timeout function will be disabled if `tout_thrd == 0`.
*
* @return None.
*/
static inline void uart_ll_set_rx_tout(uart_dev_t *hw, uint16_t tout_thrd)
{
uint16_t tout_val = tout_thrd;
if(tout_thrd > 0) {
hw->mem_conf.rx_tout_thrhd = tout_val;
hw->conf1.rx_tout_en = 1;
} else {
hw->conf1.rx_tout_en = 0;
}
}
/**
* @brief Get the timeout value for receiver receiving a byte.
*
* @param hw Beginning address of the peripheral registers.
*
* @return tout_thr The timeout threshold value. If timeout feature is disabled returns 0.
*/
static inline uint16_t uart_ll_get_rx_tout_thr(uart_dev_t *hw)
{
uint16_t tout_thrd = 0;
if(hw->conf1.rx_tout_en > 0) {
tout_thrd = hw->mem_conf.rx_tout_thrhd;
}
return tout_thrd;
}
/**
* @brief Get UART maximum timeout threshold.
*
* @param hw Beginning address of the peripheral registers.
*
* @return maximum timeout threshold.
*/
static inline uint16_t uart_ll_max_tout_thrd(uart_dev_t *hw)
{
return UART_RX_TOUT_THRHD_V;
}

View File

@ -127,13 +127,14 @@ typedef struct {
/**
* @brief Read data from the UART rxfifo
*
* @param hal Context of the HAL layer
* @param buf Pointer to the buffer used to store the read data. The buffer size should be large than 128 byts
* @param rd_len The length has been read out from the rxfifo
* @param[in] hal Context of the HAL layer
* @param[in] buf Pointer to the buffer used to store the read data. The buffer size should be large than 128 bytes
* @param[inout] inout_rd_len As input, the size of output buffer to read (set to 0 to read all available data).
* As output, returns the actual size written into the output buffer.
*
* @return None
*/
void uart_hal_read_rxfifo(uart_hal_context_t *hal, uint8_t *buf, int *rd_len);
void uart_hal_read_rxfifo(uart_hal_context_t *hal, uint8_t *buf, int *inout_rd_len);
/**
* @brief Write data into the UART txfifo
@ -430,6 +431,42 @@ void uart_hal_get_sclk(uart_hal_context_t *hal, uart_sclk_t *sclk);
*/
void uart_hal_set_loop_back(uart_hal_context_t *hal, bool loop_back_en);
/**
* @brief Calculate uart symbol bit length, as defined in configuration.
*
* @param hw Beginning address of the peripheral registers.
*
* @return number of bits per UART symbol.
*/
uint8_t uart_hal_get_symb_len(uart_hal_context_t *hal);
/**
* @brief Get UART maximum timeout threshold.
*
* @param hw Beginning address of the peripheral registers.
*
* @return maximum timeout threshold value for target.
*/
uint16_t uart_hal_get_max_rx_timeout_thrd(uart_hal_context_t *hal);
/**
* @brief Get the timeout threshold value set for receiver.
*
* @param hw Beginning address of the peripheral registers.
*
* @return tout_thr The timeout value. If timeout is disabled then returns 0.
*/
#define uart_hal_get_rx_tout_thr(hal) uart_ll_get_rx_tout_thr((hal)->dev)
/**
* @brief Get the length of readable data in UART rxfifo.
*
* @param hw Beginning address of the peripheral registers.
*
* @return The readable data length in rxfifo.
*/
#define uart_hal_get_rxfifo_len(hal) uart_ll_get_rxfifo_len((hal)->dev)
#ifdef __cplusplus
}
#endif
#endif

View File

@ -76,11 +76,6 @@ void uart_hal_set_at_cmd_char(uart_hal_context_t *hal, uart_at_cmd_t *at_cmd)
uart_ll_set_at_cmd_char(hal->dev, at_cmd);
}
void uart_hal_set_rx_timeout(uart_hal_context_t *hal, const uint8_t tout)
{
uart_ll_set_rx_tout(hal->dev, tout);
}
void uart_hal_get_sclk(uart_hal_context_t *hal, uart_sclk_t *sclk)
{
uart_ll_get_sclk(hal->dev, sclk);
@ -153,4 +148,33 @@ void uart_hal_init(uart_hal_context_t *hal, int uart_num)
uart_ll_set_tx_idle_num(hal->dev, 0);
// Disable hw-flow control
uart_ll_set_hw_flow_ctrl(hal->dev, UART_HW_FLOWCTRL_DISABLE, 100);
}
}
uint8_t uart_hal_get_symb_len(uart_hal_context_t *hal)
{
uint8_t symbol_len = 1; // number of bits per symbol including start
uart_parity_t parity_mode;
uart_stop_bits_t stop_bit;
uart_word_length_t data_bit;
uart_ll_get_data_bit_num(hal->dev, &data_bit);
uart_ll_get_stop_bits(hal->dev, &stop_bit);
uart_ll_get_parity(hal->dev, &parity_mode);
symbol_len += (data_bit < UART_DATA_BITS_MAX) ? (uint8_t)data_bit + 5 : 8;
symbol_len += (stop_bit > UART_STOP_BITS_1) ? 2 : 1;
symbol_len += (parity_mode > UART_PARITY_DISABLE) ? 1 : 0;
return symbol_len;
}
void uart_hal_set_rx_timeout(uart_hal_context_t *hal, const uint8_t tout)
{
uint8_t symb_len = uart_hal_get_symb_len(hal);
uart_ll_set_rx_tout(hal->dev, symb_len * tout);
}
uint16_t uart_hal_get_max_rx_timeout_thrd(uart_hal_context_t *hal)
{
uint8_t symb_len = uart_hal_get_symb_len(hal);
uint16_t max_tout_thresh = uart_ll_max_tout_thrd(hal->dev);
return (max_tout_thresh / symb_len);
}

View File

@ -40,9 +40,11 @@ void uart_hal_write_txfifo(uart_hal_context_t *hal, const uint8_t *buf, uint32_t
uart_ll_write_txfifo(hal->dev, buf, fill_len);
}
void uart_hal_read_rxfifo(uart_hal_context_t *hal, uint8_t *buf, int *rd_len)
void uart_hal_read_rxfifo(uart_hal_context_t *hal, uint8_t *buf, int *inout_rd_len)
{
uint16_t read_len = uart_ll_get_rxfifo_len(hal->dev);
*rd_len = read_len;
uart_ll_read_rxfifo(hal->dev, buf, read_len);
if (*inout_rd_len <= 0) {
*inout_rd_len = uart_ll_get_rxfifo_len(hal->dev);
}
uart_ll_read_rxfifo(hal->dev, buf, *inout_rd_len);
}