Skip to content

Commit db5347f

Browse files
committed
refactor(rng): refactor to use hal/ll apis for ESP32C2
1 parent 34587f3 commit db5347f

File tree

2 files changed

+243
-45
lines changed

2 files changed

+243
-45
lines changed
Lines changed: 45 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -12,56 +12,60 @@
1212
#include "soc/system_reg.h"
1313
#include "esp_private/regi2c_ctrl.h"
1414
#include "soc/regi2c_saradc.h"
15+
#include "hal/adc_ll.h"
16+
#include "hal/sar_ctrl_ll.h"
17+
#include "hal/clk_gate_ll.h"
18+
19+
#define ADC_RNG_CLKM_DIV_NUM 15
20+
#define ADC_RNG_CLKM_DIV_B 0
21+
#define ADC_RNG_CLKM_DIV_A 0
1522

1623
void bootloader_random_enable(void)
1724
{
18-
/* RNG module is always clock enabled */
19-
REG_SET_FIELD(RTC_CNTL_SENSOR_CTRL_REG, RTC_CNTL_FORCE_XPD_SAR, 0x3);
25+
sar_ctrl_ll_set_power_mode(SAR_CTRL_LL_POWER_ON);
2026
SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_PU_M);
2127

22-
// Bridging sar2 internal reference voltage
23-
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC2_ENCAL_REF_ADDR, 1);
24-
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR, 0);
25-
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_RTC_ADDR, 0);
26-
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_TSENS_ADDR, 0);
28+
#ifndef BOOTLOADER_BUILD
29+
regi2c_saradc_enable();
30+
#else
31+
regi2c_ctrl_ll_i2c_sar_periph_enable();
32+
#endif
33+
ANALOG_CLOCK_ENABLE();
34+
adc_ll_regi2c_init();
35+
36+
_adc_ll_enable_bus_clock(true);
37+
_adc_ll_reset_register();
38+
adc_ll_digi_clk_sel(ADC_DIGI_CLK_SRC_PLL_F80M);
39+
adc_ll_digi_controller_clk_div(ADC_RNG_CLKM_DIV_NUM, ADC_RNG_CLKM_DIV_B, ADC_RNG_CLKM_DIV_A);
40+
adc_ll_digi_set_power_manage(ADC_LL_POWER_SW_ON);
41+
adc_ll_digi_set_clk_div(1);
2742

28-
// Enable SAR ADC2 internal channel to read adc2 ref voltage for additional entropy
29-
SET_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_APB_SARADC_CLK_EN_M);
30-
CLEAR_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_APB_SARADC_RST_M);
31-
REG_SET_FIELD(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_REG_CLK_SEL, 0x2);
32-
SET_PERI_REG_MASK(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_CLK_EN_M);
33-
SET_PERI_REG_MASK(APB_SARADC_CTRL_REG, APB_SARADC_SAR_CLK_GATED_M);
34-
REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_XPD_SAR_FORCE, 0x3);
35-
REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_SAR_CLK_DIV, 1);
43+
adc_ll_digi_set_fsm_time(ADC_LL_FSM_RSTB_WAIT_DEFAULT, ADC_LL_FSM_START_WAIT_DEFAULT,
44+
ADC_LL_FSM_STANDBY_WAIT_DEFAULT);
3645

37-
REG_SET_FIELD(APB_SARADC_FSM_WAIT_REG, APB_SARADC_RSTB_WAIT, 8);
38-
REG_SET_FIELD(APB_SARADC_FSM_WAIT_REG, APB_SARADC_XPD_WAIT, 5);
39-
REG_SET_FIELD(APB_SARADC_FSM_WAIT_REG, APB_SARADC_STANDBY_WAIT, 100);
46+
adc_digi_pattern_config_t pattern_config = {};
47+
pattern_config.unit = ADC_UNIT_2;
48+
pattern_config.atten = ADC_ATTEN_DB_12;
49+
pattern_config.channel = ADC_CHANNEL_1; //Use reserved channel 1 to get internal voltage
50+
adc_ll_digi_set_pattern_table(ADC_UNIT_2, 0, pattern_config);
51+
adc_ll_digi_set_pattern_table_len(ADC_UNIT_2, 1);
4052

