Skip to content

Commit cef8baf

Browse files
committed
bugfix(rtc): make sure peripherals (DAC, HALL) are turned off before conversion.
refactor structure of ``rtc_module.c`` to make it more clearly. Closes #1517
1 parent 391c3ff commit cef8baf

File tree

4 files changed

+199
-79
lines changed

4 files changed

+199
-79
lines changed

components/driver/Kconfig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ config ADC_FORCE_XPD_FSM
1010
be shut off when it is not working leading to lower power consumption. However
1111
using the FSM control ADC power will increase the noise of ADC.
1212

13+
config ADC2_DISABLE_DAC
14+
bool "Disable DAC when ADC2 is used on GPIO 25 and 26"
15+
default y
16+
help
17+
If this is set, the ADC2 driver will disables the output of the DAC corresponding to the specified channel. This is the default value.
18+
19+
For testing, disable this option so that we can measure the output of DAC by internal ADC.
20+
1321
endmenu # ADC Configuration
1422

1523
#endmenu # Driver configurations

components/driver/rtc_module.c

Lines changed: 181 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,19 @@ const rtc_gpio_desc_t rtc_gpio_desc[GPIO_PIN_COUNT] = {
156156
{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
157157
};
158158

159+
typedef enum {
160+
ADC_CTRL_RTC = 0,
161+
ADC_CTRL_ULP = 1,
162+
ADC_CTRL_DIG = 2,
163+
ADC2_CTRL_PWDET = 3,
164+
} adc_controller_t ;
165+
166+
static const char TAG[] = "adc";
167+
168+
static inline void dac_output_set_enable(dac_channel_t channel, bool enable);
169+
static inline void adc1_hall_enable(bool enable);
170+
171+
159172
/*---------------------------------------------------------------
160173
RTC IO
161174
---------------------------------------------------------------*/
@@ -1136,6 +1149,102 @@ esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t bits)
11361149
return ESP_OK;
11371150
}
11381151

