diff --git a/components/bootloader_support/src/bootloader_random_esp32s2.c b/components/bootloader_support/src/bootloader_random_esp32s2.c index 9d1474f550..579b998609 100644 --- a/components/bootloader_support/src/bootloader_random_esp32s2.c +++ b/components/bootloader_support/src/bootloader_random_esp32s2.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,6 +16,10 @@ #include "esp_private/regi2c_ctrl.h" #include "hal/adc_ll.h" +#include "esp_rom_sys.h" +#include "hal/clk_tree_ll.h" +#include "hal/sar_ctrl_ll.h" + #ifndef BOOTLOADER_BUILD #include "esp_private/periph_ctrl.h" #endif @@ -33,63 +37,63 @@ void bootloader_random_enable(void) // Enable 8M clock source for RNG (this is actually enough to produce strong random results, // but enabling the SAR ADC as well adds some insurance.) - REG_SET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN); + clk_ll_rc_fast_digi_enable(); // Enable SAR ADC to read a disconnected input for additional entropy - SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN0_REG,DPORT_APB_SARADC_CLK_EN); + _adc_ll_reset_register(); + _adc_ll_enable_bus_clock(true); - REG_SET_FIELD(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_CLK_SEL, 2); + adc_ll_digi_clk_sel(ADC_DIGI_CLK_SRC_APB); + adc_ll_calibration_prepare(ADC_UNIT_1, false); + adc_ll_calibration_prepare(ADC_UNIT_2, false); + adc_ll_calibration_init(ADC_UNIT_1); + adc_ll_calibration_init(ADC_UNIT_2); - CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_FORCE_PD_M); - SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_FORCE_PU_M); - CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, BIT(18)); - SET_PERI_REG_MASK(ANA_CONFIG2_REG, BIT(16)); +#ifndef BOOTLOADER_BUILD + regi2c_saradc_enable(); +#else + regi2c_ctrl_ll_i2c_sar_periph_enable(); +#endif + // enable analog i2c master clock for RNG runtime + ANALOG_CLOCK_ENABLE(); - REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_DREF_ADDR, 0x4); - REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_DREF_ADDR, 0x4); + adc_ll_regi2c_init(); + sar_ctrl_ll_set_power_mode(SAR_CTRL_LL_POWER_ON); - REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENCAL_REF_ADDR, 1); - REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_TSENS_ADDR, 1); - REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_RTC_ADDR, 0); + adc_digi_pattern_config_t pattern_config = {}; + pattern_config.unit = ADC_UNIT_1; + pattern_config.atten = ADC_ATTEN_DB_12; + pattern_config.channel = ADC_CHANNEL_10; //Use reserved channel 10 to get internal voltage + adc_ll_digi_set_pattern_table(ADC_UNIT_1, 0, pattern_config); + pattern_config.unit = ADC_UNIT_2; + pattern_config.atten = ADC_ATTEN_DB_12; + pattern_config.channel = ADC_CHANNEL_10; //Use reserved channel 10 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_1, 1); + adc_ll_digi_set_pattern_table_len(ADC_UNIT_2, 1); - REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_SAR1_PATT_LEN, 0); - WRITE_PERI_REG(APB_SARADC_SAR1_PATT_TAB1_REG,0xafffffff); // set adc1 channel & bitwidth & atten + adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_BOTH_UNIT); - REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_SAR2_PATT_LEN, 0); - WRITE_PERI_REG(APB_SARADC_SAR2_PATT_TAB1_REG,0xafffffff); //set adc2 channel & bitwidth & atten + adc_ll_set_controller(ADC_UNIT_1, ADC_LL_CTRL_DIG); - SET_PERI_REG_MASK(SENS_SAR_MEAS1_MUX_REG,SENS_SAR1_DIG_FORCE); - - REG_SET_FIELD(APB_SARADC_CTRL_REG,APB_SARADC_WORK_MODE, 1); - - CLEAR_PERI_REG_MASK(APB_SARADC_CTRL2_REG,APB_SARADC_MEAS_NUM_LIMIT); - - REG_SET_FIELD(SENS_SAR_POWER_XPD_SAR_REG, SENS_FORCE_XPD_SAR, 3); - - SET_PERI_REG_MASK(APB_SARADC_CTRL2_REG,APB_SARADC_TIMER_SEL); - - REG_SET_FIELD(APB_SARADC_CTRL2_REG, APB_SARADC_TIMER_TARGET, 100); - - CLEAR_PERI_REG_MASK(APB_SARADC_CTRL_REG,APB_SARADC_START_FORCE); - - SET_PERI_REG_MASK(APB_SARADC_CTRL2_REG,APB_SARADC_TIMER_EN); + adc_ll_digi_set_clk_div(4); + adc_ll_digi_set_trigger_interval(100); + adc_ll_digi_trigger_enable(); } void bootloader_random_disable(void) { - /* Restore internal I2C bus state */ - REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_DREF_ADDR, 0x1); - REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_DREF_ADDR, 0x1); + adc_ll_calibration_clear(); + _adc_ll_enable_bus_clock(false); + adc_ll_digi_trigger_disable(); + adc_ll_digi_reset_pattern_table(); - REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENCAL_REF_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); + adc_ll_regi2c_adc_deinit(); + #ifndef BOOTLOADER_BUILD + regi2c_saradc_disable(); + #endif - /* Restore SARADC to default mode */ - CLEAR_PERI_REG_MASK(SENS_SAR_MEAS1_MUX_REG, SENS_SAR1_DIG_FORCE); - SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN0_REG, DPORT_APB_SARADC_CLK_EN); - SET_PERI_REG_BITS(SENS_SAR_POWER_XPD_SAR_REG, SENS_FORCE_XPD_SAR, 0, SENS_FORCE_XPD_SAR_S); - CLEAR_PERI_REG_MASK(APB_SARADC_CTRL2_REG, APB_SARADC_TIMER_EN); + ANALOG_CLOCK_DISABLE(); /* Note: the 8M CLK entropy source continues running even after this function is called, but as mentioned above it's better to enable Wi-Fi or BT or call bootloader_random_enable() diff --git a/components/hal/esp32s2/include/hal/adc_ll.h b/components/hal/esp32s2/include/hal/adc_ll.h index a6e1000970..6ce842d015 100644 --- a/components/hal/esp32s2/include/hal/adc_ll.h +++ b/components/hal/esp32s2/include/hal/adc_ll.h @@ -247,6 +247,17 @@ static inline void adc_ll_digi_set_pattern_table_len(adc_unit_t adc_n, uint32_t } } +/** + * Rest pattern table to default value + */ +static inline void adc_ll_digi_reset_pattern_table(void) +{ + for(int i = 0; i < 4; i++) { + APB_SARADC.sar1_patt_tab[i] = 0xffffff; + APB_SARADC.sar2_patt_tab[i] = 0xffffff; + } +} + /** * Set pattern table for digital controller. * The pattern table that defines the conversion rules for each SAR ADC. Each table has 16 items, in which channel selection, @@ -928,7 +939,7 @@ static inline void adc_oneshot_ll_disable_all_unit(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) { uint32_t reg_val = READ_PERI_REG(DPORT_PERIP_CLK_EN0_REG); reg_val = reg_val & (~DPORT_APB_SARADC_CLK_EN); @@ -938,13 +949,13 @@ static inline void adc_ll_enable_bus_clock(bool 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) { SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_APB_SARADC_RST); CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_APB_SARADC_RST); @@ -952,7 +963,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) /** @@ -1170,6 +1181,19 @@ static inline void adc_ll_calibration_prepare(adc_unit_t adc_n, bool internal_gn } } +/** + * Clear calibration prepare settings + * This function reverses the operations done by adc_ll_calibration_prepare + */ +static inline void adc_ll_calibration_clear(void) +{ + /* Reverse the operations done in adc_ll_calibration_prepare */ + SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_FORCE_PD_M); + CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_FORCE_PU_M); + SET_PERI_REG_MASK(ANA_CONFIG_REG, I2C_SAR_M); + CLEAR_PERI_REG_MASK(ANA_CONFIG2_REG, ANA_SAR_CFG2_M); +} + /** * Resume register status after calibration. * @@ -1209,6 +1233,68 @@ static inline void adc_ll_set_calibration_param(adc_unit_t adc_n, uint32_t param REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_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) +{ + (void)adc_n; + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_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(1); + // 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); +} + + /* Temp code end. */ /**