]> granicus.if.org Git - esp-idf/commitdiff
Convert DOS line ends to Unix line ends in drivers
authorJeroen Domburg <jeroen@espressif.com>
Thu, 15 Dec 2016 01:45:40 +0000 (09:45 +0800)
committerJeroen Domburg <jeroen@espressif.com>
Thu, 15 Dec 2016 01:45:40 +0000 (09:45 +0800)
components/driver/include/driver/uart.h
components/driver/timer.c
components/driver/uart.c

index 1d5320601e869a9c4284d1292dd14cfd84bb7209..34ca9fc4018d67c0a426ff4b113d0f860cca256b 100644 (file)
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD\r
-//\r
-// Licensed under the Apache License, Version 2.0 (the "License");\r
-// you may not use this file except in compliance with the License.\r
-// You may obtain a copy of the License at\r
-\r
-//     http://www.apache.org/licenses/LICENSE-2.0\r
-//\r
-// Unless required by applicable law or agreed to in writing, software\r
-// distributed under the License is distributed on an "AS IS" BASIS,\r
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-// See the License for the specific language governing permissions and\r
-// limitations under the License.\r
-\r
-#ifndef _DRIVER_UART_H_\r
-#define _DRIVER_UART_H_\r
-\r
-\r
-#ifdef __cplusplus\r
-extern "C" {\r
-#endif\r
-\r
-#include "soc/uart_reg.h"\r
-#include "soc/uart_struct.h"\r
-#include "esp_err.h"\r
-#include "driver/periph_ctrl.h"\r
-#include "freertos/FreeRTOS.h"\r
-#include "freertos/semphr.h"\r
-#include "freertos/xtensa_api.h"\r
-#include "freertos/task.h"\r
-#include "freertos/queue.h"\r
-#include "freertos/ringbuf.h"\r
-#include <esp_types.h>\r
-\r
-#define UART_FIFO_LEN           (128)        /*!< Length of the hardware FIFO buffers */\r
-#define UART_INTR_MASK          0x1ff        /*!< mask of all UART interrupts */\r
-#define UART_LINE_INV_MASK      (0x3f << 19) /*!< TBD */\r
-#define UART_BITRATE_MAX        5000000      /*!< Max bit rate supported by UART */\r
-#define UART_PIN_NO_CHANGE      (-1)         /*!< Constant for uart_set_pin function which indicates that UART pin should not be changed */\r
-\r
-#define UART_INVERSE_DISABLE  (0x0)            /*!< Disable UART signal inverse*/\r
-#define UART_INVERSE_RXD   (UART_RXD_INV_M)    /*!< UART RXD input inverse*/\r
-#define UART_INVERSE_CTS   (UART_CTS_INV_M)    /*!< UART CTS input inverse*/\r
-#define UART_INVERSE_TXD   (UART_TXD_INV_M)    /*!< UART TXD output inverse*/\r
-#define UART_INVERSE_RTS   (UART_RTS_INV_M)    /*!< UART RTS output inverse*/\r
-\r
-/**\r
- * @brief UART word length constants\r
- */\r
-typedef enum {\r
-    UART_DATA_5_BITS = 0x0,    /*!< word length: 5bits*/\r
-    UART_DATA_6_BITS = 0x1,    /*!< word length: 6bits*/\r
-    UART_DATA_7_BITS = 0x2,    /*!< word length: 7bits*/\r
-    UART_DATA_8_BITS = 0x3,    /*!< word length: 8bits*/\r
-    UART_DATA_BITS_MAX = 0X4,\r
-} uart_word_length_t;\r
-\r
-/**\r
- * @brief UART stop bits number\r
- */\r
-typedef enum {\r
-    UART_STOP_BITS_1   = 0x1,  /*!< stop bit: 1bit*/\r
-    UART_STOP_BITS_1_5 = 0x2,  /*!< stop bit: 1.5bits*/\r
-    UART_STOP_BITS_2   = 0x3,  /*!< stop bit: 2bits*/\r
-    UART_STOP_BITS_MAX = 0x4,\r
-} uart_stop_bits_t;\r
-\r
-/**\r
- * @brief UART peripheral number\r
- */\r
-typedef enum {\r
-    UART_NUM_0 = 0x0,  /*!< UART base address 0x3ff40000*/\r
-    UART_NUM_1 = 0x1,  /*!< UART base address 0x3ff50000*/\r
-    UART_NUM_2 = 0x2,  /*!< UART base address 0x3ff6E000*/\r
-    UART_NUM_MAX,\r
-} uart_port_t;\r
-\r
-/**\r
- * @brief UART parity constants\r
- */\r
-typedef enum {\r
-    UART_PARITY_DISABLE = 0x0,   /*!< Disable UART parity*/\r
-    UART_PARITY_EVEN = 0x2,     /*!< Enable UART even parity*/\r
-    UART_PARITY_ODD  = 0x3      /*!< Enable UART odd parity*/\r
-} uart_parity_t;\r
-\r
-/**\r
- * @brief UART hardware flow control modes\r
- */\r
-typedef enum {\r
-    UART_HW_FLOWCTRL_DISABLE = 0x0,   /*!< disable hardware flow control*/\r
-    UART_HW_FLOWCTRL_RTS     = 0x1,   /*!< enable RX hardware flow control (rts)*/\r
-    UART_HW_FLOWCTRL_CTS     = 0x2,   /*!< enable TX hardware flow control (cts)*/\r
-    UART_HW_FLOWCTRL_CTS_RTS = 0x3,   /*!< enable hardware flow control*/\r
-    UART_HW_FLOWCTRL_MAX     = 0x4,\r
-} uart_hw_flowcontrol_t;\r
-\r
-/**\r
- * @brief UART configuration parameters for uart_param_config function\r
- */\r
-typedef struct {\r
-    int baud_rate;                      /*!< UART baudrate*/\r
-    uart_word_length_t data_bits;       /*!< UART byte size*/\r
-    uart_parity_t parity;               /*!< UART parity mode*/\r
-    uart_stop_bits_t stop_bits;         /*!< UART stop bits*/\r
-    uart_hw_flowcontrol_t flow_ctrl;    /*!< UART HW flow control mode(cts/rts)*/\r
-    uint8_t rx_flow_ctrl_thresh ;       /*!< UART HW RTS threshold*/\r
-} uart_config_t;\r
-\r
-/**\r
- * @brief UART interrupt configuration parameters for uart_intr_config function\r
- */\r
-typedef struct {\r
-    uint32_t intr_enable_mask;          /*!< UART interrupt enable mask, choose from UART_XXXX_INT_ENA_M under UART_INT_ENA_REG(i), connect with bit-or operator*/\r
-    uint8_t  rx_timeout_thresh;         /*!< UART timeout interrupt threshold(unit: time of sending one byte)*/\r
-    uint8_t  txfifo_empty_intr_thresh;  /*!< UART TX empty interrupt threshold.*/\r
-    uint8_t  rxfifo_full_thresh;        /*!< UART RX full interrupt threshold.*/\r
-} uart_intr_config_t;\r
-\r
-/**\r
- * @brief UART event types used in the ringbuffer\r
- */\r
-typedef enum {\r
-    UART_DATA,              /*!< UART data event*/\r
-    UART_BREAK,             /*!< UART break event*/\r
-    UART_BUFFER_FULL,       /*!< UART RX buffer full event*/\r
-    UART_FIFO_OVF,          /*!< UART FIFO overflow event*/\r
-    UART_FRAME_ERR,         /*!< UART RX frame error event*/\r
-    UART_PARITY_ERR,        /*!< UART RX parity event*/\r
-    UART_DATA_BREAK,        /*!< UART TX data and break event*/\r
-    UART_EVENT_MAX,         /*!< UART event max index*/\r
-} uart_event_type_t;\r
-\r
-/**\r
- * @brief Event structure used in UART event queue\r
- */\r
-typedef struct {\r
-    uart_event_type_t type; /*!< UART event type */\r
-    size_t size;            /*!< UART data size for UART_DATA event*/\r
-} uart_event_t;\r
-\r
-/**\r
- * @brief Set UART data bits.\r
- *\r
- * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- * @param data_bit UART data bits\r
- *\r
- * @return\r
- *     - ESP_OK   Success\r
- *     - ESP_FAIL Parameter error\r
- */\r
-esp_err_t uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit);\r
-\r
-/**\r
- * @brief Get UART data bits.\r
- *\r
- * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- * @param data_bit Pointer to accept value of UART data bits.\r
- *\r
- * @return\r
- *     - ESP_FAIL  Parameter error\r
- *     - ESP_OK    Success, result will be put in (*data_bit)\r
- */\r
-esp_err_t uart_get_word_length(uart_port_t uart_num, uart_word_length_t* data_bit);\r
-\r
-/**\r
- * @brief Set UART stop bits.\r
- *\r
- * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- * @param stop_bits  UART stop bits\r
- *\r
- * @return\r
- *     - ESP_OK   Success\r
- *     - ESP_FAIL Fail\r
- */\r
-esp_err_t uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t stop_bits);\r
-\r
-/**\r
- * @brief Set UART stop bits.\r
- *\r
- * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- * @param stop_bits  Pointer to accept value of UART stop bits.\r
- *\r
- * @return\r
- *     - ESP_FAIL Parameter error\r
- *     - ESP_OK   Success, result will be put in (*stop_bit)\r
- */\r
-esp_err_t uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t* stop_bits);\r
-\r
-/**\r
- * @brief Set UART parity.\r
- *\r
- * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- * @param parity_mode the enum of uart parity configuration\r
- *\r
- * @return\r
- *     - ESP_FAIL  Parameter error\r
- *     - ESP_OK    Success\r
- */\r
-esp_err_t uart_set_parity(uart_port_t uart_num, uart_parity_t parity_mode);\r
-\r
-/**\r
- * @brief Get UART parity mode.\r
- *\r
- * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- * @param parity_mode Pointer to accept value of UART parity mode.\r
- *\r
- * @return\r
- *     - ESP_FAIL  Parameter error\r
- *     - ESP_OK    Success, result will be put in (*parity_mode)\r
- *\r
- */\r
-esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t* parity_mode);\r
-\r
-/**\r
- * @brief Set UART baud rate.\r
- *\r
- * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- * @param baudrate UART baud rate.\r
- *\r
- * @return\r
- *     - ESP_FAIL Parameter error\r
- *     - ESP_OK   Success\r
- */\r
-esp_err_t uart_set_baudrate(uart_port_t uart_num, uint32_t baudrate);\r
-\r
-/**\r
- * @brief Get UART bit-rate.\r
- *\r
- * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- * @param baudrate Pointer to accept value of UART baud rate\r
- *\r
- * @return\r
- *     - ESP_FAIL Parameter error\r
- *     - ESP_OK   Success, result will be put in (*baudrate)\r
- *\r
- */\r
-esp_err_t uart_get_baudrate(uart_port_t uart_num, uint32_t* baudrate);\r
-\r
-/**\r
- * @brief Set UART line inverse mode\r
- *\r
- * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- * @param inverse_mask Choose the wires that need to be inverted.\r
- *        Inverse_mask should be chosen from UART_INVERSE_RXD/UART_INVERSE_TXD/UART_INVERSE_RTS/UART_INVERSE_CTS, combine with OR operation.\r
- *\r
- * @return\r
- *     - ESP_OK   Success\r
- *     - ESP_FAIL Parameter error\r
- */\r
-esp_err_t uart_set_line_inverse(uart_port_t uart_num, uint32_t inverse_mask);\r
-\r
-/**\r
- * @brief Set hardware flow control.\r
- *\r
- * @param uart_num   UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- * @param flow_ctrl Hardware flow control mode\r
- * @param rx_thresh Threshold of Hardware RX flow control(0 ~ UART_FIFO_LEN).\r
- *          Only when UART_HW_FLOWCTRL_RTS is set, will the rx_thresh value be set.\r
- *\r
- * @return\r
- *     - ESP_OK   Success\r
- *     - ESP_FAIL Parameter error\r
- */\r
-esp_err_t uart_set_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t flow_ctrl, uint8_t rx_thresh);\r
-\r
-/**\r
- * @brief Get hardware flow control mode\r
- *\r
- * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- * @param flow_ctrl Option for different flow control mode.\r
- *\r
- * @return\r
- *     - ESP_FAIL Parameter error\r
- *     - ESP_OK   Success, result will be put in (*flow_ctrl)\r
- */\r
-esp_err_t uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t* flow_ctrl);\r
-\r
-/**\r
- * @brief Clear UART interrupt status\r
- *\r
- * @param uart_num   UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- * @param clr_mask  Bit mask of the status that to be cleared.\r
- *                  enable_mask should be chosen from the fields of register UART_INT_CLR_REG.\r
- *\r
- * @return\r
- *     - ESP_OK   Success\r
- *     - ESP_FAIL Parameter error\r
- */\r
-esp_err_t uart_clear_intr_status(uart_port_t uart_num, uint32_t clr_mask);\r
-\r
-/**\r
- * @brief Set UART interrupt enable\r
- *\r
- * @param uart_num      UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- * @param enable_mask  Bit mask of the enable bits.\r
- *                     enable_mask should be chosen from the fields of register UART_INT_ENA_REG.\r
- *\r
- * @return\r
- *     - ESP_OK   Success\r
- *     - ESP_FAIL Parameter error\r
- */\r
-esp_err_t uart_enable_intr_mask(uart_port_t uart_num, uint32_t enable_mask);\r
-\r
-/**\r
- * @brief Clear UART interrupt enable bits\r
- *\r
- * @param uart_num       UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- * @param disable_mask  Bit mask of the disable bits.\r
- *                      disable_mask should be chosen from the fields of register UART_INT_ENA_REG.\r
- *\r
- * @return\r
- *     - ESP_OK   Success\r
- *     - ESP_FAIL Parameter error\r
- */\r
-esp_err_t uart_disable_intr_mask(uart_port_t uart_num, uint32_t disable_mask);\r
-\r
-\r
-/**\r
- * @brief Enable UART RX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT)\r
- *\r
- * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- *\r
- * @return\r
- *     - ESP_OK   Success\r
- *     - ESP_FAIL Parameter error\r
- */\r
-esp_err_t uart_enable_rx_intr(uart_port_t uart_num);\r
-\r
-/**\r
- * @brief Disable UART RX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT)\r
- *\r
- * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- *\r
- * @return\r
- *     - ESP_OK   Success\r
- *     - ESP_FAIL Parameter error\r
- */\r
-esp_err_t uart_disable_rx_intr(uart_port_t uart_num);\r
-\r
-/**\r
- * @brief Disable UART TX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT)\r
- *\r
- * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- *\r
- * @return\r
- *     - ESP_OK   Success\r
- *     - ESP_FAIL Parameter error\r
- */\r
-esp_err_t uart_disable_tx_intr(uart_port_t uart_num);\r
-\r
-/**\r
- * @brief Enable UART TX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT)\r
- *\r
- * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- * @param enable  1: enable; 0: disable\r
- * @param thresh  Threshold of TX interrupt, 0 ~ UART_FIFO_LEN\r
- *\r
- * @return\r
- *     - ESP_OK   Success\r
- *     - ESP_FAIL Parameter error\r
- */\r
-esp_err_t uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh);\r
-\r
-/**\r
- * @brief register UART interrupt handler(ISR).\r
- *\r
- * @note UART ISR handler will be attached to the same CPU core that this function is running on.\r
- *\r
- * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- * @param fn  Interrupt handler function.\r
- * @param arg parameter for handler function\r
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef _DRIVER_UART_H_
+#define _DRIVER_UART_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "soc/uart_reg.h"
+#include "soc/uart_struct.h"
+#include "esp_err.h"
+#include "driver/periph_ctrl.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/semphr.h"
+#include "freertos/xtensa_api.h"
+#include "freertos/task.h"
+#include "freertos/queue.h"
+#include "freertos/ringbuf.h"
+#include <esp_types.h>
+
+#define UART_FIFO_LEN           (128)        /*!< Length of the hardware FIFO buffers */
+#define UART_INTR_MASK          0x1ff        /*!< mask of all UART interrupts */
+#define UART_LINE_INV_MASK      (0x3f << 19) /*!< TBD */
+#define UART_BITRATE_MAX        5000000      /*!< Max bit rate supported by UART */
+#define UART_PIN_NO_CHANGE      (-1)         /*!< Constant for uart_set_pin function which indicates that UART pin should not be changed */
+
+#define UART_INVERSE_DISABLE  (0x0)            /*!< Disable UART signal inverse*/
+#define UART_INVERSE_RXD   (UART_RXD_INV_M)    /*!< UART RXD input inverse*/
+#define UART_INVERSE_CTS   (UART_CTS_INV_M)    /*!< UART CTS input inverse*/
+#define UART_INVERSE_TXD   (UART_TXD_INV_M)    /*!< UART TXD output inverse*/
+#define UART_INVERSE_RTS   (UART_RTS_INV_M)    /*!< UART RTS output inverse*/
+
+/**
+ * @brief UART word length constants
+ */
+typedef enum {
+    UART_DATA_5_BITS = 0x0,    /*!< word length: 5bits*/
+    UART_DATA_6_BITS = 0x1,    /*!< word length: 6bits*/
+    UART_DATA_7_BITS = 0x2,    /*!< word length: 7bits*/
+    UART_DATA_8_BITS = 0x3,    /*!< word length: 8bits*/
+    UART_DATA_BITS_MAX = 0X4,
+} uart_word_length_t;
+
+/**
+ * @brief UART stop bits number
+ */
+typedef enum {
+    UART_STOP_BITS_1   = 0x1,  /*!< stop bit: 1bit*/
+    UART_STOP_BITS_1_5 = 0x2,  /*!< stop bit: 1.5bits*/
+    UART_STOP_BITS_2   = 0x3,  /*!< stop bit: 2bits*/
+    UART_STOP_BITS_MAX = 0x4,
+} uart_stop_bits_t;
+
+/**
+ * @brief UART peripheral number
+ */
+typedef enum {
+    UART_NUM_0 = 0x0,  /*!< UART base address 0x3ff40000*/
+    UART_NUM_1 = 0x1,  /*!< UART base address 0x3ff50000*/
+    UART_NUM_2 = 0x2,  /*!< UART base address 0x3ff6E000*/
+    UART_NUM_MAX,
+} uart_port_t;
+
+/**
+ * @brief UART parity constants
+ */
+typedef enum {
+    UART_PARITY_DISABLE = 0x0,   /*!< Disable UART parity*/
+    UART_PARITY_EVEN = 0x2,     /*!< Enable UART even parity*/
+    UART_PARITY_ODD  = 0x3      /*!< Enable UART odd parity*/
+} uart_parity_t;
+
+/**
+ * @brief UART hardware flow control modes
+ */
+typedef enum {
+    UART_HW_FLOWCTRL_DISABLE = 0x0,   /*!< disable hardware flow control*/
+    UART_HW_FLOWCTRL_RTS     = 0x1,   /*!< enable RX hardware flow control (rts)*/
+    UART_HW_FLOWCTRL_CTS     = 0x2,   /*!< enable TX hardware flow control (cts)*/
+    UART_HW_FLOWCTRL_CTS_RTS = 0x3,   /*!< enable hardware flow control*/
+    UART_HW_FLOWCTRL_MAX     = 0x4,
+} uart_hw_flowcontrol_t;
+
+/**
+ * @brief UART configuration parameters for uart_param_config function
+ */
+typedef struct {
+    int baud_rate;                      /*!< UART baudrate*/
+    uart_word_length_t data_bits;       /*!< UART byte size*/
+    uart_parity_t parity;               /*!< UART parity mode*/
+    uart_stop_bits_t stop_bits;         /*!< UART stop bits*/
+    uart_hw_flowcontrol_t flow_ctrl;    /*!< UART HW flow control mode(cts/rts)*/
+    uint8_t rx_flow_ctrl_thresh ;       /*!< UART HW RTS threshold*/
+} uart_config_t;
+
+/**
+ * @brief UART interrupt configuration parameters for uart_intr_config function
+ */
+typedef struct {
+    uint32_t intr_enable_mask;          /*!< UART interrupt enable mask, choose from UART_XXXX_INT_ENA_M under UART_INT_ENA_REG(i), connect with bit-or operator*/
+    uint8_t  rx_timeout_thresh;         /*!< UART timeout interrupt threshold(unit: time of sending one byte)*/
+    uint8_t  txfifo_empty_intr_thresh;  /*!< UART TX empty interrupt threshold.*/
+    uint8_t  rxfifo_full_thresh;        /*!< UART RX full interrupt threshold.*/
+} uart_intr_config_t;
+
+/**
+ * @brief UART event types used in the ringbuffer
+ */
+typedef enum {
+    UART_DATA,              /*!< UART data event*/
+    UART_BREAK,             /*!< UART break event*/
+    UART_BUFFER_FULL,       /*!< UART RX buffer full event*/
+    UART_FIFO_OVF,          /*!< UART FIFO overflow event*/
+    UART_FRAME_ERR,         /*!< UART RX frame error event*/
+    UART_PARITY_ERR,        /*!< UART RX parity event*/
+    UART_DATA_BREAK,        /*!< UART TX data and break event*/
+    UART_EVENT_MAX,         /*!< UART event max index*/
+} uart_event_type_t;
+
+/**
+ * @brief Event structure used in UART event queue
+ */
+typedef struct {
+    uart_event_type_t type; /*!< UART event type */
+    size_t size;            /*!< UART data size for UART_DATA event*/
+} uart_event_t;
+
+/**
+ * @brief Set UART data bits.
+ *
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param data_bit UART data bits
+ *
+ * @return
+ *     - ESP_OK   Success
+ *     - ESP_FAIL Parameter error
+ */
+esp_err_t uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit);
+
+/**
+ * @brief Get UART data bits.
+ *
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param data_bit Pointer to accept value of UART data bits.
+ *
+ * @return
+ *     - ESP_FAIL  Parameter error
+ *     - ESP_OK    Success, result will be put in (*data_bit)
+ */
+esp_err_t uart_get_word_length(uart_port_t uart_num, uart_word_length_t* data_bit);
+
+/**
+ * @brief Set UART stop bits.
+ *
+ * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param stop_bits  UART stop bits
+ *
+ * @return
+ *     - ESP_OK   Success
+ *     - ESP_FAIL Fail
+ */
+esp_err_t uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t stop_bits);
+
+/**
+ * @brief Set UART stop bits.
+ *
+ * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param stop_bits  Pointer to accept value of UART stop bits.
+ *
+ * @return
+ *     - ESP_FAIL Parameter error
+ *     - ESP_OK   Success, result will be put in (*stop_bit)
+ */
+esp_err_t uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t* stop_bits);
+
+/**
+ * @brief Set UART parity.
+ *
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param parity_mode the enum of uart parity configuration
+ *
+ * @return
+ *     - ESP_FAIL  Parameter error
+ *     - ESP_OK    Success
+ */
+esp_err_t uart_set_parity(uart_port_t uart_num, uart_parity_t parity_mode);
+
+/**
+ * @brief Get UART parity mode.
+ *
+ * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param parity_mode Pointer to accept value of UART parity mode.
+ *
+ * @return
+ *     - ESP_FAIL  Parameter error
+ *     - ESP_OK    Success, result will be put in (*parity_mode)
+ *
+ */
+esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t* parity_mode);
+
+/**
+ * @brief Set UART baud rate.
+ *
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param baudrate UART baud rate.
+ *
+ * @return
+ *     - ESP_FAIL Parameter error
+ *     - ESP_OK   Success
+ */
+esp_err_t uart_set_baudrate(uart_port_t uart_num, uint32_t baudrate);
+
+/**
+ * @brief Get UART bit-rate.
+ *
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param baudrate Pointer to accept value of UART baud rate
+ *
+ * @return
+ *     - ESP_FAIL Parameter error
+ *     - ESP_OK   Success, result will be put in (*baudrate)
+ *
+ */
+esp_err_t uart_get_baudrate(uart_port_t uart_num, uint32_t* baudrate);
+
+/**
+ * @brief Set UART line inverse mode
+ *
+ * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param inverse_mask Choose the wires that need to be inverted.
+ *        Inverse_mask should be chosen from UART_INVERSE_RXD/UART_INVERSE_TXD/UART_INVERSE_RTS/UART_INVERSE_CTS, combine with OR operation.
+ *
+ * @return
+ *     - ESP_OK   Success
+ *     - ESP_FAIL Parameter error
+ */
+esp_err_t uart_set_line_inverse(uart_port_t uart_num, uint32_t inverse_mask);
+
+/**
+ * @brief Set hardware flow control.
+ *
+ * @param uart_num   UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param flow_ctrl Hardware flow control mode
+ * @param rx_thresh Threshold of Hardware RX flow control(0 ~ UART_FIFO_LEN).
+ *          Only when UART_HW_FLOWCTRL_RTS is set, will the rx_thresh value be set.
+ *
+ * @return
+ *     - ESP_OK   Success
+ *     - ESP_FAIL Parameter error
+ */
+esp_err_t uart_set_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t flow_ctrl, uint8_t rx_thresh);
+
+/**
+ * @brief Get hardware flow control mode
+ *
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param flow_ctrl Option for different flow control mode.
+ *
+ * @return
+ *     - ESP_FAIL Parameter error
+ *     - ESP_OK   Success, result will be put in (*flow_ctrl)
+ */
+esp_err_t uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t* flow_ctrl);
+
+/**
+ * @brief Clear UART interrupt status
+ *
+ * @param uart_num   UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param clr_mask  Bit mask of the status that to be cleared.
+ *                  enable_mask should be chosen from the fields of register UART_INT_CLR_REG.
+ *
+ * @return
+ *     - ESP_OK   Success
+ *     - ESP_FAIL Parameter error
+ */
+esp_err_t uart_clear_intr_status(uart_port_t uart_num, uint32_t clr_mask);
+
+/**
+ * @brief Set UART interrupt enable
+ *
+ * @param uart_num      UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param enable_mask  Bit mask of the enable bits.
+ *                     enable_mask should be chosen from the fields of register UART_INT_ENA_REG.
+ *
+ * @return
+ *     - ESP_OK   Success
+ *     - ESP_FAIL Parameter error
+ */
+esp_err_t uart_enable_intr_mask(uart_port_t uart_num, uint32_t enable_mask);
+
+/**
+ * @brief Clear UART interrupt enable bits
+ *
+ * @param uart_num       UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param disable_mask  Bit mask of the disable bits.
+ *                      disable_mask should be chosen from the fields of register UART_INT_ENA_REG.
+ *
+ * @return
+ *     - ESP_OK   Success
+ *     - ESP_FAIL Parameter error
+ */
+esp_err_t uart_disable_intr_mask(uart_port_t uart_num, uint32_t disable_mask);
+
+
+/**
+ * @brief Enable UART RX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT)
+ *
+ * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ *
+ * @return
+ *     - ESP_OK   Success
+ *     - ESP_FAIL Parameter error
+ */
+esp_err_t uart_enable_rx_intr(uart_port_t uart_num);
+
+/**
+ * @brief Disable UART RX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT)
+ *
+ * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ *
+ * @return
+ *     - ESP_OK   Success
+ *     - ESP_FAIL Parameter error
+ */
+esp_err_t uart_disable_rx_intr(uart_port_t uart_num);
+
+/**
+ * @brief Disable UART TX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT)
+ *
+ * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ *
+ * @return
+ *     - ESP_OK   Success
+ *     - ESP_FAIL Parameter error
+ */
+esp_err_t uart_disable_tx_intr(uart_port_t uart_num);
+
+/**
+ * @brief Enable UART TX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT)
+ *
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param enable  1: enable; 0: disable
+ * @param thresh  Threshold of TX interrupt, 0 ~ UART_FIFO_LEN
+ *
+ * @return
+ *     - ESP_OK   Success
+ *     - ESP_FAIL Parameter error
+ */
+esp_err_t uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh);
+
+/**
+ * @brief register UART interrupt handler(ISR).
+ *
+ * @note UART ISR handler will be attached to the same CPU core that this function is running on.
+ *
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param fn  Interrupt handler function.
+ * @param arg parameter for handler function
  * @param  intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
- *            ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info. \r
- *\r
- * @return\r
- *     - ESP_OK   Success\r
- *     - ESP_FAIL Parameter error\r
- */\r
-esp_err_t uart_isr_register(uart_port_t uart_num, void (*fn)(void*), void * arg, int intr_alloc_flags);\r
-\r
-
-/**\r
- * @brief Free UART interrupt handler registered by uart_isr_register. Must be called on the same core as\r
- * uart_isr_register was called.\r
- *\r
- * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- *\r
- * @return\r
- *     - ESP_OK   Success\r
- *     - ESP_FAIL Parameter error\r
- */\r
+ *            ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info. 
+ *
+ * @return
+ *     - ESP_OK   Success
+ *     - ESP_FAIL Parameter error
+ */
+esp_err_t uart_isr_register(uart_port_t uart_num, void (*fn)(void*), void * arg, int intr_alloc_flags);
+
+
+/**
+ * @brief Free UART interrupt handler registered by uart_isr_register. Must be called on the same core as
+ * uart_isr_register was called.
+ *
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ *
+ * @return
+ *     - ESP_OK   Success
+ *     - ESP_FAIL Parameter error
+ */
 esp_err_t uart_isr_free(uart_port_t uart_num);
