From cef8baf4242b6aa09d217e453387024cc365cd30 Mon Sep 17 00:00:00 2001 From: "Michael (Xiao Xufeng)" Date: Wed, 24 Jan 2018 18:46:34 +0800 Subject: [PATCH] bugfix(rtc): make sure peripherals (DAC, HALL) are turned off before conversion. refactor structure of ``rtc_module.c`` to make it more clearly. Closes https://github.com/espressif/esp-idf/issues/1517 --- components/driver/Kconfig | 8 + components/driver/rtc_module.c | 251 +++++++++++++----- .../soc/esp32/include/soc/sens_struct.h | 18 +- tools/unit-test-app/sdkconfig.defaults | 1 + 4 files changed, 199 insertions(+), 79 deletions(-) diff --git a/components/driver/Kconfig b/components/driver/Kconfig index 7ef1a7f751..a327a4e867 100644 --- a/components/driver/Kconfig +++ b/components/driver/Kconfig @@ -10,6 +10,14 @@ config ADC_FORCE_XPD_FSM be shut off when it is not working leading to lower power consumption. However using the FSM control ADC power will increase the noise of ADC. +config ADC2_DISABLE_DAC + bool "Disable DAC when ADC2 is used on GPIO 25 and 26" + default y + help + If this is set, the ADC2 driver will disables the output of the DAC corresponding to the specified channel. This is the default value. + + For testing, disable this option so that we can measure the output of DAC by internal ADC. + endmenu # ADC Configuration #endmenu # Driver configurations diff --git a/components/driver/rtc_module.c b/components/driver/rtc_module.c index 10833c92ee..31804a78a1 100644 --- a/components/driver/rtc_module.c +++ b/components/driver/rtc_module.c @@ -156,6 +156,19 @@ const rtc_gpio_desc_t rtc_gpio_desc[GPIO_PIN_COUNT] = { {RTC_IO_SENSOR_PADS_REG, RTC_IO_SENSE4_MUX_SEL_M, RTC_IO_SENSE4_FUN_SEL_S, RTC_IO_SENSE4_FUN_IE_M, 0, 0, RTC_IO_SENSE4_SLP_SEL_M, RTC_IO_SENSE4_SLP_IE_M, RTC_IO_SENSE1_HOLD_M, RTC_CNTL_SENSE4_HOLD_FORCE_M, 0, 0, RTCIO_GPIO39_CHANNEL}, //39 }; +typedef enum { + ADC_CTRL_RTC = 0, + ADC_CTRL_ULP = 1, + ADC_CTRL_DIG = 2, + ADC2_CTRL_PWDET = 3, +} adc_controller_t ; + +static const char TAG[] = "adc"; + +static inline void dac_output_set_enable(dac_channel_t channel, bool enable); +static inline void adc1_hall_enable(bool enable); + + /*--------------------------------------------------------------- RTC IO ---------------------------------------------------------------*/ @@ -1136,6 +1149,102 @@ esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t bits) return ESP_OK; } +// this function should be called in the critical section +static void adc_set_controller(adc_unit_t unit, adc_controller_t ctrl ) +{ + if ( unit == ADC_UNIT_1 ) { + switch( ctrl ) { + case ADC_CTRL_RTC: + SENS.sar_read_ctrl.sar1_dig_force = false; //RTC controller controls the ADC, not digital controller + SENS.sar_meas_start1.meas1_start_force = true; //RTC controller controls the ADC,not ulp coprocessor + SENS.sar_meas_start1.sar1_en_pad_force = true; //RTC controller controls the data port, not ulp coprocessor + SENS.sar_touch_ctrl1.xpd_hall_force = true; // RTC controller controls the hall sensor power,not ulp coprocessor + SENS.sar_touch_ctrl1.hall_phase_force = true; // RTC controller controls the hall sensor phase,not ulp coprocessor + break; + case ADC_CTRL_ULP: + SENS.sar_read_ctrl.sar1_dig_force = false; + SENS.sar_meas_start1.meas1_start_force = false; + SENS.sar_meas_start1.sar1_en_pad_force = false; + SENS.sar_touch_ctrl1.xpd_hall_force = false; + SENS.sar_touch_ctrl1.hall_phase_force = false; + break; + case ADC_CTRL_DIG: + SENS.sar_read_ctrl.sar1_dig_force = true; + SENS.sar_meas_start1.meas1_start_force = true; + SENS.sar_meas_start1.sar1_en_pad_force = true; + SENS.sar_touch_ctrl1.xpd_hall_force = true; + SENS.sar_touch_ctrl1.hall_phase_force = true; + break; + default: + ESP_LOGE(TAG, "adc1 selects invalid controller"); + break; + } + } else if ( unit == ADC_UNIT_2) { + switch( ctrl ) { + case ADC_CTRL_RTC: + SENS.sar_meas_start2.meas2_start_force = true; //RTC controller controls the ADC,not ulp coprocessor + SENS.sar_meas_start2.sar2_en_pad_force = true; //RTC controller controls the data port, not ulp coprocessor + SENS.sar_read_ctrl2.sar2_dig_force = false; //RTC controller controls the ADC, not digital controller + SENS.sar_read_ctrl2.sar2_pwdet_force = false; //RTC controller controls the ADC, not PWDET + SYSCON.saradc_ctrl.sar2_mux = true; //RTC controller controls the ADC, not PWDET + break; + case ADC_CTRL_ULP: + SENS.sar_meas_start2.meas2_start_force = false; + SENS.sar_meas_start2.sar2_en_pad_force = false; + SENS.sar_read_ctrl2.sar2_dig_force = false; + SENS.sar_read_ctrl2.sar2_pwdet_force = false; + SYSCON.saradc_ctrl.sar2_mux = true; + break; + case ADC_CTRL_DIG: + SENS.sar_meas_start2.meas2_start_force = true; + SENS.sar_meas_start2.sar2_en_pad_force = true; + SENS.sar_read_ctrl2.sar2_dig_force = true; + SENS.sar_read_ctrl2.sar2_pwdet_force = false; + SYSCON.saradc_ctrl.sar2_mux = true; + break; + case ADC2_CTRL_PWDET: + //currently only used by Wi-Fi + SENS.sar_meas_start2.meas2_start_force = true; + SENS.sar_meas_start2.sar2_en_pad_force = true; + SENS.sar_read_ctrl2.sar2_dig_force = false; + SENS.sar_read_ctrl2.sar2_pwdet_force = true; + SYSCON.saradc_ctrl.sar2_mux = false; + break; + default: + ESP_LOGE(TAG, "adc2 selects invalid controller"); + break; + } + } else { + ESP_LOGE(TAG, "invalid adc unit"); + assert(0); + } +} + +// this function should be called in the critical section +static int adc_convert( adc_unit_t unit, int channel) +{ + uint16_t adc_value; + if ( unit == ADC_UNIT_1 ) { + SENS.sar_meas_start1.sar1_en_pad = (1 << channel); //only one channel is selected. + while (SENS.sar_slave_addr1.meas_status != 0); + SENS.sar_meas_start1.meas1_start_sar = 0; + SENS.sar_meas_start1.meas1_start_sar = 1; + while (SENS.sar_meas_start1.meas1_done_sar == 0); + adc_value = SENS.sar_meas_start1.meas1_data_sar; + } else if ( unit == ADC_UNIT_2 ) { + SENS.sar_meas_start2.sar2_en_pad = (1 << channel); //only one channel is selected. + + SENS.sar_meas_start2.meas2_start_sar = 0; //start force 0 + SENS.sar_meas_start2.meas2_start_sar = 1; //start force 1 + while (SENS.sar_meas_start2.meas2_done_sar == 0) {}; //read done + adc_value = SENS.sar_meas_start2.meas2_data_sar; + } else { + ESP_LOGE(TAG, "invalid adc unit"); + assert(0); + } + return adc_value; +} + /*------------------------------------------------------------------------------------- * ADC I2S *------------------------------------------------------------------------------------*/ @@ -1196,14 +1305,10 @@ esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel) adc_set_i2s_data_pattern(adc_unit, 0, channel, ADC_WIDTH_BIT_12, ADC_ATTEN_DB_11); portENTER_CRITICAL(&rtc_spinlock); if (adc_unit & ADC_UNIT_1) { - //switch SARADC into DIG channel - SENS.sar_read_ctrl.sar1_dig_force = 1; + adc_set_controller( ADC_UNIT_1, ADC_CTRL_DIG ); } if (adc_unit & ADC_UNIT_2) { - //switch SARADC into DIG channel - SENS.sar_read_ctrl2.sar2_dig_force = 1; - //1: SAR ADC2 is controlled by DIG ADC2 CTRL 0: SAR ADC2 is controlled by PWDET CTRL - SYSCON.saradc_ctrl.sar2_mux = 1; + adc_set_controller( ADC_UNIT_2, ADC_CTRL_DIG ); } portEXIT_CRITICAL(&rtc_spinlock); adc_set_i2s_data_source(ADC_I2S_DATA_SRC_ADC); @@ -1275,6 +1380,19 @@ esp_err_t adc1_config_width(adc_bits_width_t width_bit) return ESP_OK; } +static inline void adc1_fsm_disable() +{ + //channel is set in the convert function + SENS.sar_meas_wait2.force_xpd_amp = SENS_FORCE_XPD_AMP_PD; + //disable FSM, it's only used by the LNA. + SENS.sar_meas_ctrl.amp_rst_fb_fsm = 0; + SENS.sar_meas_ctrl.amp_short_ref_fsm = 0; + SENS.sar_meas_ctrl.amp_short_ref_gnd_fsm = 0; + SENS.sar_meas_wait1.sar_amp_wait1 = 1; + SENS.sar_meas_wait1.sar_amp_wait2 = 1; + SENS.sar_meas_wait2.sar_amp_wait3 = 1; +} + esp_err_t adc1_i2s_mode_acquire() { //lazy initialization @@ -1325,26 +1443,14 @@ int adc1_get_raw(adc1_channel_t channel) adc1_adc_mode_acquire(); adc_power_on(); - portENTER_CRITICAL(&rtc_spinlock); - //Adc Controler is Rtc module,not ulp coprocessor - SENS.sar_meas_start1.meas1_start_force = 1; - //Disable Amp Bit1=0:Fsm Bit1=1(Bit0=0:PownDown Bit10=1:Powerup) - SENS.sar_meas_wait2.force_xpd_amp = 0x2; - //Open the ADC1 Data port Not ulp coprocessor - SENS.sar_meas_start1.sar1_en_pad_force = 1; - //Select channel - SENS.sar_meas_start1.sar1_en_pad = (1 << channel); - SENS.sar_meas_ctrl.amp_rst_fb_fsm = 0; - SENS.sar_meas_ctrl.amp_short_ref_fsm = 0; - SENS.sar_meas_ctrl.amp_short_ref_gnd_fsm = 0; - SENS.sar_meas_wait1.sar_amp_wait1 = 1; - SENS.sar_meas_wait1.sar_amp_wait2 = 1; - SENS.sar_meas_wait2.sar_amp_wait3 = 1; - while (SENS.sar_slave_addr1.meas_status != 0); - SENS.sar_meas_start1.meas1_start_sar = 0; - SENS.sar_meas_start1.meas1_start_sar = 1; - while (SENS.sar_meas_start1.meas1_done_sar == 0); - adc_value = SENS.sar_meas_start1.meas1_data_sar; + portENTER_CRITICAL(&rtc_spinlock); + //disable other peripherals + adc1_hall_enable(false); + adc1_fsm_disable(); //currently the LNA is not open, close it by default + //set controller + adc_set_controller( ADC_UNIT_1, ADC_CTRL_RTC ); + //start conversion + adc_value = adc_convert( ADC_UNIT_1, channel ); portEXIT_CRITICAL(&rtc_spinlock); adc1_lock_release(); return adc_value; @@ -1360,15 +1466,11 @@ void adc1_ulp_enable(void) adc_power_on(); portENTER_CRITICAL(&rtc_spinlock); - SENS.sar_meas_start1.meas1_start_force = 0; - SENS.sar_meas_start1.sar1_en_pad_force = 0; - SENS.sar_meas_wait2.force_xpd_amp = 0x2; - SENS.sar_meas_ctrl.amp_rst_fb_fsm = 0; - SENS.sar_meas_ctrl.amp_short_ref_fsm = 0; - SENS.sar_meas_ctrl.amp_short_ref_gnd_fsm = 0; - SENS.sar_meas_wait1.sar_amp_wait1 = 0x1; - SENS.sar_meas_wait1.sar_amp_wait2 = 0x1; - SENS.sar_meas_wait2.sar_amp_wait3 = 0x1; + adc_set_controller( ADC_UNIT_1, ADC_CTRL_ULP ); + // since most users do not need LNA and HALL with uLP, we disable them here + // open them in the uLP if needed. + adc1_fsm_disable(); + adc1_hall_enable(false); portEXIT_CRITICAL(&rtc_spinlock); } @@ -1481,8 +1583,15 @@ static inline void adc2_config_width(adc_bits_width_t width_bit) SENS.sar_read_ctrl2.sar2_data_inv = 1; //Set The adc sample width,invert adc value,must digital sar2_bit_width[1:0]=3 SENS.sar_read_ctrl2.sar2_sample_bit = width_bit; - //Take the control from WIFI - SENS.sar_read_ctrl2.sar2_pwdet_force = 0; +} + +static inline void adc2_dac_disable( adc2_channel_t channel) +{ + if ( channel == ADC2_CHANNEL_8 ) { // the same as DAC channel 1 + dac_output_set_enable( DAC_CHANNEL_1, false ); + } else if ( channel == ADC2_CHANNEL_9 ) { + dac_output_set_enable( DAC_CHANNEL_2, false ); + } } //registers in critical section with adc1: @@ -1503,19 +1612,18 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int* portEXIT_CRITICAL( &adc2_spinlock ); return ESP_ERR_TIMEOUT; } - //in critical section with whole rtc module + + //disable other peripherals +#ifdef CONFIG_ADC2_DISABLE_DAC + adc2_dac_disable( channel ); +#endif + // set controller + // in critical section with whole rtc module + // because the PWDET use the same registers, place it here. adc2_config_width( width_bit ); - - //Adc Controler is Rtc module,not ulp coprocessor - SENS.sar_meas_start2.meas2_start_force = 1; //force pad mux and force start - //Open the ADC2 Data port Not ulp coprocessor - SENS.sar_meas_start2.sar2_en_pad_force = 1; //open the ADC2 data port - //Select channel - SENS.sar_meas_start2.sar2_en_pad = 1 << channel; //pad enable - SENS.sar_meas_start2.meas2_start_sar = 0; //start force 0 - SENS.sar_meas_start2.meas2_start_sar = 1; //start force 1 - while (SENS.sar_meas_start2.meas2_done_sar == 0) {}; //read done - adc_value = SENS.sar_meas_start2.meas2_data_sar; + adc_set_controller( ADC_UNIT_2, ADC_CTRL_RTC ); + //start converting + adc_value = adc_convert( ADC_UNIT_2, channel ); _lock_release( &adc2_wifi_lock ); portEXIT_CRITICAL(&adc2_spinlock); @@ -1596,16 +1704,18 @@ static esp_err_t dac_rtc_pad_init(dac_channel_t channel) return ESP_OK; } +static inline void dac_output_set_enable(dac_channel_t channel, bool enable) +{ + RTCIO.pad_dac[channel-DAC_CHANNEL_1].dac_xpd_force = enable; + RTCIO.pad_dac[channel-DAC_CHANNEL_1].xpd_dac = enable; +} + esp_err_t dac_output_enable(dac_channel_t channel) { RTC_MODULE_CHECK((channel >= DAC_CHANNEL_1) && (channel < DAC_CHANNEL_MAX), DAC_ERR_STR_CHANNEL_ERROR, ESP_ERR_INVALID_ARG); dac_rtc_pad_init(channel); portENTER_CRITICAL(&rtc_spinlock); - if (channel == DAC_CHANNEL_1) { - SET_PERI_REG_MASK(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_XPD_DAC | RTC_IO_PDAC1_DAC_XPD_FORCE); - } else if (channel == DAC_CHANNEL_2) { - SET_PERI_REG_MASK(RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_XPD_DAC | RTC_IO_PDAC2_DAC_XPD_FORCE); - } + dac_output_set_enable(channel, true); portEXIT_CRITICAL(&rtc_spinlock); return ESP_OK; @@ -1615,11 +1725,7 @@ esp_err_t dac_output_disable(dac_channel_t channel) { RTC_MODULE_CHECK((channel >= DAC_CHANNEL_1) && (channel < DAC_CHANNEL_MAX), DAC_ERR_STR_CHANNEL_ERROR, ESP_ERR_INVALID_ARG); portENTER_CRITICAL(&rtc_spinlock); - if (channel == DAC_CHANNEL_1) { - CLEAR_PERI_REG_MASK(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_XPD_DAC | RTC_IO_PDAC1_DAC_XPD_FORCE); - } else if (channel == DAC_CHANNEL_2) { - CLEAR_PERI_REG_MASK(RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_XPD_DAC | RTC_IO_PDAC2_DAC_XPD_FORCE); - } + dac_output_set_enable(channel, false); portEXIT_CRITICAL(&rtc_spinlock); return ESP_OK; @@ -1699,6 +1805,12 @@ esp_err_t dac_i2s_disable() /*--------------------------------------------------------------- HALL SENSOR ---------------------------------------------------------------*/ + +static inline void adc1_hall_enable(bool enable) +{ + RTCIO.hall_sens.xpd_hall = enable; +} + static int hall_sensor_get_value() //hall sensor without LNA { int Sens_Vp0; @@ -1710,19 +1822,18 @@ static int hall_sensor_get_value() //hall sensor without LNA adc_power_on(); portENTER_CRITICAL(&rtc_spinlock); - SENS.sar_touch_ctrl1.xpd_hall_force = 1; // hall sens force enable - RTCIO.hall_sens.xpd_hall = 1; // xpd hall - SENS.sar_touch_ctrl1.hall_phase_force = 1; // phase force - + //disable other peripherals + adc1_fsm_disable();//currently the LNA is not open, close it by default + adc1_hall_enable(true); + // set controller + adc_set_controller( ADC_UNIT_1, ADC_CTRL_RTC ); + // convert for 4 times with different phase and outputs RTCIO.hall_sens.hall_phase = 0; // hall phase - Sens_Vp0 = adc1_get_raw(ADC1_CHANNEL_0); - Sens_Vn0 = adc1_get_raw(ADC1_CHANNEL_3); + Sens_Vp0 = adc_convert( ADC_UNIT_1, ADC1_CHANNEL_0 ); + Sens_Vn0 = adc_convert( ADC_UNIT_1, ADC1_CHANNEL_3 ); RTCIO.hall_sens.hall_phase = 1; - Sens_Vp1 = adc1_get_raw(ADC1_CHANNEL_0); - Sens_Vn1 = adc1_get_raw(ADC1_CHANNEL_3); - - SENS.sar_touch_ctrl1.xpd_hall_force = 0; - SENS.sar_touch_ctrl1.hall_phase_force = 0; + Sens_Vp1 = adc_convert( ADC_UNIT_1, ADC1_CHANNEL_0 ); + Sens_Vn1 = adc_convert( ADC_UNIT_1, ADC1_CHANNEL_3 ); portEXIT_CRITICAL(&rtc_spinlock); hall_value = (Sens_Vp1 - Sens_Vp0) - (Sens_Vn1 - Sens_Vn0); diff --git a/components/soc/esp32/include/soc/sens_struct.h b/components/soc/esp32/include/soc/sens_struct.h index 825c85b17e..37069a9456 100644 --- a/components/soc/esp32/include/soc/sens_struct.h +++ b/components/soc/esp32/include/soc/sens_struct.h @@ -26,7 +26,7 @@ typedef volatile struct { uint32_t sar1_sample_bit: 2; uint32_t sar1_clk_gated: 1; uint32_t sar1_sample_num: 8; - uint32_t sar1_dig_force: 1; + uint32_t sar1_dig_force: 1; /*1: ADC1 is controlled by the digital controller 0: RTC controller*/ uint32_t sar1_data_inv: 1; uint32_t reserved29: 3; }; @@ -162,9 +162,9 @@ typedef volatile struct { uint32_t meas1_data_sar: 16; uint32_t meas1_done_sar: 1; uint32_t meas1_start_sar: 1; - uint32_t meas1_start_force: 1; + uint32_t meas1_start_force: 1; /*1: ADC1 is controlled by the digital or RTC controller 0: Ulp coprocessor*/ uint32_t sar1_en_pad: 12; - uint32_t sar1_en_pad_force: 1; + uint32_t sar1_en_pad_force: 1; /*1: Data ports are controlled by the digital or RTC controller 0: Ulp coprocessor*/ }; uint32_t val; } sar_meas_start1; @@ -174,8 +174,8 @@ typedef volatile struct { uint32_t touch_xpd_wait: 8; uint32_t touch_out_sel: 1; uint32_t touch_out_1en: 1; - uint32_t xpd_hall_force: 1; - uint32_t hall_phase_force: 1; + uint32_t xpd_hall_force: 1; /*1: Power of hall sensor is controlled by the digital or RTC controller 0: Ulp coprocessor*/ + uint32_t hall_phase_force: 1; /*1: Phase of hall sensor is controlled by the digital or RTC controller 0: Ulp coprocessor*/ uint32_t reserved28: 4; }; uint32_t val; @@ -224,8 +224,8 @@ typedef volatile struct { uint32_t sar2_sample_bit: 2; uint32_t sar2_clk_gated: 1; uint32_t sar2_sample_num: 8; - uint32_t sar2_pwdet_force: 1; - uint32_t sar2_dig_force: 1; + uint32_t sar2_pwdet_force: 1; /*1: ADC2 is controlled by PWDET 0: digital or RTC controller*/ + uint32_t sar2_dig_force: 1; /*1: ADC2 is controlled by the digital controller 0: RTC controller*/ uint32_t sar2_data_inv: 1; uint32_t reserved30: 2; }; @@ -236,9 +236,9 @@ typedef volatile struct { uint32_t meas2_data_sar: 16; uint32_t meas2_done_sar: 1; uint32_t meas2_start_sar: 1; - uint32_t meas2_start_force: 1; + uint32_t meas2_start_force: 1; /*1: ADC2 is controlled by the digital or RTC controller 0: Ulp coprocessor*/ uint32_t sar2_en_pad: 12; - uint32_t sar2_en_pad_force: 1; + uint32_t sar2_en_pad_force: 1; /*1: Data ports are controlled by the digital or RTC controller 0: Ulp coprocessor*/ }; uint32_t val; } sar_meas_start2; diff --git a/tools/unit-test-app/sdkconfig.defaults b/tools/unit-test-app/sdkconfig.defaults index 9e9dfa6916..a9a34a25a8 100644 --- a/tools/unit-test-app/sdkconfig.defaults +++ b/tools/unit-test-app/sdkconfig.defaults @@ -25,3 +25,4 @@ CONFIG_STACK_CHECK_STRONG=y CONFIG_STACK_CHECK=y CONFIG_SUPPORT_STATIC_ALLOCATION=y CONFIG_ESP_TIMER_PROFILING=y +CONFIG_ADC2_DISABLE_DAC=n -- 2.40.0