1152+
// this function should be called in the critical section
1153+
static void adc_set_controller(adc_unit_t unit, adc_controller_t ctrl )
1154+
{
1155+
if ( unit == ADC_UNIT_1 ) {
1156+
switch( ctrl ) {
1157+
case ADC_CTRL_RTC:
1158+
SENS.sar_read_ctrl.sar1_dig_force = false; //RTC controller controls the ADC, not digital controller
1159+
SENS.sar_meas_start1.meas1_start_force = true; //RTC controller controls the ADC,not ulp coprocessor
1160+
SENS.sar_meas_start1.sar1_en_pad_force = true; //RTC controller controls the data port, not ulp coprocessor
1161+
SENS.sar_touch_ctrl1.xpd_hall_force = true; // RTC controller controls the hall sensor power,not ulp coprocessor
1162+
SENS.sar_touch_ctrl1.hall_phase_force = true; // RTC controller controls the hall sensor phase,not ulp coprocessor
1163+
break;
1164+
case ADC_CTRL_ULP:
1165+
SENS.sar_read_ctrl.sar1_dig_force = false;
1166+
SENS.sar_meas_start1.meas1_start_force = false;
1167+
SENS.sar_meas_start1.sar1_en_pad_force = false;
1168+
SENS.sar_touch_ctrl1.xpd_hall_force = false;
1169+
SENS.sar_touch_ctrl1.hall_phase_force = false;
1170+
break;
1171+
case ADC_CTRL_DIG:
1172+
SENS.sar_read_ctrl.sar1_dig_force = true;
1173+
SENS.sar_meas_start1.meas1_start_force = true;
1174+
SENS.sar_meas_start1.sar1_en_pad_force = true;
1175+
SENS.sar_touch_ctrl1.xpd_hall_force = true;
1176+
SENS.sar_touch_ctrl1.hall_phase_force = true;
1177+
break;
1178+
default:
1179+
ESP_LOGE(TAG, "adc1 selects invalid controller");
1180+
break;
1181+
}
1182+
} else if ( unit == ADC_UNIT_2) {
1183+
switch( ctrl ) {
1184+
case ADC_CTRL_RTC:
1185+
SENS.sar_meas_start2.meas2_start_force = true; //RTC controller controls the ADC,not ulp coprocessor
1186+
SENS.sar_meas_start2.sar2_en_pad_force = true; //RTC controller controls the data port, not ulp coprocessor
1187+
SENS.sar_read_ctrl2.sar2_dig_force = false; //RTC controller controls the ADC, not digital controller
1188+
SENS.sar_read_ctrl2.sar2_pwdet_force = false; //RTC controller controls the ADC, not PWDET
1189+
SYSCON.saradc_ctrl.sar2_mux = true; //RTC controller controls the ADC, not PWDET
1190+
break;
1191+
case ADC_CTRL_ULP:
1192+
SENS.sar_meas_start2.meas2_start_force = false;
1193+
SENS.sar_meas_start2.sar2_en_pad_force = false;
1194+
SENS.sar_read_ctrl2.sar2_dig_force = false;
1195+
SENS.sar_read_ctrl2.sar2_pwdet_force = false;
1196+
SYSCON.saradc_ctrl.sar2_mux = true;
1197+
break;
1198+
case ADC_CTRL_DIG:
1199+
SENS.sar_meas_start2.meas2_start_force = true;
1200+
SENS.sar_meas_start2.sar2_en_pad_force = true;
1201+
SENS.sar_read_ctrl2.sar2_dig_force = true;
1202+
SENS.sar_read_ctrl2.sar2_pwdet_force = false;
1203+
SYSCON.saradc_ctrl.sar2_mux = true;
1204+
break;
1205+
case ADC2_CTRL_PWDET:
1206+
//currently only used by Wi-Fi
1207+
SENS.sar_meas_start2.meas2_start_force = true;
1208+
SENS.sar_meas_start2.sar2_en_pad_force = true;
1209+
SENS.sar_read_ctrl2.sar2_dig_force = false;
1210+
SENS.sar_read_ctrl2.sar2_pwdet_force = true;
1211+
SYSCON.saradc_ctrl.sar2_mux = false;
1212+
break;
1213+
default:
1214+
ESP_LOGE(TAG, "adc2 selects invalid controller");
1215+
break;
1216+
}
1217+
} else {
1218+
ESP_LOGE(TAG, "invalid adc unit");
1219+
assert(0);
1220+
}
1221+
}
1222+
1223+
// this function should be called in the critical section
1224+
static int adc_convert( adc_unit_t unit, int channel)
1225+
{
1226+
uint16_t adc_value;
1227+
if ( unit == ADC_UNIT_1 ) {
1228+
SENS.sar_meas_start1.sar1_en_pad = (1 << channel); //only one channel is selected.
1229+
while (SENS.sar_slave_addr1.meas_status != 0);
1230+
SENS.sar_meas_start1.meas1_start_sar = 0;
1231+
SENS.sar_meas_start1.meas1_start_sar = 1;
1232+
while (SENS.sar_meas_start1.meas1_done_sar == 0);
1233+
adc_value = SENS.sar_meas_start1.meas1_data_sar;
1234+
} else if ( unit == ADC_UNIT_2 ) {
1235+
SENS.sar_meas_start2.sar2_en_pad = (1 << channel); //only one channel is selected.
1236+
1237+
SENS.sar_meas_start2.meas2_start_sar = 0; //start force 0
1238+
SENS.sar_meas_start2.meas2_start_sar = 1; //start force 1
1239+
while (SENS.sar_meas_start2.meas2_done_sar == 0) {}; //read done
1240+
adc_value = SENS.sar_meas_start2.meas2_data_sar;
1241+
} else {
1242+
ESP_LOGE(TAG, "invalid adc unit");
1243+
assert(0);
1244+
}
1245+
return adc_value;
1246+
}
1247+
11391248
/*-------------------------------------------------------------------------------------
11401249
* ADC I2S
11411250
*------------------------------------------------------------------------------------*/
@@ -1196,14 +1305,10 @@ esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel)
11961305
adc_set_i2s_data_pattern(adc_unit, 0, channel, ADC_WIDTH_BIT_12, ADC_ATTEN_DB_11);
11971306
portENTER_CRITICAL(&rtc_spinlock);
11981307
if (adc_unit & ADC_UNIT_1) {
1199-
//switch SARADC into DIG channel
1200-
SENS.sar_read_ctrl.sar1_dig_force = 1;
1308+
adc_set_controller( ADC_UNIT_1, ADC_CTRL_DIG );
12011309
}
12021310
if (adc_unit & ADC_UNIT_2) {
1203-
//switch SARADC into DIG channel
1204-
SENS.sar_read_ctrl2.sar2_dig_force = 1;
1205-
//1: SAR ADC2 is controlled by DIG ADC2 CTRL 0: SAR ADC2 is controlled by PWDET CTRL
1206-
SYSCON.saradc_ctrl.sar2_mux = 1;
1311+
adc_set_controller( ADC_UNIT_2, ADC_CTRL_DIG );
12071312
}
12081313
portEXIT_CRITICAL(&rtc_spinlock);
12091314
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)
12751380
return ESP_OK;
12761381
}
12771382

