From faf898b6591e468d3faa30e5c608e8c202118444 Mon Sep 17 00:00:00 2001 From: xiongyu Date: Mon, 9 Dec 2019 15:20:41 +0800 Subject: [PATCH 1/3] bugfix(i2s): fix driver ut i2s * Add test support for ESP32S2 * Add loop back test * Support chip internal connection, no external wiring required. * Delete the relevant codes of PDM of ESP32-S2 ll layer. * fix dac dma mode issue --- components/driver/i2s.c | 17 ++- components/driver/include/driver/i2s.h | 2 +- components/driver/test/test_i2s.c | 143 +++++++++++++++++- components/soc/include/hal/i2s_hal.h | 4 + components/soc/include/hal/i2s_types.h | 15 +- .../soc/soc/esp32/include/soc/i2s_caps.h | 7 +- .../soc/soc/esp32s2/include/soc/i2s_caps.h | 10 +- .../soc/src/esp32s2/include/hal/i2s_ll.h | 121 --------------- components/soc/src/hal/i2s_hal.c | 13 +- .../coex/a2dp_gatts_coex/main/main.c | 3 +- .../peripherals/i2s_adc_dac/CMakeLists.txt | 2 +- .../peripherals/i2s_adc_dac/main/app_main.c | 12 +- tools/ci/config/target-test.yml | 6 + 13 files changed, 195 insertions(+), 160 deletions(-) diff --git a/components/driver/i2s.c b/components/driver/i2s.c index cf80ff80a8..c7dd573a72 100644 --- a/components/driver/i2s.c +++ b/components/driver/i2s.c @@ -110,7 +110,7 @@ static esp_err_t i2s_reset_fifo(i2s_port_t i2s_num) return ESP_OK; } -inline static void gpio_matrix_out_check(uint32_t gpio, uint32_t signal_idx, bool out_inv, bool oen_inv) +static inline 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) { @@ -120,7 +120,7 @@ inline static void gpio_matrix_out_check(uint32_t gpio, uint32_t signal_idx, boo } } -inline static void gpio_matrix_in_check(uint32_t gpio, uint32_t signal_idx, bool inv) +static inline 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); @@ -403,14 +403,14 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b //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; + fi2s_clk /= 2; int factor2 = 60; mclk = b_clk * factor2; clkmdiv = ((double) I2S_BASE_CLK) / mclk; clkmInteger = clkmdiv; clkmDecimals = (clkmdiv - clkmInteger) / denom; bck = mclk / b_clk; -#if SOC_I2S_SUPPORT_PDM +#if I2S_SUPPORTS_PDM } 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) { @@ -697,11 +697,11 @@ esp_err_t i2s_set_dac_mode(i2s_dac_mode_t dac_mode) } if (dac_mode & I2S_DAC_CHANNEL_RIGHT_EN) { - //DAC1, right channel, GPIO25 + //DAC1, right channel dac_output_enable(DAC_CHANNEL_1); } if (dac_mode & I2S_DAC_CHANNEL_LEFT_EN) { - //DAC2, left channel, GPIO26 + //DAC2, left channel dac_output_enable(DAC_CHANNEL_2); } return ESP_OK; @@ -803,7 +803,7 @@ esp_err_t i2s_set_sample_rates(i2s_port_t i2s_num, uint32_t rate) return i2s_set_clk(i2s_num, rate, p_i2s_obj[i2s_num]->bits_per_sample, p_i2s_obj[i2s_num]->channel_num); } -#if SOC_I2S_SUPPORT_PDM +#if I2S_SUPPORTS_PDM 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); @@ -818,7 +818,8 @@ static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_co 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); -#if SOC_I2S_SUPPORT_PDM + I2S_CHECK(((i2s_config->communication_format & I2S_COMM_FORMAT_I2S) || (i2s_config->communication_format & I2S_COMM_FORMAT_PCM)), "I2S communication format invalid.", ESP_ERR_INVALID_ARG); +#if I2S_SUPPORTS_PDM I2S_CHECK(!((i2s_config->mode & I2S_MODE_PDM) && (i2s_num != I2S_NUM_0)), "I2S DAC PDM only support on I2S0", ESP_ERR_INVALID_ARG); #endif periph_module_enable(i2s_periph_signal[i2s_num].module); diff --git a/components/driver/include/driver/i2s.h b/components/driver/include/driver/i2s.h index 84a2610661..5c71609455 100644 --- a/components/driver/include/driver/i2s.h +++ b/components/driver/include/driver/i2s.h @@ -54,7 +54,7 @@ typedef intr_handle_t i2s_isr_handle_t; */ esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin); -#if SOC_I2S_SUPPORT_PDM +#if I2S_SUPPORTS_PDM /** * @brief Set PDM mode down-sample rate * In PDM RX mode, there would be 2 rounds of downsample process in hardware. diff --git a/components/driver/test/test_i2s.c b/components/driver/test/test_i2s.c index 01dab2aa99..1b8a44eea9 100644 --- a/components/driver/test/test_i2s.c +++ b/components/driver/test/test_i2s.c @@ -1,6 +1,7 @@ /** * I2S test environment UT_T1_I2S: - * connect GPIO18 and GPIO19, GPIO25 and GPIO26, GPIO21 and GPIO22 + * We use internal signals instead of external wiring, but please keep the following IO connections, or connect nothing to prevent the signal from being disturbed. + * connect GPIO18 and GPIO19, GPIO25(ESP32)/GPIO17(ESP32-S2) and GPIO26, GPIO21 and GPIO22(ESP32)/GPIO20(ESP32-S2) */ #include @@ -28,6 +29,63 @@ #define PERCENT_DIFF 0.0001 +// mode: 0, master rx, slave tx. mode: 1, master tx, slave rx. mode: 2, master tx rx loopback +// Since ESP32-S2 has only one I2S, only loop back test can be tested. +static void i2s_test_io_config(int mode) +{ + // Connect internal signals using IO matrix. + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[MASTER_BCK_IO], PIN_FUNC_GPIO); + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[MASTER_WS_IO], PIN_FUNC_GPIO); + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[DATA_OUT_IO], PIN_FUNC_GPIO); + + gpio_set_direction(MASTER_BCK_IO, GPIO_MODE_INPUT_OUTPUT); + gpio_set_direction(MASTER_WS_IO, GPIO_MODE_INPUT_OUTPUT); + gpio_set_direction(DATA_OUT_IO, GPIO_MODE_INPUT_OUTPUT); + +#if CONFIG_IDF_TARGET_ESP32 + switch (mode) { + case 0: { + gpio_matrix_out(MASTER_BCK_IO, I2S0I_BCK_OUT_IDX, 0, 0); + gpio_matrix_in(MASTER_BCK_IO, I2S1O_BCK_IN_IDX, 0); + + gpio_matrix_out(MASTER_WS_IO, I2S0I_WS_OUT_IDX, 0, 0); + gpio_matrix_in(MASTER_WS_IO, I2S1O_WS_IN_IDX, 0); + + gpio_matrix_out(DATA_OUT_IO, I2S1O_DATA_OUT23_IDX, 0, 0); + gpio_matrix_in(DATA_OUT_IO, I2S0I_DATA_IN15_IDX, 0); + } + break; + + case 1: { + gpio_matrix_out(MASTER_BCK_IO, I2S0O_BCK_OUT_IDX, 0, 0); + gpio_matrix_in(MASTER_BCK_IO, I2S1I_BCK_IN_IDX, 0); + + gpio_matrix_out(MASTER_WS_IO, I2S0O_WS_OUT_IDX, 0, 0); + gpio_matrix_in(MASTER_WS_IO, I2S1I_WS_IN_IDX, 0); + + gpio_matrix_out(DATA_OUT_IO, I2S0O_DATA_OUT23_IDX, 0, 0); + gpio_matrix_in(DATA_OUT_IO, I2S1I_DATA_IN15_IDX, 0); + } + break; + + case 2: { + gpio_matrix_out(DATA_OUT_IO, I2S0O_DATA_OUT23_IDX, 0, 0); + gpio_matrix_in(DATA_OUT_IO, I2S0I_DATA_IN15_IDX, 0); + } + break; + } +#else + switch (mode) { + case 2: { + gpio_matrix_out(DATA_OUT_IO, I2S0O_DATA_OUT23_IDX, 0, 0); + gpio_matrix_in(DATA_OUT_IO, I2S0I_DATA_IN15_IDX, 0); + } + break; + } +#endif +} + + /** * i2s initialize test * 1. i2s_driver_install @@ -52,6 +110,7 @@ TEST_CASE("I2S basic driver install, uninstall, set pin test", "[i2s]") TEST_ESP_OK(i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL)); //for internal DAC, this will enable both of the internal channels TEST_ESP_OK(i2s_set_pin(I2S_NUM_0, NULL)); + i2s_test_io_config(1); //stop & destroy i2s driver TEST_ESP_OK(i2s_driver_uninstall(I2S_NUM_0)); @@ -64,6 +123,7 @@ TEST_CASE("I2S basic driver install, uninstall, set pin test", "[i2s]") }; TEST_ESP_OK(i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL)); TEST_ESP_OK(i2s_set_pin(I2S_NUM_0, &pin_config)); + i2s_test_io_config(1); TEST_ESP_OK(i2s_driver_uninstall(I2S_NUM_0)); //error param test @@ -76,9 +136,72 @@ TEST_CASE("I2S basic driver install, uninstall, set pin test", "[i2s]") TEST_ESP_OK(i2s_driver_uninstall(I2S_NUM_0)); } -#if !DISABLED_FOR_TARGETS(ESP32S2) -/* ESP32S2 has only single I2S port and hence following test cases are not applicable */ +TEST_CASE("I2S Loopback test(master tx and rx)", "[i2s][test_env=UT_T1_I2S]") +{ + // master driver installed and send data + i2s_config_t master_i2s_config = { + .mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_RX, + .sample_rate = SAMPLE_RATE, + .bits_per_sample = SAMPLE_BITS, + .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, + .communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB, + .dma_buf_count = 6, + .dma_buf_len = 100, + .use_apll = 0, + .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 , + }; + i2s_pin_config_t master_pin_config = { + .bck_io_num = MASTER_BCK_IO, + .ws_io_num = MASTER_WS_IO, + .data_out_num = DATA_OUT_IO, + .data_in_num = DATA_IN_IO + }; + TEST_ESP_OK(i2s_driver_install(I2S_NUM_0, &master_i2s_config, 0, NULL)); + TEST_ESP_OK(i2s_set_pin(I2S_NUM_0, &master_pin_config)); + i2s_test_io_config(2); + printf("\r\nheap size: %d\n", esp_get_free_heap_size()); + uint8_t* data_wr = (uint8_t*)malloc(sizeof(uint8_t)*400); + size_t i2s_bytes_write = 0; + size_t bytes_read = 0; + int length = 0; + uint8_t *i2s_read_buff = (uint8_t*)malloc(sizeof(uint8_t)*10000); + + for(int i=0; i<100; i++) { + data_wr[i] = i+1; + } + int flag=0; // break loop flag + int end_position = 0; + // write data to slave + i2s_write(I2S_NUM_0, data_wr, sizeof(uint8_t)*400, &i2s_bytes_write, 1000 / portTICK_PERIOD_MS); + while(!flag){ + if (length >= 10000 - 500) { + break; + } + i2s_read(I2S_NUM_0, i2s_read_buff + length, sizeof(uint8_t)*500, &bytes_read, 1000/portMAX_DELAY); + if(bytes_read>0) { + printf("read data size: %d\n", bytes_read); + for(int i=length; idev, dsr) +#endif /** * @brief Config I2S param diff --git a/components/soc/include/hal/i2s_types.h b/components/soc/include/hal/i2s_types.h index 471d105fee..f1bd67d195 100644 --- a/components/soc/include/hal/i2s_types.h +++ b/components/soc/include/hal/i2s_types.h @@ -26,7 +26,14 @@ extern "C" { /** * @brief I2S port number, the max port number is (I2S_NUM_MAX -1). */ -typedef int i2s_port_t; +typedef enum { + I2S_NUM_0 = 0, /*!< I2S port 0 */ +#if SOC_I2S_NUM > 1 + I2S_NUM_1 = 1, /*!< I2S port 1 */ +#endif + I2S_NUM_MAX, /*!< I2S port max */ +} i2s_port_t; + #define I2S_PIN_NO_CHANGE (-1) /*!< Use in i2s_pin_config_t for pins which should not be changed */ @@ -75,6 +82,7 @@ typedef enum { I2S_CHANNEL_FMT_ONLY_LEFT, } i2s_channel_fmt_t; +#if I2S_SUPPORTS_PDM /** * @brief PDM sample rate ratio, measured in Hz. * @@ -92,6 +100,7 @@ typedef enum { PDM_PCM_CONV_ENABLE, PDM_PCM_CONV_DISABLE, } pdm_pcm_conv_t; +#endif /** * @brief I2S Mode, defaut is I2S_MODE_MASTER | I2S_MODE_TX @@ -106,7 +115,7 @@ typedef enum { I2S_MODE_RX = 8, I2S_MODE_DAC_BUILT_IN = 16, /*!< Output I2S data to built-in DAC, no matter the data format is 16bit or 32 bit, the DAC module will only take the 8bits from MSB*/ I2S_MODE_ADC_BUILT_IN = 32, /*!< Input I2S data from built-in ADC, each data can be 12-bit width at most*/ -#if SOC_I2S_SUPPORT_PDM +#if I2S_SUPPORTS_PDM I2S_MODE_PDM = 64, #endif } i2s_mode_t; @@ -173,7 +182,7 @@ typedef struct { int data_in_num; /*!< DATA in pin*/ } i2s_pin_config_t; -#if SOC_I2S_SUPPORT_PDM +#if I2S_SUPPORTS_PDM /** * @brief I2S PDM RX downsample mode */ diff --git a/components/soc/soc/esp32/include/soc/i2s_caps.h b/components/soc/soc/esp32/include/soc/i2s_caps.h index fff916d7e7..038ac0bc8f 100644 --- a/components/soc/soc/esp32/include/soc/i2s_caps.h +++ b/components/soc/soc/esp32/include/soc/i2s_caps.h @@ -26,12 +26,9 @@ extern "C" { #define I2S_BASE_CLK (2*APB_CLK_FREQ) // ESP32 have 2 I2S -#define I2S_NUM_0 (0) /*!< I2S port 0 */ -#define I2S_NUM_1 (1) /*!< I2S port 1 */ -#define I2S_NUM_MAX (2) /*!< I2S port max */ -#define SOC_I2S_NUM (I2S_NUM_MAX) +#define SOC_I2S_NUM (2) -#define SOC_I2S_SUPPORT_PDM (1) //ESP32 support PDM +#define I2S_SUPPORTS_PDM (1) //ESP32 support PDM #ifdef __cplusplus } diff --git a/components/soc/soc/esp32s2/include/soc/i2s_caps.h b/components/soc/soc/esp32s2/include/soc/i2s_caps.h index a3614408c6..95f4ed294d 100644 --- a/components/soc/soc/esp32s2/include/soc/i2s_caps.h +++ b/components/soc/soc/esp32s2/include/soc/i2s_caps.h @@ -17,14 +17,12 @@ #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_AD_BCK_FACTOR (1) #define I2S_PDM_BCK_FACTOR (64) #define I2S_MAX_BUFFER_SIZE (4 * 1024 * 1024) //the maximum RAM can be allocated #define I2S_BASE_CLK (2*APB_CLK_FREQ) -// ESP32-S2 have 1 I2S -#define I2S_NUM_0 (0) /*!< I2S port 0 */ -#define I2S_NUM_MAX (1) /*!< I2S port max */ -#define SOC_I2S_NUM (I2S_NUM_MAX) +// ESP32-S2 have 2 I2S +#define SOC_I2S_NUM (1) -#define SOC_I2S_SUPPORT_PDM (0) // ESP32-S2 do not support PDM +#define I2S_SUPPORTS_PDM (0) // ESP32-S2 do not support PDM diff --git a/components/soc/src/esp32s2/include/hal/i2s_ll.h b/components/soc/src/esp32s2/include/hal/i2s_ll.h index 30df72a695..4156a6c80d 100644 --- a/components/soc/src/esp32s2/include/hal/i2s_ll.h +++ b/components/soc/src/esp32s2/include/hal/i2s_ll.h @@ -386,61 +386,6 @@ static inline void i2s_ll_set_rx_eof_num(i2s_dev_t *hw, uint32_t val) hw->rx_eof_num = val; } -/** - * @brief Get I2S tx pdm fp - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get tx pdm fp - */ -static inline void i2s_ll_get_tx_pdm_fp(i2s_dev_t *hw, uint32_t *val) -{ - *val = hw->pdm_freq_conf.tx_pdm_fp; -} - -/** - * @brief Get I2S tx pdm fs - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get tx pdm fs - */ -static inline void i2s_ll_get_tx_pdm_fs(i2s_dev_t *hw, uint32_t *val) -{ - *val = hw->pdm_freq_conf.tx_pdm_fs; -} - -/** - * @brief Set I2S tx pdm fp - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx pdm fp - */ -static inline void i2s_ll_set_tx_pdm_fp(i2s_dev_t *hw, uint32_t val) -{ - hw->pdm_freq_conf.tx_pdm_fp = val; -} - -/** - * @brief Set I2S tx pdm fs - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx pdm fs - */ -static inline void i2s_ll_set_tx_pdm_fs(i2s_dev_t *hw, uint32_t val) -{ - hw->pdm_freq_conf.tx_pdm_fs = val; -} - -/** - * @brief Get I2S rx sinc dsr 16 en - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get rx sinc dsr 16 en - */ -static inline void i2s_ll_get_rx_sinc_dsr_16_en(i2s_dev_t *hw, bool *val) -{ - *val = hw->pdm_conf.rx_sinc_dsr_16_en; -} - /** * @brief Set I2S clkm div num * @@ -529,17 +474,6 @@ static inline void i2s_ll_set_rx_bits_mod(i2s_dev_t *hw, uint32_t val) hw->sample_rate_conf.rx_bits_mod = val; } -/** - * @brief Set I2S rx sinc dsr 16 en - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx sinc dsr 16 en - */ -static inline void i2s_ll_set_rx_sinc_dsr_16_en(i2s_dev_t *hw, bool val) -{ - hw->pdm_conf.rx_sinc_dsr_16_en = val; -} - /** * @brief Set I2S dscr en * @@ -573,50 +507,6 @@ static inline void i2s_ll_set_camera_en(i2s_dev_t *hw, bool val) hw->conf2.camera_en = val; } -/** - * @brief Set I2S pcm2pdm conv en - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set pcm2pdm conv en - */ -static inline void i2s_ll_set_pcm2pdm_conv_en(i2s_dev_t *hw, bool val) -{ - hw->pdm_conf.pcm2pdm_conv_en = val; -} - -/** - * @brief Set I2S pdm2pcm conv en - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set pdm2pcm conv en - */ -static inline void i2s_ll_set_pdm2pcm_conv_en(i2s_dev_t *hw, bool val) -{ - hw->pdm_conf.pdm2pcm_conv_en = val; -} - -/** - * @brief Set I2S rx pdm en - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx pdm en - */ -static inline void i2s_ll_set_rx_pdm_en(i2s_dev_t *hw, bool val) -{ - hw->pdm_conf.rx_pdm_en = val; -} - -/** - * @brief Set I2S tx pdm en - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx pdm en - */ -static inline void i2s_ll_set_tx_pdm_en(i2s_dev_t *hw, bool val) -{ - hw->pdm_conf.tx_pdm_en = val; -} - /** * @brief Set I2S tx msb shift * @@ -793,17 +683,6 @@ static inline void i2s_ll_set_rx_mono(i2s_dev_t *hw, uint32_t val) hw->conf.rx_mono = val; } -/** - * @brief Set I2S tx sinc osr2 - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx sinc osr2 - */ -static inline void i2s_ll_set_tx_sinc_osr2(i2s_dev_t *hw, uint32_t val) -{ - hw->pdm_conf.tx_sinc_osr2 = val; -} - /** * @brief Set I2S sig loopback * diff --git a/components/soc/src/hal/i2s_hal.c b/components/soc/src/hal/i2s_hal.c index 6639525ea8..9efec774c7 100644 --- a/components/soc/src/hal/i2s_hal.c +++ b/components/soc/src/hal/i2s_hal.c @@ -50,11 +50,13 @@ void i2s_hal_set_in_link(i2s_hal_context_t *hal, uint32_t bytes_num, uint32_t ad i2s_ll_set_rx_eof_num(hal->dev, bytes_num); } +#if I2S_SUPPORTS_PDM void i2s_hal_get_tx_pdm(i2s_hal_context_t *hal, int *fp, int *fs) { i2s_ll_get_tx_pdm_fp(hal->dev, (uint32_t *)fp); i2s_ll_get_tx_pdm_fs(hal->dev, (uint32_t *)fs); } +#endif void i2s_hal_set_clk_div(i2s_hal_context_t *hal, int div_num, int div_a, int div_b, int tx_bck_div, int rx_bck_div) { @@ -121,8 +123,10 @@ void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_config_t *i2s_config i2s_ll_set_lcd_en(hal->dev, 0); i2s_ll_set_camera_en(hal->dev, 0); +#if I2S_SUPPORTS_PDM i2s_ll_set_pcm2pdm_conv_en(hal->dev, 0); i2s_ll_set_pdm2pcm_conv_en(hal->dev, 0); +#endif i2s_ll_set_dscr_en(hal->dev, 0); @@ -168,7 +172,7 @@ void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_config_t *i2s_config i2s_ll_set_camera_en(hal->dev, 0); } -#if SOC_I2S_SUPPORT_PDM +#if I2S_SUPPORTS_PDM if (i2s_config->mode & I2S_MODE_PDM) { i2s_ll_set_rx_fifo_mod_force_en(hal->dev, 1); i2s_ll_set_tx_fifo_mod_force_en(hal->dev, 1); @@ -190,11 +194,8 @@ void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_config_t *i2s_config i2s_ll_set_rx_pdm_en(hal->dev, 0); i2s_ll_set_tx_pdm_en(hal->dev, 0); } -#else - i2s_ll_set_rx_pdm_en(hal->dev, 0); - i2s_ll_set_tx_pdm_en(hal->dev, 0); #endif - if (i2s_config->communication_format & I2S_COMM_FORMAT_I2S || i2s_config->communication_format & I2S_COMM_FORMAT_I2S_MSB || i2s_config->communication_format & I2S_COMM_FORMAT_I2S_LSB) { + if (i2s_config->communication_format & I2S_COMM_FORMAT_I2S) { i2s_ll_set_tx_short_sync(hal->dev, 0); i2s_ll_set_rx_short_sync(hal->dev, 0); i2s_ll_set_tx_msb_shift(hal->dev, 1); @@ -209,7 +210,7 @@ void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_config_t *i2s_config } } - if (i2s_config->communication_format & I2S_COMM_FORMAT_PCM || i2s_config->communication_format & I2S_COMM_FORMAT_PCM_LONG || i2s_config->communication_format & I2S_COMM_FORMAT_PCM_SHORT) { + if (i2s_config->communication_format & I2S_COMM_FORMAT_PCM) { i2s_ll_set_tx_msb_shift(hal->dev, 0); i2s_ll_set_rx_msb_shift(hal->dev, 0); i2s_ll_set_tx_short_sync(hal->dev, 0); diff --git a/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/main.c b/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/main.c index b69fada106..386612a1c4 100644 --- a/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/main.c +++ b/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/main.c @@ -682,13 +682,14 @@ void app_main(void) i2s_config_t i2s_config = { #ifdef CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_INTERNAL_DAC .mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN, + .communication_format = I2S_COMM_FORMAT_PCM, #else .mode = I2S_MODE_MASTER | I2S_MODE_TX, // Only TX + .communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB, #endif .sample_rate = 44100, .bits_per_sample = 16, .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels - .communication_format = I2S_COMM_FORMAT_I2S_MSB, .dma_buf_count = 6, .dma_buf_len = 60, .intr_alloc_flags = 0, //Default interrupt priority diff --git a/examples/peripherals/i2s_adc_dac/CMakeLists.txt b/examples/peripherals/i2s_adc_dac/CMakeLists.txt index 4d8f5ef280..247885dafc 100644 --- a/examples/peripherals/i2s_adc_dac/CMakeLists.txt +++ b/examples/peripherals/i2s_adc_dac/CMakeLists.txt @@ -2,6 +2,6 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) -set(SUPPORTED_TARGETS esp32) +set(SUPPORTED_TARGETS esp32 esp32s2beta) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(i2s-adc-dac) diff --git a/examples/peripherals/i2s_adc_dac/main/app_main.c b/examples/peripherals/i2s_adc_dac/main/app_main.c index 44bdea4efa..a964cde243 100644 --- a/examples/peripherals/i2s_adc_dac/main/app_main.c +++ b/examples/peripherals/i2s_adc_dac/main/app_main.c @@ -9,7 +9,9 @@ #include "driver/i2s.h" #include "driver/adc.h" #include "audio_example_file.h" +#ifdef CONFIG_IDF_TARGET_ESP32 #include "esp_adc_cal.h" +#endif static const char* TAG = "ad/da"; #define V_REF 1100 @@ -63,10 +65,10 @@ void example_i2s_init(void) .mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN, .sample_rate = EXAMPLE_I2S_SAMPLE_RATE, .bits_per_sample = EXAMPLE_I2S_SAMPLE_BITS, - .communication_format = I2S_COMM_FORMAT_I2S_MSB, + .communication_format = I2S_COMM_FORMAT_PCM, .channel_format = EXAMPLE_I2S_FORMAT, .intr_alloc_flags = 0, - .dma_buf_count = 2, + .dma_buf_count = 4, .dma_buf_len = 1024, .use_apll = 1, }; @@ -270,11 +272,17 @@ void adc_read_task(void* arg) { adc1_config_width(ADC_WIDTH_12Bit); adc1_config_channel_atten(ADC1_TEST_CHANNEL, ADC_ATTEN_11db); +#ifdef CONFIG_IDF_TARGET_ESP32 esp_adc_cal_characteristics_t characteristics; esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, V_REF, &characteristics); +#endif while(1) { uint32_t voltage; +#ifdef CONFIG_IDF_TARGET_ESP32 esp_adc_cal_get_voltage(ADC1_TEST_CHANNEL, &characteristics, &voltage); +#else + voltage = adc1_get_raw(ADC1_TEST_CHANNEL) * (3300.0 / 4095); // At 11 dB attenuation the maximum voltage is limited by VDD_A(3300 mV), not the full scale voltage. +#endif ESP_LOGI(TAG, "%d mV", voltage); vTaskDelay(200 / portTICK_RATE_MS); } diff --git a/tools/ci/config/target-test.yml b/tools/ci/config/target-test.yml index d739733db5..d42ef24a4d 100644 --- a/tools/ci/config/target-test.yml +++ b/tools/ci/config/target-test.yml @@ -460,6 +460,12 @@ UT_026: - UT_T1_I2S - psram +UT_027: + extends: .unit_test_template + tags: + - ESP32S2BETA_IDF + - UT_T1_I2S + UT_028: extends: .unit_test_template tags: From 3ad5138dd8432efb1371edf9aafb1bd2e1e961a0 Mon Sep 17 00:00:00 2001 From: fuzhibo Date: Fri, 20 Dec 2019 14:57:34 +0800 Subject: [PATCH 2/3] fix coexist i2s_adc and rtc_adc --- components/driver/i2s.c | 5 +- components/driver/test/test_i2s.c | 58 +++++++++++++++++ .../soc/soc/esp32/include/soc/i2s_caps.h | 5 +- .../soc/soc/esp32s2/include/soc/i2s_caps.h | 7 ++- components/soc/src/esp32/include/hal/adc_ll.h | 18 +++--- .../soc/src/esp32s2/include/hal/adc_ll.h | 63 +++++++++---------- .../soc/src/esp32s2/include/hal/i2s_ll.h | 22 +++++++ components/soc/src/hal/adc_hal.c | 1 - components/soc/src/hal/i2s_hal.c | 6 ++ .../peripherals/i2s_adc_dac/main/app_main.c | 30 ++++----- 10 files changed, 151 insertions(+), 64 deletions(-) diff --git a/components/driver/i2s.c b/components/driver/i2s.c index c7dd573a72..2bb7d74b88 100644 --- a/components/driver/i2s.c +++ b/components/driver/i2s.c @@ -403,7 +403,7 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b //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 /= 2; + fi2s_clk /= I2S_AD_BCK_FACTOR; int factor2 = 60; mclk = b_clk * factor2; clkmdiv = ((double) I2S_BASE_CLK) / mclk; @@ -1043,6 +1043,8 @@ esp_err_t i2s_adc_enable(i2s_port_t i2s_num) adc1_i2s_mode_acquire(); _i2s_adc_mode_recover(); + i2s_hal_start_rx(&(p_i2s_obj[i2s_num]->hal)); + i2s_hal_reset(&(p_i2s_obj[i2s_num]->hal)); 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); } @@ -1052,6 +1054,7 @@ esp_err_t i2s_adc_disable(i2s_port_t i2s_num) 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); + i2s_hal_stop_rx(&(p_i2s_obj[i2s_num]->hal)); adc1_lock_release(); return ESP_OK; } diff --git a/components/driver/test/test_i2s.c b/components/driver/test/test_i2s.c index 1b8a44eea9..2853ba974c 100644 --- a/components/driver/test/test_i2s.c +++ b/components/driver/test/test_i2s.c @@ -2,6 +2,7 @@ * I2S test environment UT_T1_I2S: * We use internal signals instead of external wiring, but please keep the following IO connections, or connect nothing to prevent the signal from being disturbed. * connect GPIO18 and GPIO19, GPIO25(ESP32)/GPIO17(ESP32-S2) and GPIO26, GPIO21 and GPIO22(ESP32)/GPIO20(ESP32-S2) + * Please do not connect GPIO32(ESP32)/GPIO5(ESP32-S2) any pull-up resistors externally, it will be used to test i2s adc function. */ #include @@ -22,9 +23,11 @@ #if CONFIG_IDF_TARGET_ESP32 #define MASTER_WS_IO 25 #define DATA_OUT_IO 22 +#define ADC1_CHANNEL_4_IO 32 #elif CONFIG_IDF_TARGET_ESP32S2 #define MASTER_WS_IO 28 #define DATA_OUT_IO 20 +#define ADC1_CHANNEL_4_IO 5 #endif #define PERCENT_DIFF 0.0001 @@ -201,6 +204,61 @@ TEST_CASE("I2S Loopback test(master tx and rx)", "[i2s][test_env=UT_T1_I2S]") } #if !DISABLED_FOR_TARGETS(ESP32S2) +TEST_CASE("I2S adc test", "[i2s][test_env=UT_T1_I2S]") +{ + // init I2S ADC + i2s_config_t i2s_config = { + .mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN, + .sample_rate = SAMPLE_RATE, + .bits_per_sample = SAMPLE_BITS, + .communication_format = I2S_COMM_FORMAT_PCM, + .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, + .intr_alloc_flags = 0, + .dma_buf_count = 2, + .dma_buf_len = 1024, + .use_apll = 0, + }; + // install and start I2S driver + i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL); + // init ADC pad + i2s_set_adc_mode(ADC_UNIT_1, ADC1_CHANNEL_4); + // enable adc sampling, ADC_WIDTH_BIT_12, ADC_ATTEN_DB_11 hard-coded in adc_i2s_mode_init + i2s_adc_enable(I2S_NUM_0); + // init read buffer + uint16_t* i2sReadBuffer = (uint16_t*)calloc(1024, sizeof(uint16_t)); + size_t bytesRead; + + for (int loop = 0; loop < 10; loop++) { + for (int level = 0; level <= 1; level++) { + if (level == 0) { + gpio_set_pull_mode(ADC1_CHANNEL_4_IO, GPIO_PULLDOWN_ONLY); + } else { + gpio_set_pull_mode(ADC1_CHANNEL_4_IO, GPIO_PULLUP_ONLY); + } + vTaskDelay(200 / portTICK_RATE_MS); + // read data from adc, will block until buffer is full + i2s_read(I2S_NUM_0, (void*)i2sReadBuffer, 1024 * sizeof(uint16_t), &bytesRead, portMAX_DELAY); + + // calc average + int64_t adcSumValue = 0; + for (size_t i = 0; i < 1024; i++) { + adcSumValue += i2sReadBuffer[i] & 0xfff; + } + int adcAvgValue = adcSumValue / 1024; + printf("adc average val: %d\n", adcAvgValue); + + if (level == 0) { + TEST_ASSERT_LESS_THAN(100, adcAvgValue); + } else { + TEST_ASSERT_GREATER_THAN(4000, adcAvgValue); + } + } + } + i2s_adc_disable(I2S_NUM_0); + free(i2sReadBuffer); + i2s_driver_uninstall(I2S_NUM_0); +} + /* ESP32S2BETA has only single I2S port and hence following test cases are not applicable */ TEST_CASE("I2S write and read test(master tx and slave rx)", "[i2s][test_env=UT_T1_I2S]") { diff --git a/components/soc/soc/esp32/include/soc/i2s_caps.h b/components/soc/soc/esp32/include/soc/i2s_caps.h index 038ac0bc8f..5c111790c9 100644 --- a/components/soc/soc/esp32/include/soc/i2s_caps.h +++ b/components/soc/soc/esp32/include/soc/i2s_caps.h @@ -26,9 +26,10 @@ extern "C" { #define I2S_BASE_CLK (2*APB_CLK_FREQ) // ESP32 have 2 I2S -#define SOC_I2S_NUM (2) +#define SOC_I2S_NUM (2) -#define I2S_SUPPORTS_PDM (1) //ESP32 support PDM +#define I2S_SUPPORTS_PDM (1) // ESP32 support PDM +#define I2S_SUPPORTS_DMA_EQUAL (0) // ESP32 don't support dma equal #ifdef __cplusplus } diff --git a/components/soc/soc/esp32s2/include/soc/i2s_caps.h b/components/soc/soc/esp32s2/include/soc/i2s_caps.h index 95f4ed294d..2432c3a603 100644 --- a/components/soc/soc/esp32s2/include/soc/i2s_caps.h +++ b/components/soc/soc/esp32s2/include/soc/i2s_caps.h @@ -17,12 +17,13 @@ #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 (1) +#define I2S_AD_BCK_FACTOR (2) #define I2S_PDM_BCK_FACTOR (64) #define I2S_MAX_BUFFER_SIZE (4 * 1024 * 1024) //the maximum RAM can be allocated #define I2S_BASE_CLK (2*APB_CLK_FREQ) // ESP32-S2 have 2 I2S -#define SOC_I2S_NUM (1) +#define SOC_I2S_NUM (1) -#define I2S_SUPPORTS_PDM (0) // ESP32-S2 do not support PDM +#define I2S_SUPPORTS_PDM (0) // ESP32-S2 don't support PDM +#define I2S_SUPPORTS_DMA_EQUAL (1) // ESP32-S2 need dma equal diff --git a/components/soc/src/esp32/include/hal/adc_ll.h b/components/soc/src/esp32/include/hal/adc_ll.h index 019d4164d6..222d4598b4 100644 --- a/components/soc/src/esp32/include/hal/adc_ll.h +++ b/components/soc/src/esp32/include/hal/adc_ll.h @@ -203,18 +203,16 @@ static inline void adc_ll_set_pattern_table_len(adc_ll_num_t adc_n, uint32_t pat */ static inline void adc_ll_set_pattern_table(adc_ll_num_t adc_n, uint32_t pattern_index, adc_ll_pattern_table_t pattern) { - uint32_t tab; - uint8_t *arg; + const uint32_t patt_tab_idx = pattern_index / 4; + const uint32_t patt_shift = (3 - (pattern_index % 4)) * 8; + const uint32_t patt_mask = 0xFF << patt_shift; + if (adc_n == ADC_NUM_1) { - tab = SYSCON.saradc_sar1_patt_tab[pattern_index / 4]; - arg = (uint8_t *)&tab; - arg[pattern_index % 4] = pattern.val; - SYSCON.saradc_sar1_patt_tab[pattern_index / 4] = tab; + SYSCON.saradc_sar1_patt_tab[patt_tab_idx] &= ~patt_mask; + SYSCON.saradc_sar1_patt_tab[patt_tab_idx] |= pattern.val << patt_shift; } else { // adc_n == ADC_NUM_2 - tab = SYSCON.saradc_sar2_patt_tab[pattern_index / 4]; - arg = (uint8_t *)&tab; - arg[pattern_index % 4] = pattern.val; - SYSCON.saradc_sar2_patt_tab[pattern_index / 4] = tab; + SYSCON.saradc_sar2_patt_tab[patt_tab_idx] &= ~patt_mask; + SYSCON.saradc_sar2_patt_tab[patt_tab_idx] |= pattern.val << patt_shift; } } diff --git a/components/soc/src/esp32s2/include/hal/adc_ll.h b/components/soc/src/esp32s2/include/hal/adc_ll.h index 5ad1bd5d56..bf409c89d4 100644 --- a/components/soc/src/esp32s2/include/hal/adc_ll.h +++ b/components/soc/src/esp32s2/include/hal/adc_ll.h @@ -2,7 +2,7 @@ #include "soc/adc_periph.h" #include "hal/adc_types.h" -#include "soc/apb_ctrl_struct.h" +#include "soc/apb_saradc_struct.h" #include #ifdef __cplusplus @@ -83,11 +83,11 @@ typedef enum { static inline void adc_ll_dig_set_fsm_time(uint32_t rst_wait, uint32_t start_wait, uint32_t standby_wait) { // Internal FSM reset wait time - APB_CTRL.saradc_fsm_wait.rstb_wait = rst_wait; + APB_SARADC.fsm_wait.rstb_wait = rst_wait; // Internal FSM start wait time - APB_CTRL.saradc_fsm_wait.xpd_wait = start_wait; + APB_SARADC.fsm_wait.xpd_wait = start_wait; // Internal FSM standby wait time - APB_CTRL.saradc_fsm_wait.standby_wait = standby_wait; + APB_SARADC.fsm_wait.standby_wait = standby_wait; } /** @@ -99,7 +99,7 @@ static inline void adc_ll_dig_set_fsm_time(uint32_t rst_wait, uint32_t start_wai */ static inline void adc_ll_dig_set_sample_cycle(uint32_t sample_cycle) { - APB_CTRL.saradc_fsm.sample_cycle = sample_cycle; + APB_SARADC.fsm.sample_cycle = sample_cycle; } /** @@ -109,7 +109,7 @@ static inline void adc_ll_dig_set_sample_cycle(uint32_t sample_cycle) */ static inline void adc_ll_dig_set_output_format(adc_ll_dig_output_format_t format) { - APB_CTRL.saradc_ctrl.data_sar_sel = format; + APB_SARADC.ctrl.data_sar_sel = format; } /** @@ -120,7 +120,7 @@ static inline void adc_ll_dig_set_output_format(adc_ll_dig_output_format_t forma */ static inline void adc_ll_dig_set_convert_limit_num(uint32_t meas_num) { - APB_CTRL.saradc_ctrl2.max_meas_num = meas_num; + APB_SARADC.ctrl2.max_meas_num = meas_num; } /** @@ -129,7 +129,7 @@ static inline void adc_ll_dig_set_convert_limit_num(uint32_t meas_num) */ static inline void adc_ll_dig_convert_limit_enable(void) { - APB_CTRL.saradc_ctrl2.meas_num_limit = 1; + APB_SARADC.ctrl2.meas_num_limit = 1; } /** @@ -138,7 +138,7 @@ static inline void adc_ll_dig_convert_limit_enable(void) */ static inline void adc_ll_dig_convert_limit_disable(void) { - APB_CTRL.saradc_ctrl2.meas_num_limit = 0; + APB_SARADC.ctrl2.meas_num_limit = 0; } /** @@ -151,15 +151,15 @@ static inline void adc_ll_dig_convert_limit_disable(void) static inline void adc_ll_dig_set_convert_mode(adc_ll_convert_mode_t mode) { if (mode == ADC_CONV_SINGLE_UNIT_1) { - APB_CTRL.saradc_ctrl.work_mode = 0; - APB_CTRL.saradc_ctrl.sar_sel = 0; + APB_SARADC.ctrl.work_mode = 0; + APB_SARADC.ctrl.sar_sel = 0; } else if (mode == ADC_CONV_SINGLE_UNIT_2) { - APB_CTRL.saradc_ctrl.work_mode = 0; - APB_CTRL.saradc_ctrl.sar_sel = 1; + APB_SARADC.ctrl.work_mode = 0; + APB_SARADC.ctrl.sar_sel = 1; } else if (mode == ADC_CONV_BOTH_UNIT) { - APB_CTRL.saradc_ctrl.work_mode = 1; + APB_SARADC.ctrl.work_mode = 1; } else if (mode == ADC_CONV_ALTER_UNIT) { - APB_CTRL.saradc_ctrl.work_mode = 2; + APB_SARADC.ctrl.work_mode = 2; } } @@ -171,7 +171,7 @@ static inline void adc_ll_dig_set_convert_mode(adc_ll_convert_mode_t mode) static inline void adc_ll_dig_set_data_source(adc_i2s_source_t src) { /* 1: I2S input data is from SAR ADC (for DMA) 0: I2S input data is from GPIO matrix */ - APB_CTRL.saradc_ctrl.data_to_i2s = src; + APB_SARADC.ctrl.data_to_i2s = src; } /** @@ -186,9 +186,9 @@ static inline void adc_ll_dig_set_data_source(adc_i2s_source_t src) static inline void adc_ll_set_pattern_table_len(adc_ll_num_t adc_n, uint32_t patt_len) { if (adc_n == ADC_NUM_1) { - APB_CTRL.saradc_ctrl.sar1_patt_len = patt_len - 1; + APB_SARADC.ctrl.sar1_patt_len = patt_len - 1; } else { // adc_n == ADC_NUM_2 - APB_CTRL.saradc_ctrl.sar2_patt_len = patt_len - 1; + APB_SARADC.ctrl.sar2_patt_len = patt_len - 1; } } @@ -204,18 +204,17 @@ static inline void adc_ll_set_pattern_table_len(adc_ll_num_t adc_n, uint32_t pat */ static inline void adc_ll_set_pattern_table(adc_ll_num_t adc_n, uint32_t pattern_index, adc_ll_pattern_table_t pattern) { - uint32_t tab; - uint8_t *arg; + const uint32_t patt_tab_idx = pattern_index / 4; + const uint32_t patt_shift = (3 - (pattern_index % 4)) * 8; + const uint32_t patt_mask = 0xFF << patt_shift; + if (adc_n == ADC_NUM_1) { - tab = *(uint32_t *)(&APB_CTRL.saradc_sar1_patt_tab1 + pattern_index / 4); - arg = (uint8_t *)&tab; - arg[pattern_index % 4] = pattern.val; - *(uint32_t *)(&APB_CTRL.saradc_sar1_patt_tab1 + pattern_index / 4) = tab; - } else { // adc_n == ADC_NUM_2 - tab = *(uint32_t *)(&APB_CTRL.saradc_sar2_patt_tab1 + pattern_index / 4); - arg = (uint8_t *)&tab; - arg[pattern_index % 4] = pattern.val; - *(uint32_t *)(&APB_CTRL.saradc_sar2_patt_tab1 + pattern_index / 4) = tab; + APB_SARADC.sar1_patt_tab[patt_tab_idx] &= ~patt_mask; + APB_SARADC.sar1_patt_tab[patt_tab_idx] |= pattern.val << patt_shift; + } + else { // adc_n == ADC_NUM_2 + APB_SARADC.sar2_patt_tab[patt_tab_idx] &= ~patt_mask; + APB_SARADC.sar2_patt_tab[patt_tab_idx] |= pattern.val << patt_shift; } } @@ -390,7 +389,7 @@ static inline adc_ll_power_t adc_ll_get_power_manage(void) static inline void adc_ll_set_clk_div(uint32_t div) { /* ADC clock devided from APB clk, e.g. 80 / 2 = 40Mhz, */ - APB_CTRL.saradc_ctrl.sar_clk_div = div; + APB_SARADC.ctrl.sar_clk_div = div; } /** @@ -457,9 +456,9 @@ static inline void adc_ll_rtc_output_invert(adc_ll_num_t adc_n, bool inv_en) static inline void adc_ll_dig_output_invert(adc_ll_num_t adc_n, bool inv_en) { if (adc_n == ADC_NUM_1) { - APB_CTRL.saradc_ctrl2.sar1_inv = inv_en; // Enable / Disable ADC data invert + APB_SARADC.ctrl2.sar1_inv = inv_en; // Enable / Disable ADC data invert } else { // adc_n == ADC_NUM_2 - APB_CTRL.saradc_ctrl2.sar2_inv = inv_en; // Enable / Disable ADC data invert + APB_SARADC.ctrl2.sar2_inv = inv_en; // Enable / Disable ADC data invert } } diff --git a/components/soc/src/esp32s2/include/hal/i2s_ll.h b/components/soc/src/esp32s2/include/hal/i2s_ll.h index 4156a6c80d..b4f63f1e98 100644 --- a/components/soc/src/esp32s2/include/hal/i2s_ll.h +++ b/components/soc/src/esp32s2/include/hal/i2s_ll.h @@ -353,6 +353,28 @@ static inline void i2s_ll_set_rx_chan_mod(i2s_dev_t *hw, uint32_t val) hw->conf_chan.rx_chan_mod = val; } +/** + * @brief Set I2S tx dma equal + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx dma equal + */ +static inline void i2s_ll_set_tx_dma_equal(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.tx_dma_equal = val; +} + +/** + * @brief Set I2S rx dma equal + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx dma equal + */ +static inline void i2s_ll_set_rx_dma_equal(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.rx_dma_equal = val; +} + /** * @brief Set I2S out link address * diff --git a/components/soc/src/hal/adc_hal.c b/components/soc/src/hal/adc_hal.c index 9867ed26e8..562e3b7880 100644 --- a/components/soc/src/hal/adc_hal.c +++ b/components/soc/src/hal/adc_hal.c @@ -16,7 +16,6 @@ void adc_hal_init(void) { - adc_ll_set_power_manage(ADC_POWER_BY_FSM); // Set internal FSM wait time, fixed value. adc_ll_dig_set_fsm_time(SOC_ADC_FSM_RSTB_WAIT_DEFAULT, SOC_ADC_FSM_START_WAIT_DEFAULT, SOC_ADC_FSM_STANDBY_WAIT_DEFAULT); diff --git a/components/soc/src/hal/i2s_hal.c b/components/soc/src/hal/i2s_hal.c index 9efec774c7..ca8e725ab7 100644 --- a/components/soc/src/hal/i2s_hal.c +++ b/components/soc/src/hal/i2s_hal.c @@ -32,6 +32,9 @@ void i2s_hal_set_tx_mode(i2s_hal_context_t *hal, i2s_channel_t ch, i2s_bits_per_ i2s_ll_set_tx_fifo_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 2 : 3); } i2s_ll_set_tx_chan_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1); +#if I2S_SUPPORTS_DMA_EQUAL + i2s_ll_set_tx_dma_equal(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1); +#endif } void i2s_hal_set_rx_mode(i2s_hal_context_t *hal, i2s_channel_t ch, i2s_bits_per_sample_t bits) @@ -42,6 +45,9 @@ void i2s_hal_set_rx_mode(i2s_hal_context_t *hal, i2s_channel_t ch, i2s_bits_per_ i2s_ll_set_rx_fifo_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 2 : 3); } i2s_ll_set_rx_chan_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1); +#if I2S_SUPPORTS_DMA_EQUAL + i2s_ll_set_rx_dma_equal(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1); +#endif } void i2s_hal_set_in_link(i2s_hal_context_t *hal, uint32_t bytes_num, uint32_t addr) diff --git a/examples/peripherals/i2s_adc_dac/main/app_main.c b/examples/peripherals/i2s_adc_dac/main/app_main.c index a964cde243..075e81e6ff 100644 --- a/examples/peripherals/i2s_adc_dac/main/app_main.c +++ b/examples/peripherals/i2s_adc_dac/main/app_main.c @@ -60,24 +60,24 @@ static const char* TAG = "ad/da"; */ void example_i2s_init(void) { - int i2s_num = EXAMPLE_I2S_NUM; - i2s_config_t i2s_config = { + int i2s_num = EXAMPLE_I2S_NUM; + i2s_config_t i2s_config = { .mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN, .sample_rate = EXAMPLE_I2S_SAMPLE_RATE, .bits_per_sample = EXAMPLE_I2S_SAMPLE_BITS, - .communication_format = I2S_COMM_FORMAT_PCM, - .channel_format = EXAMPLE_I2S_FORMAT, - .intr_alloc_flags = 0, - .dma_buf_count = 4, - .dma_buf_len = 1024, - .use_apll = 1, - }; - //install and start i2s driver - i2s_driver_install(i2s_num, &i2s_config, 0, NULL); - //init DAC pad - i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN); - //init ADC pad - i2s_set_adc_mode(I2S_ADC_UNIT, I2S_ADC_CHANNEL); + .communication_format = I2S_COMM_FORMAT_PCM, + .channel_format = EXAMPLE_I2S_FORMAT, + .intr_alloc_flags = 0, + .dma_buf_count = 2, + .dma_buf_len = 1024, + .use_apll = 1, + }; + //install and start i2s driver + i2s_driver_install(i2s_num, &i2s_config, 0, NULL); + //init DAC pad + i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN); + //init ADC pad + i2s_set_adc_mode(I2S_ADC_UNIT, I2S_ADC_CHANNEL); } /* From b3ae9fa97820276b4c1dd1976a1b4d42a76ccd43 Mon Sep 17 00:00:00 2001 From: xiongyu Date: Thu, 20 Feb 2020 16:00:48 +0800 Subject: [PATCH 3/3] bugfix(i2s): Updated ESP32-S2 ADC DAC support * Delete the relevant codes of ADC DAC of ESP32-S2. --- components/driver/i2s.c | 29 ++++++- components/driver/include/driver/i2s.h | 13 ++- components/driver/test/test_i2s.c | 80 +++++++++---------- components/soc/include/hal/i2s_hal.h | 4 +- components/soc/include/hal/i2s_types.h | 8 +- .../soc/soc/esp32/include/soc/i2s_caps.h | 5 +- .../soc/soc/esp32s2/include/soc/i2s_caps.h | 5 +- components/soc/src/hal/i2s_hal.c | 12 +-- .../peripherals/i2s_adc_dac/CMakeLists.txt | 2 +- .../peripherals/i2s_adc_dac/main/app_main.c | 8 -- tools/ci/config/target-test.yml | 17 +--- 11 files changed, 96 insertions(+), 87 deletions(-) diff --git a/components/driver/i2s.c b/components/driver/i2s.c index 2bb7d74b88..ed5bd11471 100644 --- a/components/driver/i2s.c +++ b/components/driver/i2s.c @@ -25,9 +25,11 @@ #include "esp32/rom/lldesc.h" #include "driver/gpio.h" #include "driver/i2s.h" +#if SOC_I2S_SUPPORTS_ADC_DAC #include "driver/dac.h" #include "hal/i2s_hal.h" #include "adc1_i2s_private.h" +#endif #include "esp_intr_alloc.h" #include "esp_err.h" @@ -95,8 +97,10 @@ typedef struct { static i2s_obj_t *p_i2s_obj[I2S_NUM_MAX] = {0}; static portMUX_TYPE i2s_spinlock[I2S_NUM_MAX]; +#if SOC_I2S_SUPPORTS_ADC_DAC static int _i2s_adc_unit = -1; static int _i2s_adc_channel = -1; +#endif 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); @@ -398,7 +402,9 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b double mclk; int sdm0, sdm1, sdm2, odir, m_scale = 8; int fi2s_clk = rate*channel*bits*m_scale; +#if SOC_I2S_SUPPORTS_ADC_DAC 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 @@ -410,7 +416,8 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b clkmInteger = clkmdiv; clkmDecimals = (clkmdiv - clkmInteger) / denom; bck = mclk / b_clk; -#if I2S_SUPPORTS_PDM +#endif +#if SOC_I2S_SUPPORTS_PDM } 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) { @@ -431,8 +438,9 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b clkmInteger = clkmdiv; clkmDecimals = (clkmdiv - clkmInteger) / denom; bck = mclk / b_clk; + } else #endif - } else { + { clkmInteger = clkmdiv; clkmDecimals = (clkmdiv - clkmInteger) / denom; mclk = clkmInteger + denom * clkmDecimals; @@ -685,6 +693,7 @@ esp_err_t i2s_stop(i2s_port_t i2s_num) return ESP_OK; } +#if SOC_I2S_SUPPORTS_ADC_DAC 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); @@ -721,13 +730,19 @@ esp_err_t i2s_set_adc_mode(adc_unit_t adc_unit, adc1_channel_t adc_channel) _i2s_adc_channel = adc_channel; return adc_i2s_mode_init(adc_unit, adc_channel); } +#endif 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) { +#if SOC_I2S_SUPPORTS_ADC_DAC return i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN); +#else + return ESP_ERR_INVALID_ARG; +#endif } + 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; @@ -803,7 +818,7 @@ esp_err_t i2s_set_sample_rates(i2s_port_t i2s_num, uint32_t rate) return i2s_set_clk(i2s_num, rate, p_i2s_obj[i2s_num]->bits_per_sample, p_i2s_obj[i2s_num]->channel_num); } -#if I2S_SUPPORTS_PDM +#if SOC_I2S_SUPPORTS_PDM 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); @@ -816,14 +831,17 @@ static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_co { I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); I2S_CHECK((i2s_config), "param null", ESP_ERR_INVALID_ARG); +#if SOC_I2S_SUPPORTS_ADC_DAC 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); +#endif I2S_CHECK(((i2s_config->communication_format & I2S_COMM_FORMAT_I2S) || (i2s_config->communication_format & I2S_COMM_FORMAT_PCM)), "I2S communication format invalid.", ESP_ERR_INVALID_ARG); -#if I2S_SUPPORTS_PDM +#if SOC_I2S_SUPPORTS_PDM I2S_CHECK(!((i2s_config->mode & I2S_MODE_PDM) && (i2s_num != I2S_NUM_0)), "I2S DAC PDM only support on I2S0", ESP_ERR_INVALID_ARG); #endif periph_module_enable(i2s_periph_signal[i2s_num].module); +#if SOC_I2S_SUPPORTS_ADC_DAC 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. @@ -831,6 +849,7 @@ static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_co //In default data mode, the ADC data is in 12-bit resolution mode. adc_power_always_on(); } +#endif // configure I2S data port interface. i2s_reset_fifo(i2s_num); i2s_hal_config_param(&(p_i2s_obj[i2s_num]->hal), i2s_config); @@ -1035,6 +1054,7 @@ esp_err_t i2s_write(i2s_port_t i2s_num, const void *src, size_t size, size_t *by return ESP_OK; } +#if SOC_I2S_SUPPORTS_ADC_DAC 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); @@ -1058,6 +1078,7 @@ esp_err_t i2s_adc_disable(i2s_port_t i2s_num) adc1_lock_release(); return ESP_OK; } +#endif 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) { diff --git a/components/driver/include/driver/i2s.h b/components/driver/include/driver/i2s.h index 5c71609455..f976a31c00 100644 --- a/components/driver/include/driver/i2s.h +++ b/components/driver/include/driver/i2s.h @@ -17,12 +17,17 @@ #include "esp_types.h" #include "esp_err.h" #include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" #include "soc/i2s_periph.h" #include "soc/rtc_periph.h" #include "soc/i2s_caps.h" -#include "driver/periph_ctrl.h" -#include "driver/adc.h" // adc1_channel_t typedef +#include "hal/i2s_hal.h" #include "hal/i2s_types.h" +#include "driver/periph_ctrl.h" +#include "esp_intr_alloc.h" +#if SOC_I2S_SUPPORTS_ADC_DAC +#include "driver/adc.h" +#endif #ifdef __cplusplus extern "C" { @@ -54,7 +59,7 @@ typedef intr_handle_t i2s_isr_handle_t; */ esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin); -#if I2S_SUPPORTS_PDM +#if SOC_I2S_SUPPORTS_PDM /** * @brief Set PDM mode down-sample rate * In PDM RX mode, there would be 2 rounds of downsample process in hardware. @@ -288,6 +293,7 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b */ float i2s_get_clk(i2s_port_t i2s_num); +#if SOC_I2S_SUPPORTS_ADC_DAC /** * @brief Set built-in ADC mode for I2S DMA, this function will initialize ADC pad, * and set ADC parameters. @@ -322,6 +328,7 @@ esp_err_t i2s_adc_enable(i2s_port_t i2s_num); * - ESP_ERR_INVALID_STATE Driver state error */ esp_err_t i2s_adc_disable(i2s_port_t i2s_num); +#endif #ifdef __cplusplus } diff --git a/components/driver/test/test_i2s.c b/components/driver/test/test_i2s.c index 2853ba974c..639213c0a1 100644 --- a/components/driver/test/test_i2s.c +++ b/components/driver/test/test_i2s.c @@ -1,8 +1,8 @@ /** * I2S test environment UT_T1_I2S: * We use internal signals instead of external wiring, but please keep the following IO connections, or connect nothing to prevent the signal from being disturbed. - * connect GPIO18 and GPIO19, GPIO25(ESP32)/GPIO17(ESP32-S2) and GPIO26, GPIO21 and GPIO22(ESP32)/GPIO20(ESP32-S2) - * Please do not connect GPIO32(ESP32)/GPIO5(ESP32-S2) any pull-up resistors externally, it will be used to test i2s adc function. + * connect GPIO15 and GPIO19, GPIO25(ESP32)/GPIO17(ESP32-S2) and GPIO26, GPIO21 and GPIO22(ESP32)/GPIO20(ESP32-S2) + * Please do not connect GPIO32(ESP32) any pull-up resistors externally, it will be used to test i2s adc function. */ #include @@ -10,12 +10,13 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/i2s.h" +#include "driver/gpio.h" #include "unity.h" #include "math.h" #define SAMPLE_RATE (36000) #define SAMPLE_BITS (16) -#define MASTER_BCK_IO 18 +#define MASTER_BCK_IO 15 #define SLAVE_BCK_IO 19 #define SLAVE_WS_IO 26 #define DATA_IN_IO 21 @@ -27,11 +28,14 @@ #elif CONFIG_IDF_TARGET_ESP32S2 #define MASTER_WS_IO 28 #define DATA_OUT_IO 20 -#define ADC1_CHANNEL_4_IO 5 #endif #define PERCENT_DIFF 0.0001 +#define I2S_TEST_MODE_SLAVE_TO_MAXTER 0 +#define I2S_TEST_MODE_MASTER_TO_SLAVE 1 +#define I2S_TEST_MODE_LOOPBACK 2 + // mode: 0, master rx, slave tx. mode: 1, master tx, slave rx. mode: 2, master tx rx loopback // Since ESP32-S2 has only one I2S, only loop back test can be tested. static void i2s_test_io_config(int mode) @@ -45,9 +49,9 @@ static void i2s_test_io_config(int mode) gpio_set_direction(MASTER_WS_IO, GPIO_MODE_INPUT_OUTPUT); gpio_set_direction(DATA_OUT_IO, GPIO_MODE_INPUT_OUTPUT); -#if CONFIG_IDF_TARGET_ESP32 switch (mode) { - case 0: { +#if SOC_I2S_NUM > 1 + case I2S_TEST_MODE_SLAVE_TO_MAXTER: { gpio_matrix_out(MASTER_BCK_IO, I2S0I_BCK_OUT_IDX, 0, 0); gpio_matrix_in(MASTER_BCK_IO, I2S1O_BCK_IN_IDX, 0); @@ -59,7 +63,7 @@ static void i2s_test_io_config(int mode) } break; - case 1: { + case I2S_TEST_MODE_MASTER_TO_SLAVE: { gpio_matrix_out(MASTER_BCK_IO, I2S0O_BCK_OUT_IDX, 0, 0); gpio_matrix_in(MASTER_BCK_IO, I2S1I_BCK_IN_IDX, 0); @@ -70,22 +74,18 @@ static void i2s_test_io_config(int mode) gpio_matrix_in(DATA_OUT_IO, I2S1I_DATA_IN15_IDX, 0); } break; - - case 2: { - gpio_matrix_out(DATA_OUT_IO, I2S0O_DATA_OUT23_IDX, 0, 0); - gpio_matrix_in(DATA_OUT_IO, I2S0I_DATA_IN15_IDX, 0); - } - break; - } -#else - switch (mode) { - case 2: { - gpio_matrix_out(DATA_OUT_IO, I2S0O_DATA_OUT23_IDX, 0, 0); - gpio_matrix_in(DATA_OUT_IO, I2S0I_DATA_IN15_IDX, 0); - } - break; - } #endif + case I2S_TEST_MODE_LOOPBACK: { + gpio_matrix_out(DATA_OUT_IO, I2S0O_DATA_OUT23_IDX, 0, 0); + gpio_matrix_in(DATA_OUT_IO, I2S0I_DATA_IN15_IDX, 0); + } + break; + + default: { + TEST_FAIL_MESSAGE("error: mode not supported"); + } + break; + } } @@ -109,13 +109,14 @@ TEST_CASE("I2S basic driver install, uninstall, set pin test", "[i2s]") .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 , }; +#if CONFIG_IDF_TARGET_ESP32 //install and start i2s driver TEST_ESP_OK(i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL)); //for internal DAC, this will enable both of the internal channels TEST_ESP_OK(i2s_set_pin(I2S_NUM_0, NULL)); - i2s_test_io_config(1); //stop & destroy i2s driver TEST_ESP_OK(i2s_driver_uninstall(I2S_NUM_0)); +#endif // normal i2s i2s_pin_config_t pin_config = { @@ -126,7 +127,6 @@ TEST_CASE("I2S basic driver install, uninstall, set pin test", "[i2s]") }; TEST_ESP_OK(i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL)); TEST_ESP_OK(i2s_set_pin(I2S_NUM_0, &pin_config)); - i2s_test_io_config(1); TEST_ESP_OK(i2s_driver_uninstall(I2S_NUM_0)); //error param test @@ -139,7 +139,7 @@ TEST_CASE("I2S basic driver install, uninstall, set pin test", "[i2s]") TEST_ESP_OK(i2s_driver_uninstall(I2S_NUM_0)); } -TEST_CASE("I2S Loopback test(master tx and rx)", "[i2s][test_env=UT_T1_I2S]") +TEST_CASE("I2S Loopback test(master tx and rx)", "[i2s]") { // master driver installed and send data i2s_config_t master_i2s_config = { @@ -161,7 +161,7 @@ TEST_CASE("I2S Loopback test(master tx and rx)", "[i2s][test_env=UT_T1_I2S]") }; TEST_ESP_OK(i2s_driver_install(I2S_NUM_0, &master_i2s_config, 0, NULL)); TEST_ESP_OK(i2s_set_pin(I2S_NUM_0, &master_pin_config)); - i2s_test_io_config(2); + i2s_test_io_config(I2S_TEST_MODE_LOOPBACK); printf("\r\nheap size: %d\n", esp_get_free_heap_size()); uint8_t* data_wr = (uint8_t*)malloc(sizeof(uint8_t)*400); @@ -194,9 +194,9 @@ TEST_CASE("I2S Loopback test(master tx and rx)", "[i2s][test_env=UT_T1_I2S]") } length = length + bytes_read; } - // test the readed data right or not + // test the read data right or not for(int i=end_position-99; i<=end_position; i++) { - TEST_ASSERT(*(i2s_read_buff + i) == (i-end_position+100)); + TEST_ASSERT_EQUAL_UINT8((i-end_position+100), *(i2s_read_buff + i)); } free(data_wr); free(i2s_read_buff); @@ -204,7 +204,8 @@ TEST_CASE("I2S Loopback test(master tx and rx)", "[i2s][test_env=UT_T1_I2S]") } #if !DISABLED_FOR_TARGETS(ESP32S2) -TEST_CASE("I2S adc test", "[i2s][test_env=UT_T1_I2S]") +/* ESP32S2 has only single I2S port and hence following test cases are not applicable */ +TEST_CASE("I2S adc test", "[i2s]") { // init I2S ADC i2s_config_t i2s_config = { @@ -259,8 +260,7 @@ TEST_CASE("I2S adc test", "[i2s][test_env=UT_T1_I2S]") i2s_driver_uninstall(I2S_NUM_0); } -/* ESP32S2BETA has only single I2S port and hence following test cases are not applicable */ -TEST_CASE("I2S write and read test(master tx and slave rx)", "[i2s][test_env=UT_T1_I2S]") +TEST_CASE("I2S write and read test(master tx and slave rx)", "[i2s]") { // master driver installed and send data i2s_config_t master_i2s_config = { @@ -282,7 +282,7 @@ TEST_CASE("I2S write and read test(master tx and slave rx)", "[i2s][test_env=UT_ }; TEST_ESP_OK(i2s_driver_install(I2S_NUM_0, &master_i2s_config, 0, NULL)); TEST_ESP_OK(i2s_set_pin(I2S_NUM_0, &master_pin_config)); - i2s_test_io_config(1); + i2s_test_io_config(I2S_TEST_MODE_MASTER_TO_SLAVE); printf("\r\nheap size: %d\n", esp_get_free_heap_size()); i2s_config_t slave_i2s_config = { @@ -305,7 +305,7 @@ TEST_CASE("I2S write and read test(master tx and slave rx)", "[i2s][test_env=UT_ // slave driver installed and receive data TEST_ESP_OK(i2s_driver_install(I2S_NUM_1, &slave_i2s_config, 0, NULL)); TEST_ESP_OK(i2s_set_pin(I2S_NUM_1, &slave_pin_config)); - i2s_test_io_config(1); + i2s_test_io_config(I2S_TEST_MODE_MASTER_TO_SLAVE); printf("\r\nheap size: %d\n", esp_get_free_heap_size()); uint8_t* data_wr = (uint8_t*)malloc(sizeof(uint8_t)*400); @@ -337,7 +337,7 @@ TEST_CASE("I2S write and read test(master tx and slave rx)", "[i2s][test_env=UT_ } // test the readed data right or not for(int i=end_position-99; i<=end_position; i++) { - TEST_ASSERT(*(i2s_read_buff + i) == (i-end_position+100)); + TEST_ASSERT_EQUAL_UINT8((i-end_position+100), *(i2s_read_buff + i)); } free(data_wr); free(i2s_read_buff); @@ -345,7 +345,7 @@ TEST_CASE("I2S write and read test(master tx and slave rx)", "[i2s][test_env=UT_ i2s_driver_uninstall(I2S_NUM_1); } -TEST_CASE("I2S write and read test(master rx and slave tx)", "[i2s][test_env=UT_T1_I2S]") +TEST_CASE("I2S write and read test(master rx and slave tx)", "[i2s]") { // master driver installed and send data i2s_config_t master_i2s_config = { @@ -367,7 +367,7 @@ TEST_CASE("I2S write and read test(master rx and slave tx)", "[i2s][test_env=UT_ }; TEST_ESP_OK(i2s_driver_install(I2S_NUM_0, &master_i2s_config, 0, NULL)); TEST_ESP_OK(i2s_set_pin(I2S_NUM_0, &master_pin_config)); - i2s_test_io_config(0); + i2s_test_io_config(I2S_TEST_MODE_SLAVE_TO_MAXTER); printf("\r\nheap size: %d\n", esp_get_free_heap_size()); i2s_config_t slave_i2s_config = { @@ -390,7 +390,7 @@ TEST_CASE("I2S write and read test(master rx and slave tx)", "[i2s][test_env=UT_ // slave driver installed and receive data TEST_ESP_OK(i2s_driver_install(I2S_NUM_1, &slave_i2s_config, 0, NULL)); TEST_ESP_OK(i2s_set_pin(I2S_NUM_1, &slave_pin_config)); - i2s_test_io_config(0); + i2s_test_io_config(I2S_TEST_MODE_SLAVE_TO_MAXTER); uint8_t* data_wr = (uint8_t*)malloc(sizeof(uint8_t)*400); size_t i2s_bytes_write = 0; @@ -422,7 +422,7 @@ TEST_CASE("I2S write and read test(master rx and slave tx)", "[i2s][test_env=UT_ } // test the readed data right or not for(int i=end_position-99; i<=end_position; i++) { - TEST_ASSERT(*(i2s_read_buff + i) == (i-end_position+100)); + TEST_ASSERT_EQUAL_UINT8((i-end_position+100), *(i2s_read_buff + i)); } free(data_wr); free(i2s_read_buff); @@ -453,14 +453,12 @@ TEST_CASE("I2S memory leaking test", "[i2s]") TEST_ESP_OK(i2s_driver_install(I2S_NUM_0, &master_i2s_config, 0, NULL)); TEST_ESP_OK(i2s_set_pin(I2S_NUM_0, &master_pin_config)); - i2s_test_io_config(1); i2s_driver_uninstall(I2S_NUM_0); int initial_size = esp_get_free_heap_size(); for(int i=0; i<100; i++) { TEST_ESP_OK(i2s_driver_install(I2S_NUM_0, &master_i2s_config, 0, NULL)); TEST_ESP_OK(i2s_set_pin(I2S_NUM_0, &master_pin_config)); - i2s_test_io_config(1); i2s_driver_uninstall(I2S_NUM_0); TEST_ASSERT(initial_size == esp_get_free_heap_size()); } @@ -496,7 +494,6 @@ TEST_CASE("I2S APLL clock variation test", "[i2s]") TEST_ESP_OK(i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL)); TEST_ESP_OK(i2s_set_pin(I2S_NUM_0, &pin_config)); - i2s_test_io_config(1); TEST_ESP_OK(i2s_driver_uninstall(I2S_NUM_0)); int initial_size = esp_get_free_heap_size(); @@ -510,7 +507,6 @@ TEST_CASE("I2S APLL clock variation test", "[i2s]") TEST_ESP_OK(i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL)); TEST_ESP_OK(i2s_set_pin(I2S_NUM_0, &pin_config)); - i2s_test_io_config(1); TEST_ASSERT((fabs((i2s_get_clk(I2S_NUM_0) - sample_rate_arr[i]))/(sample_rate_arr[i]))*100 < PERCENT_DIFF); TEST_ESP_OK(i2s_driver_uninstall(I2S_NUM_0)); TEST_ASSERT(initial_size == esp_get_free_heap_size()); diff --git a/components/soc/include/hal/i2s_hal.h b/components/soc/include/hal/i2s_hal.h index 21e800977d..aa03922616 100644 --- a/components/soc/include/hal/i2s_hal.h +++ b/components/soc/include/hal/i2s_hal.h @@ -158,7 +158,7 @@ void i2s_hal_set_rx_mode(i2s_hal_context_t *hal, i2s_channel_t ch, i2s_bits_per_ */ void i2s_hal_set_in_link(i2s_hal_context_t *hal, uint32_t rx_eof_num, uint32_t addr); -#if I2S_SUPPORTS_PDM +#if SOC_I2S_SUPPORTS_PDM /** * @brief Get I2S tx pdm * @@ -248,7 +248,7 @@ void i2s_hal_stop_tx(i2s_hal_context_t *hal); */ void i2s_hal_stop_rx(i2s_hal_context_t *hal); -#if I2S_SUPPORTS_PDM +#if SOC_I2S_SUPPORTS_PDM /** * @brief Set I2S pdm rx down sample * diff --git a/components/soc/include/hal/i2s_types.h b/components/soc/include/hal/i2s_types.h index f1bd67d195..0846741ce6 100644 --- a/components/soc/include/hal/i2s_types.h +++ b/components/soc/include/hal/i2s_types.h @@ -82,7 +82,7 @@ typedef enum { I2S_CHANNEL_FMT_ONLY_LEFT, } i2s_channel_fmt_t; -#if I2S_SUPPORTS_PDM +#if SOC_I2S_SUPPORTS_PDM /** * @brief PDM sample rate ratio, measured in Hz. * @@ -113,9 +113,11 @@ typedef enum { I2S_MODE_SLAVE = 2, I2S_MODE_TX = 4, I2S_MODE_RX = 8, +#if SOC_I2S_SUPPORTS_ADC_DAC I2S_MODE_DAC_BUILT_IN = 16, /*!< Output I2S data to built-in DAC, no matter the data format is 16bit or 32 bit, the DAC module will only take the 8bits from MSB*/ I2S_MODE_ADC_BUILT_IN = 32, /*!< Input I2S data from built-in ADC, each data can be 12-bit width at most*/ -#if I2S_SUPPORTS_PDM +#endif +#if SOC_I2S_SUPPORTS_PDM I2S_MODE_PDM = 64, #endif } i2s_mode_t; @@ -182,7 +184,7 @@ typedef struct { int data_in_num; /*!< DATA in pin*/ } i2s_pin_config_t; -#if I2S_SUPPORTS_PDM +#if SOC_I2S_SUPPORTS_PDM /** * @brief I2S PDM RX downsample mode */ diff --git a/components/soc/soc/esp32/include/soc/i2s_caps.h b/components/soc/soc/esp32/include/soc/i2s_caps.h index 5c111790c9..07c707e699 100644 --- a/components/soc/soc/esp32/include/soc/i2s_caps.h +++ b/components/soc/soc/esp32/include/soc/i2s_caps.h @@ -28,8 +28,9 @@ extern "C" { // ESP32 have 2 I2S #define SOC_I2S_NUM (2) -#define I2S_SUPPORTS_PDM (1) // ESP32 support PDM -#define I2S_SUPPORTS_DMA_EQUAL (0) // ESP32 don't support dma equal +#define SOC_I2S_SUPPORTS_PDM (1) // ESP32 support PDM +#define SOC_I2S_SUPPORTS_DMA_EQUAL (0) // ESP32 don't support dma equal +#define SOC_I2S_SUPPORTS_ADC_DAC (1) // ESP32 support ADC and DAC #ifdef __cplusplus } diff --git a/components/soc/soc/esp32s2/include/soc/i2s_caps.h b/components/soc/soc/esp32s2/include/soc/i2s_caps.h index 2432c3a603..17d46803fb 100644 --- a/components/soc/soc/esp32s2/include/soc/i2s_caps.h +++ b/components/soc/soc/esp32s2/include/soc/i2s_caps.h @@ -25,5 +25,6 @@ // ESP32-S2 have 2 I2S #define SOC_I2S_NUM (1) -#define I2S_SUPPORTS_PDM (0) // ESP32-S2 don't support PDM -#define I2S_SUPPORTS_DMA_EQUAL (1) // ESP32-S2 need dma equal +#define SOC_I2S_SUPPORTS_PDM (0) // ESP32-S2 don't support PDM +#define SOC_I2S_SUPPORTS_DMA_EQUAL (1) // ESP32-S2 need dma equal +#define SOC_I2S_SUPPORTS_ADC_DAC (0) // ESP32-S2 don't support ADC and DAC diff --git a/components/soc/src/hal/i2s_hal.c b/components/soc/src/hal/i2s_hal.c index ca8e725ab7..be3d5aef05 100644 --- a/components/soc/src/hal/i2s_hal.c +++ b/components/soc/src/hal/i2s_hal.c @@ -32,7 +32,7 @@ void i2s_hal_set_tx_mode(i2s_hal_context_t *hal, i2s_channel_t ch, i2s_bits_per_ i2s_ll_set_tx_fifo_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 2 : 3); } i2s_ll_set_tx_chan_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1); -#if I2S_SUPPORTS_DMA_EQUAL +#if SOC_I2S_SUPPORTS_DMA_EQUAL i2s_ll_set_tx_dma_equal(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1); #endif } @@ -45,7 +45,7 @@ void i2s_hal_set_rx_mode(i2s_hal_context_t *hal, i2s_channel_t ch, i2s_bits_per_ i2s_ll_set_rx_fifo_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 2 : 3); } i2s_ll_set_rx_chan_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1); -#if I2S_SUPPORTS_DMA_EQUAL +#if SOC_I2S_SUPPORTS_DMA_EQUAL i2s_ll_set_rx_dma_equal(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1); #endif } @@ -56,7 +56,7 @@ void i2s_hal_set_in_link(i2s_hal_context_t *hal, uint32_t bytes_num, uint32_t ad i2s_ll_set_rx_eof_num(hal->dev, bytes_num); } -#if I2S_SUPPORTS_PDM +#if SOC_I2S_SUPPORTS_PDM void i2s_hal_get_tx_pdm(i2s_hal_context_t *hal, int *fp, int *fs) { i2s_ll_get_tx_pdm_fp(hal->dev, (uint32_t *)fp); @@ -129,7 +129,7 @@ void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_config_t *i2s_config i2s_ll_set_lcd_en(hal->dev, 0); i2s_ll_set_camera_en(hal->dev, 0); -#if I2S_SUPPORTS_PDM +#if SOC_I2S_SUPPORTS_PDM i2s_ll_set_pcm2pdm_conv_en(hal->dev, 0); i2s_ll_set_pdm2pcm_conv_en(hal->dev, 0); #endif @@ -172,13 +172,15 @@ void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_config_t *i2s_config } } +#if SOC_I2S_SUPPORTS_ADC_DAC if (i2s_config->mode & (I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN)) { i2s_ll_set_lcd_en(hal->dev, 1); i2s_ll_set_tx_right_first(hal->dev, 1); i2s_ll_set_camera_en(hal->dev, 0); } +#endif -#if I2S_SUPPORTS_PDM +#if SOC_I2S_SUPPORTS_PDM if (i2s_config->mode & I2S_MODE_PDM) { i2s_ll_set_rx_fifo_mod_force_en(hal->dev, 1); i2s_ll_set_tx_fifo_mod_force_en(hal->dev, 1); diff --git a/examples/peripherals/i2s_adc_dac/CMakeLists.txt b/examples/peripherals/i2s_adc_dac/CMakeLists.txt index 247885dafc..4d8f5ef280 100644 --- a/examples/peripherals/i2s_adc_dac/CMakeLists.txt +++ b/examples/peripherals/i2s_adc_dac/CMakeLists.txt @@ -2,6 +2,6 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) -set(SUPPORTED_TARGETS esp32 esp32s2beta) +set(SUPPORTED_TARGETS esp32) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(i2s-adc-dac) diff --git a/examples/peripherals/i2s_adc_dac/main/app_main.c b/examples/peripherals/i2s_adc_dac/main/app_main.c index 075e81e6ff..c97fe96aae 100644 --- a/examples/peripherals/i2s_adc_dac/main/app_main.c +++ b/examples/peripherals/i2s_adc_dac/main/app_main.c @@ -9,9 +9,7 @@ #include "driver/i2s.h" #include "driver/adc.h" #include "audio_example_file.h" -#ifdef CONFIG_IDF_TARGET_ESP32 #include "esp_adc_cal.h" -#endif static const char* TAG = "ad/da"; #define V_REF 1100 @@ -272,17 +270,11 @@ void adc_read_task(void* arg) { adc1_config_width(ADC_WIDTH_12Bit); adc1_config_channel_atten(ADC1_TEST_CHANNEL, ADC_ATTEN_11db); -#ifdef CONFIG_IDF_TARGET_ESP32 esp_adc_cal_characteristics_t characteristics; esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, V_REF, &characteristics); -#endif while(1) { uint32_t voltage; -#ifdef CONFIG_IDF_TARGET_ESP32 esp_adc_cal_get_voltage(ADC1_TEST_CHANNEL, &characteristics, &voltage); -#else - voltage = adc1_get_raw(ADC1_TEST_CHANNEL) * (3300.0 / 4095); // At 11 dB attenuation the maximum voltage is limited by VDD_A(3300 mV), not the full scale voltage. -#endif ESP_LOGI(TAG, "%d mV", voltage); vTaskDelay(200 / portTICK_RATE_MS); } diff --git a/tools/ci/config/target-test.yml b/tools/ci/config/target-test.yml index d42ef24a4d..a5eb60b6dd 100644 --- a/tools/ci/config/target-test.yml +++ b/tools/ci/config/target-test.yml @@ -345,7 +345,7 @@ UT_001: UT_002: extends: .unit_test_template - parallel: 13 + parallel: 14 tags: - ESP32_IDF - UT_T1_1 @@ -419,7 +419,7 @@ UT_017: UT_018: extends: .unit_test_template - parallel: 3 + parallel: 4 tags: - ESP32_IDF - UT_T1_1 @@ -453,19 +453,6 @@ UT_024: - UT_T1_MCPWM - psram -UT_026: - extends: .unit_test_template - tags: - - ESP32_IDF - - UT_T1_I2S - - psram - -UT_027: - extends: .unit_test_template - tags: - - ESP32S2BETA_IDF - - UT_T1_I2S - UT_028: extends: .unit_test_template tags: