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
This commit is contained in:
Michael (Xiao Xufeng) 2018-01-24 18:46:34 +08:00 committed by michael
parent 391c3ff959
commit cef8baf424
4 changed files with 199 additions and 79 deletions

View File

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

View File

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

View File

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

View File

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