1383+
static inline void adc1_fsm_disable()
1384+
{
1385+
//channel is set in the convert function
1386+
SENS.sar_meas_wait2.force_xpd_amp = SENS_FORCE_XPD_AMP_PD;
1387+
//disable FSM, it's only used by the LNA.
1388+
SENS.sar_meas_ctrl.amp_rst_fb_fsm = 0;
1389+
SENS.sar_meas_ctrl.amp_short_ref_fsm = 0;
1390+
SENS.sar_meas_ctrl.amp_short_ref_gnd_fsm = 0;
1391+
SENS.sar_meas_wait1.sar_amp_wait1 = 1;
1392+
SENS.sar_meas_wait1.sar_amp_wait2 = 1;
1393+
SENS.sar_meas_wait2.sar_amp_wait3 = 1;
1394+
}
1395+
12781396
esp_err_t adc1_i2s_mode_acquire()
12791397
{
12801398
//lazy initialization
@@ -1325,26 +1443,14 @@ int adc1_get_raw(adc1_channel_t channel)
13251443
adc1_adc_mode_acquire();
13261444
adc_power_on();
13271445

1328-
portENTER_CRITICAL(&rtc_spinlock);
1329-
//Adc Controler is Rtc module,not ulp coprocessor
1330-
SENS.sar_meas_start1.meas1_start_force = 1;
1331-
//Disable Amp Bit1=0:Fsm Bit1=1(Bit0=0:PownDown Bit10=1:Powerup)
1332-
SENS.sar_meas_wait2.force_xpd_amp = 0x2;
1333-
//Open the ADC1 Data port Not ulp coprocessor
1334-
SENS.sar_meas_start1.sar1_en_pad_force = 1;
1335-
//Select channel
1336-
SENS.sar_meas_start1.sar1_en_pad = (1 << channel);
1337-
SENS.sar_meas_ctrl.amp_rst_fb_fsm = 0;
1338-
SENS.sar_meas_ctrl.amp_short_ref_fsm = 0;
1339-
SENS.sar_meas_ctrl.amp_short_ref_gnd_fsm = 0;
1340-
SENS.sar_meas_wait1.sar_amp_wait1 = 1;
1341-
SENS.sar_meas_wait1.sar_amp_wait2 = 1;
1342-
SENS.sar_meas_wait2.sar_amp_wait3 = 1;
1343-
while (SENS.sar_slave_addr1.meas_status != 0);
1344-
SENS.sar_meas_start1.meas1_start_sar = 0;
1345-
SENS.sar_meas_start1.meas1_start_sar = 1;
1346-
while (SENS.sar_meas_start1.meas1_done_sar == 0);
1347-
adc_value = SENS.sar_meas_start1.meas1_data_sar;
1446+
portENTER_CRITICAL(&rtc_spinlock);
1447+
//disable other peripherals
1448+
adc1_hall_enable(false);
1449+
adc1_fsm_disable(); //currently the LNA is not open, close it by default
1450+
//set controller
1451+
adc_set_controller( ADC_UNIT_1, ADC_CTRL_RTC );
1452+
//start conversion
1453+
adc_value = adc_convert( ADC_UNIT_1, channel );
13481454
portEXIT_CRITICAL(&rtc_spinlock);
13491455
adc1_lock_release();
13501456
return adc_value;
@@ -1360,15 +1466,11 @@ void adc1_ulp_enable(void)
13601466
adc_power_on();
13611467

13621468
portENTER_CRITICAL(&rtc_spinlock);
1363-
SENS.sar_meas_start1.meas1_start_force = 0;
1364-
SENS.sar_meas_start1.sar1_en_pad_force = 0;
1365-
SENS.sar_meas_wait2.force_xpd_amp = 0x2;
1366-
SENS.sar_meas_ctrl.amp_rst_fb_fsm = 0;
1367-
SENS.sar_meas_ctrl.amp_short_ref_fsm = 0;
1368-
SENS.sar_meas_ctrl.amp_short_ref_gnd_fsm = 0;
1369-
SENS.sar_meas_wait1.sar_amp_wait1 = 0x1;
1370-
SENS.sar_meas_wait1.sar_amp_wait2 = 0x1;
1371-
SENS.sar_meas_wait2.sar_amp_wait3 = 0x1;
1469+
adc_set_controller( ADC_UNIT_1, ADC_CTRL_ULP );
1470+
// since most users do not need LNA and HALL with uLP, we disable them here
1471+
// open them in the uLP if needed.
1472+
adc1_fsm_disable();
1473+
adc1_hall_enable(false);
13721474
portEXIT_CRITICAL(&rtc_spinlock);
13731475
}
13741476

