mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
Merge branch 'refactor/rng_ll_c2_v6.0' into 'release/v6.0'
refactor(rng): refactor to use hal/ll apis for ESP32C2 (v6.0) See merge request espressif/esp-idf!43449
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -12,56 +12,60 @@
|
||||
#include "soc/system_reg.h"
|
||||
#include "esp_private/regi2c_ctrl.h"
|
||||
#include "soc/regi2c_saradc.h"
|
||||
#include "hal/adc_ll.h"
|
||||
#include "hal/sar_ctrl_ll.h"
|
||||
#include "hal/clk_gate_ll.h"
|
||||
|
||||
#define ADC_RNG_CLKM_DIV_NUM 15
|
||||
#define ADC_RNG_CLKM_DIV_B 0
|
||||
#define ADC_RNG_CLKM_DIV_A 0
|
||||
|
||||
void bootloader_random_enable(void)
|
||||
{
|
||||
/* RNG module is always clock enabled */
|
||||
REG_SET_FIELD(RTC_CNTL_SENSOR_CTRL_REG, RTC_CNTL_FORCE_XPD_SAR, 0x3);
|
||||
sar_ctrl_ll_set_power_mode(SAR_CTRL_LL_POWER_ON);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_PU_M);
|
||||
|
||||
// Bridging sar2 internal reference voltage
|
||||
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_RTC_ADDR, 0);
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_TSENS_ADDR, 0);
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
regi2c_saradc_enable();
|
||||
#else
|
||||
regi2c_ctrl_ll_i2c_sar_periph_enable();
|
||||
#endif
|
||||
ANALOG_CLOCK_ENABLE();
|
||||
adc_ll_regi2c_init();
|
||||
|
||||
// Enable SAR ADC2 internal channel to read adc2 ref voltage for additional entropy
|
||||
SET_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_APB_SARADC_CLK_EN_M);
|
||||
CLEAR_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_APB_SARADC_RST_M);
|
||||
REG_SET_FIELD(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_REG_CLK_SEL, 0x2);
|
||||
SET_PERI_REG_MASK(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_CLK_EN_M);
|
||||
SET_PERI_REG_MASK(APB_SARADC_CTRL_REG, APB_SARADC_SAR_CLK_GATED_M);
|
||||
REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_XPD_SAR_FORCE, 0x3);
|
||||
REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_SAR_CLK_DIV, 1);
|
||||
_adc_ll_enable_bus_clock(true);
|
||||
_adc_ll_reset_register();
|
||||
adc_ll_digi_clk_sel(ADC_DIGI_CLK_SRC_PLL_F80M);
|
||||
adc_ll_digi_controller_clk_div(ADC_RNG_CLKM_DIV_NUM, ADC_RNG_CLKM_DIV_B, ADC_RNG_CLKM_DIV_A);
|
||||
adc_ll_digi_set_power_manage(ADC_LL_POWER_SW_ON);
|
||||
adc_ll_digi_set_clk_div(1);
|
||||
|
||||
REG_SET_FIELD(APB_SARADC_FSM_WAIT_REG, APB_SARADC_RSTB_WAIT, 8);
|
||||
REG_SET_FIELD(APB_SARADC_FSM_WAIT_REG, APB_SARADC_XPD_WAIT, 5);
|
||||
REG_SET_FIELD(APB_SARADC_FSM_WAIT_REG, APB_SARADC_STANDBY_WAIT, 100);
|
||||
adc_ll_digi_set_fsm_time(ADC_LL_FSM_RSTB_WAIT_DEFAULT, ADC_LL_FSM_START_WAIT_DEFAULT,
|
||||
ADC_LL_FSM_STANDBY_WAIT_DEFAULT);
|
||||
|
||||
SET_PERI_REG_MASK(APB_SARADC_CTRL_REG, APB_SARADC_SAR_PATT_P_CLEAR_M);
|
||||
CLEAR_PERI_REG_MASK(APB_SARADC_CTRL_REG, APB_SARADC_SAR_PATT_P_CLEAR_M);
|
||||
REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_SAR_PATT_LEN, 0);
|
||||
REG_SET_FIELD(APB_SARADC_SAR_PATT_TAB1_REG, APB_SARADC_SAR_PATT_TAB1, 0x9cffff);// Set adc2 internal channel & atten
|
||||
REG_SET_FIELD(APB_SARADC_SAR_PATT_TAB2_REG, APB_SARADC_SAR_PATT_TAB2, 0xffffff);
|
||||
// Set ADC sampling frequency
|
||||
REG_SET_FIELD(APB_SARADC_CTRL2_REG, APB_SARADC_TIMER_TARGET, 100);
|
||||
REG_SET_FIELD(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_REG_CLKM_DIV_NUM, 15);
|
||||
CLEAR_PERI_REG_MASK(APB_SARADC_CTRL2_REG, APB_SARADC_MEAS_NUM_LIMIT);
|
||||
SET_PERI_REG_MASK(APB_SARADC_DMA_CONF_REG, APB_SARADC_APB_ADC_TRANS_M);
|
||||
SET_PERI_REG_MASK(APB_SARADC_CTRL2_REG, APB_SARADC_TIMER_EN);
|
||||
adc_digi_pattern_config_t pattern_config = {};
|
||||
pattern_config.unit = ADC_UNIT_2;
|
||||
pattern_config.atten = ADC_ATTEN_DB_12;
|
||||
pattern_config.channel = ADC_CHANNEL_1; //Use reserved channel 1 to get internal voltage
|
||||
adc_ll_digi_set_pattern_table(ADC_UNIT_2, 0, pattern_config);
|
||||
adc_ll_digi_set_pattern_table_len(ADC_UNIT_2, 1);
|
||||
|
||||
|
||||
adc_ll_digi_set_trigger_interval(100);
|
||||
adc_ll_digi_convert_limit_enable(false);
|
||||
adc_ll_digi_dma_enable();
|
||||
adc_ll_digi_trigger_enable();
|
||||
}
|
||||
|
||||
void bootloader_random_disable(void)
|
||||
{
|
||||
/* Restore internal I2C bus state */
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC2_ENCAL_REF_ADDR, 0);
|
||||
|
||||
/* Restore SARADC to default mode */
|
||||
CLEAR_PERI_REG_MASK(APB_SARADC_CTRL2_REG, APB_SARADC_TIMER_EN);
|
||||
CLEAR_PERI_REG_MASK(APB_SARADC_DMA_CONF_REG, APB_SARADC_APB_ADC_TRANS_M);
|
||||
REG_SET_FIELD(APB_SARADC_SAR_PATT_TAB1_REG, APB_SARADC_SAR_PATT_TAB1, 0xffffff);
|
||||
REG_SET_FIELD(APB_SARADC_SAR_PATT_TAB2_REG, APB_SARADC_SAR_PATT_TAB2, 0xffffff);
|
||||
CLEAR_PERI_REG_MASK(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_CLK_EN_M);
|
||||
REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_XPD_SAR_FORCE, 0);
|
||||
REG_SET_FIELD(RTC_CNTL_SENSOR_CTRL_REG, RTC_CNTL_FORCE_XPD_SAR, 0);
|
||||
_adc_ll_enable_bus_clock(false);
|
||||
adc_ll_digi_trigger_disable();
|
||||
adc_ll_digi_reset_pattern_table();
|
||||
adc_ll_regi2c_adc_deinit();
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
regi2c_saradc_disable();
|
||||
#endif
|
||||
// disable analog i2c master clock
|
||||
ANALOG_CLOCK_DISABLE();
|
||||
}
|
||||
|
||||
@@ -67,6 +67,18 @@ typedef enum {
|
||||
ADC_LL_CTRL_DIG = 0, ///< For ADC1. Select DIG controller.
|
||||
} adc_ll_controller_t;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
struct {
|
||||
uint8_t atten: 2;
|
||||
uint8_t channel: 3;
|
||||
uint8_t unit: 1;
|
||||
uint8_t reserved: 2;
|
||||
};
|
||||
uint8_t val;
|
||||
};
|
||||
} __attribute__((packed)) adc_ll_digi_pattern_table_t;
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
@@ -114,6 +126,28 @@ static inline void adc_ll_digi_set_clk_div(uint32_t div)
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.saradc_ctrl, saradc_saradc_sar_clk_div, div);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable max conversion number detection for digital controller.
|
||||
* If the number of ADC conversion is equal to the maximum, the conversion is stopped.
|
||||
*
|
||||
* @note Only used for bootloader RNG.
|
||||
* @param enable true: enable; false: disable
|
||||
*/
|
||||
static inline void adc_ll_digi_convert_limit_enable(bool enable)
|
||||
{
|
||||
APB_SARADC.saradc_ctrl2.saradc_saradc_meas_num_limit = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable output data to DMA from adc digital controller.
|
||||
*
|
||||
* @note Only used for bootloader RNG.
|
||||
*/
|
||||
static inline void adc_ll_digi_dma_enable(void)
|
||||
{
|
||||
APB_SARADC.saradc_dma_conf.saradc_apb_adc_trans = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of cycles required for the conversion to complete and wait for the arbiter to stabilize.
|
||||
*
|
||||
@@ -140,6 +174,39 @@ static inline void adc_ll_digi_output_invert(adc_unit_t adc_n, bool inv_en)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the interval clock cycle for the digital controller to trigger the measurement.
|
||||
* Expression: `trigger_meas_freq` = `controller_clk` / 2 / interval.
|
||||
*
|
||||
* @note The trigger interval should not be smaller than the sampling time of the SAR ADC.
|
||||
* @note Only used for bootloader RNG.
|
||||
* @param cycle The clock cycle (trigger interval) of the measurement. Range: 30 ~ 4095.
|
||||
*/
|
||||
static inline void adc_ll_digi_set_trigger_interval(uint32_t cycle)
|
||||
{
|
||||
APB_SARADC.saradc_ctrl2.saradc_saradc_timer_target = cycle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable digital controller timer to trigger the measurement.
|
||||
*
|
||||
* @note Only used for bootloader RNG.
|
||||
*/
|
||||
static inline void adc_ll_digi_trigger_enable(void)
|
||||
{
|
||||
APB_SARADC.saradc_ctrl2.saradc_saradc_timer_en = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable digital controller timer to trigger the measurement.
|
||||
*
|
||||
* @note Only used for bootloader RNG.
|
||||
*/
|
||||
static inline void adc_ll_digi_trigger_disable(void)
|
||||
{
|
||||
APB_SARADC.saradc_ctrl2.saradc_saradc_timer_en = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set ADC digital controller clock division factor. The clock divided from `APLL` or `APB` clock.
|
||||
* Expression: controller_clk = (APLL or APB) / (div_num + div_a / div_b + 1).
|
||||
@@ -294,20 +361,20 @@ static inline uint32_t adc_ll_pwdet_get_cct(void)
|
||||
* @brief Enable the ADC clock
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
static inline void adc_ll_enable_bus_clock(bool enable)
|
||||
static inline void _adc_ll_enable_bus_clock(bool enable)
|
||||
{
|
||||
SYSTEM.perip_clk_en0.apb_saradc_clk_en = enable;
|
||||
}
|
||||
// SYSTEM.perip_clk_en0 is a shared register, so this function must be used in an atomic way
|
||||
#define adc_ll_enable_bus_clock(...) do { \
|
||||
(void)__DECLARE_RCC_ATOMIC_ENV; \
|
||||
adc_ll_enable_bus_clock(__VA_ARGS__); \
|
||||
_adc_ll_enable_bus_clock(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* @brief Reset ADC module
|
||||
*/
|
||||
static inline void adc_ll_reset_register(void)
|
||||
static inline void _adc_ll_reset_register(void)
|
||||
{
|
||||
SYSTEM.perip_rst_en0.apb_saradc_rst = 1;
|
||||
SYSTEM.perip_rst_en0.apb_saradc_rst = 0;
|
||||
@@ -315,7 +382,7 @@ static inline void adc_ll_reset_register(void)
|
||||
// SYSTEM.perip_rst_en0 is a shared register, so this function must be used in an atomic way
|
||||
#define adc_ll_reset_register(...) do { \
|
||||
(void)__DECLARE_RCC_ATOMIC_ENV; \
|
||||
adc_ll_reset_register(__VA_ARGS__); \
|
||||
_adc_ll_reset_register(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
@@ -346,6 +413,70 @@ static inline void adc_ll_set_controller(adc_unit_t adc_n, adc_ll_controller_t c
|
||||
//Not used on ESP32-C2
|
||||
}
|
||||
|
||||
/**
|
||||
* Set pattern table length for digital controller.
|
||||
* The pattern table that defines the conversion rules for each SAR ADC. Each table has 8 items, in which channel selection,
|
||||
* resolution and attenuation are stored. When the conversion is started, the controller reads conversion rules from the
|
||||
* pattern table one by one. For each controller the scan sequence has at most 8 different rules before repeating itself.
|
||||
*
|
||||
* @param adc_n ADC unit.
|
||||
* @param patt_len Items range: 1 ~ 8.
|
||||
*
|
||||
* @note Only used for bootloader RNG.
|
||||
*/
|
||||
static inline void adc_ll_digi_set_pattern_table_len(adc_unit_t adc_n, uint32_t patt_len)
|
||||
{
|
||||
(void)adc_n;
|
||||
APB_SARADC.saradc_ctrl.saradc_saradc_sar_patt_len = patt_len - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset pattern table to default value
|
||||
*
|
||||
* @note Only used for bootloader RNG.
|
||||
*/
|
||||
static inline void adc_ll_digi_reset_pattern_table(void)
|
||||
{
|
||||
APB_SARADC.saradc_sar_patt_tab1.saradc_saradc_sar_patt_tab1 = 0xffffff;
|
||||
APB_SARADC.saradc_sar_patt_tab2.saradc_saradc_sar_patt_tab2 = 0xffffff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set pattern table for digital controller.
|
||||
* The pattern table that defines the conversion rules for each SAR ADC. Each table has 8 items, in which channel selection,
|
||||
* resolution and attenuation are stored. When the conversion is started, the controller reads conversion rules from the
|
||||
* pattern table one by one. For each controller the scan sequence has at most 8 different rules before repeating itself.
|
||||
*
|
||||
* @param adc_n ADC unit.
|
||||
* @param pattern_index Items index. Range: 0 ~ 7.
|
||||
* @param table Stored conversion rules.
|
||||
*
|
||||
* @note Only used for bootloader RNG.
|
||||
*/
|
||||
static inline void adc_ll_digi_set_pattern_table(adc_unit_t adc_n, uint32_t pattern_index, adc_digi_pattern_config_t table)
|
||||
{
|
||||
uint32_t tab;
|
||||
uint8_t index = pattern_index / 4;
|
||||
uint8_t offset = (pattern_index % 4) * 6;
|
||||
adc_ll_digi_pattern_table_t pattern = {0};
|
||||
|
||||
(void)adc_n;
|
||||
|
||||
pattern.val = (table.atten & 0x3) | ((table.channel & 0x7) << 2) | ((table.unit & 0x1) << 5);
|
||||
|
||||
if (index == 0) {
|
||||
tab = APB_SARADC.saradc_sar_patt_tab1.saradc_saradc_sar_patt_tab1; // Read old register value
|
||||
tab &= (~(0xFC0000 >> offset)); // Clear old data
|
||||
tab |= ((uint32_t)(pattern.val & 0x3F) << 18) >> offset; // Fill in the new data
|
||||
APB_SARADC.saradc_sar_patt_tab1.saradc_saradc_sar_patt_tab1 = tab; // Write back
|
||||
} else {
|
||||
tab = APB_SARADC.saradc_sar_patt_tab2.saradc_saradc_sar_patt_tab2; // Read old register value
|
||||
tab &= (~(0xFC0000 >> offset)); // Clear old data
|
||||
tab |= ((uint32_t)(pattern.val & 0x3F) << 18) >> offset; // Fill in the new data
|
||||
APB_SARADC.saradc_sar_patt_tab2.saradc_saradc_sar_patt_tab2 = tab; // Write back
|
||||
}
|
||||
}
|
||||
|
||||
/* ADC calibration code. */
|
||||
/**
|
||||
* @brief Set common calibration configuration. Should be shared with other parts (PWDET).
|
||||
@@ -405,6 +536,69 @@ static inline void adc_ll_set_calibration_param(adc_unit_t adc_n, uint32_t param
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_LOW_ADDR, lsb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the SAR DTEST param
|
||||
*
|
||||
* @param param DTEST value
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void adc_ll_set_dtest_param(uint32_t param)
|
||||
{
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR, param);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the SAR ENT param
|
||||
*
|
||||
* @param param ENT value
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void adc_ll_set_ent_param(uint32_t param)
|
||||
{
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_TSENS_ADDR, param);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/disable the calibration voltage reference for ADC unit.
|
||||
*
|
||||
* @param adc_n ADC index number.
|
||||
* @param en true to enable, false to disable
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void adc_ll_enable_calibration_ref(adc_unit_t adc_n, bool en)
|
||||
{
|
||||
if (adc_n == ADC_UNIT_1) {
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC1_ENCAL_REF_ADDR, en);
|
||||
} else {
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC2_ENCAL_REF_ADDR, en);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Init regi2c SARADC registers
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void adc_ll_regi2c_init(void)
|
||||
{
|
||||
adc_ll_set_dtest_param(0);
|
||||
adc_ll_set_ent_param(0);
|
||||
// Config ADC circuit (Analog part) with I2C(HOST ID 0x69) and chose internal voltage as sampling source
|
||||
adc_ll_enable_calibration_ref(ADC_UNIT_1, true);
|
||||
adc_ll_enable_calibration_ref(ADC_UNIT_2, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deinit regi2c SARADC registers
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void adc_ll_regi2c_adc_deinit(void)
|
||||
{
|
||||
adc_ll_set_dtest_param(0);
|
||||
adc_ll_set_ent_param(0);
|
||||
adc_ll_enable_calibration_ref(ADC_UNIT_1, false);
|
||||
adc_ll_enable_calibration_ref(ADC_UNIT_2, false);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Oneshot Read
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
Reference in New Issue
Block a user