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.

This commit is contained in:
fuzhibo 2020-04-08 21:56:14 +08:00
parent ea78d06939
commit d90e0e4345
18 changed files with 572 additions and 486 deletions

View file

@ -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);

View file

@ -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)

View file

@ -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<TEST_ADC_CHANNEL; i++) {
scope_temp[i] = 0;
}
for (i = 0; i < adc_test_num; i++) {
if (adc_list[i] == channel && scope_temp[i] == 0) {
scope_temp[i] = data;
break;
}
}
if (i == adc_test_num) {
test_tp_print_to_scope(scope_temp, adc_test_num);
vTaskDelay(SCOPE_DEBUG_FREQ_MS / portTICK_RATE_MS);
for (int i = 0; i < adc_test_num; i++) {
scope_temp[i] = 0;
}
}
}
@ -634,34 +620,35 @@ static void scope_output(int adc_num, int channel, int data)
*/
TEST_CASE("test_adc_digi_slope_debug", "[adc_dma][ignore]")
{
adc_dma_event_t evt;
test_tp_scope_debug_init(0, -1, -1, SCOPE_UART_BUADRATE);
adc_unit_t adc = ADC_UNIT_1;
adc_unit_t adc = ADC_CONV_BOTH_UNIT;
test_adc_dig_scope_debug_unit(adc);
while (1) {
REG_SET_BIT(SPI_DMA_INT_CLR_REG(3), SPI_IN_SUC_EOF_INT_CLR);
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) {};
TEST_ESP_OK( adc_digi_stop() );
for (int cnt = 0; cnt < 2; 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);
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;
}
}
}

View file

@ -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);
/**@}*/

View file

@ -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]")

View file

@ -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.

View file

