adc: support ADC on esp32c6 (hal)

This commit is contained in:
laokaiyao
2022-12-01 17:07:14 +08:00
parent 42c6ae3522
commit e27f3e3128
36 changed files with 1111 additions and 189 deletions

View File

@@ -14,6 +14,7 @@
#include "soc/apb_saradc_reg.h"
#include "soc/rtc_cntl_struct.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/clk_tree_defs.h"
#include "hal/misc.h"
#include "hal/assert.h"
#include "hal/adc_types.h"
@@ -40,9 +41,9 @@ extern "C" {
#define ADC_LL_EVENT_THRES1_LOW BIT(26)
typedef enum {
ADC_POWER_BY_FSM, /*!< ADC XPD controled by FSM. Used for polling mode */
ADC_POWER_SW_ON, /*!< ADC XPD controled by SW. power on. Used for DMA mode */
ADC_POWER_SW_OFF, /*!< ADC XPD controled by SW. power off. */
ADC_POWER_BY_FSM, /*!< ADC XPD controlled by FSM. Used for polling mode */
ADC_POWER_SW_ON, /*!< ADC XPD controlled by SW. power on. Used for DMA mode */
ADC_POWER_SW_OFF, /*!< ADC XPD controlled by SW. power off. */
ADC_POWER_MAX, /*!< For parameter check. */
} adc_ll_power_t;
@@ -58,6 +59,12 @@ typedef enum {
ADC_LL_CTRL_ARB = 1, ///< For ADC2. The controller is selected by the arbiter.
} adc_ll_controller_t;
/**
* @brief Clock source of ADC digital controller
* @note Not public as it always uses a default value for now
*/
typedef soc_periph_adc_digi_clk_src_t adc_ll_digi_clk_src_t;
/**
* @brief ADC digital controller (DMA mode) work mode.
*
@@ -124,7 +131,7 @@ static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle)
*/
static inline void adc_ll_digi_set_clk_div(uint32_t div)
{
/* ADC clock devided from digital controller clock clk */
/* ADC clock divided from digital controller clock clk */
HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.ctrl, sar_clk_div, div);
}
@@ -283,15 +290,12 @@ static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div
/**
* Enable clock and select clock source for ADC digital controller.
*
* @param use_apll true: use APLL clock; false: use APB clock.
* @param clk_src clock source for ADC digital controller.
*/
static inline void adc_ll_digi_clk_sel(bool use_apll)
static inline void adc_ll_digi_clk_sel(adc_ll_digi_clk_src_t clk_src)
{
if (use_apll) {
APB_SARADC.apb_adc_clkm_conf.clk_sel = 1; // APLL clock
} else {
APB_SARADC.apb_adc_clkm_conf.clk_sel = 2; // APB clock
}
// Only support APB clock, should always set to 0
APB_SARADC.apb_adc_clkm_conf.clk_sel = 0;
APB_SARADC.ctrl.sar_clk_gated = 1;
}
@@ -643,60 +647,6 @@ static inline void adc_ll_set_calibration_param(adc_unit_t adc_n, uint32_t param
}
/* Temp code end. */
/**
* Output ADCn inter reference voltage to ADC2 channels.
*
* This function routes the internal reference voltage of ADCn to one of
* ADC1's channels. This reference voltage can then be manually measured
* for calibration purposes.
*
* @param[in] adc ADC unit select
* @param[in] channel ADC1 channel number
* @param[in] en Enable/disable the reference voltage output
*/
static inline void adc_ll_vref_output(adc_unit_t adc, adc_channel_t channel, bool en)
{
if (en) {
REG_SET_FIELD(RTC_CNTL_SENSOR_CTRL_REG, RTC_CNTL_FORCE_XPD_SAR, 3);
SET_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU);
REG_SET_FIELD(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_CLK_SEL, 2);
SET_PERI_REG_MASK(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_CLK_EN);
SET_PERI_REG_MASK(APB_SARADC_APB_ADC_ARB_CTRL_REG, APB_SARADC_ADC_ARB_GRANT_FORCE);
SET_PERI_REG_MASK(APB_SARADC_APB_ADC_ARB_CTRL_REG, APB_SARADC_ADC_ARB_APB_FORCE);
APB_SARADC.sar_patt_tab[0].sar_patt_tab1 = 0xFFFFFF;
APB_SARADC.sar_patt_tab[1].sar_patt_tab1 = 0xFFFFFF;
APB_SARADC.onetime_sample.adc1_onetime_sample = 1;
APB_SARADC.onetime_sample.onetime_channel = channel;
SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_PU);
if (adc == ADC_UNIT_1) {
/* Config test mux to route v_ref to ADC1 Channels */
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC1_ENCAL_REF_ADDR, 1);
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR, 1);
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_TSENS_ADDR, 0);
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_RTC_ADDR, 1);
} else {
/* Config test mux to route v_ref to ADC2 Channels */
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC2_ENCAL_REF_ADDR, 1);
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR, 0);
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_TSENS_ADDR, 0);
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_RTC_ADDR, 0);
}
} else {
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC2_ENCAL_REF_ADDR, 0);
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC1_ENCAL_REF_ADDR, 0);
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR, 0);
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_RTC_ADDR, 0);
APB_SARADC.onetime_sample.adc1_onetime_sample = 0;
APB_SARADC.onetime_sample.onetime_channel = 0xf;
REG_SET_FIELD(RTC_CNTL_SENSOR_CTRL_REG, RTC_CNTL_FORCE_XPD_SAR, 0);
REG_SET_FIELD(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_CLK_SEL, 0);
CLEAR_PERI_REG_MASK(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_CLK_EN);
CLEAR_PERI_REG_MASK(APB_SARADC_APB_ADC_ARB_CTRL_REG, APB_SARADC_ADC_ARB_GRANT_FORCE);
CLEAR_PERI_REG_MASK(APB_SARADC_APB_ADC_ARB_CTRL_REG, APB_SARADC_ADC_ARB_APB_FORCE);
}
}
/*---------------------------------------------------------------
Oneshot Read
---------------------------------------------------------------*/