From 64a355eba8b63976fe68ef36209c6c8429e6aca7 Mon Sep 17 00:00:00 2001 From: Jakob Hasse Date: Mon, 25 Oct 2021 19:13:42 +0800 Subject: [PATCH] feat (bootloader): added rng sampling Set maximum RNG query frequency to save value known from tests --- .../subproject/main/ld/esp32s3/bootloader.ld | 1 - .../src/bootloader_random.c | 9 +- .../src/bootloader_random_esp32s3.c | 88 +++++++++++++++++-- components/esp_hw_support/hw_random.c | 9 +- .../esp32s3/private_include/regi2c_saradc.h | 22 ++++- 5 files changed, 118 insertions(+), 11 deletions(-) diff --git a/components/bootloader/subproject/main/ld/esp32s3/bootloader.ld b/components/bootloader/subproject/main/ld/esp32s3/bootloader.ld index 244482f823..b35d247e3a 100644 --- a/components/bootloader/subproject/main/ld/esp32s3/bootloader.ld +++ b/components/bootloader/subproject/main/ld/esp32s3/bootloader.ld @@ -30,7 +30,6 @@ SECTIONS *libbootloader_support.a:bootloader_flash.*(.literal .text .literal.* .text.*) *libbootloader_support.a:bootloader_random.*(.literal .text .literal.* .text.*) *libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_disable .text.bootloader_random_disable) - *libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_enable .text.bootloader_random_enable) *libesp_common.a:fpga_overrides.*(.literal.bootloader_fill_random .text.bootloader_fill_random) *libbootloader_support.a:bootloader_efuse_esp32s3.*(.literal .text .literal.* .text.*) *libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*) diff --git a/components/bootloader_support/src/bootloader_random.c b/components/bootloader_support/src/bootloader_random.c index afecc32dd9..412b234f26 100644 --- a/components/bootloader_support/src/bootloader_random.c +++ b/components/bootloader_support/src/bootloader_random.c @@ -18,6 +18,13 @@ } #else + +#if !defined CONFIG_IDF_TARGET_ESP32S3 +#define RNG_CPU_WAIT_CYCLE_NUM (80 * 32 * 2) /* extra factor of 2 is precautionary */ +#else +#define RNG_CPU_WAIT_CYCLE_NUM (80 * 23) /* 45 KHz reading frequency is the maximum we have tested so far on S3 */ +#endif + __attribute__((weak)) void bootloader_fill_random(void *buffer, size_t length) { uint8_t *buffer_bytes = (uint8_t *)buffer; @@ -40,7 +47,7 @@ do { random ^= REG_READ(WDEV_RND_REG); now = cpu_hal_get_cycle_count(); - } while (now - start < 80 * 32 * 2); /* extra factor of 2 is precautionary */ + } while (now - start < RNG_CPU_WAIT_CYCLE_NUM); } buffer_bytes[i] = random >> ((i % 4) * 8); } diff --git a/components/bootloader_support/src/bootloader_random_esp32s3.c b/components/bootloader_support/src/bootloader_random_esp32s3.c index 4b7c1d9a1e..3f80020c2c 100644 --- a/components/bootloader_support/src/bootloader_random_esp32s3.c +++ b/components/bootloader_support/src/bootloader_random_esp32s3.c @@ -6,18 +6,92 @@ #include "sdkconfig.h" #include "bootloader_random.h" #include "esp_log.h" - -static const char *TAG = "bootloader_random"; +#include "soc/system_reg.h" +#include "soc/syscon_reg.h" +#include "soc/apb_saradc_reg.h" +#include "soc/rtc_cntl_reg.h" +#include "soc/sens_reg.h" +#include "regi2c_ctrl.h" +#include "regi2c_saradc.h" void bootloader_random_enable(void) { - ESP_LOGW(TAG, "RNG for ESP32-S3 not currently supported"); // IDF-1878 - // Don't forget to remove the following line - // *libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_enable .text.bootloader_random_enable) - // In the bootloader.ld when RNG support is ready for ESP32-S3 + SET_PERI_REG_MASK(SYSTEM_WIFI_CLK_EN_REG, SYSTEM_WIFI_CLK_RNG_EN); + + // 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); + + /// Enable SAR ADC to read a disconnected input for additional entropy + + // Reset ADC clock + SET_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_APB_SARADC_CLK_EN); + CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_APB_SARADC_CLK_EN); + + // Enable clock and select clock source for ADC digital controller + REG_SET_FIELD(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_CLK_SEL, 2); //APB clock + SET_PERI_REG_MASK(APB_SARADC_CTRL_REG, APB_SARADC_SAR_CLK_GATED); + SET_PERI_REG_MASK(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_CLK_EN); + + // Read freq = apb_clk / (APB_SARADC_CLKM_DIV_NUM + 1) / TIMER_TARGET / 2 + // Internal ADC sample freq = apb_clk / (APB_SARADC_CLKM_DIV_NUM + 1) / (APB_SARADC_SAR_CLK_DIV + 1) + // Read frequency has to be at least 35 times lower than the sampling frequency + + REG_SET_FIELD(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_CLKM_DIV_NUM, 3); + REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_SAR_CLK_DIV, 3); // SAR clock divider has to be at least 2 + REG_SET_FIELD(APB_SARADC_CTRL2_REG, APB_SARADC_TIMER_TARGET, 70); + + CLEAR_PERI_REG_MASK(APB_SARADC_CTRL_REG, APB_SARADC_START_FORCE); + REG_SET_FIELD(SENS_SAR_POWER_XPD_SAR_REG, SENS_FORCE_XPD_SAR, 3); + CLEAR_PERI_REG_MASK(APB_SARADC_CTRL2_REG, APB_SARADC_MEAS_NUM_LIMIT); + REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_WORK_MODE, 1); + + REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_SAR2_PATT_LEN, 0); + WRITE_PERI_REG(APB_SARADC_SAR2_PATT_TAB1_REG,0xafffff); // Test internal voltage if the channel info is 0xa. + REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_SAR1_PATT_LEN, 0); + WRITE_PERI_REG(APB_SARADC_SAR1_PATT_TAB1_REG,0xafffff); // Test internal voltage if the channel info is 0xa. + + // Enable adc1 digital controller + SET_PERI_REG_MASK(SENS_SAR_MEAS1_MUX_REG, SENS_SAR1_DIG_FORCE); + + // Set SARADC2 arbiter + CLEAR_PERI_REG_MASK(SENS_SAR_MEAS2_MUX_REG, SENS_SAR2_RTC_FORCE); + 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_FIX_PRIORITY); + + // Disable ADC filter + REG_SET_FIELD(APB_SARADC_FILTER_CTRL0_REG, APB_SARADC_FILTER_CHANNEL0, 0xD); + REG_SET_FIELD(APB_SARADC_FILTER_CTRL0_REG, APB_SARADC_FILTER_CHANNEL1, 0xD); + + // Start ADC sample + SET_PERI_REG_MASK(APB_SARADC_CTRL2_REG, APB_SARADC_TIMER_SEL); + SET_PERI_REG_MASK(APB_SARADC_CTRL2_REG, APB_SARADC_TIMER_EN); + + /*Choose the appropriate internal voltage to measure*/ + 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); + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR, 0); } void bootloader_random_disable(void) { - ESP_LOGW(TAG, "RNG for ESP32-S3 not currently supported"); // IDF-1878 + /* Restore internal I2C bus state */ + 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); + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR, 0); + + /* Restore SARADC to default mode */ + CLEAR_PERI_REG_MASK(SENS_SAR_MEAS1_MUX_REG, SENS_SAR1_DIG_FORCE); + SET_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_APB_SARADC_CLK_EN); + REG_SET_FIELD(SENS_SAR_POWER_XPD_SAR_REG, SENS_FORCE_XPD_SAR, 0); + CLEAR_PERI_REG_MASK(APB_SARADC_CTRL2_REG, APB_SARADC_TIMER_EN); + CLEAR_PERI_REG_MASK(SENS_SAR_PERI_CLK_GATE_CONF_REG, SENS_SARADC_CLK_EN); + CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_APB_SARADC_CLK_EN); + + /* 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() + in order to get a secondary entropy source. + */ } diff --git a/components/esp_hw_support/hw_random.c b/components/esp_hw_support/hw_random.c index 1dc54d05df..aaf2cc53f2 100644 --- a/components/esp_hw_support/hw_random.c +++ b/components/esp_hw_support/hw_random.c @@ -14,6 +14,13 @@ #include "soc/wdev_reg.h" #include "esp_private/esp_clk.h" +#if defined CONFIG_IDF_TARGET_ESP32S3 +#define APB_CYCLE_WAIT_NUM (1778) /* If APB clock is 80 MHz, maximum sampling frequency is around 45 KHz*/ + /* 45 KHz reading frequency is the maximum we have tested so far on S3 */ +#else +#define APB_CYCLE_WAIT_NUM (16) +#endif + uint32_t IRAM_ATTR esp_random(void) { /* The PRNG which implements WDEV_RANDOM register gets 2 bits @@ -42,7 +49,7 @@ uint32_t IRAM_ATTR esp_random(void) do { ccount = cpu_hal_get_cycle_count(); result ^= REG_READ(WDEV_RND_REG); - } while (ccount - last_ccount < cpu_to_apb_freq_ratio * 16); + } while (ccount - last_ccount < cpu_to_apb_freq_ratio * APB_CYCLE_WAIT_NUM); last_ccount = ccount; return result ^ REG_READ(WDEV_RND_REG); } diff --git a/components/esp_hw_support/port/esp32s3/private_include/regi2c_saradc.h b/components/esp_hw_support/port/esp32s3/private_include/regi2c_saradc.h index 4224e92dcf..388f9c6221 100644 --- a/components/esp_hw_support/port/esp32s3/private_include/regi2c_saradc.h +++ b/components/esp_hw_support/port/esp32s3/private_include/regi2c_saradc.h @@ -16,7 +16,7 @@ */ #define I2C_SAR_ADC 0X69 -#define I2C_SAR_ADC_HOSTID 0 +#define I2C_SAR_ADC_HOSTID 1 #define ADC_SAR1_ENCAL_GND_ADDR 0x7 #define ADC_SAR1_ENCAL_GND_ADDR_MSB 5 @@ -53,3 +53,23 @@ #define ADC_SAR1_SAMPLE_CYCLE_ADDR 0x2 #define ADC_SAR1_SAMPLE_CYCLE_ADDR_MSB 0x2 #define ADC_SAR1_SAMPLE_CYCLE_ADDR_LSB 0x0 + +#define ADC_SARADC_DTEST_RTC_ADDR 0x7 +#define ADC_SARADC_DTEST_RTC_ADDR_MSB 1 +#define ADC_SARADC_DTEST_RTC_ADDR_LSB 0 + +#define ADC_SARADC_ENT_TSENS_ADDR 0x7 +#define ADC_SARADC_ENT_TSENS_ADDR_MSB 2 +#define ADC_SARADC_ENT_TSENS_ADDR_LSB 2 + +#define ADC_SARADC_ENT_RTC_ADDR 0x7 +#define ADC_SARADC_ENT_RTC_ADDR_MSB 3 +#define ADC_SARADC_ENT_RTC_ADDR_LSB 3 + +#define ADC_SARADC_ENCAL_REF_ADDR 0x7 +#define ADC_SARADC_ENCAL_REF_ADDR_MSB 4 +#define ADC_SARADC_ENCAL_REF_ADDR_LSB 4 + +#define I2C_SARADC_TSENS_DAC 0x6 +#define I2C_SARADC_TSENS_DAC_MSB 3 +#define I2C_SARADC_TSENS_DAC_LSB 0