@@ -1481,8 +1583,15 @@ static inline void adc2_config_width(adc_bits_width_t width_bit)
14811583
SENS.sar_read_ctrl2.sar2_data_inv = 1;
14821584
//Set The adc sample width,invert adc value,must digital sar2_bit_width[1:0]=3
14831585
SENS.sar_read_ctrl2.sar2_sample_bit = width_bit;
1484-
//Take the control from WIFI
1485-
SENS.sar_read_ctrl2.sar2_pwdet_force = 0;
1586+
}
1587+
1588+
static inline void adc2_dac_disable( adc2_channel_t channel)
1589+
{
1590+
if ( channel == ADC2_CHANNEL_8 ) { // the same as DAC channel 1
1591+
dac_output_set_enable( DAC_CHANNEL_1, false );
1592+
} else if ( channel == ADC2_CHANNEL_9 ) {
1593+
dac_output_set_enable( DAC_CHANNEL_2, false );
1594+
}
14861595
}
14871596

14881597
//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*
15031612
portEXIT_CRITICAL( &adc2_spinlock );
15041613
return ESP_ERR_TIMEOUT;
15051614
}
1506-
//in critical section with whole rtc module
1615+
1616+
//disable other peripherals
1617+
#ifdef CONFIG_ADC2_DISABLE_DAC
1618+
adc2_dac_disable( channel );
1619+
#endif
1620+
// set controller
1621+
// in critical section with whole rtc module
1622+
// because the PWDET use the same registers, place it here.
15071623
adc2_config_width( width_bit );
1508-
1509-
//Adc Controler is Rtc module,not ulp coprocessor
1510-
SENS.sar_meas_start2.meas2_start_force = 1; //force pad mux and force start
1511-
//Open the ADC2 Data port Not ulp coprocessor
1512-
SENS.sar_meas_start2.sar2_en_pad_force = 1; //open the ADC2 data port
1513-
//Select channel
1514-
SENS.sar_meas_start2.sar2_en_pad = 1 << channel; //pad enable
1515-
SENS.sar_meas_start2.meas2_start_sar = 0; //start force 0
1516-
SENS.sar_meas_start2.meas2_start_sar = 1; //start force 1
1517-
while (SENS.sar_meas_start2.meas2_done_sar == 0) {}; //read done
1518-
adc_value = SENS.sar_meas_start2.meas2_data_sar;
1624+
adc_set_controller( ADC_UNIT_2, ADC_CTRL_RTC );
1625+
//start converting
1626+
adc_value = adc_convert( ADC_UNIT_2, channel );
15191627
_lock_release( &adc2_wifi_lock );
15201628
portEXIT_CRITICAL(&adc2_spinlock);
15211629

@@ -1596,16 +1704,18 @@ static esp_err_t dac_rtc_pad_init(dac_channel_t channel)
15961704
return ESP_OK;
15971705
}
15981706

1707+
static inline void dac_output_set_enable(dac_channel_t channel, bool enable)
1708+
{
1709+
RTCIO.pad_dac[channel-DAC_CHANNEL_1].dac_xpd_force = enable;
1710+
RTCIO.pad_dac[channel-DAC_CHANNEL_1].xpd_dac = enable;
1711+
}
1712+
15991713
esp_err_t dac_output_enable(dac_channel_t channel)
16001714
{
16011715
RTC_MODULE_CHECK((channel >= DAC_CHANNEL_1) && (channel < DAC_CHANNEL_MAX), DAC_ERR_STR_CHANNEL_ERROR, ESP_ERR_INVALID_ARG);
16021716
dac_rtc_pad_init(channel);
16031717
portENTER_CRITICAL(&rtc_spinlock);
1604-
if (channel == DAC_CHANNEL_1) {
1605-
SET_PERI_REG_MASK(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_XPD_DAC | RTC_IO_PDAC1_DAC_XPD_FORCE);
1606-
} else if (channel == DAC_CHANNEL_2) {
1607-
SET_PERI_REG_MASK(RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_XPD_DAC | RTC_IO_PDAC2_DAC_XPD_FORCE);
1608-
}
1718+
dac_output_set_enable(channel, true);
16091719
portEXIT_CRITICAL(&rtc_spinlock);
16101720

16111721
return ESP_OK;
@@ -1615,11 +1725,7 @@ esp_err_t dac_output_disable(dac_channel_t channel)
16151725
{
16161726
RTC_MODULE_CHECK((channel >= DAC_CHANNEL_1) && (channel < DAC_CHANNEL_MAX), DAC_ERR_STR_CHANNEL_ERROR, ESP_ERR_INVALID_ARG);
16171727
portENTER_CRITICAL(&rtc_spinlock);
1618-
if (channel == DAC_CHANNEL_1) {
1619-
CLEAR_PERI_REG_MASK(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_XPD_DAC | RTC_IO_PDAC1_DAC_XPD_FORCE);
1620-
} else if (channel == DAC_CHANNEL_2) {
1621-
CLEAR_PERI_REG_MASK(RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_XPD_DAC | RTC_IO_PDAC2_DAC_XPD_FORCE);
1622-
}
1728+
dac_output_set_enable(channel, false);
16231729
portEXIT_CRITICAL(&rtc_spinlock);
16241730

16251731
return ESP_OK;
@@ -1699,6 +1805,12 @@ esp_err_t dac_i2s_disable()
16991805
/*---------------------------------------------------------------
17001806
HALL SENSOR
17011807
---------------------------------------------------------------*/
1808+
1809+
static inline void adc1_hall_enable(bool enable)
1810+
{
1811+
RTCIO.hall_sens.xpd_hall = enable;
1812+
}
1813+
17021814
static int hall_sensor_get_value() //hall sensor without LNA
17031815
{
17041816
int Sens_Vp0;
@@ -1710,19 +1822,18 @@ static int hall_sensor_get_value() //hall sensor without LNA
17101822
adc_power_on();
17111823

17121824
portENTER_CRITICAL(&rtc_spinlock);
1713-
SENS.sar_touch_ctrl1.xpd_hall_force = 1; // hall sens force enable
1714-
RTCIO.hall_sens.xpd_hall = 1; // xpd hall
1715-
SENS.sar_touch_ctrl1.hall_phase_force = 1; // phase force
1716-
1825+
//disable other peripherals
1826+
adc1_fsm_disable();//currently the LNA is not open, close it by default
1827+
adc1_hall_enable(true);
1828+
// set controller
1829+
adc_set_controller( ADC_UNIT_1, ADC_CTRL_RTC );
1830+
// convert for 4 times with different phase and outputs
17171831
RTCIO.hall_sens.hall_phase = 0; // hall phase
1718-
Sens_Vp0 = adc1_get_raw(ADC1_CHANNEL_0);
1719-
Sens_Vn0 = adc1_get_raw(ADC1_CHANNEL_3);
1832+
Sens_Vp0 = adc_convert( ADC_UNIT_1, ADC1_CHANNEL_0 );
1833+
Sens_Vn0 = adc_convert( ADC_UNIT_1, ADC1_CHANNEL_3 );
17201834
RTCIO.hall_sens.hall_phase = 1;
1721-
Sens_Vp1 = adc1_get_raw(ADC1_CHANNEL_0);
1722-
Sens_Vn1 = adc1_get_raw(ADC1_CHANNEL_3);
1723-
1724-
SENS.sar_touch_ctrl1.xpd_hall_force = 0;
1725-
SENS.sar_touch_ctrl1.hall_phase_force = 0;
1835+
Sens_Vp1 = adc_convert( ADC_UNIT_1, ADC1_CHANNEL_0 );
1836+
Sens_Vn1 = adc_convert( ADC_UNIT_1, ADC1_CHANNEL_3 );
17261837
portEXIT_CRITICAL(&rtc_spinlock);
17271838
hall_value = (Sens_Vp1 - Sens_Vp0) - (Sens_Vn1 - Sens_Vn0);
17281839

0 commit comments

Comments
 (0)