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

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