41-
SET_PERI_REG_MASK(APB_SARADC_CTRL_REG, APB_SARADC_SAR_PATT_P_CLEAR_M);
42-
CLEAR_PERI_REG_MASK(APB_SARADC_CTRL_REG, APB_SARADC_SAR_PATT_P_CLEAR_M);
43-
REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_SAR_PATT_LEN, 0);
44-
REG_SET_FIELD(APB_SARADC_SAR_PATT_TAB1_REG, APB_SARADC_SAR_PATT_TAB1, 0x9cffff);// Set adc2 internal channel & atten
45-
REG_SET_FIELD(APB_SARADC_SAR_PATT_TAB2_REG, APB_SARADC_SAR_PATT_TAB2, 0xffffff);
46-
// Set ADC sampling frequency
47-
REG_SET_FIELD(APB_SARADC_CTRL2_REG, APB_SARADC_TIMER_TARGET, 100);
48-
REG_SET_FIELD(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_REG_CLKM_DIV_NUM, 15);
49-
CLEAR_PERI_REG_MASK(APB_SARADC_CTRL2_REG, APB_SARADC_MEAS_NUM_LIMIT);
50-
SET_PERI_REG_MASK(APB_SARADC_DMA_CONF_REG, APB_SARADC_APB_ADC_TRANS_M);
51-
SET_PERI_REG_MASK(APB_SARADC_CTRL2_REG, APB_SARADC_TIMER_EN);
53+
54+
adc_ll_digi_set_trigger_interval(100);
55+
adc_ll_digi_convert_limit_enable(false);
56+
adc_ll_digi_dma_enable();
57+
adc_ll_digi_trigger_enable();
5258
}
5359

5460
void bootloader_random_disable(void)
5561
{
56-
/* Restore internal I2C bus state */
57-
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC2_ENCAL_REF_ADDR, 0);
58-
59-
/* Restore SARADC to default mode */
60-
CLEAR_PERI_REG_MASK(APB_SARADC_CTRL2_REG, APB_SARADC_TIMER_EN);
61-
CLEAR_PERI_REG_MASK(APB_SARADC_DMA_CONF_REG, APB_SARADC_APB_ADC_TRANS_M);
62-
REG_SET_FIELD(APB_SARADC_SAR_PATT_TAB1_REG, APB_SARADC_SAR_PATT_TAB1, 0xffffff);
63-
REG_SET_FIELD(APB_SARADC_SAR_PATT_TAB2_REG, APB_SARADC_SAR_PATT_TAB2, 0xffffff);
64-
CLEAR_PERI_REG_MASK(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_CLK_EN_M);
65-
REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_XPD_SAR_FORCE, 0);
66-
REG_SET_FIELD(RTC_CNTL_SENSOR_CTRL_REG, RTC_CNTL_FORCE_XPD_SAR, 0);
62+
_adc_ll_enable_bus_clock(false);
63+
adc_ll_digi_trigger_disable();
64+
adc_ll_digi_reset_pattern_table();
65+
adc_ll_regi2c_adc_deinit();
66+
#ifndef BOOTLOADER_BUILD
67+
regi2c_saradc_disable();
68+
#endif
69+
// disable analog i2c master clock
70+
ANALOG_CLOCK_DISABLE();
6771
}

components/hal/esp32c2/include/hal/adc_ll.h

Lines changed: 198 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,18 @@ typedef enum {
6767
ADC_LL_CTRL_DIG = 0, ///< For ADC1. Select DIG controller.
6868
} adc_ll_controller_t;
6969

70+
typedef struct {
71+
union {
72+
struct {
73+
uint8_t atten: 2;
74+
uint8_t channel: 3;
75+
uint8_t unit: 1;
76+
uint8_t reserved: 2;
77+
};
78+
uint8_t val;
79+
};
80+
} __attribute__((packed)) adc_ll_digi_pattern_table_t;
81+
7082
/*---------------------------------------------------------------
7183
Digital controller setting
7284
---------------------------------------------------------------*/
@@ -114,6 +126,28 @@ static inline void adc_ll_digi_set_clk_div(uint32_t div)
114126
HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.saradc_ctrl, saradc_saradc_sar_clk_div, div);
115127
}
116128

129+
/**
130+
* Enable max conversion number detection for digital controller.
131+
* If the number of ADC conversion is equal to the maximum, the conversion is stopped.
132+
*
133+
* @note Only used for bootloader RNG.
134+
* @param enable true: enable; false: disable
135+
*/
136+
static inline void adc_ll_digi_convert_limit_enable(bool enable)
137+
{
138+
APB_SARADC.saradc_ctrl2.saradc_saradc_meas_num_limit = enable;
139+
}
140+
141+
/**
142+
* Enable output data to DMA from adc digital controller.
143+
*
144+
* @note Only used for bootloader RNG.
145+
*/
146+
static inline void adc_ll_digi_dma_enable(void)
147+
{
148+
APB_SARADC.saradc_dma_conf.saradc_apb_adc_trans = 1;
149+
}
150+
117151
/**
118152
* Sets the number of cycles required for the conversion to complete and wait for the arbiter to stabilize.
119153
*
@@ -140,6 +174,39 @@ static inline void adc_ll_digi_output_invert(adc_unit_t adc_n, bool inv_en)
140174
}
141175
}
142176

177+
/**
178+
* Set the interval clock cycle for the digital controller to trigger the measurement.
179+
* Expression: `trigger_meas_freq` = `controller_clk` / 2 / interval.
180+
*
181+
* @note The trigger interval should not be smaller than the sampling time of the SAR ADC.
182+
* @note Only used for bootloader RNG.
183+
* @param cycle The clock cycle (trigger interval) of the measurement. Range: 30 ~ 4095.
184+
*/
185+
static inline void adc_ll_digi_set_trigger_interval(uint32_t cycle)
186+
{
187+
APB_SARADC.saradc_ctrl2.saradc_saradc_timer_target = cycle;
188+
}
189+
190+
/**
191+
* Enable digital controller timer to trigger the measurement.
192+
*
193+
* @note Only used for bootloader RNG.
194+
*/
195+
static inline void adc_ll_digi_trigger_enable(void)
196+
{
197+
APB_SARADC.saradc_ctrl2.saradc_saradc_timer_en = 1;
198+
}
199+
200+
/**
201+
* Disable digital controller timer to trigger the measurement.
202+
*
203+
* @note Only used for bootloader RNG.
204+
*/
205+
static inline void adc_ll_digi_trigger_disable(void)
206+
{
207+
APB_SARADC.saradc_ctrl2.saradc_saradc_timer_en = 0;
208+
}
209+
143210
/**
144211
* Set ADC digital controller clock division factor. The clock divided from `APLL` or `APB` clock.
145212
* Expression: controller_clk = (APLL or APB) / (div_num + div_a / div_b + 1).
@@ -294,28 +361,28 @@ static inline uint32_t adc_ll_pwdet_get_cct(void)
294361
* @brief Enable the ADC clock
295362
* @param enable true to enable, false to disable
296363
*/
297-
static inline void adc_ll_enable_bus_clock(bool enable)
364+
static inline void _adc_ll_enable_bus_clock(bool enable)
298365
{
299366
SYSTEM.perip_clk_en0.apb_saradc_clk_en = enable;
300367
}
301368
// SYSTEM.perip_clk_en0 is a shared register, so this function must be used in an atomic way
302369
#define adc_ll_enable_bus_clock(...) do { \
303370
(void)__DECLARE_RCC_ATOMIC_ENV; \
304-
adc_ll_enable_bus_clock(__VA_ARGS__); \
371+
_adc_ll_enable_bus_clock(__VA_ARGS__); \
305372
} while(0)
306373

307374
/**
308375
* @brief Reset ADC module
309376
*/
310-
static inline void adc_ll_reset_register(void)
377+
static inline void _adc_ll_reset_register(void)
311378
{
312379
SYSTEM.perip_rst_en0.apb_saradc_rst = 1;
313380
SYSTEM.perip_rst_en0.apb_saradc_rst = 0;
314381
}
315382
// SYSTEM.perip_rst_en0 is a shared register, so this function must be used in an atomic way
316383
#define adc_ll_reset_register(...) do { \
317384
(void)__DECLARE_RCC_ATOMIC_ENV; \
318-
adc_ll_reset_register(__VA_ARGS__); \
385+
_adc_ll_reset_register(__VA_ARGS__); \
319386
} while(0)
320387