@ -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 to DMA data format, [15:12]-channel, [11: 0]-12 bits ADC data (`adc_digi_output_data_t`).
Note: In single convert mode. */
ADC_DIGI_FORMAT_11BIT, /*!<ADC to DMA data format, [15]-adc unit, [14:11]-channel, [10: 0]-11 bits ADC data (`adc_digi_output_data_t`).
Note: In multi or alter convert mode. */
ADC_DIGI_FORMAT_MAX,
} adc_digi_output_format_t;
/**
* @brief ADC digital controller (DMA mode) output data format.
* Used to analyze the acquired ADC (DMA) data.
*
* @note ESP32S2:
* Member `channel` can be used to judge the validity of the ADC data, because the role of the arbiter may get invalid ADC data.
*/
typedef struct {
union {
struct {
uint16_t data: 12; /*!<ADC real output data info. Resolution: 12 bit. */
uint16_t channel: 4; /*!<ADC channel index info. For ESP32S2:
If (channel < ADC_CHANNEL_MAX), The data is valid.
If (channel > ADC_CHANNEL_MAX), The data is invalid. */
} type1; /*!<When the configured output format is 12bit. `ADC_DIGI_FORMAT_12BIT` */
struct {
uint16_t data: 11; /*!<ADC real output data info. Resolution: 11 bit. */
uint16_t channel: 4; /*!<ADC channel index info. For ESP32S2:
If (channel < ADC_CHANNEL_MAX), The data is valid.
If (channel > ADC_CHANNEL_MAX), The data is invalid. */
uint16_t unit: 1; /*!<ADC unit index info. 0: ADC1; 1: ADC2. */
} type2; /*!<When the configured output format is 11bit. `ADC_DIGI_FORMAT_11BIT` */
uint16_t val;
};
} adc_digi_output_data_t;
#ifdef CONFIG_IDF_TARGET_ESP32S2
/**
* @brief ADC digital controller (DMA mode) clock system setting.
* Expression: controller_clk = (`APLL` or `APB`) * (div_num + div_b / div_a).
* Expression: controller_clk = (`APLL` or `APB`) / (div_num + div_a / div_b + 1).
*/
typedef struct {
bool use_apll; /*!<true: use APLL clock; false: use APB clock. */
uint32_t div_num; /*!<Division factor. Range: 1 ~ 255. */
uint32_t div_num; /*!<Division factor. Range: 0 ~ 255.
Note: When a higher frequency clock is used (the division factor is less than 9),
the ADC reading value will be slightly offset. */
uint32_t div_b; /*!<Division factor. Range: 1 ~ 63. */
uint32_t div_a; /*!<Division factor. Range: 1 ~ 63. */
uint32_t div_a; /*!<Division factor. Range: 0 ~ 63. */
} adc_digi_clk_t;
/**
* @brief ADC digital controller (DMA mode) clock system default setting.
*/
#define ADC_DIGITAL_CLK_DEFAULT() { \
.use_apll = 0, \
.div_num = 40, \
.div_b = 1, \
.div_a = 1, \
}
/**
* @brief ADC arbiter work mode option.
*
@ -116,7 +145,7 @@ typedef enum {
* @note ESP32S2: Only ADC2 support arbiter.
*/
typedef struct {
adc_arbiter_mode_t mode; /*!<Refer to `adc_arbiter_mode_t`. Note: only support ADC2. */
adc_arbiter_mode_t mode; /*!<Refer to ``adc_arbiter_mode_t``. Note: only support ADC2. */
uint8_t rtc_pri; /*!<RTC controller priority. Range: 0 ~ 2. */
uint8_t dig_pri; /*!<Digital controller priority. Range: 0 ~ 2. */
uint8_t pwdet_pri; /*!<Wi-Fi controller priority. Range: 0 ~ 2. */
@ -137,7 +166,11 @@ typedef struct {
/**
* @brief ADC digital controller (DMA mode) work mode.
*
* @note Member `channel` can be used to judge the validity of the ADC data, because the role of the arbiter may get invalid ADC data.
* @note The conversion mode affects the sampling frequency:
* SINGLE_UNIT_1: When the measurement is triggered, only ADC1 is sampled once.
* SINGLE_UNIT_2: When the measurement is triggered, only ADC2 is sampled once.
* BOTH_UNIT : When the measurement is triggered, ADC1 and ADC2 are sampled at the same time.
* ALTER_UNIT : When the measurement is triggered, ADC1 or ADC2 samples alternately.
*/
typedef enum {
ADC_CONV_SINGLE_UNIT_1 = 1, /*!< SAR ADC 1. */
@ -147,42 +180,6 @@ typedef enum {
ADC_CONV_UNIT_MAX,
} adc_digi_convert_mode_t;
/**
* @brief ADC digital controller (DMA mode) output data format option.
*/
typedef enum {
ADC_DIGI_FORMAT_12BIT, /*!<ADC to DMA data format, [15:12]-channel, [11: 0]-12 bits ADC data (`adc_digi_output_data_t`).
Note: In single convert mode. */
ADC_DIGI_FORMAT_11BIT, /*!<ADC to DMA data format, [15]-adc unit, [14:11]-channel, [10: 0]-11 bits ADC data (`adc_digi_output_data_t`).
Note: In multi or alter convert mode. */
ADC_DIGI_FORMAT_MAX,
} adc_digi_output_format_t;
/**
* @brief ADC digital controller (DMA mode) output data format.
* Used to analyze the acquired ADC (DMA) data.
*
* @note Member `channel` can be used to judge the validity of the ADC data, because the role of the arbiter may get invalid ADC data.
*/
typedef struct {
union {
struct {
uint16_t data: 12; /*!<ADC real output data info. Resolution: 12 bit. */
uint16_t channel: 4; /*!<ADC channel index info.
If (channel < ADC_CHANNEL_MAX), The data is valid.
If (channel > ADC_CHANNEL_MAX), The data is invalid. */
} type1; /*!<When the configured output format is 12bit. `ADC_DIGI_FORMAT_12BIT` */
struct {
uint16_t data: 11; /*!<ADC real output data info. Resolution: 11 bit. */
uint16_t channel: 4; /*!<ADC channel index info.
If (channel < ADC_CHANNEL_MAX), The data is valid.
If (channel > ADC_CHANNEL_MAX), The data is invalid. */
uint16_t unit: 1; /*!<ADC unit index info. 0: ADC1; 1: ADC2. */
} type2; /*!<When the configured output format is 11bit. `ADC_DIGI_FORMAT_11BIT` */
uint16_t val;
};
} adc_digi_output_data_t;
/**
* @brief ADC digital controller (DMA mode) conversion rules setting.
*/
@ -212,26 +209,54 @@ typedef enum {
/**
* @brief ADC digital controller (DMA mode) configuration parameters.
*
* Example setting: Use ADC1 channel0 to measure voltage, the sampling rate is required to be 1KHz:
* +---------------------+--------+--------+--------+
* | sample rate | 1KHz | 1KHz | 1KHz |
* +---------------------+--------+--------+--------+
* | conv_mode | single | both | alter |
* | adc1_pattern_len | 1 | 1 | 1 |
* | dig_clk.use_apll | 0 | 0 | 0 |
* | dig_clk.div_num | 99 | 99 | 99 |
* | dig_clk.div_b | 0 | 0 | 0 |
* | dig_clk.div_a | 0 | 0 | 0 |
* | interval | 400 | 400 | 200 |
* +---------------------+--------+--------+--------+
* | `trigger_meas_freq` | 1KHz | 1KHz | 2KHz |
* +---------------------+--------+--------+--------+
*
* Explain the relationship between `conv_limit_num`, `dma_eof_num` and the number of DMA output:
* +---------------------+--------+--------+--------+
* | conv_mode | single | both | alter |
* +---------------------+--------+--------+--------+
* | trigger meas times | 1 | 1 | 1 |
* +---------------------+--------+--------+--------+
* | conv_limit_num | +1 | +1 | +1 |
* | dma_eof_num | +1 | +2 | +1 |
* | dma output (byte) | +2 | +4 | +2 |
* +---------------------+--------+--------+--------+
*/
typedef struct {
bool conv_limit_en; /*!<Enable max conversion number detection for digital controller.
If the number of ADC conversion is equal to the `limit_num`, the conversion is stopped. */
uint32_t conv_limit_num; /*!<ADC max conversion number for digital controller. */
uint32_t adc1_pattern_len; /*!<Pattern table length for digital controller. Range: 0 ~ 16.
bool conv_limit_en; /*!<Enable the function of limiting ADC conversion times.
If the number of ADC conversion trigger count is equal to the `limit_num`, the conversion is stopped. */
uint32_t conv_limit_num; /*!<Set the upper limit of the number of ADC conversion triggers. Range: 1 ~ 255. */
uint32_t adc1_pattern_len; /*!<Pattern table length for digital controller. Range: 0 ~ 16 (0: Don't change the pattern table setting).
The pattern table that defines the conversion rules for each SAR ADC. Each table has 16 items, in which channel selection,
resolution and attenuation are stored. When the conversion is started, the controller reads conversion rules from the
pattern table one by one. For each controller the scan sequence has at most 16 different rules before repeating itself. */
uint32_t adc2_pattern_len; /*!<Refer to `adc1_pattern_len` */
uint32_t adc2_pattern_len; /*!<Refer to ``adc1_pattern_len`` */
adc_digi_pattern_table_t *adc1_pattern; /*!<Pointer to pattern table for digital controller. The table size defined by `adc1_pattern_len`. */
adc_digi_pattern_table_t *adc2_pattern; /*!<Refer to `adc1_pattern` */
adc_digi_convert_mode_t conv_mode; /*!<ADC conversion mode for digital controller. */
adc_digi_output_format_t format; /*!<ADC output data format for digital controller. */
adc_digi_pattern_table_t *adc2_pattern; /*!<Refer to ``adc1_pattern`` */
adc_digi_convert_mode_t conv_mode; /*!<ADC conversion mode for digital controller. See ``adc_digi_convert_mode_t``. */
adc_digi_output_format_t format; /*!<ADC output data format for digital controller. See ``adc_digi_output_format_t``. */
uint32_t interval; /*!<The number of interval clock cycles for the digital controller to trigger the measurement.
The unit is the divided clock. Range: 40 ~ 4095. */
adc_digi_clk_t dig_clk; /*!<Refer to `adc_digi_clk_t` */
The unit is the divided clock. Range: 40 ~ 4095.
Expression: `trigger_meas_freq` = `controller_clk` / 2 / interval. Refer to ``adc_digi_clk_t``.
Note: The sampling rate of each channel is also related to the conversion mode (See ``adc_digi_convert_mode_t``) and pattern table settings. */
adc_digi_clk_t dig_clk; /*!<ADC digital controller clock divider settings. Refer to ``adc_digi_clk_t`` */
uint32_t dma_eof_num; /*!<DMA eof num of adc digital controller.
If the number of measurements reaches `dma_eof_num`,
then `dma_in_suc_eof` signal is generated. */
If the number of measurements reaches `dma_eof_num`, then `dma_in_suc_eof` signal is generated in DMA.
Note: The converted data in the DMA in link buffer will be multiple of two bytes. */
} adc_digi_config_t;
/**

View file

@ -265,7 +265,7 @@ typedef struct touch_filter_config {
uint32_t hysteresis_thr; /*!<Hysteresis threshold coefficient. hysteresis = hysteresis coefficient * touch threshold.
If (raw data - baseline) > (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 threshold coefficient. noise = noise coefficient * touch threshold.
If (raw data - baseline) > (noise), the baseline stop updating.
If (raw data - baseline) < (noise), the baseline start updating.

View file

@ -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.

View file

@ -43,7 +43,7 @@ typedef struct {
adc_hal_digi_pattern_table_t *adc1_pattern; /*!<Pointer to pattern table for digital controller. The table size defined by `adc1_pattern_len`. */
adc_hal_digi_pattern_table_t *adc2_pattern; /*!<Refer to `adc1_pattern` */
adc_hal_digi_convert_mode_t conv_mode; /*!<ADC conversion mode for digital controller. ESP32 only support ADC1 single mode. */
adc_hal_digi_output_format_t format; /*!<ADC output data format for digital controller. */
adc_digi_output_format_t format; /*!<ADC output data format for digital controller. */
uint32_t clk_div; /*!< ADC module clock division factor. ADC clock divided from APB clock.*/
} adc_hal_digi_config_t;

View file

@ -8,14 +8,6 @@
extern "C" {
#endif
typedef enum {
ADC_DIGI_FORMAT_12BIT, /*!< ADC to I2S data format, [15:12]-channel [11:0]-12 bits ADC data.
Note: In single convert mode. */
ADC_DIGI_FORMAT_11BIT, /*!< ADC to I2S data format, [15]-adc unit [14:11]-channel [10:0]-11 bits ADC data.
Note: In multi convert mode. */
ADC_DIGI_FORMAT_MAX,
} adc_hal_digi_output_format_t;
typedef enum {
ADC_CONV_SINGLE_UNIT_1 = 1, /*!< SAR ADC 1*/
ADC_CONV_SINGLE_UNIT_2 = 2, /*!< SAR ADC 2, not supported yet*/
@ -94,13 +86,12 @@ static inline void adc_ll_digi_set_fsm_time(uint32_t rst_wait, uint32_t start_wa
}
/**
* 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.
*/
static inline void adc_ll_digi_set_sample_cycle(uint32_t sample_cycle)
static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle)
{
SYSCON.saradc_fsm.sample_cycle = sample_cycle;
}
@ -119,9 +110,9 @@ static inline void adc_ll_digi_set_clk_div(uint32_t div)
/**
* Set adc output data format for digital controller.
*
* @param format Output data format, see ``adc_hal_digi_output_format_t``.
* @param format Output data format, see ``adc_digi_output_format_t``.
*/
static inline void adc_ll_digi_set_output_format(adc_hal_digi_output_format_t format)
static inline void adc_ll_digi_set_output_format(adc_digi_output_format_t format)
{
SYSCON.saradc_ctrl.data_sar_sel = format;
}

View file

@ -94,9 +94,9 @@ void adc_hal_digi_controller_config(const adc_digi_config_t *cfg)
/**
* 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)
{
@ -127,7 +127,7 @@ void adc_hal_digi_disable(void)
*
* @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)
{
@ -148,7 +148,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)
{

View file

@ -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);

View file

@ -1,11 +1,13 @@
#pragma once
#include <stdbool.h>
#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 <stdbool.h>
#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, /*!<For ADC2. Arbiter in shield mode. Force select digital controller work. */
} adc_controller_t;
/* ADC calibration defines. */
#define ADC_LL_I2C_ADC 0X69
#define ADC_LL_I2C_ADC_HOSTID 0
#define ADC_LL_ANA_CONFIG2_REG 0x6000E048
#define ADC_LL_SAR1_ENCAL_GND_ADDR 0x7
#define ADC_LL_SAR1_ENCAL_GND_ADDR_MSB 5
#define ADC_LL_SAR1_ENCAL_GND_ADDR_LSB 5
#define ADC_LL_SAR2_ENCAL_GND_ADDR 0x7
#define ADC_LL_SAR2_ENCAL_GND_ADDR_MSB 7
#define ADC_LL_SAR2_ENCAL_GND_ADDR_LSB 7
#define ADC_LL_SAR1_INITIAL_CODE_HIGH_ADDR 0x1
#define ADC_LL_SAR1_INITIAL_CODE_HIGH_ADDR_MSB 0x3
#define ADC_LL_SAR1_INITIAL_CODE_HIGH_ADDR_LSB 0x0
#define ADC_LL_SAR1_INITIAL_CODE_LOW_ADDR 0x0
#define ADC_LL_SAR1_INITIAL_CODE_LOW_ADDR_MSB 0x7
#define ADC_LL_SAR1_INITIAL_CODE_LOW_ADDR_LSB 0x0
#define ADC_LL_SAR2_INITIAL_CODE_HIGH_ADDR 0x4
#define ADC_LL_SAR2_INITIAL_CODE_HIGH_ADDR_MSB 0x3
#define ADC_LL_SAR2_INITIAL_CODE_HIGH_ADDR_LSB 0x0
#define ADC_LL_SAR2_INITIAL_CODE_LOW_ADDR 0x3
#define ADC_LL_SAR2_INITIAL_CODE_LOW_ADDR_MSB 0x7
#define ADC_LL_SAR2_INITIAL_CODE_LOW_ADDR_LSB 0x0
#define ADC_LL_SAR1_DREF_ADDR 0x2
#define ADC_LL_SAR1_DREF_ADDR_MSB 0x6
#define ADC_LL_SAR1_DREF_ADDR_LSB 0x4
#define ADC_LL_SAR2_DREF_ADDR 0x5
#define ADC_LL_SAR2_DREF_ADDR_MSB 0x6
#define ADC_LL_SAR2_DREF_ADDR_LSB 0x4
#define ADC_LL_SAR1_SAMPLE_CYCLE_ADDR 0x2
#define ADC_LL_SAR1_SAMPLE_CYCLE_ADDR_MSB 0x2
#define ADC_LL_SAR1_SAMPLE_CYCLE_ADDR_LSB 0x0
/* ADC calibration defines end. */
/*---------------------------------------------------------------
Digital controller setting
---------------------------------------------------------------*/
@ -89,15 +134,21 @@ static inline void adc_ll_digi_set_fsm_time(uint32_t rst_wait, uint32_t start_wa
}
/**
* 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.
*/
static inline void adc_ll_digi_set_sample_cycle(uint32_t sample_cycle)
static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle)
{
APB_SARADC.fsm.sample_cycle = sample_cycle;
/* 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(ADC_LL_ANA_CONFIG2_REG, BIT(16));
I2C_WRITEREG_MASK_RTC(ADC_LL_I2C_ADC, ADC_LL_SAR1_SAMPLE_CYCLE_ADDR, sample_cycle);
}
/**
@ -263,6 +314,7 @@ static inline void adc_ll_digi_output_invert(adc_ll_num_t adc_n, bool inv_en)
/**
* 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.
@ -292,11 +344,11 @@ static inline void adc_ll_digi_trigger_disable(void)
/**
* Set ADC digital controller clock division factor. The clock divided from `APLL` or `APB` clock.
* 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 div_num Division factor. Range: 1 ~ 255.
* @param div_num Division factor. Range: 0 ~ 255.
* @param div_b Division factor. Range: 1 ~ 63.
* @param div_a Division factor. Range: 1 ~ 63.
* @param div_a Division factor. Range: 0 ~ 63.
*/
static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div_b, uint32_t div_a)
{
@ -1027,7 +1079,7 @@ static inline void adc_ll_set_controller(adc_ll_num_t adc_n, adc_controller_t ct
* @note Only ADC2 support arbiter.
* @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.
*
* @param mode Refer to `adc_arbiter_mode_t`.
* @param mode Refer to ``adc_arbiter_mode_t``.
*/
static inline void adc_ll_set_arbiter_work_mode(adc_arbiter_mode_t mode)
{
@ -1092,7 +1144,7 @@ static inline void adc_ll_set_arbiter_priority(uint8_t pri_rtc, uint8_t pri_dig,
* In sleep mode, the arbiter is in power-down mode.
* Need to switch the controller to RTC to shield the control of the arbiter.
* After waking up, it needs to switch to arbiter control.
*
*
* @note The hardware will do this automatically. In normal use, there is no need to call this interface to manually switch the controller.
* @note Only support ADC2.
*/
@ -1116,47 +1168,6 @@ static inline void adc_ll_disable_sleep_controller(void)
}
/* ADC calibration code. */
#include "soc/rtc_cntl_reg.h"
#include "i2c_rtc_clk.h"
#define I2C_ADC 0X69
#define I2C_ADC_HOSTID 0
#define ANA_CONFIG2_REG 0x6000E048
#define ANA_CONFIG2_M (BIT(18))
#define SAR1_ENCAL_GND_ADDR 0x7
#define SAR1_ENCAL_GND_ADDR_MSB 5
#define SAR1_ENCAL_GND_ADDR_LSB 5
#define SAR2_ENCAL_GND_ADDR 0x7
#define SAR2_ENCAL_GND_ADDR_MSB 7
#define SAR2_ENCAL_GND_ADDR_LSB 7
#define SAR1_INITIAL_CODE_HIGH_ADDR 0x1
#define SAR1_INITIAL_CODE_HIGH_ADDR_MSB 0x3
#define SAR1_INITIAL_CODE_HIGH_ADDR_LSB 0x0
#define SAR1_INITIAL_CODE_LOW_ADDR 0x0
#define SAR1_INITIAL_CODE_LOW_ADDR_MSB 0x7
#define SAR1_INITIAL_CODE_LOW_ADDR_LSB 0x0
#define SAR2_INITIAL_CODE_HIGH_ADDR 0x4
#define SAR2_INITIAL_CODE_HIGH_ADDR_MSB 0x3
#define SAR2_INITIAL_CODE_HIGH_ADDR_LSB 0x0
#define SAR2_INITIAL_CODE_LOW_ADDR 0x3
#define SAR2_INITIAL_CODE_LOW_ADDR_MSB 0x7
#define SAR2_INITIAL_CODE_LOW_ADDR_LSB 0x0
#define SAR1_DREF_ADDR 0x2
#define SAR1_DREF_ADDR_MSB 0x6
#define SAR1_DREF_ADDR_LSB 0x4
#define SAR2_DREF_ADDR 0x5
#define SAR2_DREF_ADDR_MSB 0x6
#define SAR2_DREF_ADDR_LSB 0x4
/**
* Configure the registers for ADC calibration. You need to call the ``adc_ll_calibration_finish`` interface to resume after calibration.
*
@ -1169,28 +1180,28 @@ static inline void adc_ll_disable_sleep_controller(void)
*/
static inline void adc_ll_calibration_prepare(adc_ll_num_t adc_n, adc_channel_t channel, bool internal_gnd)
{
/* Enable i2s_write_reg function. */
/* Should be called before writing I2C registers. */
void phy_get_romfunc_addr(void);
phy_get_romfunc_addr();
CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_FORCE_PD_M);
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));
/* Enable/disable internal connect GND (for calibration). */
if (adc_n == ADC_NUM_1) {
I2C_WRITEREG_MASK_RTC(I2C_ADC, SAR1_DREF_ADDR, 4);
I2C_WRITEREG_MASK_RTC(ADC_LL_I2C_ADC, ADC_LL_SAR1_DREF_ADDR, 4);
if (internal_gnd) {
I2C_WRITEREG_MASK_RTC(I2C_ADC, SAR1_ENCAL_GND_ADDR, 1);
I2C_WRITEREG_MASK_RTC(ADC_LL_I2C_ADC, ADC_LL_SAR1_ENCAL_GND_ADDR, 1);
} else {
I2C_WRITEREG_MASK_RTC(I2C_ADC, SAR1_ENCAL_GND_ADDR, 0);
I2C_WRITEREG_MASK_RTC(ADC_LL_I2C_ADC, ADC_LL_SAR1_ENCAL_GND_ADDR, 0);
}
} else {
I2C_WRITEREG_MASK_RTC(I2C_ADC, SAR2_DREF_ADDR, 4);
I2C_WRITEREG_MASK_RTC(ADC_LL_I2C_ADC, ADC_LL_SAR2_DREF_ADDR, 4);
if (internal_gnd) {
I2C_WRITEREG_MASK_RTC(I2C_ADC, SAR2_ENCAL_GND_ADDR, 1);
I2C_WRITEREG_MASK_RTC(ADC_LL_I2C_ADC, ADC_LL_SAR2_ENCAL_GND_ADDR, 1);
} else {
I2C_WRITEREG_MASK_RTC(I2C_ADC, SAR2_ENCAL_GND_ADDR, 0);
I2C_WRITEREG_MASK_RTC(ADC_LL_I2C_ADC, ADC_LL_SAR2_ENCAL_GND_ADDR, 0);
}
}
}
@ -1203,9 +1214,9 @@ static inline void adc_ll_calibration_prepare(adc_ll_num_t adc_n, adc_channel_t
static inline void adc_ll_calibration_finish(adc_ll_num_t adc_n)
{
if (adc_n == ADC_NUM_1) {
I2C_WRITEREG_MASK_RTC(I2C_ADC, SAR1_ENCAL_GND_ADDR, 0);
I2C_WRITEREG_MASK_RTC(ADC_LL_I2C_ADC, ADC_LL_SAR1_ENCAL_GND_ADDR, 0);
} else {
I2C_WRITEREG_MASK_RTC(I2C_ADC, SAR2_ENCAL_GND_ADDR, 0);
I2C_WRITEREG_MASK_RTC(ADC_LL_I2C_ADC, ADC_LL_SAR2_ENCAL_GND_ADDR, 0);
}
}
@ -1220,19 +1231,19 @@ static inline void adc_ll_set_calibration_param(adc_ll_num_t adc_n, uint32_t par
{
uint8_t msb = param >> 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. */

View file

@ -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.
*/

View file

@ -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)
{

View file

@ -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));

View file

@ -22,15 +22,20 @@ Overview
.. only:: esp32s2
The {IDF_TARGET_NAME} integrates two 12-bit SAR (`Successive Approximation Register <https://en.wikipedia.org/wiki/Successive_approximation_ADC>`_) ADCs supporting a total of 20 measurement channels (analog enabled pins).
The {IDF_TARGET_NAME} integrates two 13-bit SAR (`Successive Approximation Register <https://en.wikipedia.org/wiki/Successive_approximation_ADC>`_) 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