From d90e0e434568e9ecaed5a40a5e1be054ceb42601 Mon Sep 17 00:00:00 2001 From: fuzhibo Date: Wed, 8 Apr 2020 21:56:14 +0800 Subject: [PATCH] driver(adc): fix unit test for ADC-DMA (test_esp32s2.c); fix unit test for ADC-DMA (test_esp32s2.c); fix commit in adc dirver. --- components/driver/esp32/adc.c | 2 +- .../driver/test/adc_dma_test/test_esp32.c | 13 +- .../driver/test/adc_dma_test/test_esp32s2.c | 545 +++++++++--------- .../test/include/test/test_common_adc.h | 34 ++ components/driver/test/test_adc_common.c | 74 ++- components/soc/include/hal/adc_hal.h | 7 +- components/soc/include/hal/adc_types.h | 153 +++-- .../soc/include/hal/touch_sensor_types.h | 2 +- .../soc/soc/esp32s2/include/soc/adc_caps.h | 2 +- .../soc/src/esp32/include/hal/adc_hal.h | 2 +- components/soc/src/esp32/include/hal/adc_ll.h | 19 +- components/soc/src/esp32s2/adc_hal.c | 8 +- .../soc/src/esp32s2/include/hal/adc_hal.h | 9 +- .../soc/src/esp32s2/include/hal/adc_ll.h | 149 ++--- .../esp32s2/include/hal/touch_sensor_hal.h | 6 +- .../src/esp32s2/include/hal/touch_sensor_ll.h | 8 +- components/soc/src/hal/adc_hal.c | 2 +- docs/en/api-reference/peripherals/adc.rst | 23 +- 18 files changed, 572 insertions(+), 486 deletions(-) create mode 100644 components/driver/test/include/test/test_common_adc.h diff --git a/components/driver/esp32/adc.c b/components/driver/esp32/adc.c index 19fb9031f..cbbeaae1e 100644 --- a/components/driver/esp32/adc.c +++ b/components/driver/esp32/adc.c @@ -120,7 +120,7 @@ esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel) dig_cfg.adc2_pattern_len = 1; dig_cfg.adc2_pattern = adc2_pattern; } - + adc_gpio_init(adc_unit, channel); ADC_ENTER_CRITICAL(); adc_hal_digi_init(); adc_hal_digi_controller_config(&dig_cfg); diff --git a/components/driver/test/adc_dma_test/test_esp32.c b/components/driver/test/adc_dma_test/test_esp32.c index 50143f882..557fc86e1 100644 --- a/components/driver/test/adc_dma_test/test_esp32.c +++ b/components/driver/test/adc_dma_test/test_esp32.c @@ -52,7 +52,7 @@ //I2S built-in ADC unit #define I2S_ADC_UNIT ADC_UNIT_1 //I2S built-in ADC channel -//#define I2S_ADC_CHANNEL //adc1_ch[0] +#define I2S_ADC_CHANNEL ADC1_CHANNEL_4 //flash record size, for recording 5 seconds' data #define FLASH_RECORD_SIZE (EXAMPLE_I2S_CHANNEL_NUM * EXAMPLE_I2S_SAMPLE_RATE * EXAMPLE_I2S_SAMPLE_BITS / 8 * 5) @@ -60,15 +60,6 @@ //sector size of flash #define FLASH_SECTOR_SIZE (0x1000) -#define ADC1_TEST_CHANNEL_NUM 3 -#define ADC2_TEST_CHANNEL_NUM 3 - -static const int adc1_ch[ADC1_TEST_CHANNEL_NUM] = { - ADC1_CHANNEL_2, - ADC1_CHANNEL_3, - ADC1_CHANNEL_4, -}; - /** * @brief I2S ADC/DAC mode init. */ @@ -88,7 +79,7 @@ static void example_i2s_init(void) //install and start i2s driver TEST_ESP_OK( i2s_driver_install(i2s_num, &i2s_config, 0, NULL) ); //init ADC pad - TEST_ESP_OK( i2s_set_adc_mode(I2S_ADC_UNIT, adc1_ch[0]) ); + TEST_ESP_OK( i2s_set_adc_mode(I2S_ADC_UNIT, I2S_ADC_CHANNEL) ); } static void example_i2s_deinit(void) diff --git a/components/driver/test/adc_dma_test/test_esp32s2.c b/components/driver/test/adc_dma_test/test_esp32s2.c index cacb54af6..ed7985de3 100644 --- a/components/driver/test/adc_dma_test/test_esp32s2.c +++ b/components/driver/test/adc_dma_test/test_esp32s2.c @@ -17,6 +17,10 @@ */ #include "esp_system.h" +#include "esp_intr_alloc.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" #include "driver/adc.h" #include "driver/dac.h" #include "driver/rtc_io.h" @@ -30,10 +34,12 @@ #include "test_utils.h" #include "soc/spi_reg.h" #include "soc/adc_periph.h" +#include "test/test_common_adc.h" #if !DISABLED_FOR_TARGETS(ESP8266, ESP32) // This testcase for ESP32S2 #include "soc/system_reg.h" +#include "soc/lldesc.h" static const char *TAG = "test_adc"; @@ -62,12 +68,11 @@ static void test_pxp_deinit_io(void) TEST_ASSERT_EQUAL_UINT32(REG_GET_FIELD(SENS_SARDATE_REG, SENS_SAR_DATE), SENS.sardate.sar_date); \ TEST_ASSERT_EQUAL_UINT32(REG_GET_FIELD(RTC_IO_DATE_REG, RTC_IO_IO_DATE), RTCIO.date.date); \ }) -/** Sample rate = APB_CLK(80 MHz) / CLK_DIV / TRIGGER_INTERVAL */ -#define TEST_ADC_TRIGGER_INTERVAL_DEFAULT (80) -#define TEST_ADC_DIGI_CLK_DIV_DEFAULT (40) -#define TEST_ADC_COUNT_NUM (10) -#define TEST_ADC_CHANNEL (10) -static adc_channel_t adc_list[TEST_ADC_CHANNEL] = { +/** Sample rate = APB_CLK(80 MHz) / (CLK_DIV + 1) / TRIGGER_INTERVAL / 2. */ +#define TEST_ADC_TRIGGER_INTERVAL_DEFAULT (40) +#define TEST_ADC_DIGI_CLK_DIV_DEFAULT (9) +static uint8_t adc_test_num = 9; +static adc_channel_t adc_list[SOC_ADC_PATT_LEN_MAX] = { ADC_CHANNEL_0, ADC_CHANNEL_1, ADC_CHANNEL_2, @@ -75,189 +80,144 @@ static adc_channel_t adc_list[TEST_ADC_CHANNEL] = { ADC_CHANNEL_4, ADC_CHANNEL_5, ADC_CHANNEL_6, - ADC_CHANNEL_7, + // ADC_CHANNEL_7, // Workaround: IO18 is pullup outside in ESP32S2-Saola Runner. ADC_CHANNEL_8, ADC_CHANNEL_9, }; /* For ESP32S2, it should use same atten, or, it will have error. */ #define TEST_ADC_ATTEN_DEFAULT (ADC_ATTEN_11db) + /*******************************************/ /** SPI DMA INIT CODE */ /*******************************************/ extern esp_err_t adc_digi_reset(void); -typedef struct dma_link { - struct { - uint32_t size : 12; //the size of buf, must be able to be divisible by 4 - uint32_t length: 12; //in link, - uint32_t reversed: 6; //reversed - uint32_t eof: 1; //if this dma link is the last one, you shoule set this bit 1. - uint32_t owner: 1; //the owner of buf, bit 1 : DMA, bit 0 : CPU. - } des; - uint8_t *buf; //the pointer of buf - struct dma_link *pnext; //point to the next dma linker, if this link is the last one, set it NULL. -} dma_link_t; /* Work mode. * single: eof_num; * double: SAR_EOF_NUMBER/2; * alter: eof_num; * */ -#define SAR_SIMPLE_NUM 64 // Set sample number of enabled unit. -#define SAR_DMA_DATA_SIZE(unit, sample_num) (SAR_EOF_NUMBER(unit, sample_num)) // 1 adc -> 2 byte data -> 2 link buf +#define SAR_SIMPLE_NUM 512 // Set sample number of enabled unit. +/* Use two DMA linker to save ADC data. ADC sample 1 times -> 2 byte data -> 2 DMA link buf. */ +#define SAR_DMA_DATA_SIZE(unit, sample_num) (SAR_EOF_NUMBER(unit, sample_num)) // #define SAR_EOF_NUMBER(unit, sample_num) ((sample_num) * (unit)) -#define SAR_MEAS_LIMIT_NUM(unit, sample_num) (SAR_EOF_NUMBER(unit, sample_num) / unit) +#define SAR_MEAS_LIMIT_NUM(unit, sample_num) (SAR_SIMPLE_NUM) +#define SAR_SIMPLE_TIMEOUT_MS 1000 + +typedef struct dma_msg { + uint32_t int_msk; + uint8_t *data; + uint32_t data_len; +} adc_dma_event_t; static uint8_t link_buf[2][SAR_DMA_DATA_SIZE(2, SAR_SIMPLE_NUM)] = {0}; -static dma_link_t dma1; -static dma_link_t dma2; +static lldesc_t dma1 = {0}; +static lldesc_t dma2 = {0}; +static bool adc_dma_flag = false; +static QueueHandle_t que_adc = NULL; +static adc_dma_event_t adc_evt; -static void dma_linker_init(adc_unit_t adc, bool is_loop) +/** ADC-DMA ISR handler. */ +static IRAM_ATTR void adc_dma_isr(void *arg) { - dma1.des.eof = 0; - dma1.des.owner = 1; - dma1.pnext = &dma2; - dma1.des.size = SAR_DMA_DATA_SIZE((adc > 2) ? 2 : 1, SAR_SIMPLE_NUM); - dma1.des.length = 0; //For input buffer, this field is no use. - dma1.buf = &link_buf[0][0]; - - dma2.des.owner = 1; - if (is_loop) { - dma2.des.eof = 0; - dma2.pnext = &dma1; - } else { - dma2.des.eof = 1; - dma2.pnext = NULL; + uint32_t int_st = REG_READ(SPI_DMA_INT_ST_REG(3)); + int task_awoken = pdFALSE; + REG_WRITE(SPI_DMA_INT_CLR_REG(3), int_st); + if (int_st & SPI_IN_SUC_EOF_INT_ST_M) { + adc_evt.int_msk = int_st; + xQueueSendFromISR(que_adc, &adc_evt, &task_awoken); } - dma2.des.size = SAR_DMA_DATA_SIZE((adc > 2) ? 2 : 1, SAR_SIMPLE_NUM); - dma2.des.length = 0; //For input buffer, this field is no use. - dma2.buf = &link_buf[1][0]; + if (int_st & SPI_IN_DONE_INT_ST) { + adc_evt.int_msk = int_st; + xQueueSendFromISR(que_adc, &adc_evt, &task_awoken); + } + ESP_EARLY_LOGV(TAG, "int msk%x\n", int_st); + if (task_awoken == pdTRUE) { + portYIELD_FROM_ISR(); + } +} +/** Register ADC-DMA handler. */ +static esp_err_t adc_dma_isr_register(void (*fun)(void *), void *arg) +{ + esp_err_t ret = ESP_FAIL; + ret = esp_intr_alloc(ETS_SPI3_DMA_INTR_SOURCE, 0, fun, arg, NULL); + return ret; +} + +/** Reset DMA linker pointer and start DMA. */ +static void dma_linker_restart(void) +{ + REG_SET_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_STOP); + REG_CLR_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_START); + SET_PERI_REG_BITS(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_ADDR, (uint32_t)&dma1, 0); + REG_SET_BIT(SPI_DMA_CONF_REG(3), SPI_IN_RST); + REG_CLR_BIT(SPI_DMA_CONF_REG(3), SPI_IN_RST); + REG_CLR_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_STOP); + REG_SET_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_START); +} + +/** + * DMA liner initialization and start. + * @param is_loop + * - true: The two dma linked lists are connected end to end, with no end mark (eof). + * - false: The two dma linked lists are connected end to end, with end mark (eof). + * @param int_mask DMA interrupt types. + */ +static void dma_linker_init(adc_unit_t adc, bool is_loop, uint32_t int_mask) +{ + dma1 = (lldesc_t) { + .size = SAR_DMA_DATA_SIZE((adc > 2) ? 2 : 1, SAR_SIMPLE_NUM), + .owner = 1, + .buf = &link_buf[0][0], + .qe.stqe_next = &dma2, + }; + dma2 = (lldesc_t) { + .size = SAR_DMA_DATA_SIZE((adc > 2) ? 2 : 1, SAR_SIMPLE_NUM), + .owner = 1, + .buf = &link_buf[1][0], + }; + if (is_loop) { + dma2.qe.stqe_next = &dma1; + } else { + dma2.qe.stqe_next = NULL; + } REG_SET_BIT(DPORT_PERIP_CLK_EN_REG, DPORT_APB_SARADC_CLK_EN_M); REG_SET_BIT(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_DMA_CLK_EN_M); REG_SET_BIT(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_CLK_EN); REG_CLR_BIT(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_DMA_RST_M); REG_CLR_BIT(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_RST_M); - uint32_t dma_pointer = (uint32_t)&dma1; - SET_PERI_REG_BITS(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_ADDR, dma_pointer, 0); - REG_SET_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_STOP); - REG_CLR_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_START); - REG_CLR_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_STOP); - REG_SET_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_START); - REG_SET_BIT(SPI_DMA_INT_ENA_REG(3), SPI_IN_SUC_EOF_INT_ENA); - printf("reg addr 0x%08x 0x%08x \n", SPI_DMA_IN_LINK_REG(3), dma_pointer); -} - -static void dma_linker_restart(void) -{ - REG_SET_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_STOP); - REG_CLR_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_START); - REG_CLR_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_STOP); - REG_SET_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_START); - adc_digi_reset(); + if (!adc_dma_flag) { + que_adc = xQueueCreate(5, sizeof(adc_dma_event_t)); + adc_dma_isr_register(adc_dma_isr, NULL); + adc_dma_flag = true; + } + REG_WRITE(SPI_DMA_INT_CLR_REG(3), 0xFFFFFFFF); + REG_WRITE(SPI_DMA_INT_ENA_REG(3), int_mask); + dma_linker_restart(); + printf("reg addr 0x%08x 0x%08x \n", SPI_DMA_IN_LINK_REG(3), (uint32_t)&dma1); } /*******************************************/ /** SPI DMA INIT CODE END */ /*******************************************/ -/** - * TEST TOOLS - * Note: internal pullup/pulldown is weak energy. if enabled WiFi, it should be need outside pullup/pulldown. - */ -#define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel]) - -static void adc_fake_tie_middle(adc_unit_t adc) -{ - if (adc & ADC_UNIT_1) { - for (int i = 0; i < TEST_ADC_CHANNEL; i++) { - adc_gpio_init(ADC_UNIT_1, adc_list[i]); - TEST_ESP_OK(rtc_gpio_pullup_en(ADC_GET_IO_NUM(0, adc_list[i]))); - TEST_ESP_OK(rtc_gpio_pulldown_en(ADC_GET_IO_NUM(0, adc_list[i]))); - TEST_ESP_OK(rtc_gpio_set_direction(ADC_GET_IO_NUM(0, adc_list[i]), RTC_GPIO_MODE_INPUT_ONLY)); - } - } - if (adc & ADC_UNIT_2) { - for (int i = 0; i < TEST_ADC_CHANNEL; i++) { - adc_gpio_init(ADC_UNIT_2, adc_list[i]); - TEST_ESP_OK(rtc_gpio_pullup_en(ADC_GET_IO_NUM(1, adc_list[i]))); - TEST_ESP_OK(rtc_gpio_pulldown_en(ADC_GET_IO_NUM(1, adc_list[i]))); - TEST_ESP_OK(rtc_gpio_set_direction(ADC_GET_IO_NUM(1, adc_list[i]), RTC_GPIO_MODE_INPUT_ONLY)); - } - } - vTaskDelay(10 / portTICK_RATE_MS); // To wait stable of IO. -} - -static void adc_fake_tie_high(adc_unit_t adc) -{ - if (adc & ADC_UNIT_1) { - for (int i = 0; i < TEST_ADC_CHANNEL; i++) { - adc_gpio_init(ADC_UNIT_1, adc_list[i]); - TEST_ESP_OK(rtc_gpio_pullup_en(ADC_GET_IO_NUM(0, adc_list[i]))); - TEST_ESP_OK(rtc_gpio_pulldown_dis(ADC_GET_IO_NUM(0, adc_list[i]))); - TEST_ESP_OK(rtc_gpio_set_direction(ADC_GET_IO_NUM(0, adc_list[i]), RTC_GPIO_MODE_OUTPUT_ONLY)); - TEST_ESP_OK(rtc_gpio_set_level(ADC_GET_IO_NUM(0, adc_list[i]), 1)); - } - } - if (adc & ADC_UNIT_2) { - for (int i = 0; i < TEST_ADC_CHANNEL; i++) { - adc_gpio_init(ADC_UNIT_2, adc_list[i]); - TEST_ESP_OK(rtc_gpio_pullup_en(ADC_GET_IO_NUM(1, adc_list[i]))); - TEST_ESP_OK(rtc_gpio_pulldown_dis(ADC_GET_IO_NUM(1, adc_list[i]))); - TEST_ESP_OK(rtc_gpio_set_direction(ADC_GET_IO_NUM(1, adc_list[i]), RTC_GPIO_MODE_OUTPUT_ONLY)); - TEST_ESP_OK(rtc_gpio_set_level(ADC_GET_IO_NUM(1, adc_list[i]), 1)); - } - } - vTaskDelay(10 / portTICK_RATE_MS); // To wait stable of IO. -} - -static void adc_fake_tie_low(adc_unit_t adc) -{ - if (adc & ADC_UNIT_1) { - for (int i = 0; i < TEST_ADC_CHANNEL; i++) { - adc_gpio_init(ADC_UNIT_1, adc_list[i]); - TEST_ESP_OK(rtc_gpio_pullup_dis(ADC_GET_IO_NUM(0, adc_list[i]))); - TEST_ESP_OK(rtc_gpio_pulldown_en(ADC_GET_IO_NUM(0, adc_list[i]))); - TEST_ESP_OK(rtc_gpio_set_direction(ADC_GET_IO_NUM(0, adc_list[i]), RTC_GPIO_MODE_OUTPUT_ONLY)); - TEST_ESP_OK(rtc_gpio_set_level(ADC_GET_IO_NUM(0, adc_list[i]), 0)); - } - } - if (adc & ADC_UNIT_2) { - for (int i = 0; i < TEST_ADC_CHANNEL; i++) { - adc_gpio_init(ADC_UNIT_2, adc_list[i]); - TEST_ESP_OK(rtc_gpio_pullup_dis(ADC_GET_IO_NUM(1, adc_list[i]))); - TEST_ESP_OK(rtc_gpio_pulldown_en(ADC_GET_IO_NUM(1, adc_list[i]))); - TEST_ESP_OK(rtc_gpio_set_direction(ADC_GET_IO_NUM(1, adc_list[i]), RTC_GPIO_MODE_OUTPUT_ONLY)); - TEST_ESP_OK(rtc_gpio_set_level(ADC_GET_IO_NUM(1, adc_list[i]), 0)); - } - } - vTaskDelay(10 / portTICK_RATE_MS); // To wait stable of IO. -} - -static void adc_io_normal(adc_unit_t adc) -{ - if (adc & ADC_UNIT_1) { - for (int i = 0; i < TEST_ADC_CHANNEL; i++) { - adc_gpio_init(ADC_UNIT_1, adc_list[i]); - } - } - if (adc & ADC_UNIT_2) { - for (int i = 0; i < TEST_ADC_CHANNEL; i++) { - adc_gpio_init(ADC_UNIT_2, adc_list[i]); - } - } - vTaskDelay(10 / portTICK_RATE_MS); // To wait stable of IO. -} - -#define DEBUG_CHECK_ENABLE 0 +#define DEBUG_CHECK_ENABLE 1 #define DEBUG_PRINT_ENABLE 1 #define DEBUG_CHECK_ERROR 10 +/** + * Check the ADC-DMA data in linker buffer by input level. + * ideal_level + * - -1: Don't check data. + * - 0: ADC channel voltage is 0v. + * - 1: ADC channel voltage is 3.3v. + * - 2: ADC channel voltage is 1.4v. + */ static esp_err_t adc_dma_data_check(adc_unit_t adc, int ideal_level) { -#if DEBUG_CHECK_ENABLE int unit_old = 1; int ch_cnt = 0; -#endif for (int cnt = 0; cnt < 2; cnt++) { ets_printf("\n[%s] link_buf[%d]: \n", __func__, cnt % 2); for (int i = 0; i < SAR_DMA_DATA_SIZE((adc > 2) ? 2 : 1, SAR_SIMPLE_NUM); i += 2) { @@ -280,19 +240,17 @@ static esp_err_t adc_dma_data_check(adc_unit_t adc, int ideal_level) printf("Data invalid [%d]\n", data->type2.channel); continue; } - int cur_ch = ((ch_cnt++ / 2) % TEST_ADC_CHANNEL); + int cur_ch = ((ch_cnt++ / 2) % adc_test_num); TEST_ASSERT_EQUAL( data->type2.channel, adc_list[cur_ch] ); } - /*Check data channel unit*/ - if (ideal_level == 1) { // high level - TEST_ASSERT_INT_WITHIN( DEBUG_CHECK_ERROR, 0x7FF, data->type2.data ); - } else if (ideal_level == 0) { // low level - TEST_ASSERT_INT_WITHIN( DEBUG_CHECK_ERROR, 0, data->type2.data ); - } else if (ideal_level == 2) { // middle level - TEST_ASSERT_INT_WITHIN( 300, 1100, data->type1.data ); + if (ideal_level == 1) { // high level 3.3v + TEST_ASSERT_EQUAL( 0x7FF, data->type2.data ); + } else if (ideal_level == 0) { // low level 0v + TEST_ASSERT_LESS_THAN( 10, data->type2.data ); + } else if (ideal_level == 2) { // middle level 1.4v + TEST_ASSERT_INT_WITHIN( 128, 1100, data->type2.data ); } else if (ideal_level == 3) { // normal level - } else { - // no check + } else { // no check } #endif } else { //ADC_ENCODE_12BIT @@ -303,21 +261,19 @@ static esp_err_t adc_dma_data_check(adc_unit_t adc, int ideal_level) ets_printf("[%d_%04x] ", data->type1.channel, data->type1.data); #endif #if DEBUG_CHECK_ENABLE - /*Check data channel */ - if (ideal_level == 1) { // high level - TEST_ASSERT_INT_WITHIN( DEBUG_CHECK_ERROR, 0XFFF, data->type1.data ); - } else if (ideal_level == 0) { // low level - TEST_ASSERT_INT_WITHIN( DEBUG_CHECK_ERROR, 0, data->type1.data ); - } else if (ideal_level == 2) { // middle level - TEST_ASSERT_INT_WITHIN( 300, 2200, data->type1.data ); - } else if (ideal_level == 3) { // normal level - } else { - // no check - } if (ideal_level >= 0) { - int cur_ch = ((ch_cnt++) % TEST_ADC_CHANNEL); + int cur_ch = ((ch_cnt++) % adc_test_num); TEST_ASSERT_EQUAL( adc_list[cur_ch], data->type1.channel ); } + if (ideal_level == 1) { // high level 3.3v + TEST_ASSERT_EQUAL( 0XFFF, data->type1.data ); + } else if (ideal_level == 0) { // low level 0v + TEST_ASSERT_LESS_THAN( 10, data->type1.data ); + } else if (ideal_level == 2) { // middle level 1.4v + TEST_ASSERT_INT_WITHIN( 256, 2200, data->type1.data ); + } else if (ideal_level == 3) { // normal level + } else { // no check + } #endif } link_buf[cnt % 2][i] = 0; @@ -330,51 +286,82 @@ static esp_err_t adc_dma_data_check(adc_unit_t adc, int ideal_level) static esp_err_t adc_dma_data_multi_st_check(adc_unit_t adc) { - ESP_LOGI(TAG, "adc IO fake tie low, test ..."); - adc_fake_tie_low(adc); - dma_linker_restart(); - TEST_ESP_OK( adc_digi_start() ); - while (REG_GET_BIT(SPI_DMA_INT_ST_REG(3), SPI_IN_SUC_EOF_INT_ST) == 0) {}; - REG_SET_BIT(SPI_DMA_INT_CLR_REG(3), SPI_IN_SUC_EOF_INT_CLR); - TEST_ESP_OK( adc_digi_stop() ); - if ( adc_dma_data_check(adc, 0) != ESP_OK ) { - return ESP_FAIL; + adc_dma_event_t evt; + + ESP_LOGI(TAG, "adc IO normal, test ..."); + for (int i = 0; i < adc_test_num; i++) { + adc_io_normal(adc, adc_list[i]); } + TEST_ESP_OK( adc_digi_start() ); + while (1) { + TEST_ASSERT_EQUAL( xQueueReceive(que_adc, &evt, SAR_SIMPLE_TIMEOUT_MS / portTICK_RATE_MS), pdTRUE ); + if (evt.int_msk & SPI_IN_SUC_EOF_INT_ENA) { + break; + } + } + TEST_ESP_OK( adc_digi_stop() ); + dma_linker_restart(); + adc_digi_reset(); + TEST_ESP_OK( adc_dma_data_check(adc, -1) ); // Don't check data. ESP_LOGI(TAG, "adc IO fake tie high, test ..."); - adc_fake_tie_high(adc); - dma_linker_restart(); - TEST_ESP_OK( adc_digi_start() ); - while (REG_GET_BIT(SPI_DMA_INT_ST_REG(3), SPI_IN_SUC_EOF_INT_ST) == 0) {}; - REG_SET_BIT(SPI_DMA_INT_CLR_REG(3), SPI_IN_SUC_EOF_INT_CLR); - TEST_ESP_OK( adc_digi_stop() ); - if ( adc_dma_data_check(adc, 1) != ESP_OK ) { - return ESP_FAIL; + for (int i = 0; i < adc_test_num; i++) { + adc_fake_tie_high(adc, adc_list[i]); } + TEST_ESP_OK( adc_digi_start() ); + while (1) { + TEST_ASSERT_EQUAL( xQueueReceive(que_adc, &evt, SAR_SIMPLE_TIMEOUT_MS / portTICK_RATE_MS), pdTRUE ); + if (evt.int_msk & SPI_IN_SUC_EOF_INT_ENA) { + break; + } + } + TEST_ESP_OK( adc_digi_stop() ); + dma_linker_restart(); + adc_digi_reset(); + TEST_ESP_OK( adc_dma_data_check(adc, 1) ); + + ESP_LOGI(TAG, "adc IO fake tie low, test ..."); + for (int i = 0; i < adc_test_num; i++) { + adc_fake_tie_low(adc, adc_list[i]); + } + TEST_ESP_OK( adc_digi_start() ); + while (1) { + TEST_ASSERT_EQUAL( xQueueReceive(que_adc, &evt, SAR_SIMPLE_TIMEOUT_MS / portTICK_RATE_MS), pdTRUE ); + if (evt.int_msk & SPI_IN_SUC_EOF_INT_ENA) { + break; + } + } + TEST_ESP_OK( adc_digi_stop() ); + dma_linker_restart(); + adc_digi_reset(); + TEST_ESP_OK( adc_dma_data_check(adc, 0) ); ESP_LOGI(TAG, "adc IO fake tie middle, test ..."); - adc_fake_tie_middle(adc); - dma_linker_restart(); - TEST_ESP_OK( adc_digi_start() ); - while (REG_GET_BIT(SPI_DMA_INT_ST_REG(3), SPI_IN_SUC_EOF_INT_ST) == 0) {}; - REG_SET_BIT(SPI_DMA_INT_CLR_REG(3), SPI_IN_SUC_EOF_INT_CLR); - TEST_ESP_OK( adc_digi_stop() ); - if ( adc_dma_data_check(adc, 2) != ESP_OK ) { - return ESP_FAIL; + for (int i = 0; i < adc_test_num; i++) { + adc_fake_tie_middle(adc, adc_list[i]); } - - adc_io_normal(adc); + TEST_ESP_OK( adc_digi_start() ); + while (1) { + TEST_ASSERT_EQUAL( xQueueReceive(que_adc, &evt, SAR_SIMPLE_TIMEOUT_MS / portTICK_RATE_MS), pdTRUE ); + if (evt.int_msk & SPI_IN_SUC_EOF_INT_ENA) { + break; + } + } + TEST_ESP_OK( adc_digi_stop() ); + dma_linker_restart(); + adc_digi_reset(); + TEST_ESP_OK( adc_dma_data_check(adc, 2) ); return ESP_OK; } #include "soc/apb_saradc_struct.h" /** - * @brief Test the partten table setting. It's easy wrong. + * Test the partten table setting. It's easy wrong. * * @param adc_n ADC unit. * @param in_partten_len The length of partten be set. - * @param in_partten_len The channel number of the last message. + * @param in_last_ch The channel number of the last message. */ static esp_err_t adc_check_patt_table(adc_unit_t adc, uint32_t in_partten_len, adc_channel_t in_last_ch) { @@ -414,6 +401,12 @@ static esp_err_t adc_check_patt_table(adc_unit_t adc, uint32_t in_partten_len, a return ret; } +/** + * Testcase: Check the base function of ADC-DMA. Include: + * - Various conversion modes. + * - Whether the channel and data are lost. + * - Whether the data is the same as the channel voltage. + */ int test_adc_dig_dma_single_unit(adc_unit_t adc) { ESP_LOGI(TAG, " >> %s << ", __func__); @@ -434,27 +427,27 @@ int test_adc_dig_dma_single_unit(adc_unit_t adc) .conv_limit_num = 0, .interval = TEST_ADC_TRIGGER_INTERVAL_DEFAULT, .dig_clk.use_apll = 0, // APB clk - .dig_clk.div_num = TEST_ADC_DIGI_CLK_DIV_DEFAULT, // 80 MHz / 2 = 40 MHz - .dig_clk.div_b = 1, - .dig_clk.div_a = 1, + .dig_clk.div_num = TEST_ADC_DIGI_CLK_DIV_DEFAULT, + .dig_clk.div_b = 0, + .dig_clk.div_a = 0, .dma_eof_num = SAR_EOF_NUMBER((adc > 2) ? 2 : 1, SAR_SIMPLE_NUM), }; /* Config pattern table */ - adc_digi_pattern_table_t adc1_patt[TEST_ADC_CHANNEL] = {0}; - adc_digi_pattern_table_t adc2_patt[TEST_ADC_CHANNEL] = {0}; + adc_digi_pattern_table_t adc1_patt[SOC_ADC_PATT_LEN_MAX] = {0}; + adc_digi_pattern_table_t adc2_patt[SOC_ADC_PATT_LEN_MAX] = {0}; if (adc & ADC_UNIT_1) { - config.adc1_pattern_len = TEST_ADC_CHANNEL; + config.adc1_pattern_len = adc_test_num; config.adc1_pattern = adc1_patt; - for (int i = 0; i < TEST_ADC_CHANNEL; i++) { + for (int i = 0; i < adc_test_num; i++) { adc1_patt[i].atten = TEST_ADC_ATTEN_DEFAULT; adc1_patt[i].channel = adc_list[i]; adc_gpio_init(ADC_UNIT_1, adc_list[i]); } } if (adc & ADC_UNIT_2) { - config.adc2_pattern_len = TEST_ADC_CHANNEL; + config.adc2_pattern_len = adc_test_num; config.adc2_pattern = adc2_patt; - for (int i = 0; i < TEST_ADC_CHANNEL; i++) { + for (int i = 0; i < adc_test_num; i++) { adc2_patt[i].atten = TEST_ADC_ATTEN_DEFAULT; adc2_patt[i].channel = adc_list[i]; adc_gpio_init(ADC_UNIT_2, adc_list[i]); @@ -475,19 +468,9 @@ int test_adc_dig_dma_single_unit(adc_unit_t adc) } TEST_ESP_OK( adc_digi_controller_config(&config) ); - dma_linker_init(adc, false); - TEST_ESP_OK( adc_check_patt_table(adc, TEST_ADC_CHANNEL, adc_list[TEST_ADC_CHANNEL - 1]) ); - - ESP_LOGI(TAG, "adc IO normal, test ..."); - dma_linker_restart(); - TEST_ESP_OK( adc_digi_start() ); - while (REG_GET_BIT(SPI_DMA_INT_ST_REG(3), SPI_IN_SUC_EOF_INT_ST) == 0) {}; - REG_SET_BIT(SPI_DMA_INT_CLR_REG(3), SPI_IN_SUC_EOF_INT_CLR); - TEST_ESP_OK( adc_digi_stop() ); - if ( adc_dma_data_check(adc, -1) != ESP_OK ) { - return ESP_FAIL; - } + dma_linker_init(adc, false, SPI_IN_SUC_EOF_INT_ENA); + TEST_ESP_OK( adc_check_patt_table(adc, adc_test_num, adc_list[adc_test_num - 1]) ); adc_dma_data_multi_st_check(adc); TEST_ESP_OK( adc_digi_deinit() ); @@ -509,6 +492,7 @@ TEST_CASE("ADC DMA single read", "[ADC]") /** * 0: ADC1 channels raw data debug. * 1: ADC2 channels raw data debug. + * 2: ADC1 one channel raw data debug. */ #define SCOPE_DEBUG_TYPE 0 #define SCOPE_DEBUG_CHANNEL_MAX (10) @@ -516,6 +500,7 @@ TEST_CASE("ADC DMA single read", "[ADC]") #define SCOPE_UART_BUADRATE (256000) #define SCOPE_DEBUG_FREQ_MS (50) #define SCOPE_OUTPUT_UART (0) +static float scope_temp[SCOPE_DEBUG_CHANNEL_MAX] = {0}; // max scope channel is 10. int test_adc_dig_scope_debug_unit(adc_unit_t adc) { @@ -523,41 +508,42 @@ int test_adc_dig_scope_debug_unit(adc_unit_t adc) ESP_LOGI(TAG, " >> adc unit: %x << ", adc); TEST_ESP_OK( adc_digi_init() ); - /* arbiter config */ - adc_arbiter_t arb_cfg = { - .mode = ADC_ARB_MODE_FIX, - .dig_pri = 0, - .pwdet_pri = 2, - .rtc_pri = 1, - }; - TEST_ESP_OK( adc_arbiter_config(ADC_UNIT_2, &arb_cfg) ); // If you want use force - + if (adc & ADC_UNIT_2) { + /* arbiter config */ + adc_arbiter_t arb_cfg = { + .mode = ADC_ARB_MODE_FIX, + .dig_pri = 0, + .pwdet_pri = 2, + .rtc_pri = 1, + }; + TEST_ESP_OK( adc_arbiter_config(ADC_UNIT_2, &arb_cfg) ); // If you want use force + } adc_digi_config_t config = { .conv_limit_en = false, .conv_limit_num = 0, .interval = TEST_ADC_TRIGGER_INTERVAL_DEFAULT, .dig_clk.use_apll = 0, // APB clk - .dig_clk.div_num = TEST_ADC_DIGI_CLK_DIV_DEFAULT, // 80 MHz / 80 = 1 MHz - .dig_clk.div_b = 1, - .dig_clk.div_a = 1, + .dig_clk.div_num = TEST_ADC_DIGI_CLK_DIV_DEFAULT, + .dig_clk.div_a = 0, + .dig_clk.div_b = 0, .dma_eof_num = SAR_EOF_NUMBER((adc > 2) ? 2 : 1, SAR_SIMPLE_NUM), }; /* Config pattern table */ - adc_digi_pattern_table_t adc1_patt[TEST_ADC_CHANNEL] = {0}; - adc_digi_pattern_table_t adc2_patt[TEST_ADC_CHANNEL] = {0}; + adc_digi_pattern_table_t adc1_patt[SOC_ADC_PATT_LEN_MAX] = {0}; + adc_digi_pattern_table_t adc2_patt[SOC_ADC_PATT_LEN_MAX] = {0}; if (adc & ADC_UNIT_1) { - config.adc1_pattern_len = TEST_ADC_CHANNEL; + config.adc1_pattern_len = adc_test_num; config.adc1_pattern = adc1_patt; - for (int i = 0; i < TEST_ADC_CHANNEL; i++) { + for (int i = 0; i < adc_test_num; i++) { adc1_patt[i].atten = TEST_ADC_ATTEN_DEFAULT; adc1_patt[i].channel = adc_list[i]; adc_gpio_init(ADC_UNIT_1, adc_list[i]); } } if (adc & ADC_UNIT_2) { - config.adc2_pattern_len = TEST_ADC_CHANNEL; + config.adc2_pattern_len = adc_test_num; config.adc2_pattern = adc2_patt; - for (int i = 0; i < TEST_ADC_CHANNEL; i++) { + for (int i = 0; i < adc_test_num; i++) { adc2_patt[i].atten = TEST_ADC_ATTEN_DEFAULT; adc2_patt[i].channel = adc_list[i]; adc_gpio_init(ADC_UNIT_2, adc_list[i]); @@ -578,25 +564,22 @@ int test_adc_dig_scope_debug_unit(adc_unit_t adc) } TEST_ESP_OK( adc_digi_controller_config(&config) ); - dma_linker_init(adc, false); - TEST_ESP_OK( adc_check_patt_table(adc, TEST_ADC_CHANNEL, adc_list[TEST_ADC_CHANNEL - 1]) ); + dma_linker_init(adc, false, SPI_IN_DONE_INT_ENA & SPI_IN_SUC_EOF_INT_ENA); ESP_LOGI(TAG, "adc IO fake tie middle, test ..."); - adc_fake_tie_middle(adc); - - TEST_ESP_OK( adc_digi_start() ); + for (int i = 0; i < adc_test_num; i++) { + adc_fake_tie_middle(adc, adc_list[i]); + } return 0; } static void scope_output(int adc_num, int channel, int data) { - static float scope_temp[TEST_ADC_CHANNEL] = {0}; // max scope channel is 10. - static int scope_cnt = 0; /** can replace by uart log.*/ #if SCOPE_OUTPUT_UART - static int i = 0; - if (i++ % 8 == 0) { + static int icnt = 0; + if (icnt++ % 8 == 0) { ets_printf("\n"); } ets_printf("[%d_%d_%04x] ", adc_num, channel, data); @@ -611,16 +594,19 @@ static void scope_output(int adc_num, int channel, int data) return; } #endif + int i; /* adc Read */ - if (adc_num == 0) { - scope_temp[channel] = data; - if (++scope_cnt >= TEST_ADC_CHANNEL) { - scope_cnt = 0; - test_tp_print_to_scope(scope_temp, TEST_ADC_CHANNEL); - vTaskDelay(SCOPE_DEBUG_FREQ_MS / portTICK_RATE_MS); - for (int i=0; i 2) ? 2 : 1, SAR_SIMPLE_NUM); i += 2) { - uint8_t h = link_buf[cnt % 2][i + 1], l = link_buf[cnt % 2][i]; - uint16_t temp = (h << 8 | l); - adc_digi_output_data_t *data = (adc_digi_output_data_t *)&temp; - if (adc > ADC_UNIT_2) { //ADC_ENCODE_11BIT - scope_output(data->type2.unit, data->type2.channel, data->type2.data); - } else { //ADC_ENCODE_12BIT - if (adc == ADC_UNIT_1) { - scope_output(0, data->type1.channel, data->type1.data); - } else if (adc == ADC_UNIT_2) { - scope_output(1, data->type1.channel, data->type1.data); + TEST_ASSERT_EQUAL( xQueueReceive(que_adc, &evt, portMAX_DELAY), pdTRUE ); + if (evt.int_msk & SPI_IN_SUC_EOF_INT_ST) { + TEST_ESP_OK( adc_digi_stop() ); + dma_linker_restart(); + adc_digi_reset(); + for (int cnt = 0; cnt < 2; cnt++) { + ets_printf("cnt%d\n", cnt); + for (int i = 0; i < SAR_DMA_DATA_SIZE((adc > 2) ? 2 : 1, SAR_SIMPLE_NUM); i += 2) { + uint8_t h = link_buf[cnt % 2][i + 1], l = link_buf[cnt % 2][i]; + uint16_t temp = (h << 8 | l); + adc_digi_output_data_t *data = (adc_digi_output_data_t *)&temp; + if (adc > ADC_UNIT_2) { //ADC_ENCODE_11BIT + scope_output(data->type2.unit, data->type2.channel, data->type2.data); + } else { //ADC_ENCODE_12BIT + if (adc == ADC_UNIT_1) { + scope_output(0, data->type1.channel, data->type1.data); + } else if (adc == ADC_UNIT_2) { + scope_output(1, data->type1.channel, data->type1.data); + } } + link_buf[cnt % 2][i] = 0; + link_buf[cnt % 2][i + 1] = 0; } - link_buf[cnt % 2][i] = 0; - link_buf[cnt % 2][i + 1] = 0; } } } diff --git a/components/driver/test/include/test/test_common_adc.h b/components/driver/test/include/test/test_common_adc.h new file mode 100644 index 000000000..cc2fef82d --- /dev/null +++ b/components/driver/test/include/test/test_common_adc.h @@ -0,0 +1,34 @@ +// Copyright 2015-2020 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. + +#pragma once + +#include "driver/adc.h" + +/**@{*/ +/** + * Tie the ADC channel input to the middle (1.4V) by connecting both internal pullup and pulldown. + * + * `tie_middle`: 1.4v; + * `tie_high` : 3.3v; + * `tie_low` : 0v; + * + * @param adc_unit_t ADC unit. + * @param adc_channel_t ADC channel. + */ +void adc_fake_tie_middle(adc_unit_t adc_unit, adc_channel_t channel); +void adc_fake_tie_high(adc_unit_t adc_unit, adc_channel_t channel); +void adc_fake_tie_low(adc_unit_t adc_unit, adc_channel_t channel); +void adc_io_normal(adc_unit_t adc_unit, adc_channel_t channel); +/**@}*/ \ No newline at end of file diff --git a/components/driver/test/test_adc_common.c b/components/driver/test/test_adc_common.c index adc916000..2b7929f55 100644 --- a/components/driver/test/test_adc_common.c +++ b/components/driver/test/test_adc_common.c @@ -61,66 +61,96 @@ static const int adc2_ch[ADC2_TEST_CHANNEL_NUM] = { #define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel]) -static void adc_fake_tie_middle(adc_unit_t adc_unit, adc_channel_t channel) +void adc_fake_tie_middle(adc_unit_t adc_unit, adc_channel_t channel) { gpio_num_t gpio_num = 0; if (adc_unit & ADC_UNIT_1) { gpio_num = ADC_GET_IO_NUM(0, channel); + TEST_ESP_OK(rtc_gpio_init(gpio_num)); + TEST_ESP_OK(rtc_gpio_pullup_en(gpio_num)); + TEST_ESP_OK(rtc_gpio_pulldown_en(gpio_num)); + TEST_ESP_OK(gpio_set_pull_mode(gpio_num, GPIO_PULLUP_PULLDOWN)); + TEST_ESP_OK(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED)); } if (adc_unit & ADC_UNIT_2) { gpio_num = ADC_GET_IO_NUM(1, channel); + TEST_ESP_OK(rtc_gpio_init(gpio_num)); + TEST_ESP_OK(rtc_gpio_pullup_en(gpio_num)); + TEST_ESP_OK(rtc_gpio_pulldown_en(gpio_num)); + TEST_ESP_OK(gpio_set_pull_mode(gpio_num, GPIO_PULLUP_PULLDOWN)); + TEST_ESP_OK(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED)); } - TEST_ESP_OK(rtc_gpio_pullup_en(gpio_num)); - TEST_ESP_OK(rtc_gpio_pulldown_en(gpio_num)); - TEST_ESP_OK(gpio_set_pull_mode(gpio_num, GPIO_PULLUP_PULLDOWN)); - TEST_ESP_OK(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED)); + vTaskDelay(10 / portTICK_RATE_MS); } -static void adc_fake_tie_high(adc_unit_t adc_unit, adc_channel_t channel) +void adc_fake_tie_high(adc_unit_t adc_unit, adc_channel_t channel) { gpio_num_t gpio_num = 0; if (adc_unit & ADC_UNIT_1) { gpio_num = ADC_GET_IO_NUM(0, channel); + TEST_ESP_OK(rtc_gpio_init(gpio_num)); + TEST_ESP_OK(rtc_gpio_pullup_en(gpio_num)); + TEST_ESP_OK(rtc_gpio_pulldown_dis(gpio_num)); + TEST_ESP_OK(gpio_set_pull_mode(gpio_num, GPIO_PULLUP_ONLY)); + TEST_ESP_OK(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_OUTPUT_ONLY)); + TEST_ESP_OK(rtc_gpio_set_level(gpio_num, 1)); } if (adc_unit & ADC_UNIT_2) { gpio_num = ADC_GET_IO_NUM(1, channel); + TEST_ESP_OK(rtc_gpio_init(gpio_num)); + TEST_ESP_OK(rtc_gpio_pullup_en(gpio_num)); + TEST_ESP_OK(rtc_gpio_pulldown_dis(gpio_num)); + TEST_ESP_OK(gpio_set_pull_mode(gpio_num, GPIO_PULLUP_ONLY)); + TEST_ESP_OK(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_OUTPUT_ONLY)); + TEST_ESP_OK(rtc_gpio_set_level(gpio_num, 1)); } - TEST_ESP_OK(rtc_gpio_pullup_en(gpio_num)); - TEST_ESP_OK(rtc_gpio_pulldown_dis(gpio_num)); - TEST_ESP_OK(gpio_set_pull_mode(gpio_num, GPIO_PULLUP_ONLY)); - TEST_ESP_OK(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_OUTPUT_ONLY)); - TEST_ESP_OK(rtc_gpio_set_level(gpio_num, 1)); + vTaskDelay(10 / portTICK_RATE_MS); } -static void adc_fake_tie_low(adc_unit_t adc_unit, adc_channel_t channel) +void adc_fake_tie_low(adc_unit_t adc_unit, adc_channel_t channel) { gpio_num_t gpio_num = 0; if (adc_unit & ADC_UNIT_1) { gpio_num = ADC_GET_IO_NUM(0, channel); + TEST_ESP_OK(rtc_gpio_init(gpio_num)); + TEST_ESP_OK(rtc_gpio_pullup_dis(gpio_num)); + TEST_ESP_OK(rtc_gpio_pulldown_en(gpio_num)); + TEST_ESP_OK(gpio_set_pull_mode(gpio_num, GPIO_PULLDOWN_ONLY)); + TEST_ESP_OK(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_OUTPUT_ONLY)); + TEST_ESP_OK(rtc_gpio_set_level(gpio_num, 0)); } if (adc_unit & ADC_UNIT_2) { gpio_num = ADC_GET_IO_NUM(1, channel); + TEST_ESP_OK(rtc_gpio_init(gpio_num)); + TEST_ESP_OK(rtc_gpio_pullup_dis(gpio_num)); + TEST_ESP_OK(rtc_gpio_pulldown_en(gpio_num)); + TEST_ESP_OK(gpio_set_pull_mode(gpio_num, GPIO_PULLDOWN_ONLY)); + TEST_ESP_OK(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_OUTPUT_ONLY)); + TEST_ESP_OK(rtc_gpio_set_level(gpio_num, 0)); } - TEST_ESP_OK(rtc_gpio_pullup_dis(gpio_num)); - TEST_ESP_OK(rtc_gpio_pulldown_en(gpio_num)); - TEST_ESP_OK(gpio_set_pull_mode(gpio_num, GPIO_PULLDOWN_ONLY)); - TEST_ESP_OK(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_OUTPUT_ONLY)); - TEST_ESP_OK(rtc_gpio_set_level(gpio_num, 0)); + vTaskDelay(10 / portTICK_RATE_MS); } -static void adc_io_normal(adc_unit_t adc_unit, adc_channel_t channel) +void adc_io_normal(adc_unit_t adc_unit, adc_channel_t channel) { gpio_num_t gpio_num = 0; if (adc_unit & ADC_UNIT_1) { gpio_num = ADC_GET_IO_NUM(0, channel); + TEST_ESP_OK(rtc_gpio_init(gpio_num)); + TEST_ESP_OK(rtc_gpio_pullup_dis(gpio_num)); + TEST_ESP_OK(rtc_gpio_pulldown_dis(gpio_num)); + TEST_ESP_OK(gpio_set_pull_mode(gpio_num, GPIO_FLOATING)); + TEST_ESP_OK(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED)); } if (adc_unit & ADC_UNIT_2) { gpio_num = ADC_GET_IO_NUM(1, channel); + TEST_ESP_OK(rtc_gpio_init(gpio_num)); + TEST_ESP_OK(rtc_gpio_pullup_dis(gpio_num)); + TEST_ESP_OK(rtc_gpio_pulldown_dis(gpio_num)); + TEST_ESP_OK(gpio_set_pull_mode(gpio_num, GPIO_FLOATING)); + TEST_ESP_OK(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED)); } - TEST_ESP_OK(rtc_gpio_pullup_dis(gpio_num)); - TEST_ESP_OK(rtc_gpio_pulldown_dis(gpio_num)); - TEST_ESP_OK(gpio_set_pull_mode(gpio_num, GPIO_FLOATING)); - TEST_ESP_OK(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED)); + vTaskDelay(10 / portTICK_RATE_MS); } TEST_CASE("ADC1 rtc read", "[adc1]") diff --git a/components/soc/include/hal/adc_hal.h b/components/soc/include/hal/adc_hal.h index a243ad1ae..621b23d13 100644 --- a/components/soc/include/hal/adc_hal.h +++ b/components/soc/include/hal/adc_hal.h @@ -17,13 +17,12 @@ void adc_hal_init(void); void adc_hal_deinit(void); /** - * Set adc sample cycle for digital controller. + * Set adc sample cycle. * * @note Normally, please use default value. - * @param sample_cycle Cycles between DIG ADC controller start ADC sensor and beginning to receive data from sensor. - * Range: 2 ~ 0xFF. + * @param sample_cycle The number of ADC sampling cycles. Range: 1 ~ 7. */ -#define adc_hal_digi_set_sample_cycle(sample_cycle) adc_ll_digi_set_sample_cycle(sample_cycle) +#define adc_hal_set_sample_cycle(sample_cycle) adc_ll_set_sample_cycle(sample_cycle) /** * Set ADC module power management. diff --git a/components/soc/include/hal/adc_types.h b/components/soc/include/hal/adc_types.h index f40836ad4..1305d276c 100644 --- a/components/soc/include/hal/adc_types.h +++ b/components/soc/include/hal/adc_types.h @@ -13,7 +13,7 @@ typedef enum { ADC_UNIT_1 = 1, /*!< SAR ADC 1. */ ADC_UNIT_2 = 2, /*!< SAR ADC 2. */ ADC_UNIT_BOTH = 3, /*!< SAR ADC 1 and 2. */ - ADC_UNIT_ALTER = 7, /*!< SAR ADC 1 and 2 alternative mode, not supported yet */ + ADC_UNIT_ALTER = 7, /*!< SAR ADC 1 and 2 alternative mode. */ ADC_UNIT_MAX, } adc_unit_t; @@ -75,29 +75,58 @@ typedef enum { ADC_WIDTH_MAX, } adc_bits_width_t; +/** + * @brief ADC digital controller (DMA mode) output data format option. + */ +typedef enum { + ADC_DIGI_FORMAT_12BIT, /*! ADC_CHANNEL_MAX), The data is invalid. */ + } type1; /*! ADC_CHANNEL_MAX), The data is invalid. */ + uint16_t unit: 1; /*! ADC_CHANNEL_MAX), The data is invalid. */ - } type1; /*! ADC_CHANNEL_MAX), The data is invalid. */ - uint16_t unit: 1; /*! (touch threshold + hysteresis), the touch channel be touched. If (raw data - baseline) < (touch threshold - hysteresis), the touch channel be released. - Range: 0 ~ 3. The coefficient is 0: 4/32; 1: 3/32; 2: 2/32; 3: OFF */ + Range: 0 ~ 3. The coefficient is 0: 4/32; 1: 3/32; 2: 1/32; 3: OFF */ uint32_t noise_thr; /*! (noise), the baseline stop updating. If (raw data - baseline) < (noise), the baseline start updating. diff --git a/components/soc/soc/esp32s2/include/soc/adc_caps.h b/components/soc/soc/esp32s2/include/soc/adc_caps.h index ad7325333..a29892d28 100644 --- a/components/soc/soc/esp32s2/include/soc/adc_caps.h +++ b/components/soc/soc/esp32s2/include/soc/adc_caps.h @@ -14,7 +14,7 @@ #define SOC_ADC_FSM_RSTB_WAIT_DEFAULT (8) #define SOC_ADC_FSM_START_WAIT_DEFAULT (5) #define SOC_ADC_FSM_STANDBY_WAIT_DEFAULT (100) -#define ADC_FSM_SAMPLE_CYCLE_DEFAULT (2) +#define ADC_FSM_SAMPLE_CYCLE_DEFAULT (3) /** * Check if adc support digital controller (DMA) mode. diff --git a/components/soc/src/esp32/include/hal/adc_hal.h b/components/soc/src/esp32/include/hal/adc_hal.h index f13fa295b..091c51d25 100644 --- a/components/soc/src/esp32/include/hal/adc_hal.h +++ b/components/soc/src/esp32/include/hal/adc_hal.h @@ -43,7 +43,7 @@ typedef struct { adc_hal_digi_pattern_table_t *adc1_pattern; /*! RTC > Digital; * - * @param config Refer to `adc_arbiter_t`. + * @param config Refer to ``adc_arbiter_t``. */ void adc_hal_arbiter_config(adc_arbiter_t *config) { diff --git a/components/soc/src/esp32s2/include/hal/adc_hal.h b/components/soc/src/esp32s2/include/hal/adc_hal.h index 76ab02ea0..a533ec18c 100644 --- a/components/soc/src/esp32s2/include/hal/adc_hal.h +++ b/components/soc/src/esp32s2/include/hal/adc_hal.h @@ -61,6 +61,7 @@ void adc_hal_digi_controller_config(const adc_digi_config_t *cfg); /** * Sets the number of interval clock cycles for the digital controller to trigger the measurement. + * Expression: `trigger_meas_freq` = `controller_clk` / 2 / interval. Refer to ``adc_digi_clk_t``. * * @note The trigger interval should not be less than the sampling time of the SAR ADC. * @param cycle The number of clock cycles for the trigger interval. The unit is the divided clock. Range: 40 ~ 4095. @@ -80,9 +81,9 @@ void adc_hal_digi_disable(void); /** * Set ADC digital controller clock division factor. The clock divided from `APLL` or `APB` clock. * Enable clock and select clock source for ADC digital controller. - * Expression: controller_clk = APLL/APB * (div_num + div_b / div_a). + * Expression: controller_clk = (`APLL` or `APB`) / (div_num + div_a / div_b + 1). * - * @param clk Refer to `adc_digi_clk_t`. + * @param clk Refer to ``adc_digi_clk_t``. */ void adc_hal_digi_clk_config(const adc_digi_clk_t *clk); @@ -133,7 +134,7 @@ void adc_hal_digi_clk_config(const adc_digi_clk_t *clk); * * @note The monitor will monitor all the enabled channel data of the each ADC unit at the same time. * @param adc_n ADC unit. - * @param config Refer to `adc_digi_monitor_t`. + * @param config Refer to ``adc_digi_monitor_t``. */ void adc_hal_digi_monitor_config(adc_ll_num_t adc_n, adc_digi_monitor_t *config); @@ -223,7 +224,7 @@ void adc_hal_digi_monitor_config(adc_ll_num_t adc_n, adc_digi_monitor_t *config) * @note The arbiter's working clock is APB_CLK. When the APB_CLK clock drops below 8 MHz, the arbiter must be in shield mode. * @note Default priority: Wi-Fi > RTC > Digital; * - * @param config Refer to `adc_arbiter_t`. + * @param config Refer to ``adc_arbiter_t``. */ void adc_hal_arbiter_config(adc_arbiter_t *config); diff --git a/components/soc/src/esp32s2/include/hal/adc_ll.h b/components/soc/src/esp32s2/include/hal/adc_ll.h index bfff6daeb..3eaadfb8c 100644 --- a/components/soc/src/esp32s2/include/hal/adc_ll.h +++ b/components/soc/src/esp32s2/include/hal/adc_ll.h @@ -1,11 +1,13 @@ #pragma once +#include #include "soc/adc_periph.h" #include "hal/adc_types.h" #include "soc/apb_saradc_struct.h" #include "soc/apb_saradc_reg.h" #include "soc/rtc_cntl_struct.h" -#include +#include "soc/rtc_cntl_reg.h" +#include "i2c_rtc_clk.h" #ifdef __cplusplus extern "C" { @@ -51,7 +53,7 @@ typedef struct { /** * @brief ADC controller type selection. - * + * * @note For ADC2, use the force option with care. The system power consumption detection will use ADC2. * If it is forced to switch to another controller, it may cause the system to obtain incorrect values. * @note Normally, there is no need to switch the controller manually. @@ -67,6 +69,49 @@ typedef enum { ADC2_CTRL_FORCE_DIG = 6, /*!> 8; uint8_t lsb = param & 0xFF; - /* Enable i2s_write_reg function. */ + /* Should be called before writing I2C registers. */ void phy_get_romfunc_addr(void); phy_get_romfunc_addr(); SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_FORCE_PU_M); CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, BIT(18)); - SET_PERI_REG_MASK(ANA_CONFIG2_REG, BIT(16)); + SET_PERI_REG_MASK(ADC_LL_ANA_CONFIG2_REG, BIT(16)); if (adc_n == ADC_NUM_1) { - I2C_WRITEREG_MASK_RTC(I2C_ADC, SAR1_INITIAL_CODE_HIGH_ADDR, msb); - I2C_WRITEREG_MASK_RTC(I2C_ADC, SAR1_INITIAL_CODE_LOW_ADDR, lsb); + I2C_WRITEREG_MASK_RTC(ADC_LL_I2C_ADC, ADC_LL_SAR1_INITIAL_CODE_HIGH_ADDR, msb); + I2C_WRITEREG_MASK_RTC(ADC_LL_I2C_ADC, ADC_LL_SAR1_INITIAL_CODE_LOW_ADDR, lsb); } else { - I2C_WRITEREG_MASK_RTC(I2C_ADC, SAR2_INITIAL_CODE_HIGH_ADDR, msb); - I2C_WRITEREG_MASK_RTC(I2C_ADC, SAR2_INITIAL_CODE_LOW_ADDR, lsb); + I2C_WRITEREG_MASK_RTC(ADC_LL_I2C_ADC, ADC_LL_SAR2_INITIAL_CODE_HIGH_ADDR, msb); + I2C_WRITEREG_MASK_RTC(ADC_LL_I2C_ADC, ADC_LL_SAR2_INITIAL_CODE_LOW_ADDR, lsb); } } /* Temp code end. */ diff --git a/components/soc/src/esp32s2/include/hal/touch_sensor_hal.h b/components/soc/src/esp32s2/include/hal/touch_sensor_hal.h index 5aab11106..d0aaff522 100644 --- a/components/soc/src/esp32s2/include/hal/touch_sensor_hal.h +++ b/components/soc/src/esp32s2/include/hal/touch_sensor_hal.h @@ -202,14 +202,14 @@ void touch_hal_filter_get_config(touch_filter_config_t *filter_info); * Set filter mode. The input to the filter is raw data and the output is the baseline value. * Larger filter coefficients increase the stability of the baseline. * - * @param mode Filter mode type. Refer to `touch_filter_mode_t`. + * @param mode Filter mode type. Refer to ``touch_filter_mode_t``. */ #define touch_hal_filter_set_filter_mode(mode) touch_ll_filter_set_filter_mode(mode) /** * Get filter mode. The input to the filter is raw data and the output is the baseline value. * - * @param mode Filter mode type. Refer to `touch_filter_mode_t`. + * @param mode Filter mode type. Refer to ``touch_filter_mode_t``. */ #define touch_hal_filter_get_filter_mode(mode) touch_ll_filter_get_filter_mode(mode) @@ -566,7 +566,7 @@ void touch_hal_sleep_channel_get_config(touch_pad_sleep_channel_t *slp_config); * After the sleep channel is configured, users should query the channel reading using a specific function. * * @note ESP32S2 only support one channel to be set sleep channel. - * + * * @param pad_num touch sleep pad number. * @param enable Enable/disable sleep pad function. */ diff --git a/components/soc/src/esp32s2/include/hal/touch_sensor_ll.h b/components/soc/src/esp32s2/include/hal/touch_sensor_ll.h index 992066c5a..2d59dfe00 100644 --- a/components/soc/src/esp32s2/include/hal/touch_sensor_ll.h +++ b/components/soc/src/esp32s2/include/hal/touch_sensor_ll.h @@ -669,7 +669,7 @@ static inline void touch_ll_filter_reset_baseline(touch_pad_t touch_num) * Set filter mode. The input to the filter is raw data and the output is the baseline value. * Larger filter coefficients increase the stability of the baseline. * - * @param mode Filter mode type. Refer to `touch_filter_mode_t`. + * @param mode Filter mode type. Refer to ``touch_filter_mode_t``. */ static inline void touch_ll_filter_set_filter_mode(touch_filter_mode_t mode) { @@ -679,7 +679,7 @@ static inline void touch_ll_filter_set_filter_mode(touch_filter_mode_t mode) /** * Get filter mode. The input to the filter is raw data and the output is the baseline value. * - * @param mode Filter mode type. Refer to `touch_filter_mode_t`. + * @param mode Filter mode type. Refer to ``touch_filter_mode_t``. */ static inline void touch_ll_filter_get_filter_mode(touch_filter_mode_t *mode) { @@ -690,7 +690,7 @@ static inline void touch_ll_filter_get_filter_mode(touch_filter_mode_t *mode) * Set filter mode. The input to the filter is raw data and the output is the smooth data. * The smooth data is used to determine the touch status. * - * @param mode Filter mode type. Refer to `touch_smooth_mode_t`. + * @param mode Filter mode type. Refer to ``touch_smooth_mode_t``. */ static inline void touch_ll_filter_set_smooth_mode(touch_smooth_mode_t mode) { @@ -700,7 +700,7 @@ static inline void touch_ll_filter_set_smooth_mode(touch_smooth_mode_t mode) /** * Get filter mode. The smooth data is used to determine the touch status. * - * @param mode Filter mode type. Refer to `touch_smooth_mode_t`. + * @param mode Filter mode type. Refer to ``touch_smooth_mode_t``. */ static inline void touch_ll_filter_get_smooth_mode(touch_smooth_mode_t *mode) { diff --git a/components/soc/src/hal/adc_hal.c b/components/soc/src/hal/adc_hal.c index baaf37007..f1d08100d 100644 --- a/components/soc/src/hal/adc_hal.c +++ b/components/soc/src/hal/adc_hal.c @@ -19,7 +19,7 @@ void adc_hal_init(void) // Set internal FSM wait time, fixed value. adc_ll_digi_set_fsm_time(SOC_ADC_FSM_RSTB_WAIT_DEFAULT, SOC_ADC_FSM_START_WAIT_DEFAULT, SOC_ADC_FSM_STANDBY_WAIT_DEFAULT); - adc_ll_digi_set_sample_cycle(ADC_FSM_SAMPLE_CYCLE_DEFAULT); + adc_ll_set_sample_cycle(ADC_FSM_SAMPLE_CYCLE_DEFAULT); adc_hal_pwdet_set_cct(SOC_ADC_PWDET_CCT_DEFAULT); adc_ll_digi_output_invert(ADC_NUM_1, SOC_ADC_DIGI_DATA_INVERT_DEFAULT(ADC_NUM_1)); adc_ll_digi_output_invert(ADC_NUM_2, SOC_ADC_DIGI_DATA_INVERT_DEFAULT(ADC_NUM_2)); diff --git a/docs/en/api-reference/peripherals/adc.rst b/docs/en/api-reference/peripherals/adc.rst index 6d7d8f33d..12b19b93d 100644 --- a/docs/en/api-reference/peripherals/adc.rst +++ b/docs/en/api-reference/peripherals/adc.rst @@ -22,15 +22,20 @@ Overview .. only:: esp32s2 - The {IDF_TARGET_NAME} integrates two 12-bit SAR (`Successive Approximation Register `_) ADCs supporting a total of 20 measurement channels (analog enabled pins). + The {IDF_TARGET_NAME} integrates two 13-bit SAR (`Successive Approximation Register `_) ADCs supporting a total of 20 measurement channels (analog enabled pins). The ADC driver API supports ADC1 (10 channels, attached to GPIOs 1 - 10), and ADC2 (10 channels, attached to GPIOs 11 - 20). However, the usage of ADC2 has some restrictions for the application: - 1. ADC2 is used by the Wi-Fi driver. Therefore the application can only use ADC2 when the Wi-Fi driver has not started. + 1. Different from ADC1, the hardware arbiter function is added to ADC2, so when using the API of ADC2 to obtain the sampling voltage, you need to judge whether the result is successfully arbitrated. Configuration and Reading ADC ----------------------------- +Each ADC unit supports two work modes, ADC-RTC or ADC-DMA mode. ADC-RTC is controlled by the RTC controller and is suitable for low-frequency sampling operations. ADC-DMA is controlled by a digital controller and is suitable for high-frequency continuous sampling actions. + +ADC-RTC mode +^^^^^^^^^^^^ + The ADC should be configured before reading is taken. - For ADC1, configure desired precision and attenuation by calling functions :cpp:func:`adc1_config_width` and :cpp:func:`adc1_config_channel_atten`. @@ -50,6 +55,11 @@ This API provides convenient way to configure ADC1 for reading from :doc:`ULP <. There is another specific function :cpp:func:`adc2_vref_to_gpio` used to route internal reference voltage to a GPIO pin. It comes handy to calibrate ADC reading and this is discussed in section :ref:`adc-api-adc-calibration`. +.. todo:: + + 1. Add `ADC-DMA mode` configuration after ADC-DMA driver done. + 2. Add table for ADC-DMA clock system. + Application Examples -------------------- @@ -97,8 +107,13 @@ An example using the ADC2 driver to read the output of DAC is available in esp-i int val = hall_sensor_read(); +.. only:: esp32 -The value read in both these examples is 12 bits wide (range 0-4095). + The value read in both these examples is 12 bits wide (range 0-4095). + +.. only:: esp32s2 + + The value read in both these examples is 13 bits wide (range 0-8191). .. _adc-api-adc-calibration: @@ -248,6 +263,8 @@ ADC driver .. include-build-file:: inc/adc_types.inc +.. include-build-file:: inc/adc_common.inc + .. _adc-api-reference-adc-calibration: ADC Calibration