321388
/**
@@ -346,6 +413,70 @@ static inline void adc_ll_set_controller(adc_unit_t adc_n, adc_ll_controller_t c
346413
//Not used on ESP32-C2
347414
}
348415

416+
/**
417+
* Set pattern table length for digital controller.
418+
* The pattern table that defines the conversion rules for each SAR ADC. Each table has 8 items, in which channel selection,
419+
* resolution and attenuation are stored. When the conversion is started, the controller reads conversion rules from the
420+
* pattern table one by one. For each controller the scan sequence has at most 8 different rules before repeating itself.
421+
*
422+
* @param adc_n ADC unit.
423+
* @param patt_len Items range: 1 ~ 8.
424+
*
425+
* @note Only used for bootloader RNG.
426+
*/
427+
static inline void adc_ll_digi_set_pattern_table_len(adc_unit_t adc_n, uint32_t patt_len)
428+
{
429+
(void)adc_n;
430+
APB_SARADC.saradc_ctrl.saradc_saradc_sar_patt_len = patt_len - 1;
431+
}
432+
433+
/**
434+
* Reset pattern table to default value
435+
*
436+
* @note Only used for bootloader RNG.
437+
*/
438+
static inline void adc_ll_digi_reset_pattern_table(void)
439+
{
440+
APB_SARADC.saradc_sar_patt_tab1.saradc_saradc_sar_patt_tab1 = 0xffffff;
441+
APB_SARADC.saradc_sar_patt_tab2.saradc_saradc_sar_patt_tab2 = 0xffffff;
442+
}
443+
444+
/**
445+
* Set pattern table for digital controller.
446+
* The pattern table that defines the conversion rules for each SAR ADC. Each table has 8 items, in which channel selection,
447+
* resolution and attenuation are stored. When the conversion is started, the controller reads conversion rules from the
448+
* pattern table one by one. For each controller the scan sequence has at most 8 different rules before repeating itself.
449+
*
450+
* @param adc_n ADC unit.
451+
* @param pattern_index Items index. Range: 0 ~ 7.
452+
* @param table Stored conversion rules.
453+
*
454+
* @note Only used for bootloader RNG.
455+
*/
456+
static inline void adc_ll_digi_set_pattern_table(adc_unit_t adc_n, uint32_t pattern_index, adc_digi_pattern_config_t table)
457+
{
458+
uint32_t tab;
459+
uint8_t index = pattern_index / 4;
460+
uint8_t offset = (pattern_index % 4) * 6;
461+
adc_ll_digi_pattern_table_t pattern = {0};
462+
463+
(void)adc_n;
464+
465+
pattern.val = (table.atten & 0x3) | ((table.channel & 0x7) << 2) | ((table.unit & 0x1) << 5);
466+
467+
if (index == 0) {
468+
tab = APB_SARADC.saradc_sar_patt_tab1.saradc_saradc_sar_patt_tab1; // Read old register value
469+
tab &= (~(0xFC0000 >> offset)); // Clear old data
470+
tab |= ((uint32_t)(pattern.val & 0x3F) << 18) >> offset; // Fill in the new data
471+
APB_SARADC.saradc_sar_patt_tab1.saradc_saradc_sar_patt_tab1 = tab; // Write back
472+
} else {
473+
tab = APB_SARADC.saradc_sar_patt_tab2.saradc_saradc_sar_patt_tab2; // Read old register value
474+
tab &= (~(0xFC0000 >> offset)); // Clear old data
475+
tab |= ((uint32_t)(pattern.val & 0x3F) << 18) >> offset; // Fill in the new data
476+
APB_SARADC.saradc_sar_patt_tab2.saradc_saradc_sar_patt_tab2 = tab; // Write back
477+
}
478+
}
479+
349480
/* ADC calibration code. */
350481
/**
351482
* @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
405536
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_LOW_ADDR, lsb);
406537
}
407538

539+
/**
540+
* Set the SAR DTEST param
541+
*
542+
* @param param DTEST value
543+
*/
544+
__attribute__((always_inline))
545+
static inline void adc_ll_set_dtest_param(uint32_t param)
546+
{
547+
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR, param);
548+
}
549+
550+
/**
551+
* Set the SAR ENT param
552+
*
553+
* @param param ENT value
554+
*/
555+
__attribute__((always_inline))
556+
static inline void adc_ll_set_ent_param(uint32_t param)
557+
{
558+
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_TSENS_ADDR, param);
559+
}
560+
561+
/**
562+
* Enable/disable the calibration voltage reference for ADC unit.
563+
*
564+
* @param adc_n ADC index number.
565+
* @param en true to enable, false to disable
566+
*/
567+
__attribute__((always_inline))
568+
static inline void adc_ll_enable_calibration_ref(adc_unit_t adc_n, bool en)
569+
{
570+
if (adc_n == ADC_UNIT_1) {
571+
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC1_ENCAL_REF_ADDR, en);
572+
} else {
573+
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC2_ENCAL_REF_ADDR, en);
574+
}
575+
}
576+
577+
/**
578+
* Init regi2c SARADC registers
579+
*/
580+
__attribute__((always_inline))
581+
static inline void adc_ll_regi2c_init(void)
582+
{
583+
adc_ll_set_dtest_param(0);
584+
adc_ll_set_ent_param(0);
585+
// Config ADC circuit (Analog part) with I2C(HOST ID 0x69) and chose internal voltage as sampling source
586+
adc_ll_enable_calibration_ref(ADC_UNIT_1, true);
587+
adc_ll_enable_calibration_ref(ADC_UNIT_2, true);
588+
}
589+
590+
/**
591+
* Deinit regi2c SARADC registers
592+
*/
593+
__attribute__((always_inline))
594+
static inline void adc_ll_regi2c_adc_deinit(void)
595+
{
596+
adc_ll_set_dtest_param(0);
597+
adc_ll_set_ent_param(0);
598+
adc_ll_enable_calibration_ref(ADC_UNIT_1, false);
599+
adc_ll_enable_calibration_ref(ADC_UNIT_2, false);
600+
}
601+
408602
/*---------------------------------------------------------------
409603
Oneshot Read
410604
---------------------------------------------------------------*/

0 commit comments

Comments
 (0)