philippe44 5 lat temu
rodzic
commit
c44c31f6d4
2 zmienionych plików z 1456 dodań i 1465 usunięć
  1. 0 1465
      idf-patch/i2c.c
  2. 1456 0
      idf-patch/i2s.c

+ 0 - 1465
idf-patch/i2c.c

@@ -1,1465 +0,0 @@
-// 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 <stdio.h>
-#include "esp_types.h"
-#include "esp_attr.h"
-#include "esp_intr_alloc.h"
-#include "esp_log.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/i2c_periph.h"
-#include "driver/i2c.h"
-#include "driver/gpio.h"
-#include "driver/periph_ctrl.h"
-#include "esp_pm.h"
-#include "soc/soc_memory_layout.h"
-
-static const char* I2C_TAG = "i2c";
-#define I2C_CHECK(a, str, ret)  if(!(a)) {                                             \
-        ESP_LOGE(I2C_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str);      \
-        return (ret);                                                                   \
-        }
-
-static portMUX_TYPE i2c_spinlock[I2C_NUM_MAX] = {portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED};
-/* DRAM_ATTR is required to avoid I2C array placed in flash, due to accessed from ISR */
-static DRAM_ATTR i2c_dev_t* const I2C[I2C_NUM_MAX] = { &I2C0, &I2C1 };
-
-#define I2C_ENTER_CRITICAL_ISR(mux)    portENTER_CRITICAL_ISR(mux)
-#define I2C_EXIT_CRITICAL_ISR(mux)     portEXIT_CRITICAL_ISR(mux)
-#define I2C_ENTER_CRITICAL(mux)        portENTER_CRITICAL(mux)
-#define I2C_EXIT_CRITICAL(mux)         portEXIT_CRITICAL(mux)
-
-#define I2C_DRIVER_ERR_STR             "i2c driver install error"
-#define I2C_DRIVER_MALLOC_ERR_STR      "i2c driver malloc error"
-#define I2C_NUM_ERROR_STR              "i2c number error"
-#define I2C_TIMEING_VAL_ERR_STR        "i2c timing value error"
-#define I2C_ADDR_ERROR_STR             "i2c null address error"
-#define I2C_DRIVER_NOT_INSTALL_ERR_STR "i2c driver not installed"
-#define I2C_SLAVE_BUFFER_LEN_ERR_STR   "i2c buffer size too small for slave mode"
-#define I2C_EVT_QUEUE_ERR_STR          "i2c evt queue error"
-#define I2C_SEM_ERR_STR                "i2c semaphore error"
-#define I2C_BUF_ERR_STR                "i2c ringbuffer error"
-#define I2C_MASTER_MODE_ERR_STR        "Only allowed in master mode"
-#define I2C_MODE_SLAVE_ERR_STR         "Only allowed in slave mode"
-#define I2C_CMD_MALLOC_ERR_STR         "i2c command link malloc error"
-#define I2C_TRANS_MODE_ERR_STR         "i2c trans mode error"
-#define I2C_MODE_ERR_STR               "i2c mode error"
-#define I2C_SDA_IO_ERR_STR             "sda gpio number error"
-#define I2C_SCL_IO_ERR_STR             "scl gpio number error"
-#define I2C_CMD_LINK_INIT_ERR_STR      "i2c command link error"
-#define I2C_GPIO_PULLUP_ERR_STR        "this i2c pin does not support internal pull-up"
-#define I2C_ACK_TYPE_ERR_STR           "i2c ack type error"
-#define I2C_DATA_LEN_ERR_STR           "i2c data read length error"
-#define I2C_PSRAM_BUFFER_WARN_STR      "Using buffer allocated from psram"
-#define I2C_LOCK_ERR_STR               "Power lock creation error"
-#define I2C_FIFO_FULL_THRESH_VAL       (28)
-#define I2C_FIFO_EMPTY_THRESH_VAL      (5)
-#define I2C_IO_INIT_LEVEL              (1)
-#define I2C_CMD_ALIVE_INTERVAL_TICK    (1000 / portTICK_PERIOD_MS)
-#define I2C_CMD_EVT_ALIVE              (0)
-#define I2C_CMD_EVT_DONE               (1)
-#define I2C_EVT_QUEUE_LEN              (1)
-#define I2C_SLAVE_TIMEOUT_DEFAULT      (32000)     /* I2C slave timeout value, APB clock cycle number */
-#define I2C_SLAVE_SDA_SAMPLE_DEFAULT   (10)        /* I2C slave sample time after scl positive edge default value */
-#define I2C_SLAVE_SDA_HOLD_DEFAULT     (10)        /* I2C slave hold time after scl negative edge default value */
-#define I2C_MASTER_TOUT_CNUM_DEFAULT   (8)         /* I2C master timeout cycle number of I2C clock, after which the timeout interrupt will be triggered */
-#define I2C_ACKERR_CNT_MAX             (10)
-#define I2C_FILTER_CYC_NUM_DEF         (7)         /* The number of apb cycles filtered by default*/
-#define I2C_CLR_BUS_SCL_NUM            (9)
-#define I2C_CLR_BUS_HALF_PERIOD_US     (5)
-
-typedef struct {
-    uint8_t byte_num;  /*!< cmd byte number */
-    uint8_t ack_en;    /*!< ack check enable */
-    uint8_t ack_exp;   /*!< expected ack level to get */
-    uint8_t ack_val;   /*!< ack value to send */
-    uint8_t* data;     /*!< data address */
-    uint8_t byte_cmd;  /*!< to save cmd for one byte command mode */
-    i2c_opmode_t op_code; /*!< hardware cmd type */
-} i2c_cmd_t;
-
-typedef typeof(I2C[0]->command[0]) i2c_hw_cmd_t;
-
-typedef struct i2c_cmd_link{
-    i2c_cmd_t cmd;              /*!< command in current cmd link */
-    struct i2c_cmd_link *next;  /*!< next cmd link */
-} i2c_cmd_link_t;
-
-typedef struct {
-    i2c_cmd_link_t* head;     /*!< head of the command link */
-    i2c_cmd_link_t* cur;      /*!< last node of the command link */
-    i2c_cmd_link_t* free;     /*!< the first node to free of the command link */
-} i2c_cmd_desc_t;
-
-typedef enum {
-    I2C_STATUS_READ,      /*!< read status for current master command */
-    I2C_STATUS_WRITE,     /*!< write status for current master command */
-    I2C_STATUS_IDLE,      /*!< idle status for current master command */
-    I2C_STATUS_ACK_ERROR, /*!< ack error status for current master command */
-    I2C_STATUS_DONE,      /*!< I2C command done */
-    I2C_STATUS_TIMEOUT,   /*!< I2C bus status error, and operation timeout */
-} i2c_status_t;
-
-typedef struct {
-    int type;
-} i2c_cmd_evt_t;
-
-typedef struct {
-    int i2c_num;                     /*!< I2C port number */
-    int mode;                        /*!< I2C mode, master or slave */
-    intr_handle_t intr_handle;       /*!< I2C interrupt handle*/
-    int cmd_idx;                     /*!< record current command index, for master mode */
-    int status;                      /*!< record current command status, for master mode */
-    int rx_cnt;                      /*!< record current read index, for master mode */
-    uint8_t data_buf[I2C_FIFO_LEN];  /*!< a buffer to store i2c fifo data */
-
-    i2c_cmd_desc_t cmd_link;         /*!< I2C command link */
-    QueueHandle_t cmd_evt_queue;     /*!< I2C command event queue */
-#if CONFIG_SPIRAM_USE_MALLOC
-    uint8_t* evt_queue_storage;      /*!< The buffer that will hold the items in the queue */
-    int intr_alloc_flags;            /*!< Used to allocate the interrupt */
-    StaticQueue_t evt_queue_buffer;  /*!< The buffer that will hold the queue structure*/
-#endif
-    xSemaphoreHandle cmd_mux;        /*!< semaphore to lock command process */
-#ifdef CONFIG_PM_ENABLE
-    esp_pm_lock_handle_t pm_lock;
-#endif
-    size_t tx_fifo_remain;           /*!< tx fifo remain length, for master mode */
-    size_t rx_fifo_remain;           /*!< rx fifo remain length, for master mode */
-
-    xSemaphoreHandle slv_rx_mux;     /*!< slave rx buffer mux */
-    xSemaphoreHandle slv_tx_mux;     /*!< slave tx buffer mux */
-    size_t rx_buf_length;            /*!< rx buffer length */
-    RingbufHandle_t rx_ring_buf;     /*!< rx ringbuffer handler of slave mode */
-    size_t tx_buf_length;            /*!< tx buffer length */
-    RingbufHandle_t tx_ring_buf;     /*!< tx ringbuffer handler of slave mode */
-} i2c_obj_t;
-
-static i2c_obj_t *p_i2c_obj[I2C_NUM_MAX] = {0};
-static void i2c_isr_handler_default(void* arg);
-static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num);
-static esp_err_t IRAM_ATTR i2c_hw_fsm_reset(i2c_port_t i2c_num);
-
-/*
-    For i2c master mode, we don't need to use a buffer for the data, the APIs will execute the master commands
-and return after all of the commands have been sent out or when error occurs. So when we send master commands,
-we should free or modify the source data only after the i2c_master_cmd_begin function returns.
-    For i2c slave mode, we need a data buffer to stash the sending and receiving data, because the hardware fifo
-has only 32 bytes.
-*/
-esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_buf_len, size_t slv_tx_buf_len,
-    int intr_alloc_flags)
-{
-    I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
-    I2C_CHECK(mode == I2C_MODE_MASTER || ( slv_rx_buf_len > 100 || slv_tx_buf_len > 100 ), I2C_SLAVE_BUFFER_LEN_ERR_STR,
-        ESP_ERR_INVALID_ARG);
-    uint32_t intr_mask = 0;
-    if (p_i2c_obj[i2c_num] == NULL) {
-
-#if !CONFIG_SPIRAM_USE_MALLOC
-        p_i2c_obj[i2c_num] = (i2c_obj_t*) calloc(1, sizeof(i2c_obj_t));
-#else
-        if( !(intr_alloc_flags & ESP_INTR_FLAG_IRAM) ) {
-            p_i2c_obj[i2c_num] = (i2c_obj_t*) calloc(1, sizeof(i2c_obj_t));
-        } else {
-            p_i2c_obj[i2c_num] = (i2c_obj_t*) heap_caps_calloc(1, sizeof(i2c_obj_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
-        }
-#endif
-        if (p_i2c_obj[i2c_num] == NULL) {
-            ESP_LOGE(I2C_TAG, I2C_DRIVER_MALLOC_ERR_STR);
-            return ESP_FAIL;
-        }
-        i2c_obj_t* p_i2c = p_i2c_obj[i2c_num];
-        p_i2c->i2c_num = i2c_num;
-        p_i2c->mode = mode;
-        p_i2c->cmd_idx = 0;
-        p_i2c->rx_cnt = 0;
-        p_i2c->status = I2C_STATUS_IDLE;
-
-#if CONFIG_SPIRAM_USE_MALLOC
-        p_i2c->intr_alloc_flags = intr_alloc_flags;
-#endif
-        p_i2c->rx_fifo_remain = I2C_FIFO_LEN;
-        p_i2c->tx_fifo_remain = I2C_FIFO_LEN;
-
-        if (mode == I2C_MODE_SLAVE) {
-            //we only use ringbuffer for slave mode.
-            if (slv_rx_buf_len > 0) {
-                p_i2c->rx_ring_buf = xRingbufferCreate(slv_rx_buf_len, RINGBUF_TYPE_BYTEBUF);
-                if (p_i2c->rx_ring_buf == NULL) {
-                    ESP_LOGE(I2C_TAG, I2C_BUF_ERR_STR);
-                    goto err;
-                }
-                p_i2c->rx_buf_length = slv_rx_buf_len;
-            } else {
-                p_i2c->rx_ring_buf = NULL;
-                p_i2c->rx_buf_length = 0;
-            }
-            if (slv_tx_buf_len > 0) {
-                p_i2c->tx_ring_buf = xRingbufferCreate(slv_tx_buf_len, RINGBUF_TYPE_BYTEBUF);
-                if (p_i2c->tx_ring_buf == NULL) {
-                    ESP_LOGE(I2C_TAG, I2C_BUF_ERR_STR);
-                    goto err;
-                }
-                p_i2c->tx_buf_length = slv_tx_buf_len;
-            } else {
-                p_i2c->tx_ring_buf = NULL;
-                p_i2c->tx_buf_length = 0;
-            }
-            p_i2c->slv_rx_mux = xSemaphoreCreateMutex();
-            p_i2c->slv_tx_mux = xSemaphoreCreateMutex();
-            if (p_i2c->slv_rx_mux == NULL || p_i2c->slv_tx_mux == NULL) {
-                ESP_LOGE(I2C_TAG, I2C_SEM_ERR_STR);
-                goto err;
-            }
-            intr_mask |= ( I2C_RXFIFO_FULL_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M);
-        } else {
-            //semaphore to sync sending process, because we only have 32 bytes for hardware fifo.
-            p_i2c->cmd_mux = xSemaphoreCreateMutex();
-#ifdef CONFIG_PM_ENABLE
-            if (esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "i2c_driver", &p_i2c->pm_lock) != ESP_OK) {
-                ESP_LOGE(I2C_TAG, I2C_LOCK_ERR_STR);
-                goto err;
-            }
-#endif
-#if !CONFIG_SPIRAM_USE_MALLOC
-            p_i2c->cmd_evt_queue = xQueueCreate(I2C_EVT_QUEUE_LEN, sizeof(i2c_cmd_evt_t));
-#else
-            if( !(intr_alloc_flags & ESP_INTR_FLAG_IRAM) ) {
-                p_i2c->cmd_evt_queue = xQueueCreate(I2C_EVT_QUEUE_LEN, sizeof(i2c_cmd_evt_t));
-            } else {
-                p_i2c->evt_queue_storage = (uint8_t *)heap_caps_calloc(I2C_EVT_QUEUE_LEN, sizeof(i2c_cmd_evt_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
-                if( p_i2c->evt_queue_storage == NULL ) {
-                    ESP_LOGE(I2C_TAG, I2C_DRIVER_MALLOC_ERR_STR);
-                    goto err;
-                }
-                memset(&p_i2c->evt_queue_buffer, 0, sizeof(StaticQueue_t));
-                p_i2c->cmd_evt_queue =  xQueueCreateStatic(I2C_EVT_QUEUE_LEN, sizeof(i2c_cmd_evt_t), p_i2c->evt_queue_storage, &p_i2c->evt_queue_buffer);
-            }
-#endif
-            if (p_i2c->cmd_mux == NULL || p_i2c->cmd_evt_queue == NULL) {
-                ESP_LOGE(I2C_TAG, I2C_SEM_ERR_STR);
-                goto err;
-            }
-            //command link
-            p_i2c->cmd_link.cur = NULL;
-            p_i2c->cmd_link.head = NULL;
-            p_i2c->cmd_link.free = NULL;
-
-            p_i2c->tx_ring_buf = NULL;
-            p_i2c->rx_buf_length = 0;
-            p_i2c->tx_ring_buf = NULL;
-            p_i2c->tx_buf_length = 0;
-            intr_mask |= I2C_ARBITRATION_LOST_INT_ENA_M | I2C_TIME_OUT_INT_ST_M;
-        }
-    } else {
-        ESP_LOGE(I2C_TAG, I2C_DRIVER_ERR_STR);
-        return ESP_FAIL;
-    }
-    //hook isr handler
-    i2c_isr_register(i2c_num, i2c_isr_handler_default, p_i2c_obj[i2c_num], intr_alloc_flags, &p_i2c_obj[i2c_num]->intr_handle);
-    intr_mask |= ( I2C_TRANS_COMPLETE_INT_ENA_M |
-                   I2C_TRANS_START_INT_ENA_M |
-                   I2C_ACK_ERR_INT_ENA_M |
-                   I2C_RXFIFO_OVF_INT_ENA_M |
-                   I2C_SLAVE_TRAN_COMP_INT_ENA_M);
-    I2C[i2c_num]->int_clr.val = intr_mask;
-    I2C[i2c_num]->int_ena.val = intr_mask;
-    return ESP_OK;
-
-    err:
-    //Some error has happened. Free/destroy all allocated things and return ESP_FAIL.
-    if (p_i2c_obj[i2c_num]) {
-        if (p_i2c_obj[i2c_num]->rx_ring_buf) {
-            vRingbufferDelete(p_i2c_obj[i2c_num]->rx_ring_buf);
-            p_i2c_obj[i2c_num]->rx_ring_buf = NULL;
-            p_i2c_obj[i2c_num]->rx_buf_length = 0;
-        }
-        if (p_i2c_obj[i2c_num]->tx_ring_buf) {
-            vRingbufferDelete(p_i2c_obj[i2c_num]->tx_ring_buf);
-            p_i2c_obj[i2c_num]->tx_ring_buf = NULL;
-            p_i2c_obj[i2c_num]->tx_buf_length = 0;
-        }
-        if (p_i2c_obj[i2c_num]->cmd_evt_queue) {
-            vQueueDelete(p_i2c_obj[i2c_num]->cmd_evt_queue);
-            p_i2c_obj[i2c_num]->cmd_evt_queue = NULL;
-        }
-        if (p_i2c_obj[i2c_num]->cmd_mux) {
-            vSemaphoreDelete(p_i2c_obj[i2c_num]->cmd_mux);
-        }
-        if (p_i2c_obj[i2c_num]->slv_rx_mux) {
-            vSemaphoreDelete(p_i2c_obj[i2c_num]->slv_rx_mux);
-        }
-        if (p_i2c_obj[i2c_num]->slv_tx_mux) {
-            vSemaphoreDelete(p_i2c_obj[i2c_num]->slv_tx_mux);
-        }
-#ifdef CONFIG_PM_ENABLE
-        if (p_i2c_obj[i2c_num]->pm_lock) {
-            esp_pm_lock_delete(p_i2c_obj[i2c_num]->pm_lock);
-            p_i2c_obj[i2c_num]->pm_lock = NULL;
-        }
-#endif
-#if CONFIG_SPIRAM_USE_MALLOC
-        if (p_i2c_obj[i2c_num]->evt_queue_storage) {
-            free(p_i2c_obj[i2c_num]->evt_queue_storage);
-            p_i2c_obj[i2c_num]->evt_queue_storage = NULL;
-        }
-#endif
-    }
-    free(p_i2c_obj[i2c_num]);
-    p_i2c_obj[i2c_num] = NULL;
-    return ESP_FAIL;
-}
-
-static esp_err_t i2c_hw_enable(i2c_port_t i2c_num)
-{
-    if (i2c_num == I2C_NUM_0) {
-        periph_module_enable(PERIPH_I2C0_MODULE);
-    } else if (i2c_num == I2C_NUM_1) {
-        periph_module_enable(PERIPH_I2C1_MODULE);
-    }
-    return ESP_OK;
-}
-
-static esp_err_t i2c_hw_disable(i2c_port_t i2c_num)
-{
-    if (i2c_num == I2C_NUM_0) {
-        periph_module_disable(PERIPH_I2C0_MODULE);
-    } else if (i2c_num == I2C_NUM_1) {
-        periph_module_disable(PERIPH_I2C1_MODULE);
-    }
-    return ESP_OK;
-}
-
-esp_err_t i2c_driver_delete(i2c_port_t i2c_num)
-{
-    I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
-    I2C_CHECK(p_i2c_obj[i2c_num] != NULL, I2C_DRIVER_ERR_STR, ESP_FAIL);
-
-    i2c_obj_t* p_i2c = p_i2c_obj[i2c_num];
-
-    I2C[i2c_num]->int_ena.val = 0;
-    esp_intr_free(p_i2c->intr_handle);
-    p_i2c->intr_handle = NULL;
-
-    if (p_i2c->cmd_mux) {
-        xSemaphoreTake(p_i2c->cmd_mux, portMAX_DELAY);
-        vSemaphoreDelete(p_i2c->cmd_mux);
-    }
-    if (p_i2c_obj[i2c_num]->cmd_evt_queue) {
-        vQueueDelete(p_i2c_obj[i2c_num]->cmd_evt_queue);
-        p_i2c_obj[i2c_num]->cmd_evt_queue = NULL;
-    }
-    if (p_i2c->slv_rx_mux) {
-        vSemaphoreDelete(p_i2c->slv_rx_mux);
-    }
-    if (p_i2c->slv_tx_mux) {
-        vSemaphoreDelete(p_i2c->slv_tx_mux);
-    }
-
-    if (p_i2c->rx_ring_buf) {
-        vRingbufferDelete(p_i2c->rx_ring_buf);
-        p_i2c->rx_ring_buf = NULL;
-        p_i2c->rx_buf_length = 0;
-    }
-    if (p_i2c->tx_ring_buf) {
-        vRingbufferDelete(p_i2c->tx_ring_buf);
-        p_i2c->tx_ring_buf = NULL;
-        p_i2c->tx_buf_length = 0;
-    }
-#ifdef CONFIG_PM_ENABLE
-        if (p_i2c->pm_lock) {
-            esp_pm_lock_delete(p_i2c->pm_lock);
-            p_i2c->pm_lock = NULL;
-        }
-#endif
-#if CONFIG_SPIRAM_USE_MALLOC
-    if (p_i2c_obj[i2c_num]->evt_queue_storage) {
-        free(p_i2c_obj[i2c_num]->evt_queue_storage);
-        p_i2c_obj[i2c_num]->evt_queue_storage = NULL;
-    }
-#endif
-
-    free(p_i2c_obj[i2c_num]);
-    p_i2c_obj[i2c_num] = NULL;
-
-    i2c_hw_disable(i2c_num);
-    return ESP_OK;
-}
-
-esp_err_t i2c_reset_tx_fifo(i2c_port_t i2c_num)
-{
-    I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
-    I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
-    I2C[i2c_num]->fifo_conf.tx_fifo_rst = 1;
-    I2C[i2c_num]->fifo_conf.tx_fifo_rst = 0;
-    I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
-    return ESP_OK;
-}
-
-esp_err_t i2c_reset_rx_fifo(i2c_port_t i2c_num)
-{
-    I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
-    I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
-    I2C[i2c_num]->fifo_conf.rx_fifo_rst = 1;
-    I2C[i2c_num]->fifo_conf.rx_fifo_rst = 0;
-    I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
-    return ESP_OK;
-}
-
-static void IRAM_ATTR i2c_isr_handler_default(void* arg)
-{
-    i2c_obj_t* p_i2c = (i2c_obj_t*) arg;
-    int i2c_num = p_i2c->i2c_num;
-    uint32_t status = I2C[i2c_num]->int_status.val;
-    int idx = 0;
-
-    portBASE_TYPE HPTaskAwoken = pdFALSE;
-    while (status != 0) {
-        status = I2C[i2c_num]->int_status.val;
-        if (status & I2C_TX_SEND_EMPTY_INT_ST_M) {
-            I2C[i2c_num]->int_clr.tx_send_empty = 1;
-        } else if (status & I2C_RX_REC_FULL_INT_ST_M) {
-            I2C[i2c_num]->int_clr.rx_rec_full = 1;
-        } else if (status & I2C_ACK_ERR_INT_ST_M) {
-            I2C[i2c_num]->int_ena.ack_err = 0;
-            I2C[i2c_num]->int_clr.ack_err = 1;
-            if (p_i2c->mode == I2C_MODE_MASTER) {
-                p_i2c_obj[i2c_num]->status = I2C_STATUS_ACK_ERROR;
-                I2C[i2c_num]->int_clr.ack_err = 1;
-                //get error ack value from slave device, stop the commands
-                i2c_master_cmd_begin_static(i2c_num);
-            }
-        } else if (status & I2C_TRANS_START_INT_ST_M) {
-            I2C[i2c_num]->int_clr.trans_start = 1;
-        } else if (status & I2C_TIME_OUT_INT_ST_M) {
-            I2C[i2c_num]->int_ena.time_out = 0;
-            I2C[i2c_num]->int_clr.time_out = 1;
-            p_i2c_obj[i2c_num]->status = I2C_STATUS_TIMEOUT;
-            i2c_master_cmd_begin_static(i2c_num);
-        } else if (status & I2C_TRANS_COMPLETE_INT_ST_M) {
-            I2C[i2c_num]->int_clr.trans_complete = 1;
-            if (p_i2c->mode == I2C_MODE_SLAVE) {
-                int rx_fifo_cnt = I2C[i2c_num]->status_reg.rx_fifo_cnt;
-                for (idx = 0; idx < rx_fifo_cnt; idx++) {
-                    p_i2c->data_buf[idx] = I2C[i2c_num]->fifo_data.data;
-                }
-                xRingbufferSendFromISR(p_i2c->rx_ring_buf, p_i2c->data_buf, rx_fifo_cnt, &HPTaskAwoken);
-                I2C[i2c_num]->int_clr.rx_fifo_full = 1;
-            } else {
-                // add check for unexcepted situations caused by noise.
-                if (p_i2c->status != I2C_STATUS_ACK_ERROR && p_i2c->status != I2C_STATUS_IDLE) {
-                    i2c_master_cmd_begin_static(i2c_num);
-                }
-            }
-        } else if (status & I2C_MASTER_TRAN_COMP_INT_ST_M) {
-            I2C[i2c_num]->int_clr.master_tran_comp = 1;
-        } else if (status & I2C_ARBITRATION_LOST_INT_ST_M) {
-            I2C[i2c_num]->int_clr.arbitration_lost = 1;
-            p_i2c_obj[i2c_num]->status = I2C_STATUS_TIMEOUT;
-            i2c_master_cmd_begin_static(i2c_num);
-        } else if (status & I2C_SLAVE_TRAN_COMP_INT_ST_M) {
-            I2C[i2c_num]->int_clr.slave_tran_comp = 1;
-        } else if (status & I2C_END_DETECT_INT_ST_M) {
-            I2C[i2c_num]->int_ena.end_detect = 0;
-            I2C[i2c_num]->int_clr.end_detect = 1;
-            i2c_master_cmd_begin_static(i2c_num);
-        } else if (status & I2C_RXFIFO_OVF_INT_ST_M) {
-            I2C[i2c_num]->int_clr.rx_fifo_ovf = 1;
-        } else if (status & I2C_TXFIFO_EMPTY_INT_ST_M) {
-            int tx_fifo_rem = I2C_FIFO_LEN - I2C[i2c_num]->status_reg.tx_fifo_cnt;
-            size_t size = 0;
-            uint8_t *data = (uint8_t*) xRingbufferReceiveUpToFromISR(p_i2c->tx_ring_buf, &size, tx_fifo_rem);
-            if (data) {
-                for (idx = 0; idx < size; idx++) {
-                    WRITE_PERI_REG(I2C_DATA_APB_REG(i2c_num), data[idx]);
-                }
-                vRingbufferReturnItemFromISR(p_i2c->tx_ring_buf, data, &HPTaskAwoken);
-                I2C[i2c_num]->int_ena.tx_fifo_empty = 1;
-                I2C[i2c_num]->int_clr.tx_fifo_empty = 1;
-            } else {
-                I2C[i2c_num]->int_ena.tx_fifo_empty = 0;
-                I2C[i2c_num]->int_clr.tx_fifo_empty = 1;
-            }
-        } else if (status & I2C_RXFIFO_FULL_INT_ST_M) {
-            int rx_fifo_cnt = I2C[i2c_num]->status_reg.rx_fifo_cnt;
-            for (idx = 0; idx < rx_fifo_cnt; idx++) {
-                p_i2c->data_buf[idx] = I2C[i2c_num]->fifo_data.data;
-            }
-            xRingbufferSendFromISR(p_i2c->rx_ring_buf, p_i2c->data_buf, rx_fifo_cnt, &HPTaskAwoken);
-            I2C[i2c_num]->int_clr.rx_fifo_full = 1;
-        } else {
-            I2C[i2c_num]->int_clr.val = status;
-        }
-    }
-    if (p_i2c->mode == I2C_MODE_MASTER) {
-        i2c_cmd_evt_t evt;
-        evt.type = I2C_CMD_EVT_ALIVE;
-        xQueueSendFromISR(p_i2c->cmd_evt_queue, &evt, &HPTaskAwoken);
-    }
-    //We only need to check here if there is a high-priority task needs to be switched.
-    if(HPTaskAwoken == pdTRUE) {
-        portYIELD_FROM_ISR();
-    }
-}
-
-esp_err_t i2c_set_data_mode(i2c_port_t i2c_num, i2c_trans_mode_t tx_trans_mode, i2c_trans_mode_t rx_trans_mode)
-{
-    I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
-    I2C_CHECK(tx_trans_mode < I2C_DATA_MODE_MAX, I2C_TRANS_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
-    I2C_CHECK(rx_trans_mode < I2C_DATA_MODE_MAX, I2C_TRANS_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
-    I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
-    I2C[i2c_num]->ctr.rx_lsb_first = rx_trans_mode; //set rx data msb first
-    I2C[i2c_num]->ctr.tx_lsb_first = tx_trans_mode; //set tx data msb first
-    I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
-    return ESP_OK;
-}
-
-esp_err_t i2c_get_data_mode(i2c_port_t i2c_num, i2c_trans_mode_t *tx_trans_mode, i2c_trans_mode_t *rx_trans_mode)
-{
-    I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
-    if (tx_trans_mode) {
-        *tx_trans_mode = I2C[i2c_num]->ctr.tx_lsb_first;
-    }
-    if (rx_trans_mode) {
-        *rx_trans_mode = I2C[i2c_num]->ctr.rx_lsb_first;
-    }
-    return ESP_OK;
-}
-
-/* Some slave device will die by accident and keep the SDA in low level,
- * in this case, master should send several clock to make the slave release the bus.
- * Slave mode of ESP32 might also get in wrong state that held the SDA low,
- * in this case, master device could send a stop signal to make esp32 slave release the bus.
- **/
-static esp_err_t i2c_master_clear_bus(i2c_port_t i2c_num)
-{
-    I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
-    const int scl_half_period = I2C_CLR_BUS_HALF_PERIOD_US; // use standard 100kHz data rate
-    int sda_in_sig = 0, scl_in_sig = 0;
-    int i = 0;
-    if (i2c_num == I2C_NUM_0) {
-        sda_in_sig = I2CEXT0_SDA_IN_IDX;
-        scl_in_sig = I2CEXT0_SCL_IN_IDX;
-    } else if (i2c_num == I2C_NUM_1) {
-        sda_in_sig = I2CEXT1_SDA_IN_IDX;
-        scl_in_sig = I2CEXT1_SCL_IN_IDX;
-    }
-    int scl_io = GPIO.func_in_sel_cfg[scl_in_sig].func_sel;
-    int sda_io = GPIO.func_in_sel_cfg[sda_in_sig].func_sel;
-    I2C_CHECK((GPIO_IS_VALID_OUTPUT_GPIO(scl_io)), I2C_SCL_IO_ERR_STR, ESP_ERR_INVALID_ARG);
-    I2C_CHECK((GPIO_IS_VALID_OUTPUT_GPIO(sda_io)), I2C_SDA_IO_ERR_STR, ESP_ERR_INVALID_ARG);
-    gpio_set_direction(scl_io, GPIO_MODE_OUTPUT_OD);
-    gpio_set_direction(sda_io, GPIO_MODE_INPUT_OUTPUT_OD);
-    // If a SLAVE device was in a read operation when the bus was interrupted, the SLAVE device is controlling SDA.
-    // The only bit during the 9 clock cycles of a READ byte the MASTER(ESP32) is guaranteed control over is during the ACK bit
-    // period. If the slave is sending a stream of ZERO bytes, it will only release SDA during the ACK bit period.
-    // So, this reset code needs to synchronize the bit stream with, Either, the ACK bit, Or a 1 bit to correctly generate
-    // a STOP condition.
-    gpio_set_level(scl_io, 0);
-    gpio_set_level(sda_io, 1);
-    ets_delay_us(scl_half_period);
-    while(!gpio_get_level(sda_io) && (i++ < I2C_CLR_BUS_SCL_NUM)) {
-        gpio_set_level(scl_io, 1);
-        ets_delay_us(scl_half_period);
-        gpio_set_level(scl_io, 0);
-        ets_delay_us(scl_half_period);
-    }
-    gpio_set_level(sda_io,0); // setup for STOP
-    gpio_set_level(scl_io,1);
-    ets_delay_us(scl_half_period);
-    gpio_set_level(sda_io, 1); // STOP, SDA low -> high while SCL is HIGH
-    i2c_set_pin(i2c_num, sda_io, scl_io, 1, 1, I2C_MODE_MASTER);
-    return ESP_OK;
-}
-
-/**if the power and SDA/SCL wires are in proper condition, everything works find with reading the slave.
- * If we remove the power supply for the slave during I2C is reading, or directly connect SDA or SCL to ground,
- * this would cause the I2C FSM get stuck in wrong state, all we can do is to reset the I2C hardware in this case.
- **/
-static esp_err_t i2c_hw_fsm_reset(i2c_port_t i2c_num)
-{
-    I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
-    uint32_t ctr              = I2C[i2c_num]->ctr.val;
-    uint32_t fifo_conf        = I2C[i2c_num]->fifo_conf.val;
-    uint32_t scl_low_period   = I2C[i2c_num]->scl_low_period.val;
-    uint32_t scl_high_period  = I2C[i2c_num]->scl_high_period.val;
-    uint32_t scl_start_hold   = I2C[i2c_num]->scl_start_hold.val;
-    uint32_t scl_rstart_setup = I2C[i2c_num]->scl_rstart_setup.val;
-    uint32_t scl_stop_hold    = I2C[i2c_num]->scl_stop_hold.val;
-    uint32_t scl_stop_setup   = I2C[i2c_num]->scl_stop_setup.val;
-    uint32_t sda_hold         = I2C[i2c_num]->sda_hold.val;
-    uint32_t sda_sample       = I2C[i2c_num]->sda_sample.val;
-    uint32_t timeout          = I2C[i2c_num]->timeout.val;
-    uint32_t scl_filter_cfg   = I2C[i2c_num]->scl_filter_cfg.val;
-    uint32_t sda_filter_cfg   = I2C[i2c_num]->sda_filter_cfg.val;
-    uint32_t slave_addr       = I2C[i2c_num]->slave_addr.val;
-
-    //to reset the I2C hw module, we need re-enable the hw
-    i2c_hw_disable(i2c_num);
-    i2c_master_clear_bus(i2c_num);
-    i2c_hw_enable(i2c_num);
-    I2C[i2c_num]->int_ena.val          = 0;
-    I2C[i2c_num]->ctr.val              = ctr & (~I2C_TRANS_START_M);
-    I2C[i2c_num]->fifo_conf.val        = fifo_conf;
-    I2C[i2c_num]->scl_low_period.val   = scl_low_period;
-    I2C[i2c_num]->scl_high_period.val  = scl_high_period;
-    I2C[i2c_num]->scl_start_hold.val   = scl_start_hold;
-    I2C[i2c_num]->scl_rstart_setup.val = scl_rstart_setup;
-    I2C[i2c_num]->scl_stop_hold.val    = scl_stop_hold;
-    I2C[i2c_num]->scl_stop_setup.val   = scl_stop_setup;
-    I2C[i2c_num]->sda_hold.val         = sda_hold;
-    I2C[i2c_num]->sda_sample.val       = sda_sample;
-    I2C[i2c_num]->timeout.val          = timeout;
-    I2C[i2c_num]->scl_filter_cfg.val   = scl_filter_cfg;
-    I2C[i2c_num]->sda_filter_cfg.val   = sda_filter_cfg;
-    uint32_t intr_mask = ( I2C_TRANS_COMPLETE_INT_ENA_M
-                         | I2C_TRANS_START_INT_ENA_M
-                         | I2C_ACK_ERR_INT_ENA_M
-                         | I2C_RXFIFO_OVF_INT_ENA_M
-                         | I2C_SLAVE_TRAN_COMP_INT_ENA_M
-                         | I2C_TIME_OUT_INT_ENA_M);
-    if (I2C[i2c_num]->ctr.ms_mode == I2C_MODE_SLAVE) {
-        I2C[i2c_num]->slave_addr.val = slave_addr;
-        intr_mask |= ( I2C_RXFIFO_FULL_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M);
-    } else {
-        intr_mask |= I2C_ARBITRATION_LOST_INT_ENA_M;
-    }
-    I2C[i2c_num]->int_clr.val = intr_mask;
-    I2C[i2c_num]->int_ena.val = intr_mask;
-    return ESP_OK;
-}
-
-esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t* i2c_conf)
-{
-    I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
-    I2C_CHECK(i2c_conf != NULL, I2C_ADDR_ERROR_STR, ESP_ERR_INVALID_ARG);
-    I2C_CHECK(i2c_conf->mode < I2C_MODE_MAX, I2C_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
-
-    esp_err_t ret = i2c_set_pin(i2c_num, i2c_conf->sda_io_num, i2c_conf->scl_io_num,
-                                i2c_conf->sda_pullup_en, i2c_conf->scl_pullup_en, i2c_conf->mode);
-    if (ret != ESP_OK) {
-        return ret;
-    }
-    // Reset the I2C hardware in case there is a soft reboot.
-    i2c_hw_disable(i2c_num);
-    i2c_hw_enable(i2c_num);
-    I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
-    I2C[i2c_num]->ctr.rx_lsb_first = I2C_DATA_MODE_MSB_FIRST; //set rx data msb first
-    I2C[i2c_num]->ctr.tx_lsb_first = I2C_DATA_MODE_MSB_FIRST; //set tx data msb first
-    I2C[i2c_num]->ctr.ms_mode = i2c_conf->mode; //mode for master or slave
-    I2C[i2c_num]->ctr.sda_force_out = 1; // set open-drain output mode
-    I2C[i2c_num]->ctr.scl_force_out = 1; // set open-drain output mode
-    I2C[i2c_num]->ctr.sample_scl_level = 0; //sample at high level of clock
-
-    if (i2c_conf->mode == I2C_MODE_SLAVE) {  //slave mode
-        I2C[i2c_num]->slave_addr.addr = i2c_conf->slave.slave_addr;
-        I2C[i2c_num]->slave_addr.en_10bit = i2c_conf->slave.addr_10bit_en;
-        I2C[i2c_num]->fifo_conf.nonfifo_en = 0;
-        I2C[i2c_num]->fifo_conf.fifo_addr_cfg_en = 0;
-        I2C[i2c_num]->fifo_conf.rx_fifo_full_thrhd = I2C_FIFO_FULL_THRESH_VAL;
-        I2C[i2c_num]->fifo_conf.tx_fifo_empty_thrhd = I2C_FIFO_EMPTY_THRESH_VAL;
-        I2C[i2c_num]->ctr.trans_start = 0;
-        I2C[i2c_num]->timeout.tout = I2C_SLAVE_TIMEOUT_DEFAULT;
-        //set timing for data
-        I2C[i2c_num]->sda_hold.time = I2C_SLAVE_SDA_HOLD_DEFAULT;
-        I2C[i2c_num]->sda_sample.time = I2C_SLAVE_SDA_SAMPLE_DEFAULT;
-    } else {
-        I2C[i2c_num]->fifo_conf.nonfifo_en = 0;
-        int cycle = (I2C_APB_CLK_FREQ / i2c_conf->master.clk_speed);
-        int half_cycle = cycle / 2;
-        I2C[i2c_num]->timeout.tout = cycle * I2C_MASTER_TOUT_CNUM_DEFAULT;
-        //set timing for data
-        I2C[i2c_num]->sda_hold.time = half_cycle / 2;
-        I2C[i2c_num]->sda_sample.time = half_cycle / 2;
-
-        I2C[i2c_num]->scl_low_period.period = half_cycle;
-        I2C[i2c_num]->scl_high_period.period = half_cycle;
-        //set timing for start signal
-        I2C[i2c_num]->scl_start_hold.time = half_cycle;
-        I2C[i2c_num]->scl_rstart_setup.time = half_cycle;
-        //set timing for stop signal
-        I2C[i2c_num]->scl_stop_hold.time = half_cycle;
-        I2C[i2c_num]->scl_stop_setup.time = half_cycle;
-        //Default, we enable hardware filter
-        i2c_filter_enable(i2c_num, I2C_FILTER_CYC_NUM_DEF);
-    }
-
-    I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
-    return ESP_OK;
-}
-
-esp_err_t i2c_set_period(i2c_port_t i2c_num, int high_period, int low_period)
-{
-    I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
-    I2C_CHECK((high_period <= I2C_SCL_HIGH_PERIOD_V) && (high_period > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
-    I2C_CHECK((low_period <= I2C_SCL_LOW_PERIOD_V) && (low_period > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
-
-    I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
-    I2C[i2c_num]->scl_high_period.period = high_period;
-    I2C[i2c_num]->scl_low_period.period = low_period;
-    I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
-    return ESP_OK;
-}
-
-esp_err_t i2c_get_period(i2c_port_t i2c_num, int* high_period, int* low_period)
-{
-    I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
-    I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
-    if (high_period) {
-        *high_period = I2C[i2c_num]->scl_high_period.period;
-    }
-    if (low_period) {
-        *low_period = I2C[i2c_num]->scl_low_period.period;
-    }
-    I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
-    return ESP_OK;
-}
-
-esp_err_t i2c_filter_enable(i2c_port_t i2c_num, uint8_t cyc_num)
-{
-    I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
-    I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
-    I2C[i2c_num]->scl_filter_cfg.thres = cyc_num;
-    I2C[i2c_num]->sda_filter_cfg.thres = cyc_num;
-    I2C[i2c_num]->scl_filter_cfg.en = 1;
-    I2C[i2c_num]->sda_filter_cfg.en = 1;
-    I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
-    return ESP_OK;
-}
-
-esp_err_t i2c_filter_disable(i2c_port_t i2c_num)
-{
-    I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
-    I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
-    I2C[i2c_num]->scl_filter_cfg.en = 0;
-    I2C[i2c_num]->sda_filter_cfg.en = 0;
-    I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
-    return ESP_OK;
-}
-
-esp_err_t i2c_set_start_timing(i2c_port_t i2c_num, int setup_time, int hold_time)
-{
-    I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
-    I2C_CHECK((hold_time <= I2C_SCL_START_HOLD_TIME_V) && (hold_time > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
-    I2C_CHECK((setup_time <= I2C_SCL_RSTART_SETUP_TIME_V) && (setup_time > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
-
-    I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
-    I2C[i2c_num]->scl_start_hold.time = hold_time;
-    I2C[i2c_num]->scl_rstart_setup.time = setup_time;
-    I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
-    return ESP_OK;
-}
-
-esp_err_t i2c_get_start_timing(i2c_port_t i2c_num, int* setup_time, int* hold_time)
-{
-    I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
-    I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
-    if (hold_time) {
-        *hold_time = I2C[i2c_num]->scl_start_hold.time;
-    }
-    if (setup_time) {
-        *setup_time = I2C[i2c_num]->scl_rstart_setup.time;
-    }
-    I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
-    return ESP_OK;
-}
-
-esp_err_t i2c_set_stop_timing(i2c_port_t i2c_num, int setup_time, int hold_time)
-{
-    I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
-    I2C_CHECK((setup_time <= I2C_SCL_STOP_SETUP_TIME_V) && (setup_time > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
-    I2C_CHECK((hold_time <= I2C_SCL_STOP_HOLD_TIME_V) && (hold_time > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
-
-    I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
-    I2C[i2c_num]->scl_stop_hold.time = hold_time;
-    I2C[i2c_num]->scl_stop_setup.time = setup_time;
-    I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
-    return ESP_OK;
-}
-
-esp_err_t i2c_get_stop_timing(i2c_port_t i2c_num, int* setup_time, int* hold_time)
-{
-    I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
-    I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
-    if (setup_time) {
-        *setup_time = I2C[i2c_num]->scl_stop_setup.time;
-    }
-    if (hold_time) {
-        *hold_time = I2C[i2c_num]->scl_stop_hold.time;
-    }
-    I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
-    return ESP_OK;
-}
-
-esp_err_t i2c_set_data_timing(i2c_port_t i2c_num, int sample_time, int hold_time)
-{
-    I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
-    I2C_CHECK((sample_time <= I2C_SDA_SAMPLE_TIME_V) && (sample_time > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
-    I2C_CHECK((hold_time <= I2C_SDA_HOLD_TIME_V) && (hold_time > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
-
-    I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
-    I2C[i2c_num]->sda_hold.time = hold_time;
-    I2C[i2c_num]->sda_sample.time = sample_time;
-    I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
-    return ESP_OK;
-}
-
-esp_err_t i2c_get_data_timing(i2c_port_t i2c_num, int* sample_time, int* hold_time)
-{
-    I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
-    I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
-    if (sample_time) {
-        *sample_time = I2C[i2c_num]->sda_sample.time;
-    }
-    if (hold_time) {
-        *hold_time = I2C[i2c_num]->sda_hold.time;
-    }
-    I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
-    return ESP_OK;
-}
-
-esp_err_t i2c_set_timeout(i2c_port_t i2c_num, int timeout)
-{
-    I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
-    I2C_CHECK((timeout <= I2C_TIME_OUT_REG_V) && (timeout > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
-
-    I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
-    I2C[i2c_num]->timeout.tout = timeout;
-    I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
-    return ESP_OK;
-}
-
-esp_err_t i2c_get_timeout(i2c_port_t i2c_num, int* timeout)
-{
-    I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
-    if (timeout) {
-        *timeout = I2C[i2c_num]->timeout.tout;
-    }
-    return ESP_OK;
-}
-
-esp_err_t i2c_isr_register(i2c_port_t i2c_num, void (*fn)(void*), void * arg, int intr_alloc_flags, intr_handle_t *handle)
-{
-    I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
-    I2C_CHECK(fn != NULL, I2C_ADDR_ERROR_STR, ESP_ERR_INVALID_ARG);
-    esp_err_t ret;
-    switch (i2c_num) {
-        case I2C_NUM_1:
-            ret = esp_intr_alloc(ETS_I2C_EXT1_INTR_SOURCE, intr_alloc_flags, fn, arg, handle);
-            break;
-        case I2C_NUM_0:
-            default:
-            ret = esp_intr_alloc(ETS_I2C_EXT0_INTR_SOURCE, intr_alloc_flags, fn, arg, handle);
-            break;
-    }
-    return ret;
-}
-
-esp_err_t i2c_isr_free(intr_handle_t handle)
-{
-    return esp_intr_free(handle);
-}
-
-esp_err_t i2c_set_pin(i2c_port_t i2c_num, int sda_io_num, int scl_io_num, gpio_pullup_t sda_pullup_en, gpio_pullup_t scl_pullup_en, i2c_mode_t mode)
-{
-    I2C_CHECK(( i2c_num < I2C_NUM_MAX ), I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
-    I2C_CHECK(((sda_io_num < 0) || ((GPIO_IS_VALID_OUTPUT_GPIO(sda_io_num)))), I2C_SDA_IO_ERR_STR, ESP_ERR_INVALID_ARG);
-    I2C_CHECK(scl_io_num < 0 ||
-              (GPIO_IS_VALID_OUTPUT_GPIO(scl_io_num)) ||
-              (GPIO_IS_VALID_GPIO(scl_io_num) && mode == I2C_MODE_SLAVE),
-              I2C_SCL_IO_ERR_STR,
-              ESP_ERR_INVALID_ARG);
-    I2C_CHECK(sda_io_num < 0 ||
-               (sda_pullup_en == GPIO_PULLUP_ENABLE && GPIO_IS_VALID_OUTPUT_GPIO(sda_io_num)) ||
-               sda_pullup_en == GPIO_PULLUP_DISABLE, I2C_GPIO_PULLUP_ERR_STR, ESP_ERR_INVALID_ARG);
-    I2C_CHECK(scl_io_num < 0 ||
-               (scl_pullup_en == GPIO_PULLUP_ENABLE && GPIO_IS_VALID_OUTPUT_GPIO(scl_io_num)) ||
-               scl_pullup_en == GPIO_PULLUP_DISABLE, I2C_GPIO_PULLUP_ERR_STR, ESP_ERR_INVALID_ARG);
-
-    int sda_in_sig, sda_out_sig, scl_in_sig, scl_out_sig;
-    switch (i2c_num) {
-        case I2C_NUM_1:
-            sda_out_sig = I2CEXT1_SDA_OUT_IDX;
-            sda_in_sig = I2CEXT1_SDA_IN_IDX;
-            scl_out_sig = I2CEXT1_SCL_OUT_IDX;
-            scl_in_sig = I2CEXT1_SCL_IN_IDX;
-            break;
-        case I2C_NUM_0:
-            default:
-            sda_out_sig = I2CEXT0_SDA_OUT_IDX;
-            sda_in_sig = I2CEXT0_SDA_IN_IDX;
-            scl_out_sig = I2CEXT0_SCL_OUT_IDX;
-            scl_in_sig = I2CEXT0_SCL_IN_IDX;
-            break;
-    }
-    if (sda_io_num >= 0) {
-        gpio_set_level(sda_io_num, I2C_IO_INIT_LEVEL);
-        PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[sda_io_num], PIN_FUNC_GPIO);
-        gpio_set_direction(sda_io_num, GPIO_MODE_INPUT_OUTPUT_OD);
-
-        if (sda_pullup_en == GPIO_PULLUP_ENABLE) {
-            gpio_set_pull_mode(sda_io_num, GPIO_PULLUP_ONLY);
-        } else {
-            gpio_set_pull_mode(sda_io_num, GPIO_FLOATING);
-        }
-        gpio_matrix_out(sda_io_num, sda_out_sig, 0, 0);
-        gpio_matrix_in(sda_io_num, sda_in_sig, 0);
-    }
-
-    if (scl_io_num >= 0) {
-        gpio_set_level(scl_io_num, I2C_IO_INIT_LEVEL);
-        PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[scl_io_num], PIN_FUNC_GPIO);
-        if (mode == I2C_MODE_MASTER) {
-            gpio_set_direction(scl_io_num, GPIO_MODE_INPUT_OUTPUT_OD);
-            gpio_matrix_out(scl_io_num, scl_out_sig, 0, 0);
-        } else {
-            gpio_set_direction(scl_io_num, GPIO_MODE_INPUT);
-        }
-        if (scl_pullup_en == GPIO_PULLUP_ENABLE) {
-            gpio_set_pull_mode(scl_io_num, GPIO_PULLUP_ONLY);
-        } else {
-            gpio_set_pull_mode(scl_io_num, GPIO_FLOATING);
-        }
-        gpio_matrix_in(scl_io_num, scl_in_sig, 0);
-    }
-    return ESP_OK;
-}
-
-i2c_cmd_handle_t i2c_cmd_link_create()
-{
-#if !CONFIG_SPIRAM_USE_MALLOC
-    i2c_cmd_desc_t* cmd_desc = (i2c_cmd_desc_t*) calloc(1, sizeof(i2c_cmd_desc_t));
-#else
-    i2c_cmd_desc_t* cmd_desc = (i2c_cmd_desc_t*) heap_caps_calloc(1, sizeof(i2c_cmd_desc_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
-#endif
-    return (i2c_cmd_handle_t) cmd_desc;
-}
-
-void i2c_cmd_link_delete(i2c_cmd_handle_t cmd_handle)
-{
-    if (cmd_handle == NULL) {
-        return;
-    }
-    i2c_cmd_desc_t* cmd = (i2c_cmd_desc_t*) cmd_handle;
-    while (cmd->free) {
-        i2c_cmd_link_t* ptmp = cmd->free;
-        cmd->free = cmd->free->next;
-        free(ptmp);
-    }
-    cmd->cur = NULL;
-    cmd->free = NULL;
-    cmd->head = NULL;
-    free(cmd_handle);
-    return;
-}
-
-static esp_err_t i2c_cmd_link_append(i2c_cmd_handle_t cmd_handle, i2c_cmd_t* cmd)
-{
-    i2c_cmd_desc_t* cmd_desc = (i2c_cmd_desc_t*) cmd_handle;
-    if (cmd_desc->head == NULL) {
-#if !CONFIG_SPIRAM_USE_MALLOC
-        cmd_desc->head = (i2c_cmd_link_t*) calloc(1, sizeof(i2c_cmd_link_t));
-#else
-        cmd_desc->head = (i2c_cmd_link_t*) heap_caps_calloc(1, sizeof(i2c_cmd_link_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
-#endif
-        if (cmd_desc->head == NULL) {
-            ESP_LOGE(I2C_TAG, I2C_CMD_MALLOC_ERR_STR);
-            goto err;
-        }
-        cmd_desc->cur = cmd_desc->head;
-        cmd_desc->free = cmd_desc->head;
-    } else {
-#if !CONFIG_SPIRAM_USE_MALLOC
-        cmd_desc->cur->next = (i2c_cmd_link_t*) calloc(1, sizeof(i2c_cmd_link_t));
-#else
-        cmd_desc->cur->next = (i2c_cmd_link_t*) heap_caps_calloc(1, sizeof(i2c_cmd_link_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
-#endif
-        if (cmd_desc->cur->next == NULL) {
-            ESP_LOGE(I2C_TAG, I2C_CMD_MALLOC_ERR_STR);
-            goto err;
-        }
-        cmd_desc->cur = cmd_desc->cur->next;
-    }
-    memcpy((uint8_t*) &cmd_desc->cur->cmd, (uint8_t*) cmd, sizeof(i2c_cmd_t));
-    cmd_desc->cur->next = NULL;
-    return ESP_OK;
-
-    err:
-    return ESP_FAIL;
-}
-
-esp_err_t i2c_master_start(i2c_cmd_handle_t cmd_handle)
-{
-    I2C_CHECK(cmd_handle != NULL, I2C_CMD_LINK_INIT_ERR_STR, ESP_ERR_INVALID_ARG);
-    i2c_cmd_t cmd;
-    cmd.ack_en = 0;
-    cmd.ack_exp = 0;
-    cmd.ack_val = 0;
-    cmd.byte_num = 0;
-    cmd.data = NULL;
-    cmd.op_code = I2C_CMD_RESTART;
-    return i2c_cmd_link_append(cmd_handle, &cmd);
-}
-
-esp_err_t i2c_master_stop(i2c_cmd_handle_t cmd_handle)
-{
-    I2C_CHECK(cmd_handle != NULL, I2C_CMD_LINK_INIT_ERR_STR, ESP_ERR_INVALID_ARG);
-    i2c_cmd_t cmd;
-    cmd.ack_en = 0;
-    cmd.ack_exp = 0;
-    cmd.ack_val = 0;
-    cmd.byte_num = 0;
-    cmd.data = NULL;
-    cmd.op_code = I2C_CMD_STOP;
-    return i2c_cmd_link_append(cmd_handle, &cmd);
-}
-
-esp_err_t i2c_master_write(i2c_cmd_handle_t cmd_handle, uint8_t* data, size_t data_len, bool ack_en)
-{
-    I2C_CHECK((data != NULL), I2C_ADDR_ERROR_STR, ESP_ERR_INVALID_ARG);
-    I2C_CHECK(cmd_handle != NULL, I2C_CMD_LINK_INIT_ERR_STR, ESP_ERR_INVALID_ARG);
-
-    uint8_t len_tmp;
-    int data_offset = 0;
-    esp_err_t ret;
-    while (data_len > 0) {
-        len_tmp = data_len > 0xff ? 0xff : data_len;
-        data_len -= len_tmp;
-        i2c_cmd_t cmd;
-        cmd.ack_en = ack_en;
-        cmd.ack_exp = 0;
-        cmd.ack_val = 0;
-        cmd.byte_num = len_tmp;
-        cmd.op_code = I2C_CMD_WRITE;
-        cmd.data = data + data_offset;
-        ret = i2c_cmd_link_append(cmd_handle, &cmd);
-        data_offset += len_tmp;
-        if (ret != ESP_OK) {
-            return ret;
-        }
-    }
-    return ESP_OK;
-}
-
-esp_err_t i2c_master_write_byte(i2c_cmd_handle_t cmd_handle, uint8_t data, bool ack_en)
-{
-    I2C_CHECK(cmd_handle != NULL, I2C_CMD_LINK_INIT_ERR_STR, ESP_ERR_INVALID_ARG);
-    i2c_cmd_t cmd;
-    cmd.ack_en = ack_en;
-    cmd.ack_exp = 0;
-    cmd.ack_val = 0;
-    cmd.byte_num = 1;
-    cmd.op_code = I2C_CMD_WRITE;
-    cmd.data = NULL;
-    cmd.byte_cmd = data;
-    return i2c_cmd_link_append(cmd_handle, &cmd);
-}
-
-static esp_err_t i2c_master_read_static(i2c_cmd_handle_t cmd_handle, uint8_t* data, size_t data_len, i2c_ack_type_t ack)
-{
-    int len_tmp;
-    int data_offset = 0;
-    esp_err_t ret;
-    while (data_len > 0) {
-        len_tmp = data_len > 0xff ? 0xff : data_len;
-        data_len -= len_tmp;
-        i2c_cmd_t cmd;
-        cmd.ack_en = 0;
-        cmd.ack_exp = 0;
-        cmd.ack_val = ack & 0x1;
-        cmd.byte_num = len_tmp;
-        cmd.op_code = I2C_CMD_READ;
-        cmd.data = data + data_offset;
-        ret = i2c_cmd_link_append(cmd_handle, &cmd);
-        data_offset += len_tmp;
-        if (ret != ESP_OK) {
-            return ret;
-        }
-    }
-    return ESP_OK;
-}
-
-esp_err_t i2c_master_read_byte(i2c_cmd_handle_t cmd_handle, uint8_t* data, i2c_ack_type_t ack)
-{
-    I2C_CHECK((data != NULL), I2C_ADDR_ERROR_STR, ESP_ERR_INVALID_ARG);
-    I2C_CHECK(cmd_handle != NULL, I2C_CMD_LINK_INIT_ERR_STR, ESP_ERR_INVALID_ARG);
-    I2C_CHECK(ack < I2C_MASTER_ACK_MAX, I2C_ACK_TYPE_ERR_STR, ESP_ERR_INVALID_ARG);
-
-    i2c_cmd_t cmd;
-    cmd.ack_en = 0;
-    cmd.ack_exp = 0;
-    cmd.ack_val = ((ack == I2C_MASTER_LAST_NACK) ? I2C_MASTER_NACK : (ack & 0x1));
-    cmd.byte_num = 1;
-    cmd.op_code = I2C_CMD_READ;
-    cmd.data = data;
-    return i2c_cmd_link_append(cmd_handle, &cmd);
-}
-
-esp_err_t i2c_master_read(i2c_cmd_handle_t cmd_handle, uint8_t* data, size_t data_len, i2c_ack_type_t ack)
-{
-    I2C_CHECK((data != NULL), I2C_ADDR_ERROR_STR, ESP_ERR_INVALID_ARG);
-    I2C_CHECK(cmd_handle != NULL, I2C_CMD_LINK_INIT_ERR_STR, ESP_ERR_INVALID_ARG);
-    I2C_CHECK(ack < I2C_MASTER_ACK_MAX, I2C_ACK_TYPE_ERR_STR, ESP_ERR_INVALID_ARG);
-    I2C_CHECK(data_len > 0, I2C_DATA_LEN_ERR_STR, ESP_ERR_INVALID_ARG);
-
-    if(ack != I2C_MASTER_LAST_NACK) {
-        return i2c_master_read_static(cmd_handle, data, data_len, ack);
-    } else {
-        if(data_len == 1) {
-            return i2c_master_read_byte(cmd_handle, data, I2C_MASTER_NACK);
-        } else {
-            esp_err_t ret;
-            if((ret =  i2c_master_read_static(cmd_handle, data, data_len - 1, I2C_MASTER_ACK)) != ESP_OK) {
-                return ret;
-            }
-            return i2c_master_read_byte(cmd_handle, data + data_len - 1, I2C_MASTER_NACK);
-        }
-    }
-}
-
-static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num)
-{
-    i2c_obj_t* p_i2c = p_i2c_obj[i2c_num];
-    portBASE_TYPE HPTaskAwoken = pdFALSE;
-    i2c_cmd_evt_t evt;
-    //This should never happen
-    if (p_i2c->mode == I2C_MODE_SLAVE) {
-        return;
-    }
-    if (p_i2c->status == I2C_STATUS_DONE) {
-        return;
-    } else if ((p_i2c->status == I2C_STATUS_ACK_ERROR)
-            || (p_i2c->status == I2C_STATUS_TIMEOUT)) {
-        I2C[i2c_num]->int_ena.end_detect = 0;
-        I2C[i2c_num]->int_clr.end_detect = 1;
-        if(p_i2c->status == I2C_STATUS_TIMEOUT) {
-            I2C[i2c_num]->int_clr.time_out = 1;
-            I2C[i2c_num]->int_ena.val = 0;
-        }
-        evt.type = I2C_CMD_EVT_DONE;
-        xQueueOverwriteFromISR(p_i2c->cmd_evt_queue, &evt, &HPTaskAwoken);
-        if (HPTaskAwoken == pdTRUE) {
-            portYIELD_FROM_ISR();
-        }
-        return;
-    } else if (p_i2c->cmd_link.head != NULL && p_i2c->status == I2C_STATUS_READ) {
-        i2c_cmd_t *cmd = &p_i2c->cmd_link.head->cmd;
-        while (p_i2c->rx_cnt-- > 0) {
-            *cmd->data++ = READ_PERI_REG(I2C_DATA_APB_REG(i2c_num));
-        }
-        if (cmd->byte_num > 0) {
-            p_i2c->rx_fifo_remain = I2C_FIFO_LEN;
-            p_i2c->cmd_idx = 0;
-        } else {
-            p_i2c->cmd_link.head = p_i2c->cmd_link.head->next;
-        }
-    }
-    if (p_i2c->cmd_link.head == NULL) {
-        p_i2c->cmd_link.cur = NULL;
-        evt.type = I2C_CMD_EVT_DONE;
-        xQueueOverwriteFromISR(p_i2c->cmd_evt_queue, &evt, &HPTaskAwoken);
-        if (HPTaskAwoken == pdTRUE) {
-            portYIELD_FROM_ISR();
-        }
-        // Return to the IDLE status after cmd_eve_done signal were send out.
-        p_i2c->status = I2C_STATUS_IDLE;
-        return;
-    }
-    while (p_i2c->cmd_link.head) {
-        i2c_cmd_t *cmd = &p_i2c->cmd_link.head->cmd;
-        i2c_hw_cmd_t * const p_cur_hw_cmd = &I2C[i2c_num]->command[p_i2c->cmd_idx];
-        i2c_hw_cmd_t hw_cmd = {
-            .ack_en = cmd->ack_en,
-            .ack_exp = cmd->ack_exp,
-            .ack_val = cmd->ack_val,
-            .byte_num = cmd->byte_num,
-            .op_code = cmd->op_code
-        };
-        const i2c_hw_cmd_t hw_end_cmd = {
-            .op_code = I2C_CMD_END
-        };
-        if (cmd->op_code == I2C_CMD_WRITE) {
-            uint32_t wr_filled = 0;
-            //TODO: to reduce interrupt number
-            if (cmd->data) {
-                while (p_i2c->tx_fifo_remain > 0 && cmd->byte_num > 0) {
-                    WRITE_PERI_REG(I2C_DATA_APB_REG(i2c_num), *cmd->data++);
-                    p_i2c->tx_fifo_remain--;
-                    cmd->byte_num--;
-                    wr_filled++;
-                }
-            } else {
-                WRITE_PERI_REG(I2C_DATA_APB_REG(i2c_num), cmd->byte_cmd);
-                p_i2c->tx_fifo_remain--;
-                cmd->byte_num--;
-                wr_filled ++;
-            }
-            hw_cmd.byte_num = wr_filled;
-            *p_cur_hw_cmd = hw_cmd;
-            *(p_cur_hw_cmd + 1) = hw_end_cmd;
-            p_i2c->tx_fifo_remain = I2C_FIFO_LEN;
-            p_i2c->cmd_idx = 0;
-            if (cmd->byte_num > 0) {
-            } else {
-                p_i2c->cmd_link.head = p_i2c->cmd_link.head->next;
-            }
-            p_i2c->status = I2C_STATUS_WRITE;
-            break;
-        } else if(cmd->op_code == I2C_CMD_READ) {
-            //TODO: to reduce interrupt number
-            p_i2c->rx_cnt = cmd->byte_num > p_i2c->rx_fifo_remain ? p_i2c->rx_fifo_remain : cmd->byte_num;
-            cmd->byte_num -= p_i2c->rx_cnt;
-            hw_cmd.byte_num = p_i2c->rx_cnt;
-            hw_cmd.ack_val = cmd->ack_val;
-            *p_cur_hw_cmd = hw_cmd;
-            *(p_cur_hw_cmd + 1) = hw_end_cmd;
-            p_i2c->status = I2C_STATUS_READ;
-            break;
-        } else {
-            *p_cur_hw_cmd = hw_cmd;
-        }
-        p_i2c->cmd_idx++;
-        p_i2c->cmd_link.head = p_i2c->cmd_link.head->next;
-        if (p_i2c->cmd_link.head == NULL || p_i2c->cmd_idx >= 15) {
-            p_i2c->tx_fifo_remain = I2C_FIFO_LEN;
-            p_i2c->cmd_idx = 0;
-            break;
-        }
-    }
-    I2C[i2c_num]->int_clr.end_detect = 1;
-    I2C[i2c_num]->int_ena.end_detect = 1;
-    I2C[i2c_num]->ctr.trans_start = 0;
-    I2C[i2c_num]->ctr.trans_start = 1;
-    return;
-}
-
-#if CONFIG_SPIRAM_USE_MALLOC
-//Check whether read or write buffer in cmd_link is internal.
-static bool is_cmd_link_buffer_internal(i2c_cmd_link_t *link)
-{
-    i2c_cmd_link_t* cmd_link = link;
-    while(cmd_link != NULL)  {
-        if (cmd_link->cmd.op_code == I2C_CMD_WRITE || cmd_link->cmd.op_code == I2C_CMD_READ) {
-            if( cmd_link->cmd.data != NULL && !esp_ptr_internal(cmd_link->cmd.data)) {
-                return false;
-            }
-        }
-        cmd_link = cmd_link->next;
-    }
-    return true;
-}
-#endif
-
-esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle, TickType_t ticks_to_wait)
-{
-    I2C_CHECK(( i2c_num < I2C_NUM_MAX ), I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
-    I2C_CHECK(p_i2c_obj[i2c_num] != NULL, I2C_DRIVER_NOT_INSTALL_ERR_STR, ESP_ERR_INVALID_STATE);
-    I2C_CHECK(p_i2c_obj[i2c_num]->mode == I2C_MODE_MASTER, I2C_MASTER_MODE_ERR_STR, ESP_ERR_INVALID_STATE);
-    I2C_CHECK(cmd_handle != NULL, I2C_CMD_LINK_INIT_ERR_STR, ESP_ERR_INVALID_ARG);
-
-#if CONFIG_SPIRAM_USE_MALLOC
-    //If the i2c read or write buffer is not in internal RAM, we will return ESP_FAIL
-    //to avoid the ISR handler function crashing when the cache is disabled.
-    if( (p_i2c_obj[i2c_num]->intr_alloc_flags & ESP_INTR_FLAG_IRAM) ) {
-        if( !is_cmd_link_buffer_internal(((i2c_cmd_desc_t*)cmd_handle)->head) ) {
-            ESP_LOGE(I2C_TAG, I2C_PSRAM_BUFFER_WARN_STR);
-            return ESP_ERR_INVALID_ARG;
-        }
-    }
-#endif
-    // Sometimes when the FSM get stuck, the ACK_ERR interrupt will occur endlessly until we reset the FSM and clear bus.
-    static uint8_t clear_bus_cnt = 0;
-    esp_err_t ret = ESP_FAIL;
-    i2c_obj_t* p_i2c = p_i2c_obj[i2c_num];
-    portTickType ticks_start = xTaskGetTickCount();
-    portBASE_TYPE res = xSemaphoreTake(p_i2c->cmd_mux, ticks_to_wait);
-#ifdef CONFIG_PM_ENABLE
-    esp_pm_lock_acquire(p_i2c->pm_lock);
-#endif
-    if (res == pdFALSE) {
-        return ESP_ERR_TIMEOUT;
-    }
-    xQueueReset(p_i2c->cmd_evt_queue);
-    if (p_i2c->status == I2C_STATUS_TIMEOUT
-        || I2C[i2c_num]->status_reg.bus_busy == 1) {
-        i2c_hw_fsm_reset(i2c_num);
-        clear_bus_cnt = 0;
-    }
-    i2c_reset_tx_fifo(i2c_num);
-    i2c_reset_rx_fifo(i2c_num);
-    i2c_cmd_desc_t* cmd = (i2c_cmd_desc_t*) cmd_handle;
-    p_i2c->cmd_link.free = cmd->free;
-    p_i2c->cmd_link.cur = cmd->cur;
-    p_i2c->cmd_link.head = cmd->head;
-    p_i2c->status = I2C_STATUS_IDLE;
-    p_i2c->cmd_idx = 0;
-    p_i2c->rx_cnt = 0;
-    p_i2c->tx_fifo_remain = I2C_FIFO_LEN;
-    p_i2c->rx_fifo_remain = I2C_FIFO_LEN;
-    i2c_reset_tx_fifo(i2c_num);
-    i2c_reset_rx_fifo(i2c_num);
-    // These two interrupts some times can not be cleared when the FSM gets stuck.
-    // so we disable them when these two interrupt occurs and re-enable them here.
-    I2C[i2c_num]->int_ena.ack_err = 1;
-    I2C[i2c_num]->int_ena.time_out = 1;
-    //start send commands, at most 32 bytes one time, isr handler will process the remaining commands.
-    i2c_master_cmd_begin_static(i2c_num);
-
-    // Wait event bits
-    i2c_cmd_evt_t evt;
-    while (1) {
-        TickType_t wait_time = xTaskGetTickCount();
-        if (wait_time - ticks_start > ticks_to_wait) { // out of time
-            wait_time = I2C_CMD_ALIVE_INTERVAL_TICK;
-        } else {
-            wait_time = ticks_to_wait - (wait_time - ticks_start);
-            if (wait_time < I2C_CMD_ALIVE_INTERVAL_TICK) {
-                wait_time = I2C_CMD_ALIVE_INTERVAL_TICK;
-            }
-        }
-        // In master mode, since we don't have an interrupt to detective bus error or FSM state, what we do here is to make
-        // sure the interrupt mechanism for master mode is still working.
-        // If the command sending is not finished and there is no interrupt any more, the bus is probably dead caused by external noise.
-        portBASE_TYPE evt_res = xQueueReceive(p_i2c->cmd_evt_queue, &evt, wait_time);
-        if (evt_res == pdTRUE) {
-            if (evt.type == I2C_CMD_EVT_DONE) {
-                if (p_i2c->status == I2C_STATUS_TIMEOUT) {
-                    // If the I2C slave are powered off or the SDA/SCL are connected to ground, for example,
-                    // I2C hw FSM would get stuck in wrong state, we have to reset the I2C module in this case.
-                    i2c_hw_fsm_reset(i2c_num);
-                    clear_bus_cnt = 0;
-                    ret = ESP_ERR_TIMEOUT;
-                } else if (p_i2c->status == I2C_STATUS_ACK_ERROR) {
-                    clear_bus_cnt++;
-                    if(clear_bus_cnt >= I2C_ACKERR_CNT_MAX) {
-                        i2c_master_clear_bus(i2c_num);
-                        clear_bus_cnt = 0;
-                    }
-                    ret = ESP_FAIL;
-                } else {
-                    ret = ESP_OK;
-                }
-                break;
-            }
-            if (evt.type == I2C_CMD_EVT_ALIVE) {
-            }
-        } else {
-            ret = ESP_ERR_TIMEOUT;
-            // If the I2C slave are powered off or the SDA/SCL are connected to ground, for example,
-            // I2C hw FSM would get stuck in wrong state, we have to reset the I2C module in this case.
-            i2c_hw_fsm_reset(i2c_num);
-            clear_bus_cnt = 0;
-            break;
-        }
-    }
-    p_i2c->status = I2C_STATUS_DONE;
-#ifdef CONFIG_PM_ENABLE
-    esp_pm_lock_release(p_i2c->pm_lock);
-#endif
-    xSemaphoreGive(p_i2c->cmd_mux);
-    return ret;
-}
-
-int i2c_slave_write_buffer(i2c_port_t i2c_num, uint8_t* data, int size, TickType_t ticks_to_wait)
-{
-    I2C_CHECK(( i2c_num < I2C_NUM_MAX ), I2C_NUM_ERROR_STR, ESP_FAIL);
-    I2C_CHECK((data != NULL), I2C_ADDR_ERROR_STR, ESP_FAIL);
-    I2C_CHECK(p_i2c_obj[i2c_num]->mode == I2C_MODE_SLAVE, I2C_MODE_SLAVE_ERR_STR, ESP_FAIL);
-    i2c_obj_t* p_i2c = p_i2c_obj[i2c_num];
-
-    portBASE_TYPE res;
-    int cnt = 0;
-    portTickType ticks_start = xTaskGetTickCount();
-
-    res = xSemaphoreTake(p_i2c->slv_tx_mux, ticks_to_wait);
-    if (res == pdFALSE) {
-        return 0;
-    }
-    TickType_t ticks_end = xTaskGetTickCount();
-    if (ticks_end - ticks_start > ticks_to_wait) {
-        ticks_to_wait = 0;
-    } else {
-        ticks_to_wait = ticks_to_wait - (ticks_end - ticks_start);
-    }
-    res = xRingbufferSend(p_i2c->tx_ring_buf, data, size, ticks_to_wait);
-    if (res == pdFALSE) {
-        cnt = 0;
-    } else {
-        I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
-        I2C[i2c_num]->int_clr.tx_fifo_empty = 1;
-        I2C[i2c_num]->int_ena.tx_fifo_empty = 1;
-        I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
-        cnt = size;
-    }
-    xSemaphoreGive(p_i2c->slv_tx_mux);
-    return cnt;
-}
-
-static int i2c_slave_read(i2c_port_t i2c_num, uint8_t* data, size_t max_size, TickType_t ticks_to_wait)
-{
-    i2c_obj_t* p_i2c = p_i2c_obj[i2c_num];
-    size_t size = 0;
-    uint8_t* pdata = (uint8_t*) xRingbufferReceiveUpTo(p_i2c->rx_ring_buf, &size, ticks_to_wait, max_size);
-    if (pdata && size > 0) {
-        memcpy(data, pdata, size);
-        vRingbufferReturnItem(p_i2c->rx_ring_buf, pdata);
-    }
-    return size;
-}
-
-int i2c_slave_read_buffer(i2c_port_t i2c_num, uint8_t* data, size_t max_size, TickType_t ticks_to_wait)
-{
-    I2C_CHECK(( i2c_num < I2C_NUM_MAX ), I2C_NUM_ERROR_STR, ESP_FAIL);
-    I2C_CHECK((data != NULL), I2C_ADDR_ERROR_STR, ESP_FAIL);
-    I2C_CHECK(p_i2c_obj[i2c_num]->mode == I2C_MODE_SLAVE, I2C_MODE_SLAVE_ERR_STR, ESP_FAIL);
-
-    i2c_obj_t* p_i2c = p_i2c_obj[i2c_num];
-    portBASE_TYPE res;
-    portTickType ticks_start = xTaskGetTickCount();
-    res = xSemaphoreTake(p_i2c->slv_rx_mux, ticks_to_wait);
-    if (res == pdFALSE) {
-        return 0;
-    }
-    TickType_t ticks_end = xTaskGetTickCount();
-    if (ticks_end - ticks_start > ticks_to_wait) {
-        ticks_to_wait = 0;
-    } else {
-        ticks_to_wait = ticks_to_wait - (ticks_end - ticks_start);
-    }
-    int cnt = i2c_slave_read(i2c_num, data, max_size, ticks_to_wait);
-    if (cnt > 0) {
-        I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
-        I2C[i2c_num]->int_ena.rx_fifo_full = 1;
-        I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
-        ticks_end = xTaskGetTickCount();
-        if (ticks_end - ticks_start > ticks_to_wait) {
-            ticks_to_wait = 0;
-        } else {
-            ticks_to_wait = ticks_to_wait - (ticks_end - ticks_start);
-        }
-        if (cnt < max_size && ticks_to_wait > 0) {
-            cnt += i2c_slave_read(i2c_num, data + cnt, max_size - cnt, ticks_to_wait);
-        }
-    } else {
-        cnt = 0;
-    }
-    xSemaphoreGive(p_i2c->slv_rx_mux);
-    return cnt;
-}

+ 1456 - 0
idf-patch/i2s.c

@@ -0,0 +1,1456 @@
+// 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 <math.h>
+#include <esp_types.h>
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/queue.h"
+#include "freertos/xtensa_api.h"
+
+#include "soc/rtc_periph.h"
+#include "soc/rtc.h"
+#include "soc/efuse_periph.h"
+#include "esp32/rom/lldesc.h"
+
+#include "driver/gpio.h"
+#include "driver/i2s.h"
+#include "driver/rtc_io.h"
+#include "driver/dac.h"
+#include "adc1_i2s_private.h"
+
+#include "esp_intr_alloc.h"
+#include "esp_err.h"
+#include "esp_log.h"
+#include "esp_pm.h"
+
+static const char* I2S_TAG = "I2S";
+
+#define I2S_CHECK(a, str, ret) if (!(a)) {                                              \
+        ESP_LOGE(I2S_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str);       \
+        return (ret);                                                                   \
+        }
+#define I2S_MAX_BUFFER_SIZE               (4 * 1024 * 1024) //the maximum RAM can be allocated
+#define I2S_BASE_CLK                      (2*APB_CLK_FREQ)
+#define I2S_ENTER_CRITICAL_ISR()          portENTER_CRITICAL_ISR(&i2s_spinlock[i2s_num])
+#define I2S_EXIT_CRITICAL_ISR()           portEXIT_CRITICAL_ISR(&i2s_spinlock[i2s_num])
+#define I2S_ENTER_CRITICAL()              portENTER_CRITICAL(&i2s_spinlock[i2s_num])
+#define I2S_EXIT_CRITICAL()               portEXIT_CRITICAL(&i2s_spinlock[i2s_num])
+#define I2S_FULL_DUPLEX_SLAVE_MODE_MASK   (I2S_MODE_TX | I2S_MODE_RX | I2S_MODE_SLAVE)
+#define I2S_FULL_DUPLEX_MASTER_MODE_MASK  (I2S_MODE_TX | I2S_MODE_RX | I2S_MODE_MASTER)
+#define APLL_MIN_FREQ                     (250000000)
+#define APLL_MAX_FREQ                     (500000000)
+#define APLL_I2S_MIN_RATE                 (10675) //in Hz, I2S Clock rate limited by hardware
+#define I2S_AD_BCK_FACTOR                 (2)
+#define I2S_PDM_BCK_FACTOR                (64)
+/**
+ * @brief DMA buffer object
+ *
+ */
+typedef struct {
+    char **buf;
+    int buf_size;
+    int rw_pos;
+    void *curr_ptr;
+    SemaphoreHandle_t mux;
+    xQueueHandle queue;
+    lldesc_t **desc;
+} i2s_dma_t;
+
+/**
+ * @brief I2S object instance
+ *
+ */
+typedef struct {
+    i2s_port_t i2s_num;         /*!< I2S port number*/
+    int queue_size;             /*!< I2S event queue size*/
+    QueueHandle_t i2s_queue;    /*!< I2S queue handler*/
+    int dma_buf_count;          /*!< DMA buffer count, number of buffer*/
+    int dma_buf_len;            /*!< DMA buffer length, length of each buffer*/
+    i2s_dma_t *rx;              /*!< DMA Tx buffer*/
+    i2s_dma_t *tx;              /*!< DMA Rx buffer*/
+    i2s_isr_handle_t i2s_isr_handle; /*!< I2S Interrupt handle*/
+    int channel_num;            /*!< Number of channels*/
+    int bytes_per_sample;        /*!< Bytes per sample*/
+    int bits_per_sample;        /*!< Bits per sample*/
+    i2s_mode_t mode;            /*!< I2S Working mode*/
+    uint32_t sample_rate;              /*!< I2S sample rate */
+    bool use_apll;               /*!< I2S use APLL clock */
+    bool tx_desc_auto_clear;    /*!< I2S auto clear tx descriptor on underflow */
+    int fixed_mclk;             /*!< I2S fixed MLCK clock */
+    double real_rate;
+#ifdef CONFIG_PM_ENABLE
+    esp_pm_lock_handle_t pm_lock;
+#endif
+} i2s_obj_t;
+
+static i2s_obj_t *p_i2s_obj[I2S_NUM_MAX] = {0};
+static i2s_dev_t* I2S[I2S_NUM_MAX] = {&I2S0, &I2S1};
+static portMUX_TYPE i2s_spinlock[I2S_NUM_MAX] = {portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED};
+static int _i2s_adc_unit = -1;
+static int _i2s_adc_channel = -1;
+
+static i2s_dma_t *i2s_create_dma_queue(i2s_port_t i2s_num, int dma_buf_count, int dma_buf_len);
+static esp_err_t i2s_destroy_dma_queue(i2s_port_t i2s_num, i2s_dma_t *dma);
+static esp_err_t i2s_reset_fifo(i2s_port_t i2s_num)
+{
+    I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
+    I2S_ENTER_CRITICAL();
+    I2S[i2s_num]->conf.rx_fifo_reset = 1;
+    I2S[i2s_num]->conf.rx_fifo_reset = 0;
+    I2S[i2s_num]->conf.tx_fifo_reset = 1;
+    I2S[i2s_num]->conf.tx_fifo_reset = 0;
+    I2S_EXIT_CRITICAL();
+    return ESP_OK;
+}
+
+inline static void gpio_matrix_out_check(uint32_t gpio, uint32_t signal_idx, bool out_inv, bool oen_inv)
+{
+    //if pin = -1, do not need to configure
+    if (gpio != -1) {
+        PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO);
+        gpio_set_direction(gpio, GPIO_MODE_DEF_OUTPUT);
+        gpio_matrix_out(gpio, signal_idx, out_inv, oen_inv);
+    }
+}
+inline static void gpio_matrix_in_check(uint32_t gpio, uint32_t signal_idx, bool inv)
+{
+    if (gpio != -1) {
+        PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO);
+        //Set direction, for some GPIOs, the input function are not enabled as default.
+        gpio_set_direction(gpio, GPIO_MODE_DEF_INPUT);
+        gpio_matrix_in(gpio, signal_idx, inv);
+    }
+}
+
+
+esp_err_t i2s_clear_intr_status(i2s_port_t i2s_num, uint32_t clr_mask)
+{
+    I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
+    I2S[i2s_num]->int_clr.val = clr_mask;
+    return ESP_OK;
+}
+
+esp_err_t i2s_enable_rx_intr(i2s_port_t i2s_num)
+{
+
+    I2S_ENTER_CRITICAL();
+    I2S[i2s_num]->int_ena.in_suc_eof = 1;
+    I2S[i2s_num]->int_ena.in_dscr_err = 1;
+    I2S_EXIT_CRITICAL();
+    return ESP_OK;
+}
+
+esp_err_t i2s_disable_rx_intr(i2s_port_t i2s_num)
+{
+    I2S_ENTER_CRITICAL();
+    I2S[i2s_num]->int_ena.in_suc_eof = 0;
+    I2S[i2s_num]->int_ena.in_dscr_err = 0;
+    I2S_EXIT_CRITICAL();
+    return ESP_OK;
+}
+
+esp_err_t i2s_disable_tx_intr(i2s_port_t i2s_num)
+{
+    I2S_ENTER_CRITICAL();
+    I2S[i2s_num]->int_ena.out_eof = 0;
+    I2S[i2s_num]->int_ena.out_dscr_err = 0;
+    I2S_EXIT_CRITICAL();
+    return ESP_OK;
+}
+
+esp_err_t i2s_enable_tx_intr(i2s_port_t i2s_num)
+{
+    I2S_ENTER_CRITICAL();
+    I2S[i2s_num]->int_ena.out_eof = 1;
+    I2S[i2s_num]->int_ena.out_dscr_err = 1;
+    I2S_EXIT_CRITICAL();
+    return ESP_OK;
+}
+
+float i2s_get_clk(i2s_port_t i2s_num)
+{
+    I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
+    return p_i2s_obj[i2s_num]->real_rate;
+}
+
+static esp_err_t i2s_isr_register(i2s_port_t i2s_num, int intr_alloc_flags, void (*fn)(void*), void * arg, i2s_isr_handle_t *handle)
+{
+    return esp_intr_alloc(ETS_I2S0_INTR_SOURCE + i2s_num, intr_alloc_flags, fn, arg, handle);
+}
+
+
+static float i2s_apll_get_fi2s(int bits_per_sample, int sdm0, int sdm1, int sdm2, int odir)
+{
+    int f_xtal = (int)rtc_clk_xtal_freq_get() * 1000000;
+    uint32_t is_rev0 = (GET_PERI_REG_BITS2(EFUSE_BLK0_RDATA3_REG, 1, 15) == 0);
+    if (is_rev0) {
+        sdm0 = 0;
+        sdm1 = 0;
+    }
+    float fout = f_xtal * (sdm2 + sdm1 / 256.0f + sdm0 / 65536.0f + 4);
+    if (fout < APLL_MIN_FREQ || fout > APLL_MAX_FREQ) {
+        return APLL_MAX_FREQ;
+    }
+    float fpll = fout / (2 * (odir+2)); //== fi2s (N=1, b=0, a=1)
+    return fpll/2;
+}
+
+/**
+ * @brief     APLL calculate function, was described by following:
+ *            APLL Output frequency is given by the formula:
+ *
+ *            apll_freq = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536)/((o_div + 2) * 2)
+ *            apll_freq = fout / ((o_div + 2) * 2)
+ *
+ *            The dividend in this expression should be in the range of 240 - 600 MHz.
+ *            In rev. 0 of ESP32, sdm0 and sdm1 are unused and always set to 0.
+ *            * sdm0  frequency adjustment parameter, 0..255
+ *            * sdm1  frequency adjustment parameter, 0..255
+ *            * sdm2  frequency adjustment parameter, 0..63
+ *            * o_div  frequency divider, 0..31
+ *
+ *            The most accurate way to find the sdm0..2 and odir parameters is to loop through them all,
+ *            then apply the above formula, finding the closest frequency to the desired one.
+ *            But 256*256*64*32 = 134.217.728 loops are too slow with ESP32
+ *            1. We will choose the parameters with the highest level of change,
+ *               With 350MHz<fout<500MHz, we limit the sdm2 from 4 to 9,
+ *               Take average frequency close to the desired frequency, and select sdm2
+ *            2. Next, we look for sequences of less influential and more detailed parameters,
+ *               also by taking the average of the largest and smallest frequencies closer to the desired frequency.
+ *            3. And finally, loop through all the most detailed of the parameters, finding the best desired frequency
+ *
+ * @param[in]  rate                  The I2S Frequency (MCLK)
+ * @param[in]  bits_per_sample       The bits per sample
+ * @param[out]      sdm0             The sdm 0
+ * @param[out]      sdm1             The sdm 1
+ * @param[out]      sdm2             The sdm 2
+ * @param[out]      odir             The odir
+ *
+ * @return     ESP_ERR_INVALID_ARG or ESP_OK
+ */
+static esp_err_t i2s_apll_calculate_fi2s(int rate, int bits_per_sample, int *sdm0, int *sdm1, int *sdm2, int *odir) 
+ {
+ 	int _odir, _sdm0, _sdm1, _sdm2;
+	float r = rtc_clk_xtal_freq_get() * 1000000. / (rate * 2 * 2);
+	int _sdm2_max;
+	uint32_t prec = -1;
+	int o, s1, s0;
+	
+	if (rate/bits_per_sample/2/8 < APLL_I2S_MIN_RATE) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+	*sdm0 = 0;
+	*sdm1 = 0;
+	*sdm2 = 0;
+	*odir = 0;
+
+	_sdm2 = 1/r * 2 - 4;
+	if (_sdm2 < 4) _sdm2 = 4;
+	_sdm2_max = ceil(1/r * (31 + 2) - (255/256 + 255/65536 + 4));
+	if (_sdm2_max > 8) _sdm2_max = 8;
+
+	// explore up to 5 sdm2 values
+	for (; _sdm2 < _sdm2_max; _sdm2++) {
+		_odir = r * (_sdm2 + 4) - 2;
+		if (_odir < 0) _odir = 0;
+		else if (_odir > 31) _odir = 31;
+
+		for (o = 0; o < 2 && _odir + o < 32; o++) {
+			_sdm1 = 256*((_odir + o + 2) / r - (_sdm2 + 4));
+			if (_sdm1 < 0) _sdm1 = 0;
+			else if (_sdm1 > 255) _sdm1 = 255;
+
+			for (s1 = 0; s1 < 2 && _sdm1 + s1 < 256; s1++) {
+				_sdm0 = 65536*((_odir + o + 2) / r - (_sdm2 + (float) (_sdm1 + s1)/256 + 4));
+				if (_sdm0 < 0) _sdm1 = 0;
+				else if (_sdm0 > 255) _sdm0 = 255;
+
+				for (s0 = 0; s0 < 2 && _sdm2 + s0 < 256; s0++) {
+					int _fi2s = i2s_apll_get_fi2s(bits_per_sample, _sdm0 + s0, _sdm1 + s1, _sdm2, _odir + o);
+					if (abs(_fi2s - rate) < prec) {
+						prec = abs(_fi2s - rate);
+						*sdm0 = _sdm0 + s0;
+						*sdm1 = _sdm1 + s1;
+						*sdm2 = _sdm2;
+						*odir = _odir + o;
+                    }
+				}
+			}
+		}
+	}
+	
+	if (*sdm2 + *sdm0 + *sdm0 + *odir) return ESP_OK;
+	else return ESP_ERR_INVALID_ARG;
+ }	
+
+#if 0
+static esp_err_t i2s_apll_calculate_fi2s(int rate, int bits_per_sample, int *sdm0, int *sdm1, int *sdm2, int *odir)
+{
+    int _odir, _sdm0, _sdm1, _sdm2;
+    float avg;
+    float min_rate, max_rate, min_diff;
+    if (rate/bits_per_sample/2/8 < APLL_I2S_MIN_RATE) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    *sdm0 = 0;
+    *sdm1 = 0;
+    *sdm2 = 0;
+    *odir = 0;
+    min_diff = APLL_MAX_FREQ;
+
+    for (_sdm2 = 4; _sdm2 < 9; _sdm2 ++) {
+        max_rate = i2s_apll_get_fi2s(bits_per_sample, 255, 255, _sdm2, 0);
+        min_rate = i2s_apll_get_fi2s(bits_per_sample, 0, 0, _sdm2, 31);
+        avg = (max_rate + min_rate)/2;
+        if (abs(avg - rate) < min_diff) {
+            min_diff = abs(avg - rate);
+            *sdm2 = _sdm2;
+        }
+    }
+    min_diff = APLL_MAX_FREQ;
+    for (_odir = 0; _odir < 32; _odir ++) {
+        max_rate = i2s_apll_get_fi2s(bits_per_sample, 255, 255, *sdm2, _odir);
+        min_rate = i2s_apll_get_fi2s(bits_per_sample, 0, 0, *sdm2, _odir);
+        avg = (max_rate + min_rate)/2;
+        if (abs(avg - rate) < min_diff) {
+            min_diff = abs(avg - rate);
+            *odir = _odir;
+        }
+    }
+    min_diff = APLL_MAX_FREQ;
+    for (_sdm2 = 4; _sdm2 < 9; _sdm2 ++) {
+        max_rate = i2s_apll_get_fi2s(bits_per_sample, 255, 255, _sdm2, *odir);
+        min_rate = i2s_apll_get_fi2s(bits_per_sample, 0, 0, _sdm2, *odir);
+        avg = (max_rate + min_rate)/2;
+        if (abs(avg - rate) < min_diff) {
+            min_diff = abs(avg - rate);
+            *sdm2 = _sdm2;
+        }
+    }
+
+    min_diff = APLL_MAX_FREQ;
+    for (_sdm1 = 0; _sdm1 < 256; _sdm1 ++) {
+        max_rate = i2s_apll_get_fi2s(bits_per_sample, 255, _sdm1, *sdm2, *odir);
+        min_rate = i2s_apll_get_fi2s(bits_per_sample, 0, _sdm1, *sdm2, *odir);
+        avg = (max_rate + min_rate)/2;
+        if (abs(avg - rate) < min_diff) {
+            min_diff = abs(avg - rate);
+            *sdm1 = _sdm1;
+        }
+    }
+
+    min_diff = APLL_MAX_FREQ;
+    for (_sdm0 = 0; _sdm0 < 256; _sdm0 ++) {
+        avg = i2s_apll_get_fi2s(bits_per_sample, _sdm0, *sdm1, *sdm2, *odir);
+        if (abs(avg - rate) < min_diff) {
+            min_diff = abs(avg - rate);
+            *sdm0 = _sdm0;
+        }
+    }
+
+    return ESP_OK;
+}
+#endif
+esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t bits, i2s_channel_t ch)
+{
+    int factor = (256%bits)? 384 : 256; // According to hardware codec requirement(supported 256fs or 384fs)
+    int clkmInteger, clkmDecimals, bck = 0;
+    double denom = (double)1 / 64;
+    int channel = 2;
+    i2s_dma_t *save_tx = NULL, *save_rx = NULL;
+
+    I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
+
+    if (bits % 8 != 0 || bits > I2S_BITS_PER_SAMPLE_32BIT || bits < I2S_BITS_PER_SAMPLE_16BIT) {
+        ESP_LOGE(I2S_TAG, "Invalid bits per sample");
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    if (p_i2s_obj[i2s_num] == NULL) {
+        ESP_LOGE(I2S_TAG, "Not initialized yet");
+        return ESP_ERR_INVALID_ARG;
+    }
+    p_i2s_obj[i2s_num]->sample_rate = rate;
+    double clkmdiv = (double)I2S_BASE_CLK / (rate * factor);
+
+    if (clkmdiv > 256) {
+        ESP_LOGE(I2S_TAG, "clkmdiv is too large\r\n");
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    // wait all on-going writing finish
+    if ((p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) && p_i2s_obj[i2s_num]->tx) {
+        xSemaphoreTake(p_i2s_obj[i2s_num]->tx->mux, (portTickType)portMAX_DELAY);
+    }
+    if ((p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) && p_i2s_obj[i2s_num]->rx) {
+        xSemaphoreTake(p_i2s_obj[i2s_num]->rx->mux, (portTickType)portMAX_DELAY);
+    }
+
+    i2s_stop(i2s_num);
+
+
+    uint32_t cur_mode = 0;
+    if (p_i2s_obj[i2s_num]->channel_num != ch) {
+        p_i2s_obj[i2s_num]->channel_num = (ch == 2) ? 2 : 1;
+        cur_mode = I2S[i2s_num]->fifo_conf.tx_fifo_mod;
+        I2S[i2s_num]->fifo_conf.tx_fifo_mod = (ch == 2) ? cur_mode - 1 : cur_mode + 1;
+        cur_mode = I2S[i2s_num]->fifo_conf.rx_fifo_mod;
+        I2S[i2s_num]->fifo_conf.rx_fifo_mod = (ch == 2) ? cur_mode -1  : cur_mode + 1;
+        I2S[i2s_num]->conf_chan.tx_chan_mod = (ch == 2) ? 0 : 1;
+        I2S[i2s_num]->conf_chan.rx_chan_mod = (ch == 2) ? 0 : 1;
+    }
+
+    if (bits != p_i2s_obj[i2s_num]->bits_per_sample) {
+
+        //change fifo mode
+        if (p_i2s_obj[i2s_num]->bits_per_sample <= 16 && bits > 16) {
+            I2S[i2s_num]->fifo_conf.tx_fifo_mod += 2;
+            I2S[i2s_num]->fifo_conf.rx_fifo_mod += 2;
+        } else if (p_i2s_obj[i2s_num]->bits_per_sample > 16 && bits <= 16) {
+            I2S[i2s_num]->fifo_conf.tx_fifo_mod -= 2;
+            I2S[i2s_num]->fifo_conf.rx_fifo_mod -= 2;
+        }
+
+        p_i2s_obj[i2s_num]->bits_per_sample = bits;
+        p_i2s_obj[i2s_num]->bytes_per_sample = p_i2s_obj[i2s_num]->bits_per_sample / 8;
+
+        // Round bytes_per_sample up to next multiple of 16 bits
+        int halfwords_per_sample = (p_i2s_obj[i2s_num]->bits_per_sample + 15) / 16;
+        p_i2s_obj[i2s_num]->bytes_per_sample = halfwords_per_sample * 2;
+
+        // Because limited of DMA buffer is 4092 bytes
+        if (p_i2s_obj[i2s_num]->dma_buf_len * p_i2s_obj[i2s_num]->bytes_per_sample * p_i2s_obj[i2s_num]->channel_num > 4092) {
+            p_i2s_obj[i2s_num]->dma_buf_len = 4092 / p_i2s_obj[i2s_num]->bytes_per_sample / p_i2s_obj[i2s_num]->channel_num;
+        }
+        // Re-create TX DMA buffer
+        if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) {
+
+            save_tx = p_i2s_obj[i2s_num]->tx;
+
+            p_i2s_obj[i2s_num]->tx = i2s_create_dma_queue(i2s_num, p_i2s_obj[i2s_num]->dma_buf_count, p_i2s_obj[i2s_num]->dma_buf_len);
+            if (p_i2s_obj[i2s_num]->tx == NULL) {
+                ESP_LOGE(I2S_TAG, "Failed to create tx dma buffer");
+                i2s_driver_uninstall(i2s_num);
+                return ESP_ERR_NO_MEM;
+            }
+            I2S[i2s_num]->out_link.addr = (uint32_t) p_i2s_obj[i2s_num]->tx->desc[0];
+
+            //destroy old tx dma if exist
+            if (save_tx) {
+                i2s_destroy_dma_queue(i2s_num, save_tx);
+            }
+        }
+        // Re-create RX DMA buffer
+        if (p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) {
+
+            save_rx = p_i2s_obj[i2s_num]->rx;
+
+            p_i2s_obj[i2s_num]->rx = i2s_create_dma_queue(i2s_num, p_i2s_obj[i2s_num]->dma_buf_count, p_i2s_obj[i2s_num]->dma_buf_len);
+            if (p_i2s_obj[i2s_num]->rx == NULL){
+                ESP_LOGE(I2S_TAG, "Failed to create rx dma buffer");
+                i2s_driver_uninstall(i2s_num);
+                return ESP_ERR_NO_MEM;
+            }
+            I2S[i2s_num]->rx_eof_num = (p_i2s_obj[i2s_num]->dma_buf_len * p_i2s_obj[i2s_num]->channel_num * p_i2s_obj[i2s_num]->bytes_per_sample)/4;
+            I2S[i2s_num]->in_link.addr = (uint32_t) p_i2s_obj[i2s_num]->rx->desc[0];
+
+            //destroy old rx dma if exist
+            if (save_rx) {
+                i2s_destroy_dma_queue(i2s_num, save_rx);
+            }
+        }
+
+    }
+
+    double mclk;
+    int sdm0, sdm1, sdm2, odir, m_scale = 8;
+    int fi2s_clk = rate*channel*bits*m_scale;
+    if (p_i2s_obj[i2s_num]->mode & (I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN)) {
+        //DAC uses bclk as sample clock, not WS. WS can be something arbitrary.
+        //Rate as given to this function is the intended sample rate;
+        //According to the TRM, WS clk equals to the sample rate, and bclk is double the speed of WS
+        uint32_t b_clk = rate * I2S_AD_BCK_FACTOR;
+        fi2s_clk /= I2S_AD_BCK_FACTOR;
+        int factor2 = 60;
+        mclk = b_clk * factor2;
+        clkmdiv = ((double) I2S_BASE_CLK) / mclk;
+        clkmInteger = clkmdiv;
+        clkmDecimals = (clkmdiv - clkmInteger) / denom;
+        bck = mclk / b_clk;
+    } else if (p_i2s_obj[i2s_num]->mode & I2S_MODE_PDM) {
+        uint32_t b_clk = 0;
+        if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) {
+            int fp = I2S[i2s_num]->pdm_freq_conf.tx_pdm_fp;
+            int fs = I2S[i2s_num]->pdm_freq_conf.tx_pdm_fs;
+            b_clk = rate * I2S_PDM_BCK_FACTOR * (fp / fs);
+            fi2s_clk /= (I2S_PDM_BCK_FACTOR * (fp / fs));
+        } else if (p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) {
+            b_clk = rate * I2S_PDM_BCK_FACTOR * (I2S[i2s_num]->pdm_conf.rx_sinc_dsr_16_en + 1);
+            fi2s_clk /= (I2S_PDM_BCK_FACTOR * (I2S[i2s_num]->pdm_conf.rx_sinc_dsr_16_en + 1));
+        }
+        int factor2 = 5 ;
+        mclk = b_clk * factor2;
+        clkmdiv = ((double) I2S_BASE_CLK) / mclk;
+        clkmInteger = clkmdiv;
+        clkmDecimals = (clkmdiv - clkmInteger) / denom;
+        bck = mclk / b_clk;
+    } else {
+        clkmInteger = clkmdiv;
+        clkmDecimals = (clkmdiv - clkmInteger) / denom;
+        mclk = clkmInteger + denom * clkmDecimals;
+        bck = factor/(bits * channel);
+    }
+
+    if(p_i2s_obj[i2s_num]->use_apll && p_i2s_obj[i2s_num]->fixed_mclk) {
+        fi2s_clk = p_i2s_obj[i2s_num]->fixed_mclk;
+        m_scale = fi2s_clk/bits/rate/channel;
+    }
+    if(p_i2s_obj[i2s_num]->use_apll && i2s_apll_calculate_fi2s(fi2s_clk, bits, &sdm0, &sdm1, &sdm2, &odir) == ESP_OK) {
+        ESP_LOGD(I2S_TAG, "sdm0=%d, sdm1=%d, sdm2=%d, odir=%d", sdm0, sdm1, sdm2, odir);
+        rtc_clk_apll_enable(1, sdm0, sdm1, sdm2, odir);
+        I2S[i2s_num]->clkm_conf.clkm_div_num = 1;
+        I2S[i2s_num]->clkm_conf.clkm_div_b = 0;
+        I2S[i2s_num]->clkm_conf.clkm_div_a = 1;
+        I2S[i2s_num]->sample_rate_conf.tx_bck_div_num = m_scale;
+        I2S[i2s_num]->sample_rate_conf.rx_bck_div_num = m_scale;
+        I2S[i2s_num]->clkm_conf.clka_en = 1;
+        double fi2s_rate = i2s_apll_get_fi2s(bits, sdm0, sdm1, sdm2, odir);
+        p_i2s_obj[i2s_num]->real_rate = fi2s_rate/bits/channel/m_scale;
+        ESP_LOGI(I2S_TAG, "APLL: Req RATE: %d, real rate: %0.3f, BITS: %u, CLKM: %u, BCK_M: %u, MCLK: %0.3f, SCLK: %f, diva: %d, divb: %d",
+            rate, fi2s_rate/bits/channel/m_scale, bits, 1, m_scale, fi2s_rate, fi2s_rate/8, 1, 0);
+    } else {
+        I2S[i2s_num]->clkm_conf.clka_en = 0;
+        I2S[i2s_num]->clkm_conf.clkm_div_a = 63;
+        I2S[i2s_num]->clkm_conf.clkm_div_b = clkmDecimals;
+        I2S[i2s_num]->clkm_conf.clkm_div_num = clkmInteger;
+        I2S[i2s_num]->sample_rate_conf.tx_bck_div_num = bck;
+        I2S[i2s_num]->sample_rate_conf.rx_bck_div_num = bck;
+        double real_rate = (double) (I2S_BASE_CLK / (bck * bits * clkmInteger) / 2);
+        p_i2s_obj[i2s_num]->real_rate = real_rate;
+        ESP_LOGI(I2S_TAG, "PLL_D2: Req RATE: %d, real rate: %0.3f, BITS: %u, CLKM: %u, BCK: %u, MCLK: %0.3f, SCLK: %f, diva: %d, divb: %d",
+            rate, real_rate, bits, clkmInteger, bck, (double)I2S_BASE_CLK / mclk, real_rate*bits*channel, 64, clkmDecimals);
+    }
+
+    I2S[i2s_num]->sample_rate_conf.tx_bits_mod = bits;
+    I2S[i2s_num]->sample_rate_conf.rx_bits_mod = bits;
+
+    // wait all writing on-going finish
+    if ((p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) && p_i2s_obj[i2s_num]->tx) {
+        xSemaphoreGive(p_i2s_obj[i2s_num]->tx->mux);
+    }
+    if ((p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) && p_i2s_obj[i2s_num]->rx) {
+        xSemaphoreGive(p_i2s_obj[i2s_num]->rx->mux);
+    }
+    i2s_start(i2s_num);
+    return ESP_OK;
+}
+
+static void IRAM_ATTR i2s_intr_handler_default(void *arg)
+{
+    i2s_obj_t *p_i2s = (i2s_obj_t*) arg;
+    uint8_t i2s_num = p_i2s->i2s_num;
+    i2s_dev_t* i2s_reg = I2S[i2s_num];
+    i2s_event_t i2s_event;
+    int dummy;
+
+    portBASE_TYPE high_priority_task_awoken = 0;
+
+    lldesc_t *finish_desc;
+
+    if (i2s_reg->int_st.out_dscr_err || i2s_reg->int_st.in_dscr_err) {
+        ESP_EARLY_LOGE(I2S_TAG, "dma error, interrupt status: 0x%08x", i2s_reg->int_st.val);
+        if (p_i2s->i2s_queue) {
+            i2s_event.type = I2S_EVENT_DMA_ERROR;
+            if (xQueueIsQueueFullFromISR(p_i2s->i2s_queue)) {
+                xQueueReceiveFromISR(p_i2s->i2s_queue, &dummy, &high_priority_task_awoken);
+            }
+            xQueueSendFromISR(p_i2s->i2s_queue, (void * )&i2s_event, &high_priority_task_awoken);
+        }
+    }
+
+    if (i2s_reg->int_st.out_eof && p_i2s->tx) {
+        finish_desc = (lldesc_t*) i2s_reg->out_eof_des_addr;
+        // All buffers are empty. This means we have an underflow on our hands.
+        if (xQueueIsQueueFullFromISR(p_i2s->tx->queue)) {
+            xQueueReceiveFromISR(p_i2s->tx->queue, &dummy, &high_priority_task_awoken);
+            // See if tx descriptor needs to be auto cleared:
+            // This will avoid any kind of noise that may get introduced due to transmission
+            // of previous data from tx descriptor on I2S line.
+            if (p_i2s->tx_desc_auto_clear == true) {
+                memset((void *) dummy, 0, p_i2s->tx->buf_size);
+            }
+        }
+        xQueueSendFromISR(p_i2s->tx->queue, (void*)(&finish_desc->buf), &high_priority_task_awoken);
+        if (p_i2s->i2s_queue) {
+            i2s_event.type = I2S_EVENT_TX_DONE;
+            if (xQueueIsQueueFullFromISR(p_i2s->i2s_queue)) {
+                xQueueReceiveFromISR(p_i2s->i2s_queue, &dummy, &high_priority_task_awoken);
+            }
+            xQueueSendFromISR(p_i2s->i2s_queue, (void * )&i2s_event, &high_priority_task_awoken);
+        }
+    }
+
+    if (i2s_reg->int_st.in_suc_eof && p_i2s->rx) {
+        // All buffers are full. This means we have an overflow.
+        finish_desc = (lldesc_t*) i2s_reg->in_eof_des_addr;
+        if (xQueueIsQueueFullFromISR(p_i2s->rx->queue)) {
+            xQueueReceiveFromISR(p_i2s->rx->queue, &dummy, &high_priority_task_awoken);
+        }
+        xQueueSendFromISR(p_i2s->rx->queue, (void*)(&finish_desc->buf), &high_priority_task_awoken);
+        if (p_i2s->i2s_queue) {
+            i2s_event.type = I2S_EVENT_RX_DONE;
+            if (p_i2s->i2s_queue && xQueueIsQueueFullFromISR(p_i2s->i2s_queue)) {
+                xQueueReceiveFromISR(p_i2s->i2s_queue, &dummy, &high_priority_task_awoken);
+            }
+            xQueueSendFromISR(p_i2s->i2s_queue, (void * )&i2s_event, &high_priority_task_awoken);
+        }
+    }
+    if (high_priority_task_awoken == pdTRUE) {
+        portYIELD_FROM_ISR();
+    }
+
+    i2s_reg->int_clr.val = I2S[i2s_num]->int_st.val;
+}
+
+static esp_err_t i2s_destroy_dma_queue(i2s_port_t i2s_num, i2s_dma_t *dma)
+{
+    int bux_idx;
+    if (p_i2s_obj[i2s_num] == NULL) {
+        ESP_LOGE(I2S_TAG, "Not initialized yet");
+        return ESP_ERR_INVALID_ARG;
+    }
+    if (dma == NULL) {
+        ESP_LOGE(I2S_TAG, "dma is NULL");
+        return ESP_ERR_INVALID_ARG;
+    }
+    for (bux_idx = 0; bux_idx < p_i2s_obj[i2s_num]->dma_buf_count; bux_idx++) {
+        if (dma->desc && dma->desc[bux_idx]) {
+            free(dma->desc[bux_idx]);
+        }
+        if (dma->buf && dma->buf[bux_idx]) {
+            free(dma->buf[bux_idx]);
+        }
+    }
+    if (dma->buf) {
+        free(dma->buf);
+    }
+    if (dma->desc) {
+        free(dma->desc);
+    }
+    vQueueDelete(dma->queue);
+    vSemaphoreDelete(dma->mux);
+    free(dma);
+    return ESP_OK;
+}
+
+static i2s_dma_t *i2s_create_dma_queue(i2s_port_t i2s_num, int dma_buf_count, int dma_buf_len)
+{
+    int bux_idx;
+    int sample_size = p_i2s_obj[i2s_num]->bytes_per_sample * p_i2s_obj[i2s_num]->channel_num;
+    i2s_dma_t *dma = (i2s_dma_t*) malloc(sizeof(i2s_dma_t));
+    if (dma == NULL) {
+        ESP_LOGE(I2S_TAG, "Error malloc i2s_dma_t");
+        return NULL;
+    }
+    memset(dma, 0, sizeof(i2s_dma_t));
+
+    dma->buf = (char **)malloc(sizeof(char*) * dma_buf_count);
+    if (dma->buf == NULL) {
+        ESP_LOGE(I2S_TAG, "Error malloc dma buffer pointer");
+        free(dma);
+        return NULL;
+    }
+    memset(dma->buf, 0, sizeof(char*) * dma_buf_count);
+
+    for (bux_idx = 0; bux_idx < dma_buf_count; bux_idx++) {
+        dma->buf[bux_idx] = (char*) heap_caps_calloc(1, dma_buf_len * sample_size, MALLOC_CAP_DMA);
+        if (dma->buf[bux_idx] == NULL) {
+            ESP_LOGE(I2S_TAG, "Error malloc dma buffer");
+            i2s_destroy_dma_queue(i2s_num, dma);
+            return NULL;
+        }
+        ESP_LOGD(I2S_TAG, "Addr[%d] = %d", bux_idx, (int)dma->buf[bux_idx]);
+    }
+
+    dma->desc = (lldesc_t**) malloc(sizeof(lldesc_t*) * dma_buf_count);
+    if (dma->desc == NULL) {
+        ESP_LOGE(I2S_TAG, "Error malloc dma description");
+        i2s_destroy_dma_queue(i2s_num, dma);
+        return NULL;
+    }
+    for (bux_idx = 0; bux_idx < dma_buf_count; bux_idx++) {
+        dma->desc[bux_idx] = (lldesc_t*) heap_caps_malloc(sizeof(lldesc_t), MALLOC_CAP_DMA);
+        if (dma->desc[bux_idx] == NULL) {
+            ESP_LOGE(I2S_TAG, "Error malloc dma description entry");
+            i2s_destroy_dma_queue(i2s_num, dma);
+            return NULL;
+        }
+    }
+
+    for (bux_idx = 0; bux_idx < dma_buf_count; bux_idx++) {
+        dma->desc[bux_idx]->owner = 1;
+        dma->desc[bux_idx]->eof = 1;
+        dma->desc[bux_idx]->sosf = 0;
+        dma->desc[bux_idx]->length = dma_buf_len * sample_size;
+        dma->desc[bux_idx]->size = dma_buf_len * sample_size;
+        dma->desc[bux_idx]->buf = (uint8_t *) dma->buf[bux_idx];
+        dma->desc[bux_idx]->offset = 0;
+        dma->desc[bux_idx]->empty = (uint32_t)((bux_idx < (dma_buf_count - 1)) ? (dma->desc[bux_idx + 1]) : dma->desc[0]);
+    }
+    dma->queue = xQueueCreate(dma_buf_count - 1, sizeof(char*));
+    dma->mux = xSemaphoreCreateMutex();
+    dma->rw_pos = 0;
+    dma->buf_size = dma_buf_len * sample_size;
+    dma->curr_ptr = NULL;
+    ESP_LOGI(I2S_TAG, "DMA Malloc info, datalen=blocksize=%d, dma_buf_count=%d", dma_buf_len * sample_size, dma_buf_count);
+    return dma;
+}
+
+
+esp_err_t i2s_start(i2s_port_t i2s_num)
+{
+    I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
+    //start DMA link
+    I2S_ENTER_CRITICAL();
+    i2s_reset_fifo(i2s_num);
+    //reset dma
+    I2S[i2s_num]->lc_conf.in_rst = 1;
+    I2S[i2s_num]->lc_conf.in_rst = 0;
+    I2S[i2s_num]->lc_conf.out_rst = 1;
+    I2S[i2s_num]->lc_conf.out_rst = 0;
+
+    I2S[i2s_num]->conf.tx_reset = 1;
+    I2S[i2s_num]->conf.tx_reset = 0;
+    I2S[i2s_num]->conf.rx_reset = 1;
+    I2S[i2s_num]->conf.rx_reset = 0;
+
+    esp_intr_disable(p_i2s_obj[i2s_num]->i2s_isr_handle);
+    I2S[i2s_num]->int_clr.val = 0xFFFFFFFF;
+    if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) {
+        i2s_enable_tx_intr(i2s_num);
+        I2S[i2s_num]->out_link.start = 1;
+        I2S[i2s_num]->conf.tx_start = 1;
+    }
+    if (p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) {
+        i2s_enable_rx_intr(i2s_num);
+        I2S[i2s_num]->in_link.start = 1;
+        I2S[i2s_num]->conf.rx_start = 1;
+    }
+    esp_intr_enable(p_i2s_obj[i2s_num]->i2s_isr_handle);
+    I2S_EXIT_CRITICAL();
+    return ESP_OK;
+}
+
+esp_err_t i2s_stop(i2s_port_t i2s_num)
+{
+    I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
+    I2S_ENTER_CRITICAL();
+    esp_intr_disable(p_i2s_obj[i2s_num]->i2s_isr_handle);
+    if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) {
+        I2S[i2s_num]->out_link.stop = 1;
+        I2S[i2s_num]->conf.tx_start = 0;
+        i2s_disable_tx_intr(i2s_num);
+    }
+    if (p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) {
+        I2S[i2s_num]->in_link.stop = 1;
+        I2S[i2s_num]->conf.rx_start = 0;
+        i2s_disable_rx_intr(i2s_num);
+    }
+    I2S[i2s_num]->int_clr.val = I2S[i2s_num]->int_st.val; //clear pending interrupt
+    I2S_EXIT_CRITICAL();
+    return ESP_OK;
+}
+
+esp_err_t i2s_set_dac_mode(i2s_dac_mode_t dac_mode)
+{
+    I2S_CHECK((dac_mode < I2S_DAC_CHANNEL_MAX), "i2s dac mode error", ESP_ERR_INVALID_ARG);
+    if (dac_mode == I2S_DAC_CHANNEL_DISABLE) {
+        dac_output_disable(DAC_CHANNEL_1);
+        dac_output_disable(DAC_CHANNEL_2);
+        dac_i2s_disable();
+    } else {
+        dac_i2s_enable();
+    }
+
+    if (dac_mode & I2S_DAC_CHANNEL_RIGHT_EN) {
+        //DAC1, right channel, GPIO25
+        dac_output_enable(DAC_CHANNEL_1);
+    }
+    if (dac_mode & I2S_DAC_CHANNEL_LEFT_EN) {
+        //DAC2, left channel, GPIO26
+        dac_output_enable(DAC_CHANNEL_2);
+    }
+    return ESP_OK;
+}
+
+static esp_err_t _i2s_adc_mode_recover(void)
+{
+    I2S_CHECK(((_i2s_adc_unit != -1) && (_i2s_adc_channel != -1)), "i2s ADC recover error, not initialized...", ESP_ERR_INVALID_ARG);
+    return adc_i2s_mode_init(_i2s_adc_unit, _i2s_adc_channel);
+}
+
+esp_err_t i2s_set_adc_mode(adc_unit_t adc_unit, adc1_channel_t adc_channel)
+{
+    I2S_CHECK((adc_unit < ADC_UNIT_2), "i2s ADC unit error, only support ADC1 for now", ESP_ERR_INVALID_ARG);
+    // For now, we only support SAR ADC1.
+    _i2s_adc_unit = adc_unit;
+    _i2s_adc_channel = adc_channel;
+    return adc_i2s_mode_init(adc_unit, adc_channel);
+}
+
+esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin)
+{
+    I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
+    if (pin == NULL) {
+        return i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN);
+    }
+    if (pin->bck_io_num != -1 && !GPIO_IS_VALID_GPIO(pin->bck_io_num)) {
+        ESP_LOGE(I2S_TAG, "bck_io_num error");
+        return ESP_FAIL;
+    }
+    if (pin->ws_io_num != -1 && !GPIO_IS_VALID_GPIO(pin->ws_io_num)) {
+        ESP_LOGE(I2S_TAG, "ws_io_num error");
+        return ESP_FAIL;
+    }
+    if (pin->data_out_num != -1 && !GPIO_IS_VALID_OUTPUT_GPIO(pin->data_out_num)) {
+        ESP_LOGE(I2S_TAG, "data_out_num error");
+        return ESP_FAIL;
+    }
+    if (pin->data_in_num != -1 && !GPIO_IS_VALID_GPIO(pin->data_in_num)) {
+        ESP_LOGE(I2S_TAG, "data_in_num error");
+        return ESP_FAIL;
+    }
+
+    int bck_sig = -1, ws_sig = -1, data_out_sig = -1, data_in_sig = -1;
+    //Each IIS hw module has a RX and TX unit.
+    //For TX unit, the output signal index should be I2SnO_xxx_OUT_IDX
+    //For TX unit, the input signal index should be I2SnO_xxx_IN_IDX
+    if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) {
+        if (p_i2s_obj[i2s_num]->mode & I2S_MODE_MASTER) {
+            if (i2s_num == I2S_NUM_0) {
+                bck_sig = I2S0O_BCK_OUT_IDX;
+                ws_sig = I2S0O_WS_OUT_IDX;
+                data_out_sig = I2S0O_DATA_OUT23_IDX;
+            } else {
+                bck_sig = I2S1O_BCK_OUT_IDX;
+                ws_sig = I2S1O_WS_OUT_IDX;
+                data_out_sig = I2S1O_DATA_OUT23_IDX;
+            }
+        } else if (p_i2s_obj[i2s_num]->mode & I2S_MODE_SLAVE) {
+            if (i2s_num == I2S_NUM_0) {
+                bck_sig = I2S0O_BCK_IN_IDX;
+                ws_sig = I2S0O_WS_IN_IDX;
+                data_out_sig = I2S0O_DATA_OUT23_IDX;
+            } else {
+                bck_sig = I2S1O_BCK_IN_IDX;
+                ws_sig = I2S1O_WS_IN_IDX;
+                data_out_sig = I2S1O_DATA_OUT23_IDX;
+            }
+        }
+    }
+    //For RX unit, the output signal index should be I2SnI_xxx_OUT_IDX
+    //For RX unit, the input signal index shuld be I2SnI_xxx_IN_IDX
+    if (p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) {
+        if (p_i2s_obj[i2s_num]->mode & I2S_MODE_MASTER) {
+            if (i2s_num == I2S_NUM_0) {
+                bck_sig = I2S0I_BCK_OUT_IDX;
+                ws_sig = I2S0I_WS_OUT_IDX;
+                data_in_sig = I2S0I_DATA_IN15_IDX;
+            } else {
+                bck_sig = I2S1I_BCK_OUT_IDX;
+                ws_sig = I2S1I_WS_OUT_IDX;
+                data_in_sig = I2S1I_DATA_IN15_IDX;
+            }
+        } else if (p_i2s_obj[i2s_num]->mode & I2S_MODE_SLAVE) {
+            if (i2s_num == I2S_NUM_0) {
+                bck_sig = I2S0I_BCK_IN_IDX;
+                ws_sig = I2S0I_WS_IN_IDX;
+                data_in_sig = I2S0I_DATA_IN15_IDX;
+            } else {
+                bck_sig = I2S1I_BCK_IN_IDX;
+                ws_sig = I2S1I_WS_IN_IDX;
+                data_in_sig = I2S1I_DATA_IN15_IDX;
+            }
+        }
+    }
+    //For "full-duplex + slave" mode, we should select RX signal index for ws and bck.
+    //For "full-duplex + master" mode, we should select TX signal index for ws and bck.
+    if ((p_i2s_obj[i2s_num]->mode & I2S_FULL_DUPLEX_SLAVE_MODE_MASK) == I2S_FULL_DUPLEX_SLAVE_MODE_MASK) {
+        if (i2s_num == I2S_NUM_0) {
+            bck_sig = I2S0I_BCK_IN_IDX;
+            ws_sig = I2S0I_WS_IN_IDX;
+        } else {
+            bck_sig = I2S1I_BCK_IN_IDX;
+            ws_sig = I2S1I_WS_IN_IDX;
+        }
+    } else if ((p_i2s_obj[i2s_num]->mode & I2S_FULL_DUPLEX_MASTER_MODE_MASK) == I2S_FULL_DUPLEX_MASTER_MODE_MASK) {
+        if (i2s_num == I2S_NUM_0) {
+            bck_sig = I2S0O_BCK_OUT_IDX;
+            ws_sig = I2S0O_WS_OUT_IDX;
+        } else {
+            bck_sig = I2S1O_BCK_OUT_IDX;
+            ws_sig = I2S1O_WS_OUT_IDX;
+        }
+    }
+
+    gpio_matrix_out_check(pin->data_out_num, data_out_sig, 0, 0);
+    gpio_matrix_in_check(pin->data_in_num, data_in_sig, 0);
+    if (p_i2s_obj[i2s_num]->mode & I2S_MODE_MASTER) {
+        gpio_matrix_out_check(pin->ws_io_num, ws_sig, 0, 0);
+        gpio_matrix_out_check(pin->bck_io_num, bck_sig, 0, 0);
+    } else if (p_i2s_obj[i2s_num]->mode & I2S_MODE_SLAVE) {
+        gpio_matrix_in_check(pin->ws_io_num, ws_sig, 0);
+        gpio_matrix_in_check(pin->bck_io_num, bck_sig, 0);
+    }
+    ESP_LOGD(I2S_TAG, "data: out %d, in: %d, ws: %d, bck: %d", data_out_sig, data_in_sig, ws_sig, bck_sig);
+
+    return ESP_OK;
+}
+
+esp_err_t i2s_set_sample_rates(i2s_port_t i2s_num, uint32_t rate)
+{
+    I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
+    I2S_CHECK((p_i2s_obj[i2s_num]->bytes_per_sample > 0), "bits_per_sample not set", ESP_ERR_INVALID_ARG);
+    return i2s_set_clk(i2s_num, rate, p_i2s_obj[i2s_num]->bits_per_sample, p_i2s_obj[i2s_num]->channel_num);
+}
+
+esp_err_t i2s_set_pdm_rx_down_sample(i2s_port_t i2s_num, i2s_pdm_dsr_t dsr)
+{
+    I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
+    I2S[i2s_num]->pdm_conf.rx_sinc_dsr_16_en = dsr;
+    return i2s_set_clk(i2s_num, p_i2s_obj[i2s_num]->sample_rate, p_i2s_obj[i2s_num]->bits_per_sample, p_i2s_obj[i2s_num]->channel_num);
+}
+
+static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_config)
+{
+    I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
+    I2S_CHECK((i2s_config), "param null", ESP_ERR_INVALID_ARG);
+    I2S_CHECK(!((i2s_config->mode & I2S_MODE_ADC_BUILT_IN) && (i2s_num != I2S_NUM_0)), "I2S ADC built-in only support on I2S0", ESP_ERR_INVALID_ARG);
+    I2S_CHECK(!((i2s_config->mode & I2S_MODE_DAC_BUILT_IN) && (i2s_num != I2S_NUM_0)), "I2S DAC built-in only support on I2S0", ESP_ERR_INVALID_ARG);
+    I2S_CHECK(!((i2s_config->mode & I2S_MODE_PDM) && (i2s_num != I2S_NUM_0)), "I2S DAC PDM only support on I2S0", ESP_ERR_INVALID_ARG);
+
+    if (i2s_num == I2S_NUM_1) {
+        periph_module_enable(PERIPH_I2S1_MODULE);
+    } else {
+        periph_module_enable(PERIPH_I2S0_MODULE);
+    }
+
+    if(i2s_config->mode & I2S_MODE_ADC_BUILT_IN) {
+        //in ADC built-in mode, we need to call i2s_set_adc_mode to
+        //initialize the specific ADC channel.
+        //in the current stage, we only support ADC1 and single channel mode.
+        //In default data mode, the ADC data is in 12-bit resolution mode.
+        adc_power_always_on();
+    }
+    // configure I2S data port interface.
+    i2s_reset_fifo(i2s_num);
+    //reset i2s
+    I2S[i2s_num]->conf.tx_reset = 1;
+    I2S[i2s_num]->conf.tx_reset = 0;
+    I2S[i2s_num]->conf.rx_reset = 1;
+    I2S[i2s_num]->conf.rx_reset = 0;
+
+    //reset dma
+    I2S[i2s_num]->lc_conf.in_rst = 1;
+    I2S[i2s_num]->lc_conf.in_rst = 0;
+    I2S[i2s_num]->lc_conf.out_rst = 1;
+    I2S[i2s_num]->lc_conf.out_rst = 0;
+
+    //Enable and configure DMA
+    I2S[i2s_num]->lc_conf.check_owner = 0;
+    I2S[i2s_num]->lc_conf.out_loop_test = 0;
+    I2S[i2s_num]->lc_conf.out_auto_wrback = 0;
+    I2S[i2s_num]->lc_conf.out_data_burst_en = 0;
+    I2S[i2s_num]->lc_conf.outdscr_burst_en = 0;
+    I2S[i2s_num]->lc_conf.out_no_restart_clr = 0;
+    I2S[i2s_num]->lc_conf.indscr_burst_en = 0;
+    I2S[i2s_num]->lc_conf.out_eof_mode = 1;
+
+    I2S[i2s_num]->conf2.lcd_en = 0;
+    I2S[i2s_num]->conf2.camera_en = 0;
+    I2S[i2s_num]->pdm_conf.pcm2pdm_conv_en = 0;
+    I2S[i2s_num]->pdm_conf.pdm2pcm_conv_en = 0;
+
+    I2S[i2s_num]->fifo_conf.dscr_en = 0;
+
+    I2S[i2s_num]->conf_chan.tx_chan_mod = i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? i2s_config->channel_format : (i2s_config->channel_format >> 1); // 0-two channel;1-right;2-left;3-righ;4-left
+    I2S[i2s_num]->fifo_conf.tx_fifo_mod = i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? 0 : 1; // 0-right&left channel;1-one channel
+    I2S[i2s_num]->conf.tx_mono = 0;
+
+    I2S[i2s_num]->conf_chan.rx_chan_mod = i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? i2s_config->channel_format : (i2s_config->channel_format >> 1); // 0-two channel;1-right;2-left;3-righ;4-left
+    I2S[i2s_num]->fifo_conf.rx_fifo_mod = i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? 0 : 1; // 0-right&left channel;1-one channel
+    I2S[i2s_num]->conf.rx_mono = 0;
+
+    I2S[i2s_num]->fifo_conf.dscr_en = 1;//connect dma to fifo
+
+    I2S[i2s_num]->conf.tx_start = 0;
+    I2S[i2s_num]->conf.rx_start = 0;
+
+    if (i2s_config->mode & I2S_MODE_TX) {
+        I2S[i2s_num]->conf.tx_msb_right = 1;
+        I2S[i2s_num]->conf.tx_right_first = 0;
+
+        I2S[i2s_num]->conf.tx_slave_mod = 0; // Master
+        I2S[i2s_num]->fifo_conf.tx_fifo_mod_force_en = 1;
+
+        if (i2s_config->mode & I2S_MODE_SLAVE) {
+            I2S[i2s_num]->conf.tx_slave_mod = 1;//TX Slave
+        }
+    }
+
+    if (i2s_config->mode & I2S_MODE_RX) {
+        I2S[i2s_num]->conf.rx_msb_right = 1;
+        I2S[i2s_num]->conf.rx_right_first = 0;
+        I2S[i2s_num]->conf.rx_slave_mod = 0; // Master
+        I2S[i2s_num]->fifo_conf.rx_fifo_mod_force_en = 1;
+
+        if (i2s_config->mode & I2S_MODE_SLAVE) {
+            I2S[i2s_num]->conf.rx_slave_mod = 1;//RX Slave
+        }
+    }
+
+    if (i2s_config->mode & (I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN)) {
+        I2S[i2s_num]->conf2.lcd_en = 1;
+        I2S[i2s_num]->conf.tx_right_first = 1;
+        I2S[i2s_num]->conf2.camera_en = 0;
+    }
+
+    if (i2s_config->mode & I2S_MODE_PDM) {
+        I2S[i2s_num]->fifo_conf.rx_fifo_mod_force_en = 1;
+        I2S[i2s_num]->fifo_conf.tx_fifo_mod_force_en = 1;
+
+        I2S[i2s_num]->pdm_freq_conf.tx_pdm_fp = 960;
+        I2S[i2s_num]->pdm_freq_conf.tx_pdm_fs = i2s_config->sample_rate / 1000 * 10;
+        I2S[i2s_num]->pdm_conf.tx_sinc_osr2 = I2S[i2s_num]->pdm_freq_conf.tx_pdm_fp / I2S[i2s_num]->pdm_freq_conf.tx_pdm_fs;
+
+        I2S[i2s_num]->pdm_conf.rx_sinc_dsr_16_en = 0;
+        I2S[i2s_num]->pdm_conf.rx_pdm_en = 1;
+        I2S[i2s_num]->pdm_conf.tx_pdm_en = 1;
+
+        I2S[i2s_num]->pdm_conf.pcm2pdm_conv_en = 1;
+        I2S[i2s_num]->pdm_conf.pdm2pcm_conv_en = 1;
+    } else {
+        I2S[i2s_num]->pdm_conf.rx_pdm_en = 0;
+        I2S[i2s_num]->pdm_conf.tx_pdm_en = 0;
+    }
+    if (i2s_config->communication_format & I2S_COMM_FORMAT_I2S) {
+        I2S[i2s_num]->conf.tx_short_sync = 0;
+        I2S[i2s_num]->conf.rx_short_sync = 0;
+        I2S[i2s_num]->conf.tx_msb_shift = 1;
+        I2S[i2s_num]->conf.rx_msb_shift = 1;
+        if (i2s_config->communication_format & I2S_COMM_FORMAT_I2S_LSB) {
+            if (i2s_config->mode & I2S_MODE_TX) {
+                I2S[i2s_num]->conf.tx_msb_shift = 0;
+            }
+            if (i2s_config->mode & I2S_MODE_RX) {
+                I2S[i2s_num]->conf.rx_msb_shift = 0;
+            }
+        }
+    }
+
+    if (i2s_config->communication_format & I2S_COMM_FORMAT_PCM) {
+        I2S[i2s_num]->conf.tx_msb_shift = 0;
+        I2S[i2s_num]->conf.rx_msb_shift = 0;
+        I2S[i2s_num]->conf.tx_short_sync = 0;
+        I2S[i2s_num]->conf.rx_short_sync = 0;
+        if (i2s_config->communication_format & I2S_COMM_FORMAT_PCM_SHORT) {
+            if (i2s_config->mode & I2S_MODE_TX) {
+                I2S[i2s_num]->conf.tx_short_sync = 1;
+            }
+            if (i2s_config->mode & I2S_MODE_RX) {
+                I2S[i2s_num]->conf.rx_short_sync = 1;
+            }
+        }
+    }
+    if ((p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) &&  (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX)) {
+        I2S[i2s_num]->conf.sig_loopback = 1;
+        if (p_i2s_obj[i2s_num]->mode & I2S_MODE_MASTER) {
+            I2S[i2s_num]->conf.tx_slave_mod = 0;    //MASTER Slave
+            I2S[i2s_num]->conf.rx_slave_mod = 1;    //RX Slave
+        } else {
+            I2S[i2s_num]->conf.tx_slave_mod = 1;    //RX Slave
+            I2S[i2s_num]->conf.rx_slave_mod = 1;    //RX Slave
+        }
+    }
+
+    p_i2s_obj[i2s_num]->use_apll = i2s_config->use_apll;
+    p_i2s_obj[i2s_num]->tx_desc_auto_clear = i2s_config->tx_desc_auto_clear;
+    p_i2s_obj[i2s_num]->fixed_mclk = i2s_config->fixed_mclk;
+    return ESP_OK;
+}
+
+esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num)
+{
+    I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
+    if (p_i2s_obj[i2s_num]->rx && p_i2s_obj[i2s_num]->rx->buf != NULL && p_i2s_obj[i2s_num]->rx->buf_size != 0) {
+        for (int i = 0; i < p_i2s_obj[i2s_num]->dma_buf_count; i++) {
+            memset(p_i2s_obj[i2s_num]->rx->buf[i], 0, p_i2s_obj[i2s_num]->rx->buf_size);
+        }
+    }
+    if (p_i2s_obj[i2s_num]->tx && p_i2s_obj[i2s_num]->tx->buf != NULL && p_i2s_obj[i2s_num]->tx->buf_size != 0) {
+        int bytes_left = 0;
+        bytes_left = (p_i2s_obj[i2s_num]->tx->buf_size - p_i2s_obj[i2s_num]->tx->rw_pos) % 4;
+        if (bytes_left) {
+            size_t zero_bytes = 0, bytes_written;
+            i2s_write(i2s_num, (void *)&zero_bytes, bytes_left, &bytes_written, portMAX_DELAY);
+        }
+        for (int i = 0; i < p_i2s_obj[i2s_num]->dma_buf_count; i++) {
+            memset(p_i2s_obj[i2s_num]->tx->buf[i], 0, p_i2s_obj[i2s_num]->tx->buf_size);
+        }
+    }
+    return ESP_OK;
+}
+
+esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, int queue_size, void* i2s_queue)
+{
+    esp_err_t err;
+    I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
+    I2S_CHECK((i2s_config != NULL), "I2S configuration must not NULL", ESP_ERR_INVALID_ARG);
+    I2S_CHECK((i2s_config->dma_buf_count >= 2 && i2s_config->dma_buf_count <= 128), "I2S buffer count less than 128 and more than 2", ESP_ERR_INVALID_ARG);
+    I2S_CHECK((i2s_config->dma_buf_len >= 8 && i2s_config->dma_buf_len <= 1024), "I2S buffer length at most 1024 and more than 8", ESP_ERR_INVALID_ARG);
+    if (p_i2s_obj[i2s_num] == NULL) {
+        p_i2s_obj[i2s_num] = (i2s_obj_t*) malloc(sizeof(i2s_obj_t));
+        if (p_i2s_obj[i2s_num] == NULL) {
+            ESP_LOGE(I2S_TAG, "Malloc I2S driver error");
+            return ESP_ERR_NO_MEM;
+        }
+        memset(p_i2s_obj[i2s_num], 0, sizeof(i2s_obj_t));
+
+        p_i2s_obj[i2s_num]->i2s_num = i2s_num;
+        p_i2s_obj[i2s_num]->dma_buf_count = i2s_config->dma_buf_count;
+        p_i2s_obj[i2s_num]->dma_buf_len = i2s_config->dma_buf_len;
+        p_i2s_obj[i2s_num]->i2s_queue = i2s_queue;
+        p_i2s_obj[i2s_num]->mode = i2s_config->mode;
+
+        p_i2s_obj[i2s_num]->bits_per_sample = 0;
+        p_i2s_obj[i2s_num]->bytes_per_sample = 0; // Not initialized yet
+        p_i2s_obj[i2s_num]->channel_num = i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? 2 : 1;
+
+#ifdef CONFIG_PM_ENABLE
+    if (i2s_config->use_apll) {
+        err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "i2s_driver", &p_i2s_obj[i2s_num]->pm_lock);
+    } else {
+        err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "i2s_driver", &p_i2s_obj[i2s_num]->pm_lock);
+    }
+    if (err != ESP_OK) {
+        free(p_i2s_obj[i2s_num]);
+        p_i2s_obj[i2s_num] = NULL;
+        ESP_LOGE(I2S_TAG, "I2S pm lock error");
+        return err;
+    }
+#endif //CONFIG_PM_ENABLE
+
+        //To make sure hardware is enabled before any hardware register operations.
+        if (i2s_num == I2S_NUM_1) {
+            periph_module_enable(PERIPH_I2S1_MODULE);
+        } else {
+            periph_module_enable(PERIPH_I2S0_MODULE);
+        }
+
+        //initial interrupt
+        err = i2s_isr_register(i2s_num, i2s_config->intr_alloc_flags, i2s_intr_handler_default, p_i2s_obj[i2s_num], &p_i2s_obj[i2s_num]->i2s_isr_handle);
+        if (err != ESP_OK) {
+#ifdef CONFIG_PM_ENABLE
+            if (p_i2s_obj[i2s_num]->pm_lock) {
+                esp_pm_lock_delete(p_i2s_obj[i2s_num]->pm_lock);
+            }
+#endif
+            free(p_i2s_obj[i2s_num]);
+            p_i2s_obj[i2s_num] = NULL;
+            ESP_LOGE(I2S_TAG, "Register I2S Interrupt error");
+            return err;
+        }
+        i2s_stop(i2s_num);
+        err = i2s_param_config(i2s_num, i2s_config);
+        if (err != ESP_OK) {
+            i2s_driver_uninstall(i2s_num);
+            ESP_LOGE(I2S_TAG, "I2S param configure error");
+            return err;
+        }
+
+        if (i2s_queue) {
+            p_i2s_obj[i2s_num]->i2s_queue = xQueueCreate(queue_size, sizeof(i2s_event_t));
+            *((QueueHandle_t*) i2s_queue) = p_i2s_obj[i2s_num]->i2s_queue;
+            ESP_LOGI(I2S_TAG, "queue free spaces: %d", uxQueueSpacesAvailable(p_i2s_obj[i2s_num]->i2s_queue));
+        } else {
+            p_i2s_obj[i2s_num]->i2s_queue = NULL;
+        }
+        //set clock and start
+        return i2s_set_clk(i2s_num, i2s_config->sample_rate, i2s_config->bits_per_sample, p_i2s_obj[i2s_num]->channel_num);
+    }
+
+    ESP_LOGW(I2S_TAG, "I2S driver already installed");
+    return ESP_OK;
+}
+
+esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num)
+{
+    I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
+    if (p_i2s_obj[i2s_num] == NULL) {
+        ESP_LOGI(I2S_TAG, "already uninstalled");
+        return ESP_OK;
+    }
+    i2s_stop(i2s_num);
+    esp_intr_free(p_i2s_obj[i2s_num]->i2s_isr_handle);
+
+    if (p_i2s_obj[i2s_num]->tx != NULL && p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) {
+        i2s_destroy_dma_queue(i2s_num, p_i2s_obj[i2s_num]->tx);
+        p_i2s_obj[i2s_num]->tx = NULL;
+    }
+    if (p_i2s_obj[i2s_num]->rx != NULL && p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) {
+        i2s_destroy_dma_queue(i2s_num, p_i2s_obj[i2s_num]->rx);
+        p_i2s_obj[i2s_num]->rx = NULL;
+    }
+
+    if (p_i2s_obj[i2s_num]->i2s_queue) {
+        vQueueDelete(p_i2s_obj[i2s_num]->i2s_queue);
+        p_i2s_obj[i2s_num]->i2s_queue = NULL;
+    }
+
+    if(p_i2s_obj[i2s_num]->use_apll) {
+        rtc_clk_apll_enable(0, 0, 0, 0, 0);
+    }
+#ifdef CONFIG_PM_ENABLE
+    if (p_i2s_obj[i2s_num]->pm_lock) {
+        esp_pm_lock_delete(p_i2s_obj[i2s_num]->pm_lock);
+    }
+#endif
+
+    free(p_i2s_obj[i2s_num]);
+    p_i2s_obj[i2s_num] = NULL;
+
+    if (i2s_num == I2S_NUM_0) {
+        periph_module_disable(PERIPH_I2S0_MODULE);
+    } else if (i2s_num == I2S_NUM_1) {
+        periph_module_disable(PERIPH_I2S1_MODULE);
+    }
+    return ESP_OK;
+}
+
+int i2s_write_bytes(i2s_port_t i2s_num, const void *src, size_t size, TickType_t ticks_to_wait)
+{
+    size_t bytes_written = 0;
+    int res = 0;
+    res = i2s_write(i2s_num, src, size, &bytes_written, ticks_to_wait);
+    if (res != ESP_OK) {
+        return ESP_FAIL;
+    } else {
+        return bytes_written;
+    }
+}
+
+esp_err_t i2s_write(i2s_port_t i2s_num, const void *src, size_t size, size_t *bytes_written, TickType_t ticks_to_wait)
+{
+    char *data_ptr, *src_byte;
+    int bytes_can_write;
+    *bytes_written = 0;
+    I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
+    I2S_CHECK((size < I2S_MAX_BUFFER_SIZE), "size is too large", ESP_ERR_INVALID_ARG);
+    I2S_CHECK((p_i2s_obj[i2s_num]->tx), "tx NULL", ESP_ERR_INVALID_ARG);
+    xSemaphoreTake(p_i2s_obj[i2s_num]->tx->mux, (portTickType)portMAX_DELAY);
+#ifdef CONFIG_PM_ENABLE
+    esp_pm_lock_acquire(p_i2s_obj[i2s_num]->pm_lock);
+#endif
+    src_byte = (char *)src;
+    while (size > 0) {
+        if (p_i2s_obj[i2s_num]->tx->rw_pos == p_i2s_obj[i2s_num]->tx->buf_size || p_i2s_obj[i2s_num]->tx->curr_ptr == NULL) {
+            if (xQueueReceive(p_i2s_obj[i2s_num]->tx->queue, &p_i2s_obj[i2s_num]->tx->curr_ptr, ticks_to_wait) == pdFALSE) {
+                break;
+            }
+            p_i2s_obj[i2s_num]->tx->rw_pos = 0;
+        }
+        ESP_LOGD(I2S_TAG, "size: %d, rw_pos: %d, buf_size: %d, curr_ptr: %d", size, p_i2s_obj[i2s_num]->tx->rw_pos, p_i2s_obj[i2s_num]->tx->buf_size, (int)p_i2s_obj[i2s_num]->tx->curr_ptr);
+        data_ptr = (char*)p_i2s_obj[i2s_num]->tx->curr_ptr;
+        data_ptr += p_i2s_obj[i2s_num]->tx->rw_pos;
+        bytes_can_write = p_i2s_obj[i2s_num]->tx->buf_size - p_i2s_obj[i2s_num]->tx->rw_pos;
+        if (bytes_can_write > size) {
+            bytes_can_write = size;
+        }
+        memcpy(data_ptr, src_byte, bytes_can_write);
+        size -= bytes_can_write;
+        src_byte += bytes_can_write;
+        p_i2s_obj[i2s_num]->tx->rw_pos += bytes_can_write;
+        (*bytes_written) += bytes_can_write;
+    }
+#ifdef CONFIG_PM_ENABLE
+    esp_pm_lock_release(p_i2s_obj[i2s_num]->pm_lock);
+#endif
+
+    xSemaphoreGive(p_i2s_obj[i2s_num]->tx->mux);
+    return ESP_OK;
+}
+
+esp_err_t i2s_adc_enable(i2s_port_t i2s_num)
+{
+    I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
+    I2S_CHECK((p_i2s_obj[i2s_num] != NULL), "Not initialized yet", ESP_ERR_INVALID_STATE);
+    I2S_CHECK((p_i2s_obj[i2s_num]->mode & I2S_MODE_ADC_BUILT_IN), "i2s built-in adc not enabled", ESP_ERR_INVALID_STATE);
+
+    adc1_i2s_mode_acquire();
+    _i2s_adc_mode_recover();
+    return i2s_set_clk(i2s_num, p_i2s_obj[i2s_num]->sample_rate, p_i2s_obj[i2s_num]->bits_per_sample, p_i2s_obj[i2s_num]->channel_num);
+}
+
+esp_err_t i2s_adc_disable(i2s_port_t i2s_num)
+{
+    I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
+    I2S_CHECK((p_i2s_obj[i2s_num] != NULL), "Not initialized yet", ESP_ERR_INVALID_STATE);
+    I2S_CHECK((p_i2s_obj[i2s_num]->mode & I2S_MODE_ADC_BUILT_IN), "i2s built-in adc not enabled", ESP_ERR_INVALID_STATE);
+
+    adc1_lock_release();
+    return ESP_OK;
+}
+
+esp_err_t i2s_write_expand(i2s_port_t i2s_num, const void *src, size_t size, size_t src_bits, size_t aim_bits, size_t *bytes_written, TickType_t ticks_to_wait)
+{
+    char *data_ptr;
+    int bytes_can_write, tail;
+    int src_bytes, aim_bytes, zero_bytes;
+    *bytes_written = 0;
+    I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
+    I2S_CHECK((size > 0), "size must greater than zero", ESP_ERR_INVALID_ARG);
+    I2S_CHECK((aim_bits * size < I2S_MAX_BUFFER_SIZE), "size is too large", ESP_ERR_INVALID_ARG);
+    I2S_CHECK((aim_bits >= src_bits), "aim_bits musn't less than src_bits", ESP_ERR_INVALID_ARG);
+    I2S_CHECK((p_i2s_obj[i2s_num]->tx), "tx NULL", ESP_ERR_INVALID_ARG);
+    if (src_bits < I2S_BITS_PER_SAMPLE_8BIT || aim_bits < I2S_BITS_PER_SAMPLE_8BIT) {
+        ESP_LOGE(I2S_TAG,"bits musn't be less than 8, src_bits %d aim_bits %d", src_bits, aim_bits);
+        return ESP_ERR_INVALID_ARG;
+    }
+    if (src_bits > I2S_BITS_PER_SAMPLE_32BIT || aim_bits > I2S_BITS_PER_SAMPLE_32BIT) {
+        ESP_LOGE(I2S_TAG,"bits musn't be greater than 32, src_bits %d aim_bits %d", src_bits, aim_bits);
+        return ESP_ERR_INVALID_ARG;
+    }
+    if ((src_bits == I2S_BITS_PER_SAMPLE_16BIT || src_bits == I2S_BITS_PER_SAMPLE_32BIT) && (size % 2 != 0)) {
+        ESP_LOGE(I2S_TAG,"size must be a even number while src_bits is even, src_bits %d size %d", src_bits, size);
+        return ESP_ERR_INVALID_ARG;
+    }
+    if (src_bits == I2S_BITS_PER_SAMPLE_24BIT && (size % 3 != 0)) {
+        ESP_LOGE(I2S_TAG,"size must be a multiple of 3 while src_bits is 24, size %d", size);
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    src_bytes = src_bits / 8;
+    aim_bytes = aim_bits / 8;
+    zero_bytes = aim_bytes - src_bytes;
+    xSemaphoreTake(p_i2s_obj[i2s_num]->tx->mux, (portTickType)portMAX_DELAY);
+    size = size * aim_bytes / src_bytes;
+    ESP_LOGD(I2S_TAG,"aim_bytes %d src_bytes %d size %d", aim_bytes, src_bytes, size);
+    while (size > 0) {
+        if (p_i2s_obj[i2s_num]->tx->rw_pos == p_i2s_obj[i2s_num]->tx->buf_size || p_i2s_obj[i2s_num]->tx->curr_ptr == NULL) {
+            if (xQueueReceive(p_i2s_obj[i2s_num]->tx->queue, &p_i2s_obj[i2s_num]->tx->curr_ptr, ticks_to_wait) == pdFALSE) {
+                break;
+            }
+            p_i2s_obj[i2s_num]->tx->rw_pos = 0;
+        }
+        data_ptr = (char*)p_i2s_obj[i2s_num]->tx->curr_ptr;
+        data_ptr += p_i2s_obj[i2s_num]->tx->rw_pos;
+        bytes_can_write = p_i2s_obj[i2s_num]->tx->buf_size - p_i2s_obj[i2s_num]->tx->rw_pos;
+        if (bytes_can_write > size) {
+            bytes_can_write = size;
+        }
+        tail = bytes_can_write % aim_bytes;
+        bytes_can_write = bytes_can_write - tail;
+
+        memset(data_ptr, 0, bytes_can_write);
+        for (int j = 0; j < bytes_can_write; j += (aim_bytes - zero_bytes)) {
+            j += zero_bytes;
+            memcpy(&data_ptr[j], (const char *)(src + *bytes_written), aim_bytes - zero_bytes);
+            (*bytes_written) += (aim_bytes - zero_bytes);
+        }
+        size -= bytes_can_write;
+        p_i2s_obj[i2s_num]->tx->rw_pos += bytes_can_write;
+    }
+    xSemaphoreGive(p_i2s_obj[i2s_num]->tx->mux);
+    return ESP_OK;
+}
+
+int i2s_read_bytes(i2s_port_t i2s_num, void *dest, size_t size, TickType_t ticks_to_wait)
+{
+    size_t bytes_read = 0;
+    int res = 0;
+    res = i2s_read(i2s_num, dest, size, &bytes_read, ticks_to_wait);
+    if (res != ESP_OK) {
+        return ESP_FAIL;
+    } else {
+        return bytes_read;
+    }
+}
+
+esp_err_t i2s_read(i2s_port_t i2s_num, void *dest, size_t size, size_t *bytes_read, TickType_t ticks_to_wait)
+{
+    char *data_ptr, *dest_byte;
+    int bytes_can_read;
+    *bytes_read = 0;
+    dest_byte = (char *)dest;
+    I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
+    I2S_CHECK((size < I2S_MAX_BUFFER_SIZE), "size is too large", ESP_ERR_INVALID_ARG);
+    I2S_CHECK((p_i2s_obj[i2s_num]->rx), "rx NULL", ESP_ERR_INVALID_ARG);
+    xSemaphoreTake(p_i2s_obj[i2s_num]->rx->mux, (portTickType)portMAX_DELAY);
+#ifdef CONFIG_PM_ENABLE
+    esp_pm_lock_acquire(p_i2s_obj[i2s_num]->pm_lock);
+#endif
+    while (size > 0) {
+        if (p_i2s_obj[i2s_num]->rx->rw_pos == p_i2s_obj[i2s_num]->rx->buf_size || p_i2s_obj[i2s_num]->rx->curr_ptr == NULL) {
+            if (xQueueReceive(p_i2s_obj[i2s_num]->rx->queue, &p_i2s_obj[i2s_num]->rx->curr_ptr, ticks_to_wait) == pdFALSE) {
+                break;
+            }
+            p_i2s_obj[i2s_num]->rx->rw_pos = 0;
+        }
+        data_ptr = (char*)p_i2s_obj[i2s_num]->rx->curr_ptr;
+        data_ptr += p_i2s_obj[i2s_num]->rx->rw_pos;
+        bytes_can_read = p_i2s_obj[i2s_num]->rx->buf_size - p_i2s_obj[i2s_num]->rx->rw_pos;
+        if (bytes_can_read > size) {
+            bytes_can_read = size;
+        }
+        memcpy(dest_byte, data_ptr, bytes_can_read);
+        size -= bytes_can_read;
+        dest_byte += bytes_can_read;
+        p_i2s_obj[i2s_num]->rx->rw_pos += bytes_can_read;
+        (*bytes_read) += bytes_can_read;
+    }
+#ifdef CONFIG_PM_ENABLE
+    esp_pm_lock_release(p_i2s_obj[i2s_num]->pm_lock);
+#endif
+    xSemaphoreGive(p_i2s_obj[i2s_num]->rx->mux);
+    return ESP_OK;
+}
+
+int i2s_push_sample(i2s_port_t i2s_num, const void *sample, TickType_t ticks_to_wait)
+{
+    size_t bytes_push = 0;
+    int res = 0;
+    I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_FAIL);
+    res = i2s_write(i2s_num, sample, p_i2s_obj[i2s_num]->bytes_per_sample, &bytes_push, ticks_to_wait);
+    if (res != ESP_OK) {
+        return ESP_FAIL;
+    } else {
+        return bytes_push;
+    }
+}
+
+int i2s_pop_sample(i2s_port_t i2s_num, void *sample, TickType_t ticks_to_wait)
+{
+    size_t bytes_pop = 0;
+    int res = 0;
+    I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_FAIL);
+    res = i2s_read(i2s_num, sample, p_i2s_obj[i2s_num]->bytes_per_sample, &bytes_pop, ticks_to_wait);
+    if (res != ESP_OK) {
+        return ESP_FAIL;
+    } else {
+        return bytes_pop;
+    }
+}