-\r
-/**\r
- * @brief Set UART pin number\r
- *\r
- * @note Internal signal can be output to multiple GPIO pads.\r
- * Only one GPIO pad can connect with input signal.\r
- *\r
- * @param uart_num    UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- * @param tx_io_num  UART TX pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin.\r
- * @param rx_io_num  UART RX pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin.\r
- * @param rts_io_num UART RTS pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin.\r
- * @param cts_io_num UART CTS pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin.\r
- *\r
- * @return\r
- *     - ESP_OK   Success\r
- *     - ESP_FAIL Parameter error\r
- */\r
-esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num);\r
-\r
-/**\r
- * @brief UART set RTS level (before inverse)\r
- *          UART rx hardware flow control should not be set.\r
- *\r
- * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- * @param level   1: RTS output low(active); 0: RTS output high(block)\r
- *\r
- * @return\r
- *     - ESP_OK   Success\r
- *     - ESP_FAIL Parameter error\r
- */\r
-esp_err_t uart_set_rts(uart_port_t uart_num, int level);\r
-\r
-/**\r
- * @brief UART set DTR level (before inverse)\r
- *\r
- * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- * @param level    1: DTR output low; 0: DTR output high\r
- *\r
- * @return\r
- *     - ESP_OK   Success\r
- *     - ESP_FAIL Parameter error\r
- */\r
-esp_err_t uart_set_dtr(uart_port_t uart_num, int level);\r
-\r
-/**\r
-* @brief UART parameter configure\r
- *\r
- * @param uart_num     UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- * @param uart_config UART parameter settings\r
- *\r
- * @return\r
- *     - ESP_OK   Success\r
- *     - ESP_FAIL Parameter error\r
- */\r
-esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_config);\r
-\r
-/**\r
-* @brief UART interrupt configure\r
- *\r
- * @param uart_num     UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- * @param intr_conf UART interrupt settings\r
- *\r
- * @return\r
- *     - ESP_OK   Success\r
- *     - ESP_FAIL Parameter error\r
- */\r
-esp_err_t uart_intr_config(uart_port_t uart_num, const uart_intr_config_t *intr_conf);\r
-\r
-/**\r
- * @brief Install UART driver.\r
- *\r
- * UART ISR handler will be attached to the same CPU core that this function is running on.\r
- * Users should know that which CPU is running and then pick a INUM that is not used by system.\r
- * We can find the information of INUM and interrupt level in soc.h.\r
- *\r
- * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- * @param rx_buffer_size UART RX ring buffer size\r
- * @param tx_buffer_size UART TX ring buffer size.\r
- *        If set to zero, driver will not use TX buffer, TX function will block task until all data have been sent out..\r
- * @param queue_size UART event queue size/depth.\r
- * @param uart_queue UART event queue handle, if set NULL, driver will not use an event queue.\r
+
+/**
+ * @brief Set UART pin number
+ *
+ * @note Internal signal can be output to multiple GPIO pads.
+ * Only one GPIO pad can connect with input signal.
+ *
+ * @param uart_num    UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param tx_io_num  UART TX pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin.
+ * @param rx_io_num  UART RX pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin.
+ * @param rts_io_num UART RTS pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin.
+ * @param cts_io_num UART CTS pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin.
+ *
+ * @return
+ *     - ESP_OK   Success
+ *     - ESP_FAIL Parameter error
+ */
+esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num);
+
+/**
+ * @brief UART set RTS level (before inverse)
+ *          UART rx hardware flow control should not be set.
+ *
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param level   1: RTS output low(active); 0: RTS output high(block)
+ *
+ * @return
+ *     - ESP_OK   Success
+ *     - ESP_FAIL Parameter error
+ */
+esp_err_t uart_set_rts(uart_port_t uart_num, int level);
+
+/**
+ * @brief UART set DTR level (before inverse)
+ *
+ * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param level    1: DTR output low; 0: DTR output high
+ *
+ * @return
+ *     - ESP_OK   Success
+ *     - ESP_FAIL Parameter error
+ */
+esp_err_t uart_set_dtr(uart_port_t uart_num, int level);
+
+/**
+* @brief UART parameter configure
+ *
+ * @param uart_num     UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param uart_config UART parameter settings
+ *
+ * @return
+ *     - ESP_OK   Success
+ *     - ESP_FAIL Parameter error
+ */
+esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_config);
+
+/**
+* @brief UART interrupt configure
+ *
+ * @param uart_num     UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param intr_conf UART interrupt settings
+ *
+ * @return
+ *     - ESP_OK   Success
+ *     - ESP_FAIL Parameter error
+ */
+esp_err_t uart_intr_config(uart_port_t uart_num, const uart_intr_config_t *intr_conf);
+
+/**
+ * @brief Install UART driver.
+ *
+ * UART ISR handler will be attached to the same CPU core that this function is running on.
+ * Users should know that which CPU is running and then pick a INUM that is not used by system.
+ * We can find the information of INUM and interrupt level in soc.h.
+ *
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param rx_buffer_size UART RX ring buffer size
+ * @param tx_buffer_size UART TX ring buffer size.
+ *        If set to zero, driver will not use TX buffer, TX function will block task until all data have been sent out..
+ * @param queue_size UART event queue size/depth.
+ * @param uart_queue UART event queue handle, if set NULL, driver will not use an event queue.
  * @param  intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
  *            ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
- *\r
- * @return\r
- *     - ESP_OK   Success\r
- *     - ESP_FAIL Parameter error\r
- */\r
-esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, void* uart_queue, int intr_alloc_flags);\r
-\r
-/**\r
- * @brief Uninstall UART driver.\r
- *\r
- * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- *\r
- * @return\r
- *     - ESP_OK   Success\r
- *     - ESP_FAIL Parameter error\r
- */\r
-esp_err_t uart_driver_delete(uart_port_t uart_num);\r
-\r
-/**\r
- * @brief Wait UART TX FIFO empty\r
- *\r
- * @param uart_num       UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- * @param ticks_to_wait Timeout, count in RTOS ticks\r
- *\r
- * @return\r
- *     - ESP_OK   Success\r
- *     - ESP_FAIL Parameter error\r
- *     - ESP_ERR_TIMEOUT  Timeout\r
- */\r
-esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait);\r
-\r
-/**\r
- * @brief Send data to the UART port from a given buffer and length.\r
- * \r
- * This function will not wait for the space in TX FIFO, just fill the TX FIFO and return when the FIFO is full.\r
- * @note This function should only be used when UART TX buffer is not enabled.\r
- *\r
- * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- * @param buffer data buffer address\r
- * @param len    data length to send\r
- *\r
- * @return\r
- *     - (-1)  Parameter error\r
- *     - OTHERS(>=0)  The number of data that pushed to the TX FIFO\r
- */\r
-int uart_tx_chars(uart_port_t uart_num, const char* buffer, uint32_t len);\r
-\r
-/**\r
- * @brief Send data to the UART port from a given buffer and length,\r
- *\r
- * If parameter tx_buffer_size is set to zero:\r
- * This function will not return until all the data have been sent out, or at least pushed into TX FIFO.\r
- *\r
- * Otherwise, if tx_buffer_size > 0, this function will return after copying all the data to tx ringbuffer,\r
- * then, UART ISR will move data from ring buffer to TX FIFO gradually.\r
- *\r
- * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- * @param src   data buffer address\r
- * @param size  data length to send\r
- *\r
- * @return\r
- *     - (-1) Parameter error\r
- *     - OTHERS(>=0)  The number of data that pushed to the TX FIFO\r
- */\r
-int uart_write_bytes(uart_port_t uart_num, const char* src, size_t size);\r
-\r
-/**\r
- * @brief Send data to the UART port from a given buffer and length,\r
- *\r
- * If parameter tx_buffer_size is set to zero:\r
- * This function will not return until all the data and the break signal have been sent out.\r
- * After all data send out, send a break signal.\r
- *\r
- * Otherwise, if tx_buffer_size > 0, this function will return after copying all the data to tx ringbuffer,\r
- * then, UART ISR will move data from ring buffer to TX FIFO gradually.\r
- * After all data send out, send a break signal.\r
- *\r
- * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- * @param src   data buffer address\r
- * @param size  data length to send\r
- * @param brk_len break signal length (unit: time of one data bit at current_baudrate)\r
- *\r
- * @return\r
- *     - (-1) Parameter error\r
- *     - OTHERS(>=0) The number of data that pushed to the TX FIFO\r
- */\r
-\r
-int uart_write_bytes_with_break(uart_port_t uart_num, const char* src, size_t size, int brk_len);\r
-\r
-/**\r
- * @brief UART read bytes from UART buffer\r
- *\r
- * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- * @param buf     pointer to the buffer.\r
- * @param length  data length\r
- * @param ticks_to_wait sTimeout, count in RTOS ticks\r
- *\r
- * @return\r
- *     - (-1) Error\r
- *     - Others return a char data from uart fifo.\r
- */\r
-int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickType_t ticks_to_wait);\r
-\r
-/**\r
- * @brief UART ring buffer flush\r
- *\r
- * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2\r
- *\r
- * @return\r
- *     - ESP_OK Success\r
- *     - ESP_FAIL Parameter error\r
- */\r
-esp_err_t uart_flush(uart_port_t uart_num);\r
-\r
-/***************************EXAMPLE**********************************\r
- *\r
- *\r
- * ----------------EXAMPLE OF UART SETTING ---------------------\r
- * @code{c}\r
- * //1. Setup UART\r
- * #include "freertos/queue.h"\r
- * #define UART_INTR_NUM 17                                //choose one interrupt number from soc.h\r
- * //a. Set UART parameter\r
- * int uart_num = 0;                                       //uart port number\r
- * uart_config_t uart_config = {\r
- *    .baud_rate = UART_BITRATE_115200,                    //baudrate\r
- *    .data_bits = UART_DATA_8_BITS,                       //data bit mode\r
- *    .parity = UART_PARITY_DISABLE,                       //parity mode\r
- *    .stop_bits = UART_STOP_BITS_1,                       //stop bit mode\r
- *    .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,               //hardware flow control(cts/rts)\r
- *    .rx_flow_ctrl_thresh = 120,                          //flow control threshold\r
- * };\r
- * uart_param_config(uart_num, &uart_config);\r
- * //b1. Setup UART driver(with UART queue)\r
- * QueueHandle_t uart_queue;\r
- * //parameters here are just an example, tx buffer size is 2048\r
- * uart_driver_install(uart_num, 1024 * 2, 1024 * 2, 10, &uart_queue, 0);\r
- * //b2. Setup UART driver(without UART queue)\r
- * //parameters here are just an example, tx buffer size is 0\r
- * uart_driver_install(uart_num, 1024 * 2, 0, 10, NULL, 0);\r
- *@endcode\r
- *-----------------------------------------------------------------------------*\r
- * @code{c}\r
- * //2. Set UART pin\r
- * //set UART pin, not needed if use default pins.\r
- * uart_set_pin(uart_num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, 15, 13);\r
- * @endcode\r
- *-----------------------------------------------------------------------------*\r
- * @code{c}\r
- * //3. Read data from UART.\r
- * uint8_t data[128];\r
- * int length = 0;\r
- * length = uart_read_bytes(uart_num, data, sizeof(data), 100);\r
- * @endcode\r
- *-----------------------------------------------------------------------------*\r
- * @code{c}\r
- * //4. Write data to UART.\r
- * char* test_str = "This is a test string.\n"\r
- * uart_write_bytes(uart_num, (const char*)test_str, strlen(test_str));\r
- * @endcode\r
- *-----------------------------------------------------------------------------*\r
- * @code{c}\r
- * //5. Write data to UART, end with a break signal.\r
- * uart_write_bytes_with_break(0, "test break\n",strlen("test break\n"), 100);\r
- * @endcode\r
- *-----------------------------------------------------------------------------*\r
- * @code{c}\r
- * //6. an example of echo test with hardware flow control on UART1\r
- * void uart_loop_back_test()\r
- * {\r
- *     int uart_num = 1;\r
- *     uart_config_t uart_config = {\r
- *         .baud_rate = 115200,\r
- *         .data_bits = UART_DATA_8_BITS,\r
- *         .parity = UART_PARITY_DISABLE,\r
- *         .stop_bits = UART_STOP_BITS_1,\r
- *         .flow_ctrl = UART_HW_FLOWCTRL_CTS_RTS,\r
- *         .rx_flow_ctrl_thresh = 122,\r
- *     };\r
- *     //Configure UART1 parameters\r
- *     uart_param_config(uart_num, &uart_config);\r
- *     //Set UART1 pins(TX: IO16, RX: IO17, RTS: IO18, CTS: IO19)\r
- *     uart_set_pin(uart_num, 16, 17, 18, 19);\r
- *     //Install UART driver( We don't need an event queue here)\r
- *     uart_driver_install(uart_num, 1024 * 2, 1024*4, 10, 17, NULL, RINGBUF_TYPE_BYTEBUF);\r
- *     uint8_t data[1000];\r
- *     while(1) {\r
- *         //Read data from UART\r
- *         int len = uart_read_bytes(uart_num, data, sizeof(data), 10);\r
- *         //Write data back to UART\r
- *         uart_write_bytes(uart_num, (const char*)data, len);\r
- *     }\r
- * }\r
- * @endcode\r
- *-----------------------------------------------------------------------------*\r
- * @code{c}\r
- * //7. An example of using UART event queue on UART0.\r
- * #include "freertos/queue.h"\r
- * //A queue to handle UART event.\r
- * QueueHandle_t uart0_queue;\r
- * static const char *TAG = "uart_example";\r
- * void uart_task(void *pvParameters)\r
- * {\r
- *     int uart_num = (int)pvParameters;\r
- *     uart_event_t event;\r
- *     size_t size = 1024;\r
- *     uint8_t* dtmp = (uint8_t*)malloc(size);\r
- *     for(;;) {\r
- *         //Waiting for UART event.\r
- *         if(xQueueReceive(uart0_queue, (void * )&event, (portTickType)portMAX_DELAY)) {\r
- *             ESP_LOGI(TAG, "uart[%d] event:", uart_num);\r
- *             switch(event.type) {\r
- *                 memset(dtmp, 0, size);\r
- *                 //Event of UART receving data\r
- *                 case UART_DATA:\r
- *                     ESP_LOGI(TAG,"data, len: %d", event.size);\r
- *                     int len = uart_read_bytes(uart_num, dtmp, event.size, 10);\r
- *                     ESP_LOGI(TAG, "uart read: %d", len);\r
-                       uart_write_bytes(uart_num, (const char*)dtmp, len);\r
- *                     break;\r
- *                 //Event of HW FIFO overflow detected\r
- *                 case UART_FIFO_OVF:\r
- *                     ESP_LOGI(TAG, "hw fifo overflow\n");\r
- *                     break;\r
- *                 //Event of UART ring buffer full\r
- *                 case UART_BUFFER_FULL:\r
- *                     ESP_LOGI(TAG, "ring buffer full\n");\r
- *                     break;\r
- *                 //Event of UART RX break detected\r
- *                 case UART_BREAK:\r
- *                     ESP_LOGI(TAG, "uart rx break\n");\r
- *                     break;\r
- *                 //Event of UART parity check error\r
- *                 case UART_PARITY_ERR:\r
- *                     ESP_LOGI(TAG, "uart parity error\n");\r
- *                     break;\r
- *                 //Event of UART frame error\r
- *                 case UART_FRAME_ERR:\r
- *                     ESP_LOGI(TAG, "uart frame error\n");\r
- *                     break;\r
- *                 //Others\r
- *                 default:\r
- *                     ESP_LOGI(TAG, "uart event type: %d\n", event.type);\r
- *                     break;\r
- *             }\r
- *        }\r
- *     }\r
- *     free(dtmp);\r
- *     dtmp = NULL;\r
- *     vTaskDelete(NULL);\r
- * }\r
- *\r
- * void uart_queue_test()\r
- * {\r
- *     int uart_num = 0;\r
- *     uart_config_t uart_config = {\r
- *        .baud_rate = 115200,\r
- *        .data_bits = UART_DATA_8_BITS,\r
- *        .parity = UART_PARITY_DISABLE,\r
- *        .stop_bits = UART_STOP_BITS_1,\r
- *        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,\r
- *        .rx_flow_ctrl_thresh = 122,\r
- *     };\r
- *     //Set UART parameters\r
- *     uart_param_config(uart_num, &uart_config);\r
- *     //Set UART pins,(-1: default pin, no change.)\r
- *     uart_set_pin(uart_num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);\r
- *     //Set UART log level\r
- *     esp_log_level_set(TAG, ESP_LOG_INFO);\r
- *     //Install UART driver, and get the queue.\r
- *     uart_driver_install(uart_num, 1024 * 2, 1024*4, 10, &uart0_queue, 0);\r
- *     //Create a task to handler UART event from ISR\r
- *     xTaskCreate(uart_task, "uTask", 1024, (void*)uart_num, 10, NULL);\r
- * }\r
- * @endcode\r
- *\r
- ***************************END OF EXAMPLE**********************************/\r
-\r
-#ifdef __cplusplus\r
-}\r
-#endif\r
-\r
-#endif /*_DRIVER_UART_H_*/\r
+ *
+ * @return
+ *     - ESP_OK   Success
+ *     - ESP_FAIL Parameter error
+ */
+esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, void* uart_queue, int intr_alloc_flags);
+
+/**
+ * @brief Uninstall UART driver.
+ *
+ * @param uart_num  UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ *
+ * @return
+ *     - ESP_OK   Success
+ *     - ESP_FAIL Parameter error
+ */
+esp_err_t uart_driver_delete(uart_port_t uart_num);
+
+/**
+ * @brief Wait UART TX FIFO empty
+ *
+ * @param uart_num       UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param ticks_to_wait Timeout, count in RTOS ticks
+ *
+ * @return
+ *     - ESP_OK   Success
+ *     - ESP_FAIL Parameter error
+ *     - ESP_ERR_TIMEOUT  Timeout
+ */
+esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait);
+
+/**
+ * @brief Send data to the UART port from a given buffer and length.
+ * 
+ * This function will not wait for the space in TX FIFO, just fill the TX FIFO and return when the FIFO is full.
+ * @note This function should only be used when UART TX buffer is not enabled.
+ *
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param buffer data buffer address
+ * @param len    data length to send
+ *
+ * @return
+ *     - (-1)  Parameter error
+ *     - OTHERS(>=0)  The number of data that pushed to the TX FIFO
+ */
+int uart_tx_chars(uart_port_t uart_num, const char* buffer, uint32_t len);
+
+/**
+ * @brief Send data to the UART port from a given buffer and length,
+ *
+ * If parameter tx_buffer_size is set to zero:
+ * This function will not return until all the data have been sent out, or at least pushed into TX FIFO.
+ *
+ * Otherwise, if tx_buffer_size > 0, this function will return after copying all the data to tx ringbuffer,
+ * then, UART ISR will move data from ring buffer to TX FIFO gradually.
+ *
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param src   data buffer address
+ * @param size  data length to send
+ *
+ * @return
+ *     - (-1) Parameter error
+ *     - OTHERS(>=0)  The number of data that pushed to the TX FIFO
+ */
+int uart_write_bytes(uart_port_t uart_num, const char* src, size_t size);
+
+/**
+ * @brief Send data to the UART port from a given buffer and length,
+ *
+ * If parameter tx_buffer_size is set to zero:
+ * This function will not return until all the data and the break signal have been sent out.
+ * After all data send out, send a break signal.
+ *
+ * Otherwise, if tx_buffer_size > 0, this function will return after copying all the data to tx ringbuffer,
+ * then, UART ISR will move data from ring buffer to TX FIFO gradually.
+ * After all data send out, send a break signal.
+ *
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param src   data buffer address
+ * @param size  data length to send
+ * @param brk_len break signal length (unit: time of one data bit at current_baudrate)
+ *
+ * @return
+ *     - (-1) Parameter error
+ *     - OTHERS(>=0) The number of data that pushed to the TX FIFO
+ */
+
+int uart_write_bytes_with_break(uart_port_t uart_num, const char* src, size_t size, int brk_len);
+
+/**
+ * @brief UART read bytes from UART buffer
+ *
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param buf     pointer to the buffer.
+ * @param length  data length
+ * @param ticks_to_wait sTimeout, count in RTOS ticks
+ *
+ * @return
+ *     - (-1) Error
+ *     - Others return a char data from uart fifo.
+ */
+int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickType_t ticks_to_wait);
+
+/**
+ * @brief UART ring buffer flush
+ *
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ *
+ * @return
+ *     - ESP_OK Success
+ *     - ESP_FAIL Parameter error
+ */
+esp_err_t uart_flush(uart_port_t uart_num);
+
+/***************************EXAMPLE**********************************
+ *
+ *
+ * ----------------EXAMPLE OF UART SETTING ---------------------
+ * @code{c}
+ * //1. Setup UART
+ * #include "freertos/queue.h"
+ * #define UART_INTR_NUM 17                                //choose one interrupt number from soc.h
+ * //a. Set UART parameter
+ * int uart_num = 0;                                       //uart port number
+ * uart_config_t uart_config = {
+ *    .baud_rate = UART_BITRATE_115200,                    //baudrate
+ *    .data_bits = UART_DATA_8_BITS,                       //data bit mode
+ *    .parity = UART_PARITY_DISABLE,                       //parity mode
+ *    .stop_bits = UART_STOP_BITS_1,                       //stop bit mode
+ *    .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,               //hardware flow control(cts/rts)
+ *    .rx_flow_ctrl_thresh = 120,                          //flow control threshold
+ * };
+ * uart_param_config(uart_num, &uart_config);
+ * //b1. Setup UART driver(with UART queue)
+ * QueueHandle_t uart_queue;
+ * //parameters here are just an example, tx buffer size is 2048
+ * uart_driver_install(uart_num, 1024 * 2, 1024 * 2, 10, &uart_queue, 0);
+ * //b2. Setup UART driver(without UART queue)
+ * //parameters here are just an example, tx buffer size is 0
+ * uart_driver_install(uart_num, 1024 * 2, 0, 10, NULL, 0);
+ *@endcode
+ *-----------------------------------------------------------------------------*
+ * @code{c}
+ * //2. Set UART pin
+ * //set UART pin, not needed if use default pins.
+ * uart_set_pin(uart_num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, 15, 13);
+ * @endcode
+ *-----------------------------------------------------------------------------*
+ * @code{c}
+ * //3. Read data from UART.
+ * uint8_t data[128];
+ * int length = 0;
+ * length = uart_read_bytes(uart_num, data, sizeof(data), 100);
+ * @endcode
+ *-----------------------------------------------------------------------------*
+ * @code{c}
+ * //4. Write data to UART.
+ * char* test_str = "This is a test string.\n"
+ * uart_write_bytes(uart_num, (const char*)test_str, strlen(test_str));
+ * @endcode
+ *-----------------------------------------------------------------------------*
+ * @code{c}
+ * //5. Write data to UART, end with a break signal.
+ * uart_write_bytes_with_break(0, "test break\n",strlen("test break\n"), 100);
+ * @endcode
+ *-----------------------------------------------------------------------------*
+ * @code{c}
+ * //6. an example of echo test with hardware flow control on UART1
+ * void uart_loop_back_test()
+ * {
+ *     int uart_num = 1;
+ *     uart_config_t uart_config = {
+ *         .baud_rate = 115200,
+ *         .data_bits = UART_DATA_8_BITS,
+ *         .parity = UART_PARITY_DISABLE,
+ *         .stop_bits = UART_STOP_BITS_1,
+ *         .flow_ctrl = UART_HW_FLOWCTRL_CTS_RTS,
+ *         .rx_flow_ctrl_thresh = 122,
+ *     };
+ *     //Configure UART1 parameters
+ *     uart_param_config(uart_num, &uart_config);
+ *     //Set UART1 pins(TX: IO16, RX: IO17, RTS: IO18, CTS: IO19)
+ *     uart_set_pin(uart_num, 16, 17, 18, 19);
+ *     //Install UART driver( We don't need an event queue here)
+ *     uart_driver_install(uart_num, 1024 * 2, 1024*4, 10, 17, NULL, RINGBUF_TYPE_BYTEBUF);
+ *     uint8_t data[1000];
+ *     while(1) {
+ *         //Read data from UART
+ *         int len = uart_read_bytes(uart_num, data, sizeof(data), 10);
+ *         //Write data back to UART
+ *         uart_write_bytes(uart_num, (const char*)data, len);
+ *     }
+ * }
+ * @endcode
+ *-----------------------------------------------------------------------------*
+ * @code{c}
+ * //7. An example of using UART event queue on UART0.
+ * #include "freertos/queue.h"
+ * //A queue to handle UART event.
+ * QueueHandle_t uart0_queue;
+ * static const char *TAG = "uart_example";
+ * void uart_task(void *pvParameters)
+ * {
+ *     int uart_num = (int)pvParameters;
+ *     uart_event_t event;
+ *     size_t size = 1024;
+ *     uint8_t* dtmp = (uint8_t*)malloc(size);
+ *     for(;;) {
+ *         //Waiting for UART event.
+ *         if(xQueueReceive(uart0_queue, (void * )&event, (portTickType)portMAX_DELAY)) {
+ *             ESP_LOGI(TAG, "uart[%d] event:", uart_num);
+ *             switch(event.type) {
+ *                 memset(dtmp, 0, size);
+ *                 //Event of UART receving data
+ *                 case UART_DATA:
+ *                     ESP_LOGI(TAG,"data, len: %d", event.size);
+ *                     int len = uart_read_bytes(uart_num, dtmp, event.size, 10);
+ *                     ESP_LOGI(TAG, "uart read: %d", len);
+                       uart_write_bytes(uart_num, (const char*)dtmp, len);
+ *                     break;
+ *                 //Event of HW FIFO overflow detected
+ *                 case UART_FIFO_OVF:
+ *                     ESP_LOGI(TAG, "hw fifo overflow\n");
+ *                     break;
+ *                 //Event of UART ring buffer full
+ *                 case UART_BUFFER_FULL:
+ *                     ESP_LOGI(TAG, "ring buffer full\n");
+ *                     break;
+ *                 //Event of UART RX break detected
+ *                 case UART_BREAK:
+ *                     ESP_LOGI(TAG, "uart rx break\n");
+ *                     break;
+ *                 //Event of UART parity check error
+ *                 case UART_PARITY_ERR:
+ *                     ESP_LOGI(TAG, "uart parity error\n");
+ *                     break;
+ *                 //Event of UART frame error
+ *                 case UART_FRAME_ERR:
+ *                     ESP_LOGI(TAG, "uart frame error\n");
+ *                     break;
+ *                 //Others
+ *                 default:
+ *                     ESP_LOGI(TAG, "uart event type: %d\n", event.type);
+ *                     break;
+ *             }
+ *        }
+ *     }
+ *     free(dtmp);
+ *     dtmp = NULL;
+ *     vTaskDelete(NULL);
+ * }
+ *
+ * void uart_queue_test()
+ * {
+ *     int uart_num = 0;
+ *     uart_config_t uart_config = {
+ *        .baud_rate = 115200,
+ *        .data_bits = UART_DATA_8_BITS,
+ *        .parity = UART_PARITY_DISABLE,
+ *        .stop_bits = UART_STOP_BITS_1,
+ *        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
+ *        .rx_flow_ctrl_thresh = 122,
+ *     };
+ *     //Set UART parameters
+ *     uart_param_config(uart_num, &uart_config);
+ *     //Set UART pins,(-1: default pin, no change.)
+ *     uart_set_pin(uart_num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
+ *     //Set UART log level
+ *     esp_log_level_set(TAG, ESP_LOG_INFO);
+ *     //Install UART driver, and get the queue.
+ *     uart_driver_install(uart_num, 1024 * 2, 1024*4, 10, &uart0_queue, 0);
+ *     //Create a task to handler UART event from ISR
+ *     xTaskCreate(uart_task, "uTask", 1024, (void*)uart_num, 10, NULL);
+ * }
+ * @endcode
+ *
+ ***************************END OF EXAMPLE**********************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*_DRIVER_UART_H_*/
index a8dacf0a040a825df7c78a65870201dfcdfa01cd..de968c5e2a8d966a61bd40e2f3c2299504b7b9e9 100644 (file)
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD\r
-//\r
-// Licensed under the Apache License, Version 2.0 (the "License");\r
-// you may not use this file except in compliance with the License.\r
-// You may obtain a copy of the License at\r
-\r
-//     http://www.apache.org/licenses/LICENSE-2.0\r
-//\r
-// Unless required by applicable law or agreed to in writing, software\r
-// distributed under the License is distributed on an "AS IS" BASIS,\r
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-// See the License for the specific language governing permissions and\r
-// limitations under the License.\r
-#include <string.h>\r
-#include "esp_log.h"\r
-#include "esp_err.h"\r
-#include "esp_intr.h"\r
-#include "esp_intr_alloc.h"\r
-#include "freertos/FreeRTOS.h"\r
-#include "freertos/xtensa_api.h"\r
-#include "driver/timer.h"\r
-#include "driver/periph_ctrl.h"\r
-\r
-static const char* TIMER_TAG = "timer_group";\r
-#define TIMER_CHECK(a, str, ret_val) \\r
-    if (!(a)) { \\r
-        ESP_LOGE(TIMER_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \\r
-        return (ret_val); \\r
-    }\r
-\r
-#define TIMER_GROUP_NUM_ERROR   "TIMER GROUP NUM ERROR"\r
-#define TIMER_NUM_ERROR         "HW TIMER NUM ERROR"\r
-#define TIMER_PARAM_ADDR_ERROR  "HW TIMER PARAM ADDR ERROR"\r
-#define TIMER_COUNT_DIR_ERROR   "HW TIMER COUNTER DIR ERROR"\r
-#define TIMER_AUTORELOAD_ERROR  "HW TIMER AUTORELOAD ERROR"\r
-#define TIMER_SCALE_ERROR       "HW TIMER SCALE ERROR"\r
-#define TIMER_ALARM_ERROR       "HW TIMER ALARM ERROR"\r
-static timg_dev_t *TG[2] = {&TIMERG0, &TIMERG1};\r
-static portMUX_TYPE timer_spinlock[TIMER_GROUP_MAX] = {portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED};\r
-\r
-#define TIMER_ENTER_CRITICAL(mux)      portENTER_CRITICAL(mux);\r
-#define TIMER_EXIT_CRITICAL(mux)       portEXIT_CRITICAL(mux);\r
-\r
-esp_err_t timer_get_counter_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t* timer_val)\r
-{\r
-    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_CHECK(timer_val != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG);\r
-    portENTER_CRITICAL(&timer_spinlock[group_num]);\r
-    TG[group_num]->hw_timer[timer_num].update = 1;\r
-    *timer_val = ((uint64_t) TG[group_num]->hw_timer[timer_num].cnt_high << 32)\r
-        | (TG[group_num]->hw_timer[timer_num].cnt_low);\r
-    portEXIT_CRITICAL(&timer_spinlock[group_num]);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t timer_get_counter_time_sec(timer_group_t group_num, timer_idx_t timer_num, double* time)\r
-{\r
-    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_CHECK(time != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG);\r
-\r
-    uint64_t timer_val;\r
-    esp_err_t err = timer_get_counter_value(group_num, timer_num, &timer_val);\r
-    if (err == ESP_OK) {\r
-        uint16_t div = TG[group_num]->hw_timer[timer_num].config.divider;\r
-        *time = (double)timer_val * div / TIMER_BASE_CLK;\r
-    }\r
-    return err;\r
-}\r
-\r
-esp_err_t timer_set_counter_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t load_val)\r
-{\r
-    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);\r
-    TG[group_num]->hw_timer[timer_num].load_high = (uint32_t) (load_val >> 32);\r
-    TG[group_num]->hw_timer[timer_num].load_low = (uint32_t) load_val;\r
-    TG[group_num]->hw_timer[timer_num].reload = 1;\r
-    TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t timer_start(timer_group_t group_num, timer_idx_t timer_num)\r
-{\r
-    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);\r
-    TG[group_num]->hw_timer[timer_num].config.enable = 1;\r
-    TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t timer_pause(timer_group_t group_num, timer_idx_t timer_num)\r
-{\r
-    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);\r
-    TG[group_num]->hw_timer[timer_num].config.enable = 0;\r
-    TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t timer_set_counter_mode(timer_group_t group_num, timer_idx_t timer_num, timer_count_dir_t counter_dir)\r
-{\r
-    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_CHECK(counter_dir < TIMER_COUNT_MAX, TIMER_COUNT_DIR_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);\r
-    TG[group_num]->hw_timer[timer_num].config.increase = counter_dir;\r
-    TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t timer_set_auto_reload(timer_group_t group_num, timer_idx_t timer_num, timer_autoreload_t reload)\r
-{\r
-    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_CHECK(reload < TIMER_AUTORELOAD_MAX, TIMER_AUTORELOAD_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);\r
-    TG[group_num]->hw_timer[timer_num].config.autoreload = reload;\r
-    TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t timer_set_divider(timer_group_t group_num, timer_idx_t timer_num, uint16_t divider)\r
-{\r
-    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);\r
-    int timer_en = TG[group_num]->hw_timer[timer_num].config.enable;\r
-    TG[group_num]->hw_timer[timer_num].config.enable = 0;\r
-    TG[group_num]->hw_timer[timer_num].config.divider = divider;\r
-    TG[group_num]->hw_timer[timer_num].config.enable = timer_en;\r
-    TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t timer_set_alarm_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t alarm_value)\r
-{\r
-    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);\r
-    TG[group_num]->hw_timer[timer_num].alarm_high = (uint32_t) (alarm_value >> 32);\r
-    TG[group_num]->hw_timer[timer_num].alarm_low = (uint32_t) alarm_value;\r
-    TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t timer_get_alarm_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t* alarm_value)\r
-{\r
-    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_CHECK(alarm_value != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG);\r
-    portENTER_CRITICAL(&timer_spinlock[group_num]);\r
-    *alarm_value = ((uint64_t) TG[group_num]->hw_timer[timer_num].alarm_high << 32)\r
-                | (TG[group_num]->hw_timer[timer_num].alarm_low);\r
-    portEXIT_CRITICAL(&timer_spinlock[group_num]);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t timer_set_alarm(timer_group_t group_num, timer_idx_t timer_num, timer_alarm_t alarm_en)\r
-{\r
-    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_CHECK(alarm_en < TIMER_ALARM_MAX, TIMER_ALARM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);\r
-    TG[group_num]->hw_timer[timer_num].config.alarm_en = alarm_en;\r
-    TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num, \r
-    void (*fn)(void*), void * arg, int intr_alloc_flags, timer_isr_handle_t *handle)\r
-{\r
-    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_CHECK(fn != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG);\r
-\r
-    int intr_source = 0;\r
-    uint32_t status_reg = 0;\r
-    int mask = 0;\r
-    switch(group_num) {\r
-        case TIMER_GROUP_0:\r
-        default:\r
-            if((intr_alloc_flags & ESP_INTR_FLAG_EDGE) == 0) {\r
-                intr_source = ETS_TG0_T0_LEVEL_INTR_SOURCE + timer_num;\r
-            } else {\r
-                intr_source = ETS_TG0_T0_EDGE_INTR_SOURCE + timer_num;\r
-            }\r
-            status_reg = TIMG_INT_ST_TIMERS_REG(0);\r
-            mask = 1<<timer_num;\r
-            break;\r
-        case TIMER_GROUP_1:\r
-            if((intr_alloc_flags & ESP_INTR_FLAG_EDGE) == 0) {\r
-                intr_source = ETS_TG1_T0_LEVEL_INTR_SOURCE + timer_num;\r
-            } else {\r
-                intr_source = ETS_TG1_T0_EDGE_INTR_SOURCE + timer_num;\r
-            }\r
-            status_reg = TIMG_INT_ST_TIMERS_REG(1);\r
-            mask = 1<<timer_num;\r
-            break;\r
-    }\r
-    return esp_intr_alloc_intrstatus(intr_source, intr_alloc_flags, status_reg, mask, fn, arg, handle);\r
-}\r
-\r
-esp_err_t timer_init(timer_group_t group_num, timer_idx_t timer_num, timer_config_t *config)\r
-{\r
-    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_CHECK(config != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG);\r
-\r
-    if(group_num == 0) {\r
-        periph_module_enable(PERIPH_TIMG0_MODULE);\r
-    } else if(group_num == 1) {\r
-        periph_module_enable(PERIPH_TIMG1_MODULE);\r
-    }\r
-    TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);\r
-    TG[group_num]->hw_timer[timer_num].config.autoreload = config->auto_reload;\r
-    TG[group_num]->hw_timer[timer_num].config.divider = config->divider;\r
-    TG[group_num]->hw_timer[timer_num].config.enable = config->counter_en;\r
-    TG[group_num]->hw_timer[timer_num].config.increase = config->counter_dir;\r
-    TG[group_num]->hw_timer[timer_num].config.alarm_en = config->alarm_en;\r
-    TG[group_num]->hw_timer[timer_num].config.level_int_en = (config->intr_type == TIMER_INTR_LEVEL ? 1 : 0);\r
-    TG[group_num]->hw_timer[timer_num].config.edge_int_en = (config->intr_type == TIMER_INTR_LEVEL ? 0 : 1);\r
-    TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t timer_get_config(timer_group_t group_num, timer_idx_t timer_num, timer_config_t *config)\r
-{\r
-    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_CHECK(config != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);\r
-    config->alarm_en = TG[group_num]->hw_timer[timer_num].config.alarm_en;\r
-    config->auto_reload = TG[group_num]->hw_timer[timer_num].config.autoreload;\r
-    config->counter_dir = TG[group_num]->hw_timer[timer_num].config.increase;\r
-    config->counter_dir = TG[group_num]->hw_timer[timer_num].config.divider;\r
-    config->counter_en = TG[group_num]->hw_timer[timer_num].config.enable;\r
-    if(TG[group_num]->hw_timer[timer_num].config.level_int_en) {\r
-        config->intr_type =TIMER_INTR_LEVEL;\r
-    }\r
-    TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t timer_group_intr_enable(timer_group_t group_num, uint32_t en_mask)\r
-{\r
-    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    portENTER_CRITICAL(&timer_spinlock[group_num]);\r
-    TG[group_num]->int_ena.val |= en_mask;\r
-    portEXIT_CRITICAL(&timer_spinlock[group_num]);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t timer_group_intr_disable(timer_group_t group_num, uint32_t disable_mask)\r
-{\r
-    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    portENTER_CRITICAL(&timer_spinlock[group_num]);\r
-    TG[group_num]->int_ena.val &= (~disable_mask);\r
-    portEXIT_CRITICAL(&timer_spinlock[group_num]);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t timer_enable_intr(timer_group_t group_num, timer_idx_t timer_num)\r
-{\r
-    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    return timer_group_intr_enable(group_num, BIT(timer_num));\r
-}\r
-\r
-esp_err_t timer_disable_intr(timer_group_t group_num, timer_idx_t timer_num)\r
-{\r
-    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);\r
-    return timer_group_intr_disable(group_num, BIT(timer_num));\r
-}\r
-\r
-\r
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include <string.h>
+#include "esp_log.h"
+#include "esp_err.h"
+#include "esp_intr.h"
+#include "esp_intr_alloc.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/xtensa_api.h"
+#include "driver/timer.h"
+#include "driver/periph_ctrl.h"
+
+static const char* TIMER_TAG = "timer_group";
+#define TIMER_CHECK(a, str, ret_val) \
+    if (!(a)) { \
+        ESP_LOGE(TIMER_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \
+        return (ret_val); \
+    }
+
+#define TIMER_GROUP_NUM_ERROR   "TIMER GROUP NUM ERROR"
+#define TIMER_NUM_ERROR         "HW TIMER NUM ERROR"
+#define TIMER_PARAM_ADDR_ERROR  "HW TIMER PARAM ADDR ERROR"
+#define TIMER_COUNT_DIR_ERROR   "HW TIMER COUNTER DIR ERROR"
+#define TIMER_AUTORELOAD_ERROR  "HW TIMER AUTORELOAD ERROR"
+#define TIMER_SCALE_ERROR       "HW TIMER SCALE ERROR"
+#define TIMER_ALARM_ERROR       "HW TIMER ALARM ERROR"
+static timg_dev_t *TG[2] = {&TIMERG0, &TIMERG1};
+static portMUX_TYPE timer_spinlock[TIMER_GROUP_MAX] = {portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED};
+
+#define TIMER_ENTER_CRITICAL(mux)      portENTER_CRITICAL(mux);
+#define TIMER_EXIT_CRITICAL(mux)       portEXIT_CRITICAL(mux);
+
+esp_err_t timer_get_counter_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t* timer_val)
+{
+    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_CHECK(timer_val != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG);
+    portENTER_CRITICAL(&timer_spinlock[group_num]);
+    TG[group_num]->hw_timer[timer_num].update = 1;
+    *timer_val = ((uint64_t) TG[group_num]->hw_timer[timer_num].cnt_high << 32)
+        | (TG[group_num]->hw_timer[timer_num].cnt_low);
+    portEXIT_CRITICAL(&timer_spinlock[group_num]);
+    return ESP_OK;
+}
+
+esp_err_t timer_get_counter_time_sec(timer_group_t group_num, timer_idx_t timer_num, double* time)
+{
+    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_CHECK(time != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG);
+
+    uint64_t timer_val;
+    esp_err_t err = timer_get_counter_value(group_num, timer_num, &timer_val);
+    if (err == ESP_OK) {
+        uint16_t div = TG[group_num]->hw_timer[timer_num].config.divider;
+        *time = (double)timer_val * div / TIMER_BASE_CLK;
+    }
+    return err;
+}
+
+esp_err_t timer_set_counter_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t load_val)
+{
+    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
+    TG[group_num]->hw_timer[timer_num].load_high = (uint32_t) (load_val >> 32);
+    TG[group_num]->hw_timer[timer_num].load_low = (uint32_t) load_val;
+    TG[group_num]->hw_timer[timer_num].reload = 1;
+    TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
+    return ESP_OK;
+}
+
+esp_err_t timer_start(timer_group_t group_num, timer_idx_t timer_num)
+{
+    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
+    TG[group_num]->hw_timer[timer_num].config.enable = 1;
+    TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
+    return ESP_OK;
+}
+
+esp_err_t timer_pause(timer_group_t group_num, timer_idx_t timer_num)
+{
+    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
+    TG[group_num]->hw_timer[timer_num].config.enable = 0;
+    TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
+    return ESP_OK;
+}
+
+esp_err_t timer_set_counter_mode(timer_group_t group_num, timer_idx_t timer_num, timer_count_dir_t counter_dir)
+{
+    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_CHECK(counter_dir < TIMER_COUNT_MAX, TIMER_COUNT_DIR_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
+    TG[group_num]->hw_timer[timer_num].config.increase = counter_dir;
+    TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
+    return ESP_OK;
+}
+
+esp_err_t timer_set_auto_reload(timer_group_t group_num, timer_idx_t timer_num, timer_autoreload_t reload)
+{
+    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_CHECK(reload < TIMER_AUTORELOAD_MAX, TIMER_AUTORELOAD_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
+    TG[group_num]->hw_timer[timer_num].config.autoreload = reload;
+    TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
+    return ESP_OK;
+}
+
+esp_err_t timer_set_divider(timer_group_t group_num, timer_idx_t timer_num, uint16_t divider)
+{
+    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
+    int timer_en = TG[group_num]->hw_timer[timer_num].config.enable;
+    TG[group_num]->hw_timer[timer_num].config.enable = 0;
+    TG[group_num]->hw_timer[timer_num].config.divider = divider;
+    TG[group_num]->hw_timer[timer_num].config.enable = timer_en;
+    TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
+    return ESP_OK;
+}
+
+esp_err_t timer_set_alarm_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t alarm_value)
+{
+    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
+    TG[group_num]->hw_timer[timer_num].alarm_high = (uint32_t) (alarm_value >> 32);
+    TG[group_num]->hw_timer[timer_num].alarm_low = (uint32_t) alarm_value;
+    TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
+    return ESP_OK;
+}
+
+esp_err_t timer_get_alarm_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t* alarm_value)
+{
+    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_CHECK(alarm_value != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG);
+    portENTER_CRITICAL(&timer_spinlock[group_num]);
+    *alarm_value = ((uint64_t) TG[group_num]->hw_timer[timer_num].alarm_high << 32)
+                | (TG[group_num]->hw_timer[timer_num].alarm_low);
+    portEXIT_CRITICAL(&timer_spinlock[group_num]);
+    return ESP_OK;
+}
+
+esp_err_t timer_set_alarm(timer_group_t group_num, timer_idx_t timer_num, timer_alarm_t alarm_en)
+{
+    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_CHECK(alarm_en < TIMER_ALARM_MAX, TIMER_ALARM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
+    TG[group_num]->hw_timer[timer_num].config.alarm_en = alarm_en;
+    TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
+    return ESP_OK;
+}
+
+esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num, 
+    void (*fn)(void*), void * arg, int intr_alloc_flags, timer_isr_handle_t *handle)
+{
+    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_CHECK(fn != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG);
+
+    int intr_source = 0;
+    uint32_t status_reg = 0;
+    int mask = 0;
+    switch(group_num) {
+        case TIMER_GROUP_0:
+        default:
+            if((intr_alloc_flags & ESP_INTR_FLAG_EDGE) == 0) {
+                intr_source = ETS_TG0_T0_LEVEL_INTR_SOURCE + timer_num;
+            } else {
+                intr_source = ETS_TG0_T0_EDGE_INTR_SOURCE + timer_num;
+            }
+            status_reg = TIMG_INT_ST_TIMERS_REG(0);
+            mask = 1<<timer_num;
+            break;
+        case TIMER_GROUP_1:
+            if((intr_alloc_flags & ESP_INTR_FLAG_EDGE) == 0) {
+                intr_source = ETS_TG1_T0_LEVEL_INTR_SOURCE + timer_num;
+            } else {
+                intr_source = ETS_TG1_T0_EDGE_INTR_SOURCE + timer_num;
+            }
+            status_reg = TIMG_INT_ST_TIMERS_REG(1);
+            mask = 1<<timer_num;
+            break;
+    }
+    return esp_intr_alloc_intrstatus(intr_source, intr_alloc_flags, status_reg, mask, fn, arg, handle);
+}
+
+esp_err_t timer_init(timer_group_t group_num, timer_idx_t timer_num, timer_config_t *config)
+{
+    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_CHECK(config != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG);
+
+    if(group_num == 0) {
+        periph_module_enable(PERIPH_TIMG0_MODULE);
+    } else if(group_num == 1) {
+        periph_module_enable(PERIPH_TIMG1_MODULE);
+    }
+    TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
+    TG[group_num]->hw_timer[timer_num].config.autoreload = config->auto_reload;
+    TG[group_num]->hw_timer[timer_num].config.divider = config->divider;
+    TG[group_num]->hw_timer[timer_num].config.enable = config->counter_en;
+    TG[group_num]->hw_timer[timer_num].config.increase = config->counter_dir;
+    TG[group_num]->hw_timer[timer_num].config.alarm_en = config->alarm_en;
+    TG[group_num]->hw_timer[timer_num].config.level_int_en = (config->intr_type == TIMER_INTR_LEVEL ? 1 : 0);
+    TG[group_num]->hw_timer[timer_num].config.edge_int_en = (config->intr_type == TIMER_INTR_LEVEL ? 0 : 1);
+    TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
+    return ESP_OK;
+}
+
+esp_err_t timer_get_config(timer_group_t group_num, timer_idx_t timer_num, timer_config_t *config)
+{
+    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_CHECK(config != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
+    config->alarm_en = TG[group_num]->hw_timer[timer_num].config.alarm_en;
+    config->auto_reload = TG[group_num]->hw_timer[timer_num].config.autoreload;
+    config->counter_dir = TG[group_num]->hw_timer[timer_num].config.increase;
+    config->counter_dir = TG[group_num]->hw_timer[timer_num].config.divider;
+    config->counter_en = TG[group_num]->hw_timer[timer_num].config.enable;
+    if(TG[group_num]->hw_timer[timer_num].config.level_int_en) {
+        config->intr_type =TIMER_INTR_LEVEL;
+    }
+    TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
+    return ESP_OK;
+}
+
+esp_err_t timer_group_intr_enable(timer_group_t group_num, uint32_t en_mask)
+{
+    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    portENTER_CRITICAL(&timer_spinlock[group_num]);
+    TG[group_num]->int_ena.val |= en_mask;
+    portEXIT_CRITICAL(&timer_spinlock[group_num]);
+    return ESP_OK;
+}
+
+esp_err_t timer_group_intr_disable(timer_group_t group_num, uint32_t disable_mask)
+{
+    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    portENTER_CRITICAL(&timer_spinlock[group_num]);
+    TG[group_num]->int_ena.val &= (~disable_mask);
+    portEXIT_CRITICAL(&timer_spinlock[group_num]);
+    return ESP_OK;
+}
+
+esp_err_t timer_enable_intr(timer_group_t group_num, timer_idx_t timer_num)
+{
+    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    return timer_group_intr_enable(group_num, BIT(timer_num));
+}
+
+esp_err_t timer_disable_intr(timer_group_t group_num, timer_idx_t timer_num)
+{
+    TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
+    return timer_group_intr_disable(group_num, BIT(timer_num));
+}
+
+
index 0c2dd55700c480c33c57ce4d352028bbadf52f63..556e97baac5473fae9a61e5c06a3c84ea99f92dc 100644 (file)
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD\r
-//\r
-// Licensed under the Apache License, Version 2.0 (the "License");\r
-// you may not use this file except in compliance with the License.\r
-// You may obtain a copy of the License at\r
-\r
-//     http://www.apache.org/licenses/LICENSE-2.0\r
-//\r
-// Unless required by applicable law or agreed to in writing, software\r
-// distributed under the License is distributed on an "AS IS" BASIS,\r
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-// See the License for the specific language governing permissions and\r
-// limitations under the License.\r
-#include <string.h>\r
-#include "esp_types.h"\r
-#include "esp_attr.h"\r
-#include "esp_intr.h"\r
-#include "esp_intr_alloc.h"\r
-#include "esp_log.h"\r
-#include "esp_err.h"\r
-#include "malloc.h"\r
-#include "freertos/FreeRTOS.h"\r
-#include "freertos/semphr.h"\r
-#include "freertos/xtensa_api.h"\r
-#include "freertos/task.h"\r
-#include "freertos/ringbuf.h"\r
-#include "soc/dport_reg.h"\r
-#include "soc/uart_struct.h"\r
-#include "driver/uart.h"\r
-#include "driver/gpio.h"\r
-\r
-static const char* UART_TAG = "uart";\r
-#define UART_CHECK(a, str, ret_val) \\r
-    if (!(a)) { \\r
-        ESP_LOGE(UART_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \\r
-        return (ret_val); \\r
-    }\r
-\r
-#define UART_EMPTY_THRESH_DEFAULT  (10)\r
-#define UART_FULL_THRESH_DEFAULT  (120)\r
-#define UART_TOUT_THRESH_DEFAULT   (10)\r
-#define UART_ENTER_CRITICAL_ISR(mux)    portENTER_CRITICAL_ISR(mux)\r
-#define UART_EXIT_CRITICAL_ISR(mux)     portEXIT_CRITICAL_ISR(mux)\r
-#define UART_ENTER_CRITICAL(mux)    portENTER_CRITICAL(mux)\r
-#define UART_EXIT_CRITICAL(mux)     portEXIT_CRITICAL(mux)\r
-\r
-typedef struct {\r
-    uart_event_type_t type;        /*!< UART TX data type */\r
-    struct {\r
-        int brk_len;\r
-        size_t size;\r
-        uint8_t data[0];\r
-    } tx_data;\r
-} uart_tx_data_t;\r
-\r
-typedef struct {\r
-    uart_port_t uart_num;               /*!< UART port number*/\r
-    int queue_size;                     /*!< UART event queue size*/\r
-    QueueHandle_t xQueueUart;           /*!< UART queue handler*/\r
-    intr_handle_t intr_handle;          /*!< UART interrupt handle*/\r
-    //rx parameters\r
-    SemaphoreHandle_t rx_mux;           /*!< UART RX data mutex*/\r
-    int rx_buf_size;                    /*!< RX ring buffer size */\r
-    RingbufHandle_t rx_ring_buf;        /*!< RX ring buffer handler*/\r
-    bool rx_buffer_full_flg;            /*!< RX ring buffer full flag. */\r
-    int rx_cur_remain;                  /*!< Data number that waiting to be read out in ring buffer item*/\r
-    uint8_t* rx_ptr;                    /*!< pointer to the current data in ring buffer*/\r
-    uint8_t* rx_head_ptr;               /*!< pointer to the head of RX item*/\r
-    uint8_t rx_data_buf[UART_FIFO_LEN]; /*!< Data buffer to stash FIFO data*/\r
-    uint8_t rx_stash_len;               /*!< stashed data length.(When using flow control, after reading out FIFO data, if we fail to push to buffer, we can just stash them.) */\r
-    //tx parameters\r
-    SemaphoreHandle_t tx_fifo_sem;      /*!< UART TX FIFO semaphore*/\r
-    SemaphoreHandle_t tx_mux;           /*!< UART TX mutex*/\r
-    SemaphoreHandle_t tx_done_sem;      /*!< UART TX done semaphore*/\r
-    SemaphoreHandle_t tx_brk_sem;       /*!< UART TX send break done semaphore*/\r
-    int tx_buf_size;                    /*!< TX ring buffer size */\r
-    RingbufHandle_t tx_ring_buf;        /*!< TX ring buffer handler*/\r
-    bool tx_waiting_fifo;               /*!< this flag indicates that some task is waiting for FIFO empty interrupt, used to send all data without any data buffer*/\r
-    uint8_t* tx_ptr;                    /*!< TX data pointer to push to FIFO in TX buffer mode*/\r
-    uart_tx_data_t* tx_head;            /*!< TX data pointer to head of the current buffer in TX ring buffer*/\r
-    uint32_t tx_len_tot;                /*!< Total length of current item in ring buffer*/\r
-    uint32_t tx_len_cur;\r
-    uint8_t tx_brk_flg;                 /*!< Flag to indicate to send a break signal in the end of the item sending procedure */\r
-    uint8_t tx_brk_len;                 /*!< TX break signal cycle length/number */\r
-    uint8_t tx_waiting_brk;             /*!< Flag to indicate that TX FIFO is ready to send break signal after FIFO is empty, do not push data into TX FIFO right now.*/\r
-} uart_obj_t;\r
-\r
-\r
-\r
-static uart_obj_t *p_uart_obj[UART_NUM_MAX] = {0};\r
-/* DRAM_ATTR is required to avoid UART array placed in flash, due to accessed from ISR */\r
-static DRAM_ATTR uart_dev_t* const UART[UART_NUM_MAX] = {&UART0, &UART1, &UART2};\r
-static portMUX_TYPE uart_spinlock[UART_NUM_MAX] = {portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED};\r
-\r
-esp_err_t uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit)\r
-{\r
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);\r
-    UART_CHECK((data_bit < UART_DATA_BITS_MAX), "data bit error", ESP_FAIL);\r
-    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);\r
-    UART[uart_num]->conf0.bit_num = data_bit;\r
-    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t uart_get_word_length(uart_port_t uart_num, uart_word_length_t* data_bit)\r
-{\r
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);\r
-    *(data_bit) = UART[uart_num]->conf0.bit_num;\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t stop_bit)\r
-{\r
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);\r
-    UART_CHECK((stop_bit < UART_STOP_BITS_MAX), "stop bit error", ESP_FAIL);\r
-    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);\r
-    UART[uart_num]->conf0.stop_bit_num = stop_bit;\r
-    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t* stop_bit)\r
-{\r
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);\r
-    (*stop_bit) = UART[uart_num]->conf0.stop_bit_num;\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t uart_set_parity(uart_port_t uart_num, uart_parity_t parity_mode)\r
-{\r
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);\r
-    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);\r
-    UART[uart_num]->conf0.parity = parity_mode & 0x1;\r
-    UART[uart_num]->conf0.parity_en = (parity_mode >> 1) & 0x1;\r
-    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t* parity_mode)\r
-{\r
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);\r
-    int val = UART[uart_num]->conf0.val;\r
-    if(val & UART_PARITY_EN_M) {\r
-        if(val & UART_PARITY_M) {\r
-            (*parity_mode) = UART_PARITY_ODD;\r
-        } else {\r
-            (*parity_mode) = UART_PARITY_EVEN;\r
-        }\r
-    } else {\r
-        (*parity_mode) = UART_PARITY_DISABLE;\r
-    }\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t uart_set_baudrate(uart_port_t uart_num, uint32_t baud_rate)\r
-{\r
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);\r
-    UART_CHECK((baud_rate < UART_BITRATE_MAX), "baud_rate error", ESP_FAIL);\r
-    uint32_t clk_div = (((UART_CLK_FREQ) << 4) / baud_rate);\r
-    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);\r
-    UART[uart_num]->clk_div.div_int = clk_div >> 4;\r
-    UART[uart_num]->clk_div.div_frag = clk_div & 0xf;\r
-    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t uart_get_baudrate(uart_port_t uart_num, uint32_t* baudrate)\r
-{\r
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);\r
-    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);\r
-    uint32_t clk_div = (UART[uart_num]->clk_div.div_int << 4) | UART[uart_num]->clk_div.div_frag;\r
-    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);\r
-    (*baudrate) = ((UART_CLK_FREQ) << 4) / clk_div;\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t uart_set_line_inverse(uart_port_t uart_num, uint32_t inverse_mask)\r
-{\r
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);\r
-    UART_CHECK((((inverse_mask & UART_LINE_INV_MASK) == 0) && (inverse_mask != 0)), "inverse_mask error", ESP_FAIL);\r
-    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);\r
-    CLEAR_PERI_REG_MASK(UART_CONF0_REG(uart_num), UART_LINE_INV_MASK);\r
-    SET_PERI_REG_MASK(UART_CONF0_REG(uart_num), inverse_mask);\r
-    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);\r
-    return ESP_OK;\r
-}\r
-\r
-//only when UART_HW_FLOWCTRL_RTS is set , will the rx_thresh value be set.\r
-esp_err_t uart_set_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t flow_ctrl, uint8_t rx_thresh)\r
-{\r
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);\r
-    UART_CHECK((rx_thresh < UART_FIFO_LEN), "rx flow thresh error", ESP_FAIL);\r
-    UART_CHECK((flow_ctrl < UART_HW_FLOWCTRL_MAX), "hw_flowctrl mode error", ESP_FAIL);\r
-    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);\r
-    if(flow_ctrl & UART_HW_FLOWCTRL_RTS) {\r
-        UART[uart_num]->conf1.rx_flow_thrhd = rx_thresh;\r
-        UART[uart_num]->conf1.rx_flow_en = 1;\r
-    } else {\r
-        UART[uart_num]->conf1.rx_flow_en = 0;\r
-    }\r
-    if(flow_ctrl & UART_HW_FLOWCTRL_CTS) {\r
-        UART[uart_num]->conf0.tx_flow_en = 1;\r
-    } else {\r
-        UART[uart_num]->conf0.tx_flow_en = 0;\r
-    }\r
-    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t* flow_ctrl)\r
-{\r
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);\r
-    uart_hw_flowcontrol_t val = UART_HW_FLOWCTRL_DISABLE;\r
-    if(UART[uart_num]->conf1.rx_flow_en) {\r
-        val |= UART_HW_FLOWCTRL_RTS;\r
-    }\r
-    if(UART[uart_num]->conf0.tx_flow_en) {\r
-        val |= UART_HW_FLOWCTRL_CTS;\r
-    }\r
-    (*flow_ctrl) = val;\r
-    return ESP_OK;\r
-}\r
-\r
-static esp_err_t uart_reset_fifo(uart_port_t uart_num)\r
-{\r
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);\r
-    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);\r
-    UART[uart_num]->conf0.rxfifo_rst = 1;\r
-    UART[uart_num]->conf0.rxfifo_rst = 0;\r
-    UART[uart_num]->conf0.txfifo_rst = 1;\r
-    UART[uart_num]->conf0.txfifo_rst = 0;\r
-    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t uart_clear_intr_status(uart_port_t uart_num, uint32_t clr_mask)\r
-{\r
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);\r
-    //intr_clr register is write-only\r
-    UART[uart_num]->int_clr.val = clr_mask;\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t uart_enable_intr_mask(uart_port_t uart_num, uint32_t enable_mask)\r
-{\r
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);\r
-    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);\r
-    SET_PERI_REG_MASK(UART_INT_CLR_REG(uart_num), enable_mask);\r
-    SET_PERI_REG_MASK(UART_INT_ENA_REG(uart_num), enable_mask);\r
-    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t uart_disable_intr_mask(uart_port_t uart_num, uint32_t disable_mask)\r
-{\r
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);\r
-    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);\r
-    CLEAR_PERI_REG_MASK(UART_INT_ENA_REG(uart_num), disable_mask);\r
-    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t uart_enable_rx_intr(uart_port_t uart_num)\r
-{\r
-    uart_enable_intr_mask(uart_num, UART_RXFIFO_FULL_INT_ENA|UART_RXFIFO_TOUT_INT_ENA);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t uart_disable_rx_intr(uart_port_t uart_num)\r
-{\r
-    uart_disable_intr_mask(uart_num, UART_RXFIFO_FULL_INT_ENA|UART_RXFIFO_TOUT_INT_ENA);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t uart_disable_tx_intr(uart_port_t uart_num)\r
-{\r
-    uart_disable_intr_mask(uart_num, UART_TXFIFO_EMPTY_INT_ENA);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh)\r
-{\r
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);\r
-    UART_CHECK((thresh < UART_FIFO_LEN), "empty intr threshold error", ESP_FAIL);\r
-    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);\r
-    UART[uart_num]->int_clr.txfifo_empty = 1;\r
-    UART[uart_num]->conf1.txfifo_empty_thrhd = thresh & UART_TXFIFO_EMPTY_THRHD_V;\r
-    UART[uart_num]->int_ena.txfifo_empty = enable & 0x1;\r
-    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t uart_isr_register(uart_port_t uart_num, void (*fn)(void*), void * arg, int intr_alloc_flags)\r
-{\r
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include <string.h>
+#include "esp_types.h"
+#include "esp_attr.h"
+#include "esp_intr.h"
+#include "esp_intr_alloc.h"
+#include "esp_log.h"
+#include "esp_err.h"
+#include "malloc.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/semphr.h"
+#include "freertos/xtensa_api.h"
+#include "freertos/task.h"
+#include "freertos/ringbuf.h"
+#include "soc/dport_reg.h"
+#include "soc/uart_struct.h"
+#include "driver/uart.h"
+#include "driver/gpio.h"
+
+static const char* UART_TAG = "uart";
+#define UART_CHECK(a, str, ret_val) \
+    if (!(a)) { \
+        ESP_LOGE(UART_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \
+        return (ret_val); \
+    }
+
+#define UART_EMPTY_THRESH_DEFAULT  (10)
+#define UART_FULL_THRESH_DEFAULT  (120)
+#define UART_TOUT_THRESH_DEFAULT   (10)
+#define UART_ENTER_CRITICAL_ISR(mux)    portENTER_CRITICAL_ISR(mux)
+#define UART_EXIT_CRITICAL_ISR(mux)     portEXIT_CRITICAL_ISR(mux)
+#define UART_ENTER_CRITICAL(mux)    portENTER_CRITICAL(mux)
+#define UART_EXIT_CRITICAL(mux)     portEXIT_CRITICAL(mux)
+
+typedef struct {
+    uart_event_type_t type;        /*!< UART TX data type */
+    struct {
+        int brk_len;
+        size_t size;
+        uint8_t data[0];
+    } tx_data;
+} uart_tx_data_t;
+
+typedef struct {
+    uart_port_t uart_num;               /*!< UART port number*/
+    int queue_size;                     /*!< UART event queue size*/
+    QueueHandle_t xQueueUart;           /*!< UART queue handler*/
+    intr_handle_t intr_handle;          /*!< UART interrupt handle*/
+    //rx parameters
+    SemaphoreHandle_t rx_mux;           /*!< UART RX data mutex*/
+    int rx_buf_size;                    /*!< RX ring buffer size */
+    RingbufHandle_t rx_ring_buf;        /*!< RX ring buffer handler*/
+    bool rx_buffer_full_flg;            /*!< RX ring buffer full flag. */
+    int rx_cur_remain;                  /*!< Data number that waiting to be read out in ring buffer item*/
+    uint8_t* rx_ptr;                    /*!< pointer to the current data in ring buffer*/
+    uint8_t* rx_head_ptr;               /*!< pointer to the head of RX item*/
+    uint8_t rx_data_buf[UART_FIFO_LEN]; /*!< Data buffer to stash FIFO data*/
+    uint8_t rx_stash_len;               /*!< stashed data length.(When using flow control, after reading out FIFO data, if we fail to push to buffer, we can just stash them.) */
+    //tx parameters
+    SemaphoreHandle_t tx_fifo_sem;      /*!< UART TX FIFO semaphore*/
+    SemaphoreHandle_t tx_mux;           /*!< UART TX mutex*/
+    SemaphoreHandle_t tx_done_sem;      /*!< UART TX done semaphore*/
+    SemaphoreHandle_t tx_brk_sem;       /*!< UART TX send break done semaphore*/
+    int tx_buf_size;                    /*!< TX ring buffer size */
+    RingbufHandle_t tx_ring_buf;        /*!< TX ring buffer handler*/
+    bool tx_waiting_fifo;               /*!< this flag indicates that some task is waiting for FIFO empty interrupt, used to send all data without any data buffer*/
+    uint8_t* tx_ptr;                    /*!< TX data pointer to push to FIFO in TX buffer mode*/
+    uart_tx_data_t* tx_head;            /*!< TX data pointer to head of the current buffer in TX ring buffer*/
+    uint32_t tx_len_tot;                /*!< Total length of current item in ring buffer*/
+    uint32_t tx_len_cur;
+    uint8_t tx_brk_flg;                 /*!< Flag to indicate to send a break signal in the end of the item sending procedure */
+    uint8_t tx_brk_len;                 /*!< TX break signal cycle length/number */
+    uint8_t tx_waiting_brk;             /*!< Flag to indicate that TX FIFO is ready to send break signal after FIFO is empty, do not push data into TX FIFO right now.*/
+} uart_obj_t;
+
+
+
+static uart_obj_t *p_uart_obj[UART_NUM_MAX] = {0};
+/* DRAM_ATTR is required to avoid UART array placed in flash, due to accessed from ISR */
+static DRAM_ATTR uart_dev_t* const UART[UART_NUM_MAX] = {&UART0, &UART1, &UART2};
+static portMUX_TYPE uart_spinlock[UART_NUM_MAX] = {portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED};
+
+esp_err_t uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit)
+{
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
+    UART_CHECK((data_bit < UART_DATA_BITS_MAX), "data bit error", ESP_FAIL);
+    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
+    UART[uart_num]->conf0.bit_num = data_bit;
+    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
+    return ESP_OK;
+}
+
+esp_err_t uart_get_word_length(uart_port_t uart_num, uart_word_length_t* data_bit)
+{
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
+    *(data_bit) = UART[uart_num]->conf0.bit_num;
+    return ESP_OK;
+}
+
+esp_err_t uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t stop_bit)
+{
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
+    UART_CHECK((stop_bit < UART_STOP_BITS_MAX), "stop bit error", ESP_FAIL);
+    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
+    UART[uart_num]->conf0.stop_bit_num = stop_bit;
+    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
+    return ESP_OK;
+}
+
+esp_err_t uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t* stop_bit)
+{
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
+    (*stop_bit) = UART[uart_num]->conf0.stop_bit_num;
+    return ESP_OK;
+}
+
+esp_err_t uart_set_parity(uart_port_t uart_num, uart_parity_t parity_mode)
+{
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
+    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
+    UART[uart_num]->conf0.parity = parity_mode & 0x1;
+    UART[uart_num]->conf0.parity_en = (parity_mode >> 1) & 0x1;
+    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
+    return ESP_OK;
+}
+
+esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t* parity_mode)
+{
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
+    int val = UART[uart_num]->conf0.val;
+    if(val & UART_PARITY_EN_M) {
+        if(val & UART_PARITY_M) {
+            (*parity_mode) = UART_PARITY_ODD;
+        } else {
+            (*parity_mode) = UART_PARITY_EVEN;
+        }
+    } else {
+        (*parity_mode) = UART_PARITY_DISABLE;
+    }
+    return ESP_OK;
+}
+
+esp_err_t uart_set_baudrate(uart_port_t uart_num, uint32_t baud_rate)
+{
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
+    UART_CHECK((baud_rate < UART_BITRATE_MAX), "baud_rate error", ESP_FAIL);
+    uint32_t clk_div = (((UART_CLK_FREQ) << 4) / baud_rate);
+    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
+    UART[uart_num]->clk_div.div_int = clk_div >> 4;
+    UART[uart_num]->clk_div.div_frag = clk_div & 0xf;
+    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
+    return ESP_OK;
+}
+
+esp_err_t uart_get_baudrate(uart_port_t uart_num, uint32_t* baudrate)
+{
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
+    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
+    uint32_t clk_div = (UART[uart_num]->clk_div.div_int << 4) | UART[uart_num]->clk_div.div_frag;
+    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
+    (*baudrate) = ((UART_CLK_FREQ) << 4) / clk_div;
+    return ESP_OK;
+}
+
+esp_err_t uart_set_line_inverse(uart_port_t uart_num, uint32_t inverse_mask)
+{
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
+    UART_CHECK((((inverse_mask & UART_LINE_INV_MASK) == 0) && (inverse_mask != 0)), "inverse_mask error", ESP_FAIL);
+    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
+    CLEAR_PERI_REG_MASK(UART_CONF0_REG(uart_num), UART_LINE_INV_MASK);
+    SET_PERI_REG_MASK(UART_CONF0_REG(uart_num), inverse_mask);
+    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
+    return ESP_OK;
+}
+
+//only when UART_HW_FLOWCTRL_RTS is set , will the rx_thresh value be set.
+esp_err_t uart_set_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t flow_ctrl, uint8_t rx_thresh)
+{
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
+    UART_CHECK((rx_thresh < UART_FIFO_LEN), "rx flow thresh error", ESP_FAIL);
+    UART_CHECK((flow_ctrl < UART_HW_FLOWCTRL_MAX), "hw_flowctrl mode error", ESP_FAIL);
+    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
+    if(flow_ctrl & UART_HW_FLOWCTRL_RTS) {
+        UART[uart_num]->conf1.rx_flow_thrhd = rx_thresh;
+        UART[uart_num]->conf1.rx_flow_en = 1;
+    } else {
+        UART[uart_num]->conf1.rx_flow_en = 0;
+    }
+    if(flow_ctrl & UART_HW_FLOWCTRL_CTS) {
+        UART[uart_num]->conf0.tx_flow_en = 1;
+    } else {
+        UART[uart_num]->conf0.tx_flow_en = 0;
+    }
+    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
+    return ESP_OK;
+}
+
+esp_err_t uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t* flow_ctrl)
+{
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
+    uart_hw_flowcontrol_t val = UART_HW_FLOWCTRL_DISABLE;
+    if(UART[uart_num]->conf1.rx_flow_en) {
+        val |= UART_HW_FLOWCTRL_RTS;
+    }
+    if(UART[uart_num]->conf0.tx_flow_en) {
+        val |= UART_HW_FLOWCTRL_CTS;
+    }
+    (*flow_ctrl) = val;
+    return ESP_OK;
+}
+
+static esp_err_t uart_reset_fifo(uart_port_t uart_num)
+{
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
+    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
+    UART[uart_num]->conf0.rxfifo_rst = 1;
+    UART[uart_num]->conf0.rxfifo_rst = 0;
+    UART[uart_num]->conf0.txfifo_rst = 1;
+    UART[uart_num]->conf0.txfifo_rst = 0;
+    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
+    return ESP_OK;
+}
+
+esp_err_t uart_clear_intr_status(uart_port_t uart_num, uint32_t clr_mask)
+{
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
+    //intr_clr register is write-only
+    UART[uart_num]->int_clr.val = clr_mask;
+    return ESP_OK;
+}
+
+esp_err_t uart_enable_intr_mask(uart_port_t uart_num, uint32_t enable_mask)
+{
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
+    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
+    SET_PERI_REG_MASK(UART_INT_CLR_REG(uart_num), enable_mask);
+    SET_PERI_REG_MASK(UART_INT_ENA_REG(uart_num), enable_mask);
+    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
+    return ESP_OK;
+}
+
+esp_err_t uart_disable_intr_mask(uart_port_t uart_num, uint32_t disable_mask)
+{
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
+    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
+    CLEAR_PERI_REG_MASK(UART_INT_ENA_REG(uart_num), disable_mask);
+    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
+    return ESP_OK;
+}
+
+esp_err_t uart_enable_rx_intr(uart_port_t uart_num)
+{
+    uart_enable_intr_mask(uart_num, UART_RXFIFO_FULL_INT_ENA|UART_RXFIFO_TOUT_INT_ENA);
+    return ESP_OK;
+}
+
+esp_err_t uart_disable_rx_intr(uart_port_t uart_num)
+{
+    uart_disable_intr_mask(uart_num, UART_RXFIFO_FULL_INT_ENA|UART_RXFIFO_TOUT_INT_ENA);
+    return ESP_OK;
+}
+
+esp_err_t uart_disable_tx_intr(uart_port_t uart_num)
+{
+    uart_disable_intr_mask(uart_num, UART_TXFIFO_EMPTY_INT_ENA);
+    return ESP_OK;
+}
+
+esp_err_t uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh)
+{
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
+    UART_CHECK((thresh < UART_FIFO_LEN), "empty intr threshold error", ESP_FAIL);
+    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
+    UART[uart_num]->int_clr.txfifo_empty = 1;
+    UART[uart_num]->conf1.txfifo_empty_thrhd = thresh & UART_TXFIFO_EMPTY_THRHD_V;
+    UART[uart_num]->int_ena.txfifo_empty = enable & 0x1;
+    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
+    return ESP_OK;
+}
+
+esp_err_t uart_isr_register(uart_port_t uart_num, void (*fn)(void*), void * arg, int intr_alloc_flags)
+{
     int ret;
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);\r
-    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);\r
-    switch(uart_num) {\r
-        case UART_NUM_1:\r
-            ret=esp_intr_alloc(ETS_UART1_INTR_SOURCE, intr_alloc_flags, fn, arg, &p_uart_obj[uart_num]->intr_handle);\r
-            break;\r
-        case UART_NUM_2:\r
-            ret=esp_intr_alloc(ETS_UART2_INTR_SOURCE, intr_alloc_flags, fn, arg, &p_uart_obj[uart_num]->intr_handle);\r
-            break;\r
-        case UART_NUM_0:\r
-            default:\r
-            ret=esp_intr_alloc(ETS_UART0_INTR_SOURCE, intr_alloc_flags, fn, arg, &p_uart_obj[uart_num]->intr_handle);\r
-            break;\r
-    }\r
-    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);\r
-    return ret;\r
-}\r
-\r
-\r
-esp_err_t uart_isr_free(uart_port_t uart_num)\r
-{\r
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
+    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
+    switch(uart_num) {
+        case UART_NUM_1:
+            ret=esp_intr_alloc(ETS_UART1_INTR_SOURCE, intr_alloc_flags, fn, arg, &p_uart_obj[uart_num]->intr_handle);
+            break;
+        case UART_NUM_2:
+            ret=esp_intr_alloc(ETS_UART2_INTR_SOURCE, intr_alloc_flags, fn, arg, &p_uart_obj[uart_num]->intr_handle);
+            break;
+        case UART_NUM_0:
+            default:
+            ret=esp_intr_alloc(ETS_UART0_INTR_SOURCE, intr_alloc_flags, fn, arg, &p_uart_obj[uart_num]->intr_handle);
+            break;
+    }
+    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
+    return ret;
+}
+
+
+esp_err_t uart_isr_free(uart_port_t uart_num)
+{
     esp_err_t ret;
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);\r
-    if (p_uart_obj[uart_num]->intr_handle==NULL) return ESP_ERR_INVALID_ARG;\r
-    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);\r
-    ret=esp_intr_free(p_uart_obj[uart_num]->intr_handle);\r
-    p_uart_obj[uart_num]->intr_handle=NULL;\r
-    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);\r
-    return ret;\r
-}\r
-\r
-//internal signal can be output to multiple GPIO pads\r
-//only one GPIO pad can connect with input signal\r
-esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num)\r
-{\r
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);\r
-    UART_CHECK((tx_io_num < 0 || (GPIO_IS_VALID_OUTPUT_GPIO(tx_io_num))), "tx_io_num error", ESP_FAIL);\r
-    UART_CHECK((rx_io_num < 0 || (GPIO_IS_VALID_GPIO(rx_io_num))), "rx_io_num error", ESP_FAIL);\r
-    UART_CHECK((rts_io_num < 0 || (GPIO_IS_VALID_OUTPUT_GPIO(rts_io_num))), "rts_io_num error", ESP_FAIL);\r
-    UART_CHECK((cts_io_num < 0 || (GPIO_IS_VALID_GPIO(cts_io_num))), "cts_io_num error", ESP_FAIL);\r
-\r
-    int tx_sig, rx_sig, rts_sig, cts_sig;\r
-    switch(uart_num) {\r
-        case UART_NUM_0:\r
-            tx_sig = U0TXD_OUT_IDX;\r
-            rx_sig = U0RXD_IN_IDX;\r
-            rts_sig = U0RTS_OUT_IDX;\r
-            cts_sig = U0CTS_IN_IDX;\r
-            break;\r
-        case UART_NUM_1:\r
-            tx_sig = U1TXD_OUT_IDX;\r
-            rx_sig = U1RXD_IN_IDX;\r
-            rts_sig = U1RTS_OUT_IDX;\r
-            cts_sig = U1CTS_IN_IDX;\r
-            break;\r
-        case UART_NUM_2:\r
-            tx_sig = U2TXD_OUT_IDX;\r
-            rx_sig = U2RXD_IN_IDX;\r
-            rts_sig = U2RTS_OUT_IDX;\r
-            cts_sig = U2CTS_IN_IDX;\r
-            break;\r
-        case UART_NUM_MAX:\r
-            default:\r
-            tx_sig = U0TXD_OUT_IDX;\r
-            rx_sig = U0RXD_IN_IDX;\r
-            rts_sig = U0RTS_OUT_IDX;\r
-            cts_sig = U0CTS_IN_IDX;\r
-            break;\r
-    }\r
-    if(tx_io_num >= 0) {\r
-        PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[tx_io_num], PIN_FUNC_GPIO);\r
-        gpio_set_direction(tx_io_num, GPIO_MODE_OUTPUT);\r
-        gpio_matrix_out(tx_io_num, tx_sig, 0, 0);\r
-    }\r
-\r
-    if(rx_io_num >= 0) {\r
-        PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[rx_io_num], PIN_FUNC_GPIO);\r
-        gpio_set_direction(rx_io_num, GPIO_MODE_INPUT);\r
-        gpio_matrix_in(rx_io_num, rx_sig, 0);\r
-    }\r
-    if(rts_io_num >= 0) {\r
-        PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[rts_io_num], PIN_FUNC_GPIO);\r
-        gpio_set_direction(rts_io_num, GPIO_MODE_OUTPUT);\r
-        gpio_matrix_out(rts_io_num, rts_sig, 0, 0);\r
-    }\r
-    if(cts_io_num >= 0) {\r
-        PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[cts_io_num], PIN_FUNC_GPIO);\r
-        gpio_set_direction(cts_io_num, GPIO_MODE_INPUT);\r
-        gpio_matrix_in(cts_io_num, cts_sig, 0);\r
-    }\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t uart_set_rts(uart_port_t uart_num, int level)\r
-{\r
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);\r
-    UART_CHECK((UART[uart_num]->conf1.rx_flow_en != 1), "disable hw flowctrl before using sw control", ESP_FAIL);\r
-    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);\r
-    UART[uart_num]->conf0.sw_rts = level & 0x1;\r
-    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t uart_set_dtr(uart_port_t uart_num, int level)\r
-{\r
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);\r
-    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);\r
-    UART[uart_num]->conf0.sw_dtr = level & 0x1;\r
-    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_config)\r
-{\r
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);\r
-    UART_CHECK((uart_config), "param null", ESP_FAIL);\r
-    if(uart_num == UART_NUM_0) {\r
-        periph_module_enable(PERIPH_UART0_MODULE);\r
-    } else if(uart_num == UART_NUM_1) {\r
-        periph_module_enable(PERIPH_UART1_MODULE);\r
-    } else if(uart_num == UART_NUM_2) {\r
-        periph_module_enable(PERIPH_UART2_MODULE);\r
-    }\r
-    uart_set_hw_flow_ctrl(uart_num, uart_config->flow_ctrl, uart_config->rx_flow_ctrl_thresh);\r
-    uart_set_baudrate(uart_num, uart_config->baud_rate);\r
-    UART[uart_num]->conf0.val = (\r
-        (uart_config->parity << UART_PARITY_S)\r
-            | (uart_config->stop_bits << UART_STOP_BIT_NUM_S)\r
-            | (uart_config->data_bits << UART_BIT_NUM_S)\r
-            | ((uart_config->flow_ctrl & UART_HW_FLOWCTRL_CTS) ? UART_TX_FLOW_EN : 0x0)\r
-            | UART_TICK_REF_ALWAYS_ON_M);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t uart_intr_config(uart_port_t uart_num, const uart_intr_config_t *intr_conf)\r
-{\r
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);\r
-    UART_CHECK((intr_conf), "param null", ESP_FAIL);\r
-    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);\r
-    UART[uart_num]->int_clr.val = UART_INTR_MASK;\r
-    if(intr_conf->intr_enable_mask & UART_RXFIFO_TOUT_INT_ENA_M) {\r
-        UART[uart_num]->conf1.rx_tout_thrhd = ((intr_conf->rx_timeout_thresh) & UART_RX_TOUT_THRHD_V);\r
-        UART[uart_num]->conf1.rx_tout_en = 1;\r
-    } else {\r
-        UART[uart_num]->conf1.rx_tout_en = 0;\r
-    }\r
-    if(intr_conf->intr_enable_mask & UART_RXFIFO_FULL_INT_ENA_M) {\r
-        UART[uart_num]->conf1.rxfifo_full_thrhd = intr_conf->rxfifo_full_thresh;\r
-    }\r
-    if(intr_conf->intr_enable_mask & UART_TXFIFO_EMPTY_INT_ENA_M) {\r
-        UART[uart_num]->conf1.txfifo_empty_thrhd = intr_conf->txfifo_empty_intr_thresh;\r
-    }\r
-    UART[uart_num]->int_ena.val = intr_conf->intr_enable_mask;\r
-    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);\r
-    return ESP_FAIL;\r
-}\r
-\r
-//internal isr handler for default driver code.\r
-static void IRAM_ATTR uart_rx_intr_handler_default(void *param)\r
-{\r
-    uart_obj_t *p_uart = (uart_obj_t*) param;\r
-    uint8_t uart_num = p_uart->uart_num;\r
-    uart_dev_t* uart_reg = UART[uart_num];\r
-    uint8_t buf_idx = 0;\r
-    uint32_t uart_intr_status = UART[uart_num]->int_st.val;\r
-    int rx_fifo_len = 0;\r
-    uart_event_t uart_event;\r
-    portBASE_TYPE HPTaskAwoken = 0;\r
-\r
-    while(uart_intr_status != 0x0) {\r
-        buf_idx = 0;\r
-        uart_event.type = UART_EVENT_MAX;\r
-        if(uart_intr_status & UART_TXFIFO_EMPTY_INT_ST_M) {\r
-            UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);\r
-            uart_reg->int_ena.txfifo_empty = 0;\r
-            uart_reg->int_clr.txfifo_empty = 1;\r
-            UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);\r
-            if(p_uart->tx_waiting_brk) {\r
-                continue;\r
-            }\r
-            //TX semaphore will only be used when tx_buf_size is zero.\r
-            if(p_uart->tx_waiting_fifo == true && p_uart->tx_buf_size == 0) {\r
-                p_uart->tx_waiting_fifo = false;\r
-                xSemaphoreGiveFromISR(p_uart->tx_fifo_sem, &HPTaskAwoken);\r
-                if(HPTaskAwoken == pdTRUE) {\r
-                    portYIELD_FROM_ISR() ;\r
-                }\r
-            }\r
-            else {\r
-                //We don't use TX ring buffer, because the size is zero.\r
-                if(p_uart->tx_buf_size == 0) {\r
-                    continue;\r
-                }\r
-                int tx_fifo_rem = UART_FIFO_LEN - UART[uart_num]->status.txfifo_cnt;\r
-                bool en_tx_flg = false;\r
-                //We need to put a loop here, in case all the buffer items are very short.\r
-                //That would cause a watch_dog reset because empty interrupt happens so often.\r
-                //Although this is a loop in ISR, this loop will execute at most 128 turns.\r
-                while(tx_fifo_rem) {\r
-                    if(p_uart->tx_len_tot == 0 || p_uart->tx_ptr == NULL || p_uart->tx_len_cur == 0) {\r
-                        size_t size;\r
-                        p_uart->tx_head = (uart_tx_data_t*) xRingbufferReceiveFromISR(p_uart->tx_ring_buf, &size);\r
-                        if(p_uart->tx_head) {\r
-                            //The first item is the data description\r
-                            //Get the first item to get the data information\r
-                            if(p_uart->tx_len_tot == 0) {\r
-                                p_uart->tx_ptr = NULL;\r
-                                p_uart->tx_len_tot = p_uart->tx_head->tx_data.size;\r
-                                if(p_uart->tx_head->type == UART_DATA_BREAK) {\r
-                                    p_uart->tx_len_tot = p_uart->tx_head->tx_data.size;\r
-                                    p_uart->tx_brk_flg = 1;\r
-                                    p_uart->tx_brk_len = p_uart->tx_head->tx_data.brk_len;\r
-                                }\r
-                                //We have saved the data description from the 1st item, return buffer.\r
-                                vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, p_uart->tx_head, &HPTaskAwoken);\r
-                                if(HPTaskAwoken == pdTRUE) {\r
-                                    portYIELD_FROM_ISR() ;\r
-                                }\r
-                            }else if(p_uart->tx_ptr == NULL) {\r
-                                //Update the TX item pointer, we will need this to return item to buffer.\r
-                                p_uart->tx_ptr =  (uint8_t*) p_uart->tx_head;\r
-                                en_tx_flg = true;\r
-                                p_uart->tx_len_cur = size;\r
-                            }\r
-                        }\r
-                        else {\r
-                            //Can not get data from ring buffer, return;\r
-                            break;\r
-                        }\r
-                    }\r
-                    if(p_uart->tx_len_tot > 0 && p_uart->tx_ptr && p_uart->tx_len_cur > 0) {\r
-                        //To fill the TX FIFO.\r
-                        int send_len = p_uart->tx_len_cur > tx_fifo_rem ? tx_fifo_rem : p_uart->tx_len_cur;\r
-                        for(buf_idx = 0; buf_idx < send_len; buf_idx++) {\r
-                            WRITE_PERI_REG(UART_FIFO_AHB_REG(uart_num), *(p_uart->tx_ptr++) & 0xff);\r
-                        }\r
-                        p_uart->tx_len_tot -= send_len;\r
-                        p_uart->tx_len_cur -= send_len;\r
-                        tx_fifo_rem -= send_len;\r
-                        if(p_uart->tx_len_cur == 0) {\r
-                            //Return item to ring buffer.\r
-                            vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, p_uart->tx_head, &HPTaskAwoken);\r
-                            if(HPTaskAwoken == pdTRUE) {\r
-                                portYIELD_FROM_ISR() ;\r
-                            }\r
-                            p_uart->tx_head = NULL;\r
-                            p_uart->tx_ptr = NULL;\r
-                            //Sending item done, now we need to send break if there is a record.\r
-                            //Set TX break signal after FIFO is empty\r
-                            if(p_uart->tx_brk_flg == 1 && p_uart->tx_len_tot == 0) {\r
-                                UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);\r
-                                uart_reg->int_ena.tx_brk_done = 0;\r
-                                uart_reg->idle_conf.tx_brk_num = p_uart->tx_brk_len;\r
-                                uart_reg->conf0.txd_brk = 1;\r
-                                uart_reg->int_clr.tx_brk_done = 1;\r
-                                uart_reg->int_ena.tx_brk_done = 1;\r
-                                UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);\r
-                                p_uart->tx_waiting_brk = 1;\r
-                            } else {\r
-                                //enable TX empty interrupt\r
-                                en_tx_flg = true;\r
-                            }\r
-                        } else {\r
-                            //enable TX empty interrupt\r
-                            en_tx_flg = true;\r
-                        }\r
-                    }\r
-                }\r
-                if(en_tx_flg) {\r
-                    UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);\r
-                    uart_reg->int_clr.txfifo_empty = 1;\r
-                    uart_reg->int_ena.txfifo_empty = 1;\r
-                    UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);\r
-                }\r
-            }\r
-        }\r
-        else if((uart_intr_status & UART_RXFIFO_TOUT_INT_ST_M) || (uart_intr_status & UART_RXFIFO_FULL_INT_ST_M)) {\r
-            if(p_uart->rx_buffer_full_flg == false) {\r
-                //Get the buffer from the FIFO\r
-                rx_fifo_len = uart_reg->status.rxfifo_cnt;\r
-                p_uart->rx_stash_len = rx_fifo_len;\r
-                //We have to read out all data in RX FIFO to clear the interrupt signal\r
-                while(buf_idx < rx_fifo_len) {\r
-                    p_uart->rx_data_buf[buf_idx++] = uart_reg->fifo.rw_byte;\r
-                }\r
-                //After Copying the Data From FIFO ,Clear intr_status\r
-                UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);\r
-                uart_reg->int_clr.rxfifo_tout = 1;\r
-                uart_reg->int_clr.rxfifo_full = 1;\r
-                UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);\r
-                uart_event.type = UART_DATA;\r
-                uart_event.size = rx_fifo_len;\r
-                //If we fail to push data to ring buffer, we will have to stash the data, and send next time.\r
-                //Mainly for applications that uses flow control or small ring buffer.\r
-                if(pdFALSE == xRingbufferSendFromISR(p_uart->rx_ring_buf, p_uart->rx_data_buf, p_uart->rx_stash_len, &HPTaskAwoken)) {\r
-                    UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);\r
-                    uart_reg->int_ena.rxfifo_full = 0;\r
-                    uart_reg->int_ena.rxfifo_tout = 0;\r
-                    UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);\r
-                    p_uart->rx_buffer_full_flg = true;\r
-                    uart_event.type = UART_BUFFER_FULL;\r
-                } else {\r
-                    uart_event.type = UART_DATA;\r
-                }\r
-                if(HPTaskAwoken == pdTRUE) {\r
-                    portYIELD_FROM_ISR() ;\r
-                }\r
-            } else {\r
-                UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);\r
-                uart_reg->int_ena.rxfifo_full = 0;\r
-                uart_reg->int_ena.rxfifo_tout = 0;\r
-                uart_reg->int_clr.val = UART_RXFIFO_FULL_INT_CLR_M | UART_RXFIFO_TOUT_INT_CLR_M;\r
-                UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);\r
-                uart_event.type = UART_BUFFER_FULL;\r
-            }\r
-        } else if(uart_intr_status & UART_RXFIFO_OVF_INT_ST_M) {\r
-            UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);\r
-            uart_reg->conf0.rxfifo_rst = 1;\r
-            uart_reg->conf0.rxfifo_rst = 0;\r
-            uart_reg->int_clr.rxfifo_ovf = 1;\r
-            UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);\r
-            uart_event.type = UART_FIFO_OVF;\r
-        } else if(uart_intr_status & UART_BRK_DET_INT_ST_M) {\r
-            uart_reg->int_clr.brk_det = 1;\r
-            uart_event.type = UART_BREAK;\r
-        } else if(uart_intr_status & UART_PARITY_ERR_INT_ST_M ) {\r
-            uart_reg->int_clr.parity_err = 1;\r
-            uart_event.type = UART_FRAME_ERR;\r
-        } else if(uart_intr_status & UART_FRM_ERR_INT_ST_M) {\r
-            uart_reg->int_clr.frm_err = 1;\r
-            uart_event.type = UART_PARITY_ERR;\r
-        } else if(uart_intr_status & UART_TX_BRK_DONE_INT_ST_M) {\r
-            UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);\r
-            uart_reg->conf0.txd_brk = 0;\r
-            uart_reg->int_ena.tx_brk_done = 0;\r
-            uart_reg->int_clr.tx_brk_done = 1;\r
-            if(p_uart->tx_brk_flg == 1) {\r
-                uart_reg->int_ena.txfifo_empty = 1;\r
-            }\r
-            UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);\r
-            if(p_uart->tx_brk_flg == 1) {\r
-                p_uart->tx_brk_flg = 0;\r
-                p_uart->tx_waiting_brk = 0;\r
-            } else {\r
-                xSemaphoreGiveFromISR(p_uart->tx_brk_sem, &HPTaskAwoken);\r
-                if(HPTaskAwoken == pdTRUE) {\r
-                    portYIELD_FROM_ISR() ;\r
-                }\r
-            }\r
-        } else if(uart_intr_status & UART_TX_BRK_IDLE_DONE_INT_ST_M) {\r
-            UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);\r
-            uart_reg->int_ena.tx_brk_idle_done = 0;\r
-            uart_reg->int_clr.tx_brk_idle_done = 1;\r
-            UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);\r
-        } else if(uart_intr_status & UART_TX_DONE_INT_ST_M) {\r
-            UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);\r
-            uart_reg->int_ena.tx_done = 0;\r
-            uart_reg->int_clr.tx_done = 1;\r
-            UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);\r
-            xSemaphoreGiveFromISR(p_uart_obj[uart_num]->tx_done_sem, &HPTaskAwoken);\r
-            if(HPTaskAwoken == pdTRUE) {\r
-                portYIELD_FROM_ISR() ;\r
-            }\r
-        }\r
-        else {\r
-            uart_reg->int_clr.val = uart_intr_status; /*simply clear all other intr status*/\r
-            uart_event.type = UART_EVENT_MAX;\r
-        }\r
-\r
-        if(uart_event.type != UART_EVENT_MAX && p_uart->xQueueUart) {\r
-            xQueueSendFromISR(p_uart->xQueueUart, (void * )&uart_event, &HPTaskAwoken);\r
-            if(HPTaskAwoken == pdTRUE) {\r
-                portYIELD_FROM_ISR() ;\r
-            }\r
-        }\r
-        uart_intr_status = uart_reg->int_st.val;\r
-    }\r
-}\r
-\r
-/**************************************************************/\r
-esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait)\r
-{\r
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);\r
-    UART_CHECK((p_uart_obj[uart_num]), "uart driver error", ESP_FAIL);\r
-    BaseType_t res;\r
-    portTickType ticks_end = xTaskGetTickCount() + ticks_to_wait;\r
-    //Take tx_mux\r
-    res = xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)ticks_to_wait);\r
-    if(res == pdFALSE) {\r
-        return ESP_ERR_TIMEOUT;\r
-    }\r
-    ticks_to_wait = ticks_end - xTaskGetTickCount();\r
-    xSemaphoreTake(p_uart_obj[uart_num]->tx_done_sem, 0);\r
-    ticks_to_wait = ticks_end - xTaskGetTickCount();\r
-    if(UART[uart_num]->status.txfifo_cnt == 0) {\r
-        xSemaphoreGive(p_uart_obj[uart_num]->tx_mux);\r
-        return ESP_OK;\r
-    }\r
-    uart_enable_intr_mask(uart_num, UART_TX_DONE_INT_ENA_M);\r
-    //take 2nd tx_done_sem, wait given from ISR\r
-    res = xSemaphoreTake(p_uart_obj[uart_num]->tx_done_sem, (portTickType)ticks_to_wait);\r
-    if(res == pdFALSE) {\r
-        uart_disable_intr_mask(uart_num, UART_TX_DONE_INT_ENA_M);\r
-        xSemaphoreGive(p_uart_obj[uart_num]->tx_mux);\r
-        return ESP_ERR_TIMEOUT;\r
-    }\r
-    xSemaphoreGive(p_uart_obj[uart_num]->tx_mux);\r
-    return ESP_OK;\r
-}\r
-\r
-static esp_err_t uart_set_break(uart_port_t uart_num, int break_num)\r
-{\r
-    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);\r
-    UART[uart_num]->idle_conf.tx_brk_num = break_num;\r
-    UART[uart_num]->conf0.txd_brk = 1;\r
-    UART[uart_num]->int_clr.tx_brk_done = 1;\r
-    UART[uart_num]->int_ena.tx_brk_done = 1;\r
-    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);\r
-    return ESP_OK;\r
-}\r
-\r
-//Fill UART tx_fifo and return a number,\r
-//This function by itself is not thread-safe, always call from within a muxed section.\r
-static int uart_fill_fifo(uart_port_t uart_num, const char* buffer, uint32_t len)\r
-{\r
-    uint8_t i = 0;\r
-    uint8_t tx_fifo_cnt = UART[uart_num]->status.txfifo_cnt;\r
-    uint8_t tx_remain_fifo_cnt = (UART_FIFO_LEN - tx_fifo_cnt);\r
-    uint8_t copy_cnt = (len >= tx_remain_fifo_cnt ? tx_remain_fifo_cnt : len);\r
-    for(i = 0; i < copy_cnt; i++) {\r
-        WRITE_PERI_REG(UART_FIFO_AHB_REG(uart_num), buffer[i]);\r
-    }\r
-    return copy_cnt;\r
-}\r
-\r
-int uart_tx_chars(uart_port_t uart_num, const char* buffer, uint32_t len)\r
-{\r
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", (-1));\r
-    UART_CHECK((p_uart_obj[uart_num]), "uart driver error", (-1));\r
-    UART_CHECK(buffer, "buffer null", (-1));\r
-    if(len == 0) {\r
-        return 0;\r
-    }\r
-    xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)portMAX_DELAY);\r
-    int tx_len = uart_fill_fifo(uart_num, (const char*) buffer, len);\r
-    xSemaphoreGive(p_uart_obj[uart_num]->tx_mux);\r
-    return tx_len;\r
-}\r
-\r
-static int uart_tx_all(uart_port_t uart_num, const char* src, size_t size, bool brk_en, int brk_len)\r
-{\r
-    if(size == 0) {\r
-        return 0;\r
-    }\r
-    size_t original_size = size;\r
-\r
-    //lock for uart_tx\r
-    xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)portMAX_DELAY);\r
-    if(p_uart_obj[uart_num]->tx_buf_size > 0) {\r
-        int max_size = xRingbufferGetMaxItemSize(p_uart_obj[uart_num]->tx_ring_buf);\r
-        int offset = 0;\r
-        uart_tx_data_t evt;\r
-        evt.tx_data.size = size;\r
-        evt.tx_data.brk_len = brk_len;\r
-        if(brk_en) {\r
-            evt.type = UART_DATA_BREAK;\r
-        } else {\r
-            evt.type = UART_DATA;\r
-        }\r
-        xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) &evt, sizeof(uart_tx_data_t), portMAX_DELAY);\r
-        while(size > 0) {\r
-            int send_size = size > max_size / 2 ? max_size / 2 : size;\r
-            xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) (src + offset), send_size, portMAX_DELAY);\r
-            size -= send_size;\r
-            offset += send_size;\r
-        }\r
-        xSemaphoreGive(p_uart_obj[uart_num]->tx_mux);\r
-        uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT);\r
-    } else {\r
-        while(size) {\r
-            //semaphore for tx_fifo available\r
-            if(pdTRUE == xSemaphoreTake(p_uart_obj[uart_num]->tx_fifo_sem, (portTickType)portMAX_DELAY)) {\r
-                size_t sent = uart_fill_fifo(uart_num, (char*) src, size);\r
-                if(sent < size) {\r
-                    p_uart_obj[uart_num]->tx_waiting_fifo = true;\r
-                    uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT);\r
-                }\r
-                size -= sent;\r
-                src += sent;\r
-            }\r
-        }\r
-        if(brk_en) {\r
-            uart_set_break(uart_num, brk_len);\r
-            xSemaphoreTake(p_uart_obj[uart_num]->tx_brk_sem, (portTickType)portMAX_DELAY);\r
-        }\r
-        xSemaphoreGive(p_uart_obj[uart_num]->tx_fifo_sem);\r
-    }\r
-    xSemaphoreGive(p_uart_obj[uart_num]->tx_mux);\r
-    return original_size;\r
-}\r
-\r
-int uart_write_bytes(uart_port_t uart_num, const char* src, size_t size)\r
-{\r
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", (-1));\r
-    UART_CHECK((p_uart_obj[uart_num] != NULL), "uart driver error", (-1));\r
-    UART_CHECK(src, "buffer null", (-1));\r
-    return uart_tx_all(uart_num, src, size, 0, 0);\r
-}\r
-\r
-int uart_write_bytes_with_break(uart_port_t uart_num, const char* src, size_t size, int brk_len)\r
-{\r
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", (-1));\r
-    UART_CHECK((p_uart_obj[uart_num]), "uart driver error", (-1));\r
-    UART_CHECK((size > 0), "uart size error", (-1));\r
-    UART_CHECK((src), "uart data null", (-1));\r
-    UART_CHECK((brk_len > 0 && brk_len < 256), "break_num error", (-1));\r
-    return uart_tx_all(uart_num, src, size, 1, brk_len);\r
-}\r
-\r
-int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickType_t ticks_to_wait)\r
-{\r
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", (-1));\r
-    UART_CHECK((buf), "uart_num error", (-1));\r
-    UART_CHECK((p_uart_obj[uart_num]), "uart driver error", (-1));\r
-    uint8_t* data = NULL;\r
-    size_t size;\r
-    size_t copy_len = 0;\r
-    int len_tmp;\r
-    if(xSemaphoreTake(p_uart_obj[uart_num]->rx_mux,(portTickType)ticks_to_wait) != pdTRUE) {\r
-        return -1;\r
-    }\r
-    while(length) {\r
-        if(p_uart_obj[uart_num]->rx_cur_remain == 0) {\r
-            data = (uint8_t*) xRingbufferReceive(p_uart_obj[uart_num]->rx_ring_buf, &size, (portTickType) ticks_to_wait);\r
-            if(data) {\r
-                p_uart_obj[uart_num]->rx_head_ptr = data;\r
-                p_uart_obj[uart_num]->rx_ptr = data;\r
-                p_uart_obj[uart_num]->rx_cur_remain = size;\r
-            } else {\r
-                xSemaphoreGive(p_uart_obj[uart_num]->rx_mux);\r
-                return copy_len;\r
-            }\r
-        }\r
-        if(p_uart_obj[uart_num]->rx_cur_remain > length) {\r
-            len_tmp = length;\r
-        } else {\r
-            len_tmp = p_uart_obj[uart_num]->rx_cur_remain;\r
-        }\r
-        memcpy(buf + copy_len, p_uart_obj[uart_num]->rx_ptr, len_tmp);\r
-        p_uart_obj[uart_num]->rx_ptr += len_tmp;\r
-        p_uart_obj[uart_num]->rx_cur_remain -= len_tmp;\r
-        copy_len += len_tmp;\r
-        length -= len_tmp;\r
-        if(p_uart_obj[uart_num]->rx_cur_remain == 0) {\r
-            vRingbufferReturnItem(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->rx_head_ptr);\r
-            p_uart_obj[uart_num]->rx_head_ptr = NULL;\r
-            p_uart_obj[uart_num]->rx_ptr = NULL;\r
-            if(p_uart_obj[uart_num]->rx_buffer_full_flg) {\r
-                BaseType_t res = xRingbufferSend(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->rx_data_buf, p_uart_obj[uart_num]->rx_stash_len, 1);\r
-                if(res == pdTRUE) {\r
-                    p_uart_obj[uart_num]->rx_buffer_full_flg = false;\r
-                    uart_enable_rx_intr(p_uart_obj[uart_num]->uart_num);\r
-                }\r
-            }\r
-        }\r
-    }\r
-    xSemaphoreGive(p_uart_obj[uart_num]->rx_mux);\r
-    return copy_len;\r
-}\r
-\r
-esp_err_t uart_flush(uart_port_t uart_num)\r
-{\r
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);\r
-    UART_CHECK((p_uart_obj[uart_num]), "uart driver error", ESP_FAIL);\r
-    uart_obj_t* p_uart = p_uart_obj[uart_num];\r
-    uint8_t* data;\r
-    size_t size;\r
-\r
-    //rx sem protect the ring buffer read related functions\r
-    xSemaphoreTake(p_uart->rx_mux, (portTickType)portMAX_DELAY);\r
-    esp_intr_disable(p_uart->intr_handle);\r
-    while(true) {\r
-        if(p_uart->rx_head_ptr) {\r
-            vRingbufferReturnItem(p_uart->rx_ring_buf, p_uart->rx_head_ptr);\r
-            p_uart->rx_ptr = NULL;\r
-            p_uart->rx_cur_remain = 0;\r
-            p_uart->rx_head_ptr = NULL;\r
-        }\r
-        data = (uint8_t*) xRingbufferReceive(p_uart->rx_ring_buf, &size, (portTickType) 0);\r
-        if(data == NULL) {\r
-            break;\r
-        }\r
-        vRingbufferReturnItem(p_uart->rx_ring_buf, data);\r
-    }\r
-    p_uart->rx_ptr = NULL;\r
-    p_uart->rx_cur_remain = 0;\r
-    p_uart->rx_head_ptr = NULL;\r
-    esp_intr_enable(p_uart->intr_handle);\r
-    xSemaphoreGive(p_uart->rx_mux);\r
-\r
-    if(p_uart->tx_buf_size > 0) {\r
-        xSemaphoreTake(p_uart->tx_mux, (portTickType)portMAX_DELAY);\r
-        esp_intr_disable(p_uart->intr_handle);\r
-        UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);\r
-        UART[uart_num]->int_ena.txfifo_empty = 0;\r
-        UART[uart_num]->int_clr.txfifo_empty = 1;\r
-        UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);\r
-        do {\r
-            data = (uint8_t*) xRingbufferReceive(p_uart->tx_ring_buf, &size, (portTickType) 0);\r
-            if(data == NULL) {\r
-                break;\r
-            }\r
-            vRingbufferReturnItem(p_uart->rx_ring_buf, data);\r
-        } while(1);\r
-        p_uart->tx_brk_flg = 0;\r
-        p_uart->tx_brk_len = 0;\r
-        p_uart->tx_head = NULL;\r
-        p_uart->tx_len_cur = 0;\r
-        p_uart->tx_len_tot = 0;\r
-        p_uart->tx_ptr = NULL;\r
-        p_uart->tx_waiting_brk = 0;\r
-        p_uart->tx_waiting_fifo = false;\r
-        esp_intr_enable(p_uart->intr_handle);\r
-        xSemaphoreGive(p_uart->tx_mux);\r
-    }\r
-    uart_reset_fifo(uart_num);\r
-    return ESP_OK;\r
-}\r
-\r
-esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, void* uart_queue, int intr_alloc_flags)\r
-{\r
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);\r
-    UART_CHECK((rx_buffer_size > 0), "uart rx buffer length error", ESP_FAIL);\r
-    if(p_uart_obj[uart_num] == NULL) {\r
-        p_uart_obj[uart_num] = (uart_obj_t*) malloc(sizeof(uart_obj_t));\r
-        if(p_uart_obj[uart_num] == NULL) {\r
-            ESP_LOGE(UART_TAG, "UART driver malloc error");\r
-            return ESP_FAIL;\r
-        }\r
-        p_uart_obj[uart_num]->uart_num = uart_num;\r
-        p_uart_obj[uart_num]->tx_fifo_sem = xSemaphoreCreateBinary();\r
-        xSemaphoreGive(p_uart_obj[uart_num]->tx_fifo_sem);\r
-        p_uart_obj[uart_num]->tx_done_sem = xSemaphoreCreateBinary();\r
-        p_uart_obj[uart_num]->tx_brk_sem = xSemaphoreCreateBinary();\r
-        p_uart_obj[uart_num]->tx_mux = xSemaphoreCreateMutex();\r
-        p_uart_obj[uart_num]->rx_mux = xSemaphoreCreateMutex();\r
-        p_uart_obj[uart_num]->queue_size = queue_size;\r
-        p_uart_obj[uart_num]->tx_ptr = NULL;\r
-        p_uart_obj[uart_num]->tx_head = NULL;\r
-        p_uart_obj[uart_num]->tx_len_tot = 0;\r
-        p_uart_obj[uart_num]->tx_brk_flg = 0;\r
-        p_uart_obj[uart_num]->tx_brk_len = 0;\r
-        p_uart_obj[uart_num]->tx_waiting_brk = 0;\r
-\r
-        if(uart_queue) {\r
-            p_uart_obj[uart_num]->xQueueUart = xQueueCreate(queue_size, sizeof(uart_event_t));\r
-            *((QueueHandle_t*) uart_queue) = p_uart_obj[uart_num]->xQueueUart;\r
-            ESP_LOGI(UART_TAG, "queue free spaces: %d", uxQueueSpacesAvailable(p_uart_obj[uart_num]->xQueueUart));\r
-        } else {\r
-            p_uart_obj[uart_num]->xQueueUart = NULL;\r
-        }\r
-        p_uart_obj[uart_num]->rx_buffer_full_flg = false;\r
-        p_uart_obj[uart_num]->tx_waiting_fifo = false;\r
-        p_uart_obj[uart_num]->rx_ptr = NULL;\r
-        p_uart_obj[uart_num]->rx_cur_remain = 0;\r
-        p_uart_obj[uart_num]->rx_head_ptr = NULL;\r
-        p_uart_obj[uart_num]->rx_ring_buf = xRingbufferCreate(rx_buffer_size, RINGBUF_TYPE_BYTEBUF);\r
-        if(tx_buffer_size > 0) {\r
-            p_uart_obj[uart_num]->tx_ring_buf = xRingbufferCreate(tx_buffer_size, RINGBUF_TYPE_NOSPLIT);\r
-            p_uart_obj[uart_num]->tx_buf_size = tx_buffer_size;\r
-        } else {\r
-            p_uart_obj[uart_num]->tx_ring_buf = NULL;\r
-            p_uart_obj[uart_num]->tx_buf_size = 0;\r
-        }\r
-    } else {\r
-        ESP_LOGE(UART_TAG, "UART driver already installed");\r
-        return ESP_FAIL;\r
-    }\r
-    uart_isr_register(uart_num, uart_rx_intr_handler_default, p_uart_obj[uart_num], intr_alloc_flags);\r
-    uart_intr_config_t uart_intr = {\r
-        .intr_enable_mask = UART_RXFIFO_FULL_INT_ENA_M\r
-                            | UART_RXFIFO_TOUT_INT_ENA_M\r
-                            | UART_FRM_ERR_INT_ENA_M\r
-                            | UART_RXFIFO_OVF_INT_ENA_M\r
-                            | UART_BRK_DET_INT_ENA_M\r
-                            | UART_PARITY_ERR_INT_ENA_M,\r
-        .rxfifo_full_thresh = UART_FULL_THRESH_DEFAULT,\r
-        .rx_timeout_thresh = UART_TOUT_THRESH_DEFAULT,\r
-        .txfifo_empty_intr_thresh = UART_EMPTY_THRESH_DEFAULT\r
-    };\r
-    uart_intr_config(uart_num, &uart_intr);\r
-    return ESP_OK;\r
-}\r
-\r
-//Make sure no other tasks are still using UART before you call this function\r
-esp_err_t uart_driver_delete(uart_port_t uart_num)\r
-{\r
-    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);\r
-    if(p_uart_obj[uart_num] == NULL) {\r
-        ESP_LOGI(UART_TAG, "ALREADY NULL");\r
-        return ESP_OK;\r
-    }\r
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
+    if (p_uart_obj[uart_num]->intr_handle==NULL) return ESP_ERR_INVALID_ARG;
+    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
+    ret=esp_intr_free(p_uart_obj[uart_num]->intr_handle);
+    p_uart_obj[uart_num]->intr_handle=NULL;
+    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
+    return ret;
+}
+
+//internal signal can be output to multiple GPIO pads
+//only one GPIO pad can connect with input signal
+esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num)
+{
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
+    UART_CHECK((tx_io_num < 0 || (GPIO_IS_VALID_OUTPUT_GPIO(tx_io_num))), "tx_io_num error", ESP_FAIL);
+    UART_CHECK((rx_io_num < 0 || (GPIO_IS_VALID_GPIO(rx_io_num))), "rx_io_num error", ESP_FAIL);
+    UART_CHECK((rts_io_num < 0 || (GPIO_IS_VALID_OUTPUT_GPIO(rts_io_num))), "rts_io_num error", ESP_FAIL);
+    UART_CHECK((cts_io_num < 0 || (GPIO_IS_VALID_GPIO(cts_io_num))), "cts_io_num error", ESP_FAIL);
+
+    int tx_sig, rx_sig, rts_sig, cts_sig;
+    switch(uart_num) {
+        case UART_NUM_0:
+            tx_sig = U0TXD_OUT_IDX;
+            rx_sig = U0RXD_IN_IDX;
+            rts_sig = U0RTS_OUT_IDX;
+            cts_sig = U0CTS_IN_IDX;
+            break;
+        case UART_NUM_1:
+            tx_sig = U1TXD_OUT_IDX;
+            rx_sig = U1RXD_IN_IDX;
+            rts_sig = U1RTS_OUT_IDX;
+            cts_sig = U1CTS_IN_IDX;
+            break;
+        case UART_NUM_2:
+            tx_sig = U2TXD_OUT_IDX;
+            rx_sig = U2RXD_IN_IDX;
+            rts_sig = U2RTS_OUT_IDX;
+            cts_sig = U2CTS_IN_IDX;
+            break;
+        case UART_NUM_MAX:
+            default:
+            tx_sig = U0TXD_OUT_IDX;
+            rx_sig = U0RXD_IN_IDX;
+            rts_sig = U0RTS_OUT_IDX;
+            cts_sig = U0CTS_IN_IDX;
+            break;
+    }
+    if(tx_io_num >= 0) {
+        PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[tx_io_num], PIN_FUNC_GPIO);
+        gpio_set_direction(tx_io_num, GPIO_MODE_OUTPUT);
+        gpio_matrix_out(tx_io_num, tx_sig, 0, 0);
+    }
+
+    if(rx_io_num >= 0) {
+        PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[rx_io_num], PIN_FUNC_GPIO);
+        gpio_set_direction(rx_io_num, GPIO_MODE_INPUT);
+        gpio_matrix_in(rx_io_num, rx_sig, 0);
+    }
+    if(rts_io_num >= 0) {
+        PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[rts_io_num], PIN_FUNC_GPIO);
+        gpio_set_direction(rts_io_num, GPIO_MODE_OUTPUT);
+        gpio_matrix_out(rts_io_num, rts_sig, 0, 0);
+    }
+    if(cts_io_num >= 0) {
+        PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[cts_io_num], PIN_FUNC_GPIO);
+        gpio_set_direction(cts_io_num, GPIO_MODE_INPUT);
+        gpio_matrix_in(cts_io_num, cts_sig, 0);
+    }
+    return ESP_OK;
+}
+
+esp_err_t uart_set_rts(uart_port_t uart_num, int level)
+{
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
+    UART_CHECK((UART[uart_num]->conf1.rx_flow_en != 1), "disable hw flowctrl before using sw control", ESP_FAIL);
+    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
+    UART[uart_num]->conf0.sw_rts = level & 0x1;
+    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
+    return ESP_OK;
+}
+
+esp_err_t uart_set_dtr(uart_port_t uart_num, int level)
+{
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
+    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
+    UART[uart_num]->conf0.sw_dtr = level & 0x1;
+    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
+    return ESP_OK;
+}
+
+esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_config)
+{
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
+    UART_CHECK((uart_config), "param null", ESP_FAIL);
+    if(uart_num == UART_NUM_0) {
+        periph_module_enable(PERIPH_UART0_MODULE);
+    } else if(uart_num == UART_NUM_1) {
+        periph_module_enable(PERIPH_UART1_MODULE);
+    } else if(uart_num == UART_NUM_2) {
+        periph_module_enable(PERIPH_UART2_MODULE);
+    }
+    uart_set_hw_flow_ctrl(uart_num, uart_config->flow_ctrl, uart_config->rx_flow_ctrl_thresh);
+    uart_set_baudrate(uart_num, uart_config->baud_rate);
+    UART[uart_num]->conf0.val = (
+        (uart_config->parity << UART_PARITY_S)
+            | (uart_config->stop_bits << UART_STOP_BIT_NUM_S)
+            | (uart_config->data_bits << UART_BIT_NUM_S)
+            | ((uart_config->flow_ctrl & UART_HW_FLOWCTRL_CTS) ? UART_TX_FLOW_EN : 0x0)
+            | UART_TICK_REF_ALWAYS_ON_M);
+    return ESP_OK;
+}
+
+esp_err_t uart_intr_config(uart_port_t uart_num, const uart_intr_config_t *intr_conf)
+{
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
+    UART_CHECK((intr_conf), "param null", ESP_FAIL);
+    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
+    UART[uart_num]->int_clr.val = UART_INTR_MASK;
+    if(intr_conf->intr_enable_mask & UART_RXFIFO_TOUT_INT_ENA_M) {
+        UART[uart_num]->conf1.rx_tout_thrhd = ((intr_conf->rx_timeout_thresh) & UART_RX_TOUT_THRHD_V);
+        UART[uart_num]->conf1.rx_tout_en = 1;
+    } else {
+        UART[uart_num]->conf1.rx_tout_en = 0;
+    }
+    if(intr_conf->intr_enable_mask & UART_RXFIFO_FULL_INT_ENA_M) {
+        UART[uart_num]->conf1.rxfifo_full_thrhd = intr_conf->rxfifo_full_thresh;
+    }
+    if(intr_conf->intr_enable_mask & UART_TXFIFO_EMPTY_INT_ENA_M) {
+        UART[uart_num]->conf1.txfifo_empty_thrhd = intr_conf->txfifo_empty_intr_thresh;
+    }
+    UART[uart_num]->int_ena.val = intr_conf->intr_enable_mask;
+    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
+    return ESP_FAIL;
+}
+
+//internal isr handler for default driver code.
+static void IRAM_ATTR uart_rx_intr_handler_default(void *param)
+{
+    uart_obj_t *p_uart = (uart_obj_t*) param;
+    uint8_t uart_num = p_uart->uart_num;
+    uart_dev_t* uart_reg = UART[uart_num];
+    uint8_t buf_idx = 0;
+    uint32_t uart_intr_status = UART[uart_num]->int_st.val;
+    int rx_fifo_len = 0;
+    uart_event_t uart_event;
+    portBASE_TYPE HPTaskAwoken = 0;
+
+    while(uart_intr_status != 0x0) {
+        buf_idx = 0;
+        uart_event.type = UART_EVENT_MAX;
+        if(uart_intr_status & UART_TXFIFO_EMPTY_INT_ST_M) {
+            UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);
+            uart_reg->int_ena.txfifo_empty = 0;
+            uart_reg->int_clr.txfifo_empty = 1;
+            UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);
+            if(p_uart->tx_waiting_brk) {
+                continue;
+            }
+            //TX semaphore will only be used when tx_buf_size is zero.
+            if(p_uart->tx_waiting_fifo == true && p_uart->tx_buf_size == 0) {
+                p_uart->tx_waiting_fifo = false;
+                xSemaphoreGiveFromISR(p_uart->tx_fifo_sem, &HPTaskAwoken);
+                if(HPTaskAwoken == pdTRUE) {
+                    portYIELD_FROM_ISR() ;
+                }
+            }
+            else {
+                //We don't use TX ring buffer, because the size is zero.
+                if(p_uart->tx_buf_size == 0) {
+                    continue;
+                }
+                int tx_fifo_rem = UART_FIFO_LEN - UART[uart_num]->status.txfifo_cnt;
+                bool en_tx_flg = false;
+                //We need to put a loop here, in case all the buffer items are very short.
+                //That would cause a watch_dog reset because empty interrupt happens so often.
+                //Although this is a loop in ISR, this loop will execute at most 128 turns.
+                while(tx_fifo_rem) {
+                    if(p_uart->tx_len_tot == 0 || p_uart->tx_ptr == NULL || p_uart->tx_len_cur == 0) {
+                        size_t size;
+                        p_uart->tx_head = (uart_tx_data_t*) xRingbufferReceiveFromISR(p_uart->tx_ring_buf, &size);
+                        if(p_uart->tx_head) {
+                            //The first item is the data description
+                            //Get the first item to get the data information
+                            if(p_uart->tx_len_tot == 0) {
+                                p_uart->tx_ptr = NULL;
+                                p_uart->tx_len_tot = p_uart->tx_head->tx_data.size;
+                                if(p_uart->tx_head->type == UART_DATA_BREAK) {
+                                    p_uart->tx_len_tot = p_uart->tx_head->tx_data.size;
+                                    p_uart->tx_brk_flg = 1;
+                                    p_uart->tx_brk_len = p_uart->tx_head->tx_data.brk_len;
+                                }
+                                //We have saved the data description from the 1st item, return buffer.
+                                vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, p_uart->tx_head, &HPTaskAwoken);
+                                if(HPTaskAwoken == pdTRUE) {
+                                    portYIELD_FROM_ISR() ;
+                                }
+                            }else if(p_uart->tx_ptr == NULL) {
+                                //Update the TX item pointer, we will need this to return item to buffer.
+                                p_uart->tx_ptr =  (uint8_t*) p_uart->tx_head;
+                                en_tx_flg = true;
+                                p_uart->tx_len_cur = size;
+                            }
+                        }
+                        else {
+                            //Can not get data from ring buffer, return;
+                            break;
+                        }
+                    }
+                    if(p_uart->tx_len_tot > 0 && p_uart->tx_ptr && p_uart->tx_len_cur > 0) {
+                        //To fill the TX FIFO.
+                        int send_len = p_uart->tx_len_cur > tx_fifo_rem ? tx_fifo_rem : p_uart->tx_len_cur;
+                        for(buf_idx = 0; buf_idx < send_len; buf_idx++) {
+                            WRITE_PERI_REG(UART_FIFO_AHB_REG(uart_num), *(p_uart->tx_ptr++) & 0xff);
+                        }
+                        p_uart->tx_len_tot -= send_len;
+                        p_uart->tx_len_cur -= send_len;
+                        tx_fifo_rem -= send_len;
+                        if(p_uart->tx_len_cur == 0) {
+                            //Return item to ring buffer.
+                            vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, p_uart->tx_head, &HPTaskAwoken);
+                            if(HPTaskAwoken == pdTRUE) {
+                                portYIELD_FROM_ISR() ;
+                            }
+                            p_uart->tx_head = NULL;
+                            p_uart->tx_ptr = NULL;
+                            //Sending item done, now we need to send break if there is a record.
+                            //Set TX break signal after FIFO is empty
+                            if(p_uart->tx_brk_flg == 1 && p_uart->tx_len_tot == 0) {
+                                UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);
+                                uart_reg->int_ena.tx_brk_done = 0;
+                                uart_reg->idle_conf.tx_brk_num = p_uart->tx_brk_len;
+                                uart_reg->conf0.txd_brk = 1;
+                                uart_reg->int_clr.tx_brk_done = 1;
+                                uart_reg->int_ena.tx_brk_done = 1;
+                                UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);
+                                p_uart->tx_waiting_brk = 1;
+                            } else {
+                                //enable TX empty interrupt
+                                en_tx_flg = true;
+                            }
+                        } else {
+                            //enable TX empty interrupt
+                            en_tx_flg = true;
+                        }
+                    }
+                }
+                if(en_tx_flg) {
+                    UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);
+                    uart_reg->int_clr.txfifo_empty = 1;
+                    uart_reg->int_ena.txfifo_empty = 1;
+                    UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);
+                }
+            }
+        }
+        else if((uart_intr_status & UART_RXFIFO_TOUT_INT_ST_M) || (uart_intr_status & UART_RXFIFO_FULL_INT_ST_M)) {
+            if(p_uart->rx_buffer_full_flg == false) {
+                //Get the buffer from the FIFO
+                rx_fifo_len = uart_reg->status.rxfifo_cnt;
+                p_uart->rx_stash_len = rx_fifo_len;
+                //We have to read out all data in RX FIFO to clear the interrupt signal
+                while(buf_idx < rx_fifo_len) {
+                    p_uart->rx_data_buf[buf_idx++] = uart_reg->fifo.rw_byte;
+                }
+                //After Copying the Data From FIFO ,Clear intr_status
+                UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);
+                uart_reg->int_clr.rxfifo_tout = 1;
+                uart_reg->int_clr.rxfifo_full = 1;
+                UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);
+                uart_event.type = UART_DATA;
+                uart_event.size = rx_fifo_len;
+                //If we fail to push data to ring buffer, we will have to stash the data, and send next time.
+                //Mainly for applications that uses flow control or small ring buffer.
+                if(pdFALSE == xRingbufferSendFromISR(p_uart->rx_ring_buf, p_uart->rx_data_buf, p_uart->rx_stash_len, &HPTaskAwoken)) {
+                    UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);
+                    uart_reg->int_ena.rxfifo_full = 0;
+                    uart_reg->int_ena.rxfifo_tout = 0;
+                    UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);
+                    p_uart->rx_buffer_full_flg = true;
+                    uart_event.type = UART_BUFFER_FULL;
+                } else {
+                    uart_event.type = UART_DATA;
+                }
+                if(HPTaskAwoken == pdTRUE) {
+                    portYIELD_FROM_ISR() ;
+                }
+            } else {
+                UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);
+                uart_reg->int_ena.rxfifo_full = 0;
+                uart_reg->int_ena.rxfifo_tout = 0;
+                uart_reg->int_clr.val = UART_RXFIFO_FULL_INT_CLR_M | UART_RXFIFO_TOUT_INT_CLR_M;
+                UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);
+                uart_event.type = UART_BUFFER_FULL;
+            }
+        } else if(uart_intr_status & UART_RXFIFO_OVF_INT_ST_M) {
+            UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);
+            uart_reg->conf0.rxfifo_rst = 1;
+            uart_reg->conf0.rxfifo_rst = 0;
+            uart_reg->int_clr.rxfifo_ovf = 1;
+            UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);
+            uart_event.type = UART_FIFO_OVF;
+        } else if(uart_intr_status & UART_BRK_DET_INT_ST_M) {
+            uart_reg->int_clr.brk_det = 1;
+            uart_event.type = UART_BREAK;
+        } else if(uart_intr_status & UART_PARITY_ERR_INT_ST_M ) {
+            uart_reg->int_clr.parity_err = 1;
+            uart_event.type = UART_FRAME_ERR;
+        } else if(uart_intr_status & UART_FRM_ERR_INT_ST_M) {
+            uart_reg->int_clr.frm_err = 1;
+            uart_event.type = UART_PARITY_ERR;
+        } else if(uart_intr_status & UART_TX_BRK_DONE_INT_ST_M) {
+            UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);
+            uart_reg->conf0.txd_brk = 0;
+            uart_reg->int_ena.tx_brk_done = 0;
+            uart_reg->int_clr.tx_brk_done = 1;
+            if(p_uart->tx_brk_flg == 1) {
+                uart_reg->int_ena.txfifo_empty = 1;
+            }
+            UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);
+            if(p_uart->tx_brk_flg == 1) {
+                p_uart->tx_brk_flg = 0;
+                p_uart->tx_waiting_brk = 0;
+            } else {
+                xSemaphoreGiveFromISR(p_uart->tx_brk_sem, &HPTaskAwoken);
+                if(HPTaskAwoken == pdTRUE) {
+                    portYIELD_FROM_ISR() ;
+                }
+            }
+        } else if(uart_intr_status & UART_TX_BRK_IDLE_DONE_INT_ST_M) {
+            UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);
+            uart_reg->int_ena.tx_brk_idle_done = 0;
+            uart_reg->int_clr.tx_brk_idle_done = 1;
+            UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);
+        } else if(uart_intr_status & UART_TX_DONE_INT_ST_M) {
+            UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);
+            uart_reg->int_ena.tx_done = 0;
+            uart_reg->int_clr.tx_done = 1;
+            UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);
+            xSemaphoreGiveFromISR(p_uart_obj[uart_num]->tx_done_sem, &HPTaskAwoken);
+            if(HPTaskAwoken == pdTRUE) {
+                portYIELD_FROM_ISR() ;
+            }
+        }
+        else {
+            uart_reg->int_clr.val = uart_intr_status; /*simply clear all other intr status*/
+            uart_event.type = UART_EVENT_MAX;
+        }
+
+        if(uart_event.type != UART_EVENT_MAX && p_uart->xQueueUart) {
+            xQueueSendFromISR(p_uart->xQueueUart, (void * )&uart_event, &HPTaskAwoken);
+            if(HPTaskAwoken == pdTRUE) {
+                portYIELD_FROM_ISR() ;
+            }
+        }
+        uart_intr_status = uart_reg->int_st.val;
+    }
+}
+
+/**************************************************************/
+esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait)
+{
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
+    UART_CHECK((p_uart_obj[uart_num]), "uart driver error", ESP_FAIL);
+    BaseType_t res;
+    portTickType ticks_end = xTaskGetTickCount() + ticks_to_wait;
+    //Take tx_mux
+    res = xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)ticks_to_wait);
+    if(res == pdFALSE) {
+        return ESP_ERR_TIMEOUT;
+    }
+    ticks_to_wait = ticks_end - xTaskGetTickCount();
+    xSemaphoreTake(p_uart_obj[uart_num]->tx_done_sem, 0);
+    ticks_to_wait = ticks_end - xTaskGetTickCount();
+    if(UART[uart_num]->status.txfifo_cnt == 0) {
+        xSemaphoreGive(p_uart_obj[uart_num]->tx_mux);
+        return ESP_OK;
+    }
+    uart_enable_intr_mask(uart_num, UART_TX_DONE_INT_ENA_M);
+    //take 2nd tx_done_sem, wait given from ISR
+    res = xSemaphoreTake(p_uart_obj[uart_num]->tx_done_sem, (portTickType)ticks_to_wait);
+    if(res == pdFALSE) {
+        uart_disable_intr_mask(uart_num, UART_TX_DONE_INT_ENA_M);
+        xSemaphoreGive(p_uart_obj[uart_num]->tx_mux);
+        return ESP_ERR_TIMEOUT;
+    }
+    xSemaphoreGive(p_uart_obj[uart_num]->tx_mux);
+    return ESP_OK;
+}
+
+static esp_err_t uart_set_break(uart_port_t uart_num, int break_num)
+{
+    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
+    UART[uart_num]->idle_conf.tx_brk_num = break_num;
+    UART[uart_num]->conf0.txd_brk = 1;
+    UART[uart_num]->int_clr.tx_brk_done = 1;
+    UART[uart_num]->int_ena.tx_brk_done = 1;
+    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
+    return ESP_OK;
+}
+
+//Fill UART tx_fifo and return a number,
+//This function by itself is not thread-safe, always call from within a muxed section.
+static int uart_fill_fifo(uart_port_t uart_num, const char* buffer, uint32_t len)
+{
+    uint8_t i = 0;
+    uint8_t tx_fifo_cnt = UART[uart_num]->status.txfifo_cnt;
+    uint8_t tx_remain_fifo_cnt = (UART_FIFO_LEN - tx_fifo_cnt);
+    uint8_t copy_cnt = (len >= tx_remain_fifo_cnt ? tx_remain_fifo_cnt : len);
+    for(i = 0; i < copy_cnt; i++) {
+        WRITE_PERI_REG(UART_FIFO_AHB_REG(uart_num), buffer[i]);
+    }
+    return copy_cnt;
+}
+
+int uart_tx_chars(uart_port_t uart_num, const char* buffer, uint32_t len)
+{
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", (-1));
+    UART_CHECK((p_uart_obj[uart_num]), "uart driver error", (-1));
+    UART_CHECK(buffer, "buffer null", (-1));
+    if(len == 0) {
+        return 0;
+    }
+    xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)portMAX_DELAY);
+    int tx_len = uart_fill_fifo(uart_num, (const char*) buffer, len);
+    xSemaphoreGive(p_uart_obj[uart_num]->tx_mux);
+    return tx_len;
+}
+
+static int uart_tx_all(uart_port_t uart_num, const char* src, size_t size, bool brk_en, int brk_len)
+{
+    if(size == 0) {
+        return 0;
+    }
+    size_t original_size = size;
+
+    //lock for uart_tx
+    xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)portMAX_DELAY);
+    if(p_uart_obj[uart_num]->tx_buf_size > 0) {
+        int max_size = xRingbufferGetMaxItemSize(p_uart_obj[uart_num]->tx_ring_buf);
+        int offset = 0;
+        uart_tx_data_t evt;
+        evt.tx_data.size = size;
+        evt.tx_data.brk_len = brk_len;
+        if(brk_en) {
+            evt.type = UART_DATA_BREAK;
+        } else {
+            evt.type = UART_DATA;
+        }
+        xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) &evt, sizeof(uart_tx_data_t), portMAX_DELAY);
+        while(size > 0) {
+            int send_size = size > max_size / 2 ? max_size / 2 : size;
+            xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) (src + offset), send_size, portMAX_DELAY);
+            size -= send_size;
+            offset += send_size;
+        }
+        xSemaphoreGive(p_uart_obj[uart_num]->tx_mux);
+        uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT);
+    } else {
+        while(size) {
+            //semaphore for tx_fifo available
+            if(pdTRUE == xSemaphoreTake(p_uart_obj[uart_num]->tx_fifo_sem, (portTickType)portMAX_DELAY)) {
+                size_t sent = uart_fill_fifo(uart_num, (char*) src, size);
+                if(sent < size) {
+                    p_uart_obj[uart_num]->tx_waiting_fifo = true;
+                    uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT);
+                }
+                size -= sent;
+                src += sent;
+            }
+        }
+        if(brk_en) {
+            uart_set_break(uart_num, brk_len);
+            xSemaphoreTake(p_uart_obj[uart_num]->tx_brk_sem, (portTickType)portMAX_DELAY);
+        }
+        xSemaphoreGive(p_uart_obj[uart_num]->tx_fifo_sem);
+    }
+    xSemaphoreGive(p_uart_obj[uart_num]->tx_mux);
+    return original_size;
+}
+
+int uart_write_bytes(uart_port_t uart_num, const char* src, size_t size)
+{
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", (-1));
+    UART_CHECK((p_uart_obj[uart_num] != NULL), "uart driver error", (-1));
+    UART_CHECK(src, "buffer null", (-1));
+    return uart_tx_all(uart_num, src, size, 0, 0);
+}
+
+int uart_write_bytes_with_break(uart_port_t uart_num, const char* src, size_t size, int brk_len)
+{
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", (-1));
+    UART_CHECK((p_uart_obj[uart_num]), "uart driver error", (-1));
+    UART_CHECK((size > 0), "uart size error", (-1));
+    UART_CHECK((src), "uart data null", (-1));
+    UART_CHECK((brk_len > 0 && brk_len < 256), "break_num error", (-1));
+    return uart_tx_all(uart_num, src, size, 1, brk_len);
+}
+
+int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickType_t ticks_to_wait)
+{
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", (-1));
+    UART_CHECK((buf), "uart_num error", (-1));
+    UART_CHECK((p_uart_obj[uart_num]), "uart driver error", (-1));
+    uint8_t* data = NULL;
+    size_t size;
+    size_t copy_len = 0;
+    int len_tmp;
+    if(xSemaphoreTake(p_uart_obj[uart_num]->rx_mux,(portTickType)ticks_to_wait) != pdTRUE) {
+        return -1;
+    }
+    while(length) {
+        if(p_uart_obj[uart_num]->rx_cur_remain == 0) {
+            data = (uint8_t*) xRingbufferReceive(p_uart_obj[uart_num]->rx_ring_buf, &size, (portTickType) ticks_to_wait);
+            if(data) {
+                p_uart_obj[uart_num]->rx_head_ptr = data;
+                p_uart_obj[uart_num]->rx_ptr = data;
+                p_uart_obj[uart_num]->rx_cur_remain = size;
+            } else {
+                xSemaphoreGive(p_uart_obj[uart_num]->rx_mux);
+                return copy_len;
+            }
+        }
+        if(p_uart_obj[uart_num]->rx_cur_remain > length) {
+            len_tmp = length;
+        } else {
+            len_tmp = p_uart_obj[uart_num]->rx_cur_remain;
+        }
+        memcpy(buf + copy_len, p_uart_obj[uart_num]->rx_ptr, len_tmp);
+        p_uart_obj[uart_num]->rx_ptr += len_tmp;
+        p_uart_obj[uart_num]->rx_cur_remain -= len_tmp;
+        copy_len += len_tmp;
+        length -= len_tmp;
+        if(p_uart_obj[uart_num]->rx_cur_remain == 0) {
+            vRingbufferReturnItem(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->rx_head_ptr);
+            p_uart_obj[uart_num]->rx_head_ptr = NULL;
+            p_uart_obj[uart_num]->rx_ptr = NULL;
+            if(p_uart_obj[uart_num]->rx_buffer_full_flg) {
+                BaseType_t res = xRingbufferSend(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->rx_data_buf, p_uart_obj[uart_num]->rx_stash_len, 1);
+                if(res == pdTRUE) {
+                    p_uart_obj[uart_num]->rx_buffer_full_flg = false;
+                    uart_enable_rx_intr(p_uart_obj[uart_num]->uart_num);
+                }
+            }
+        }
+    }
+    xSemaphoreGive(p_uart_obj[uart_num]->rx_mux);
+    return copy_len;
+}
+
+esp_err_t uart_flush(uart_port_t uart_num)
+{
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
+    UART_CHECK((p_uart_obj[uart_num]), "uart driver error", ESP_FAIL);
+    uart_obj_t* p_uart = p_uart_obj[uart_num];
+    uint8_t* data;
+    size_t size;
+
+    //rx sem protect the ring buffer read related functions
+    xSemaphoreTake(p_uart->rx_mux, (portTickType)portMAX_DELAY);
+    esp_intr_disable(p_uart->intr_handle);
+    while(true) {
+        if(p_uart->rx_head_ptr) {
+            vRingbufferReturnItem(p_uart->rx_ring_buf, p_uart->rx_head_ptr);
+            p_uart->rx_ptr = NULL;
+            p_uart->rx_cur_remain = 0;
+            p_uart->rx_head_ptr = NULL;
+        }
+        data = (uint8_t*) xRingbufferReceive(p_uart->rx_ring_buf, &size, (portTickType) 0);
+        if(data == NULL) {
+            break;
+        }
+        vRingbufferReturnItem(p_uart->rx_ring_buf, data);
+    }
+    p_uart->rx_ptr = NULL;
+    p_uart->rx_cur_remain = 0;
+    p_uart->rx_head_ptr = NULL;
+    esp_intr_enable(p_uart->intr_handle);
+    xSemaphoreGive(p_uart->rx_mux);
+
+    if(p_uart->tx_buf_size > 0) {
+        xSemaphoreTake(p_uart->tx_mux, (portTickType)portMAX_DELAY);
+        esp_intr_disable(p_uart->intr_handle);
+        UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
+        UART[uart_num]->int_ena.txfifo_empty = 0;
+        UART[uart_num]->int_clr.txfifo_empty = 1;
+        UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
+        do {
+            data = (uint8_t*) xRingbufferReceive(p_uart->tx_ring_buf, &size, (portTickType) 0);
+            if(data == NULL) {
+                break;
+            }
+            vRingbufferReturnItem(p_uart->rx_ring_buf, data);
+        } while(1);
+        p_uart->tx_brk_flg = 0;
+        p_uart->tx_brk_len = 0;
+        p_uart->tx_head = NULL;
+        p_uart->tx_len_cur = 0;
+        p_uart->tx_len_tot = 0;
+        p_uart->tx_ptr = NULL;
+        p_uart->tx_waiting_brk = 0;
+        p_uart->tx_waiting_fifo = false;
+        esp_intr_enable(p_uart->intr_handle);
+        xSemaphoreGive(p_uart->tx_mux);
+    }
+    uart_reset_fifo(uart_num);
+    return ESP_OK;
+}
+
+esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, void* uart_queue, int intr_alloc_flags)
+{
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
+    UART_CHECK((rx_buffer_size > 0), "uart rx buffer length error", ESP_FAIL);
+    if(p_uart_obj[uart_num] == NULL) {
+        p_uart_obj[uart_num] = (uart_obj_t*) malloc(sizeof(uart_obj_t));
+        if(p_uart_obj[uart_num] == NULL) {
+            ESP_LOGE(UART_TAG, "UART driver malloc error");
+            return ESP_FAIL;
+        }
+        p_uart_obj[uart_num]->uart_num = uart_num;
+        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();
+        p_uart_obj[uart_num]->tx_brk_sem = xSemaphoreCreateBinary();
+        p_uart_obj[uart_num]->tx_mux = xSemaphoreCreateMutex();
+        p_uart_obj[uart_num]->rx_mux = xSemaphoreCreateMutex();
+        p_uart_obj[uart_num]->queue_size = queue_size;
+        p_uart_obj[uart_num]->tx_ptr = NULL;
+        p_uart_obj[uart_num]->tx_head = NULL;
+        p_uart_obj[uart_num]->tx_len_tot = 0;
+        p_uart_obj[uart_num]->tx_brk_flg = 0;
+        p_uart_obj[uart_num]->tx_brk_len = 0;
+        p_uart_obj[uart_num]->tx_waiting_brk = 0;
+
+        if(uart_queue) {
+            p_uart_obj[uart_num]->xQueueUart = xQueueCreate(queue_size, sizeof(uart_event_t));
+            *((QueueHandle_t*) uart_queue) = p_uart_obj[uart_num]->xQueueUart;
+            ESP_LOGI(UART_TAG, "queue free spaces: %d", uxQueueSpacesAvailable(p_uart_obj[uart_num]->xQueueUart));
+        } else {
+            p_uart_obj[uart_num]->xQueueUart = NULL;
+        }
+        p_uart_obj[uart_num]->rx_buffer_full_flg = false;
+        p_uart_obj[uart_num]->tx_waiting_fifo = false;
+        p_uart_obj[uart_num]->rx_ptr = NULL;
+        p_uart_obj[uart_num]->rx_cur_remain = 0;
+        p_uart_obj[uart_num]->rx_head_ptr = NULL;
+        p_uart_obj[uart_num]->rx_ring_buf = xRingbufferCreate(rx_buffer_size, RINGBUF_TYPE_BYTEBUF);
+        if(tx_buffer_size > 0) {
+            p_uart_obj[uart_num]->tx_ring_buf = xRingbufferCreate(tx_buffer_size, RINGBUF_TYPE_NOSPLIT);
+            p_uart_obj[uart_num]->tx_buf_size = tx_buffer_size;
+        } else {
+            p_uart_obj[uart_num]->tx_ring_buf = NULL;
+            p_uart_obj[uart_num]->tx_buf_size = 0;
+        }
+    } else {
+        ESP_LOGE(UART_TAG, "UART driver already installed");
+        return ESP_FAIL;
+    }
+    uart_isr_register(uart_num, uart_rx_intr_handler_default, p_uart_obj[uart_num], intr_alloc_flags);
+    uart_intr_config_t uart_intr = {
+        .intr_enable_mask = UART_RXFIFO_FULL_INT_ENA_M
+                            | UART_RXFIFO_TOUT_INT_ENA_M
+                            | UART_FRM_ERR_INT_ENA_M
+                            | UART_RXFIFO_OVF_INT_ENA_M
+                            | UART_BRK_DET_INT_ENA_M
+                            | UART_PARITY_ERR_INT_ENA_M,
+        .rxfifo_full_thresh = UART_FULL_THRESH_DEFAULT,
+        .rx_timeout_thresh = UART_TOUT_THRESH_DEFAULT,
+        .txfifo_empty_intr_thresh = UART_EMPTY_THRESH_DEFAULT
+    };
+    uart_intr_config(uart_num, &uart_intr);
+    return ESP_OK;
+}
+
+//Make sure no other tasks are still using UART before you call this function
+esp_err_t uart_driver_delete(uart_port_t uart_num)
+{
+    UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
+    if(p_uart_obj[uart_num] == NULL) {
+        ESP_LOGI(UART_TAG, "ALREADY NULL");
+        return ESP_OK;
+    }
     esp_intr_free(p_uart_obj[uart_num]->intr_handle);
-    uart_disable_rx_intr(uart_num);\r
-    uart_disable_tx_intr(uart_num);\r
-\r
-    if(p_uart_obj[uart_num]->tx_fifo_sem) {\r
-        vSemaphoreDelete(p_uart_obj[uart_num]->tx_fifo_sem);\r
-        p_uart_obj[uart_num]->tx_fifo_sem = NULL;\r
-    }\r
-    if(p_uart_obj[uart_num]->tx_done_sem) {\r
-        vSemaphoreDelete(p_uart_obj[uart_num]->tx_done_sem);\r
-        p_uart_obj[uart_num]->tx_done_sem = NULL;\r
-    }\r
-    if(p_uart_obj[uart_num]->tx_brk_sem) {\r
-        vSemaphoreDelete(p_uart_obj[uart_num]->tx_brk_sem);\r
-        p_uart_obj[uart_num]->tx_brk_sem = NULL;\r
-    }\r
-    if(p_uart_obj[uart_num]->tx_mux) {\r
-        vSemaphoreDelete(p_uart_obj[uart_num]->tx_mux);\r
-        p_uart_obj[uart_num]->tx_mux = NULL;\r
-    }\r
-    if(p_uart_obj[uart_num]->rx_mux) {\r
-        vSemaphoreDelete(p_uart_obj[uart_num]->rx_mux);\r
-        p_uart_obj[uart_num]->rx_mux = NULL;\r
-    }\r
-    if(p_uart_obj[uart_num]->xQueueUart) {\r
-        vQueueDelete(p_uart_obj[uart_num]->xQueueUart);\r
-        p_uart_obj[uart_num]->xQueueUart = NULL;\r
-    }\r
-    if(p_uart_obj[uart_num]->rx_ring_buf) {\r
-        vRingbufferDelete(p_uart_obj[uart_num]->rx_ring_buf);\r
-        p_uart_obj[uart_num]->rx_ring_buf = NULL;\r
-    }\r
-    if(p_uart_obj[uart_num]->tx_ring_buf) {\r
-        vRingbufferDelete(p_uart_obj[uart_num]->tx_ring_buf);\r
-        p_uart_obj[uart_num]->tx_ring_buf = NULL;\r
-    }\r
-\r
-    free(p_uart_obj[uart_num]);\r
-    p_uart_obj[uart_num] = NULL;\r
-    return ESP_OK;\r
-}\r
+    uart_disable_rx_intr(uart_num);
+    uart_disable_tx_intr(uart_num);
+
+    if(p_uart_obj[uart_num]->tx_fifo_sem) {
+        vSemaphoreDelete(p_uart_obj[uart_num]->tx_fifo_sem);
+        p_uart_obj[uart_num]->tx_fifo_sem = NULL;
+    }
+    if(p_uart_obj[uart_num]->tx_done_sem) {
+        vSemaphoreDelete(p_uart_obj[uart_num]->tx_done_sem);
+        p_uart_obj[uart_num]->tx_done_sem = NULL;
+    }
+    if(p_uart_obj[uart_num]->tx_brk_sem) {
+        vSemaphoreDelete(p_uart_obj[uart_num]->tx_brk_sem);
+        p_uart_obj[uart_num]->tx_brk_sem = NULL;
+    }
+    if(p_uart_obj[uart_num]->tx_mux) {
+        vSemaphoreDelete(p_uart_obj[uart_num]->tx_mux);
+        p_uart_obj[uart_num]->tx_mux = NULL;
+    }
+    if(p_uart_obj[uart_num]->rx_mux) {
+        vSemaphoreDelete(p_uart_obj[uart_num]->rx_mux);
+        p_uart_obj[uart_num]->rx_mux = NULL;
+    }
+    if(p_uart_obj[uart_num]->xQueueUart) {
+        vQueueDelete(p_uart_obj[uart_num]->xQueueUart);
+        p_uart_obj[uart_num]->xQueueUart = NULL;
+    }
+    if(p_uart_obj[uart_num]->rx_ring_buf) {
+        vRingbufferDelete(p_uart_obj[uart_num]->rx_ring_buf);
+        p_uart_obj[uart_num]->rx_ring_buf = NULL;
+    }
+    if(p_uart_obj[uart_num]->tx_ring_buf) {
+        vRingbufferDelete(p_uart_obj[uart_num]->tx_ring_buf);
+        p_uart_obj[uart_num]->tx_ring_buf = NULL;
+    }
+
+    free(p_uart_obj[uart_num]);
+    p_uart_obj[uart_num] = NULL;
+    return ESP_OK;
+}