Преглед изворни кода

Merge branch 'feature/s3_rng' into 'master'

Bootloader add rng sampling

Closes IDF-1878 and IDF-4417

See merge request espressif/esp-idf!15737
Mahavir Jain пре 4 година
родитељ
комит
355e8bba76

+ 0 - 1
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_flash.*(.literal .text .literal.* .text.*)
     *libbootloader_support.a:bootloader_random.*(.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_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)
     *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_efuse_esp32s3.*(.literal .text .literal.* .text.*)
     *libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*)
     *libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*)

+ 8 - 1
components/bootloader_support/src/bootloader_random.c

@@ -18,6 +18,13 @@
 }
 }
 
 
 #else
 #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)
  __attribute__((weak)) void bootloader_fill_random(void *buffer, size_t length)
 {
 {
     uint8_t *buffer_bytes = (uint8_t *)buffer;
     uint8_t *buffer_bytes = (uint8_t *)buffer;
@@ -40,7 +47,7 @@
             do {
             do {
                 random ^= REG_READ(WDEV_RND_REG);
                 random ^= REG_READ(WDEV_RND_REG);
                 now = cpu_hal_get_cycle_count();
                 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);
         buffer_bytes[i] = random >> ((i % 4) * 8);
     }
     }

+ 81 - 7
components/bootloader_support/src/bootloader_random_esp32s3.c

@@ -6,18 +6,92 @@
 #include "sdkconfig.h"
 #include "sdkconfig.h"
 #include "bootloader_random.h"
 #include "bootloader_random.h"
 #include "esp_log.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)
 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)
 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.
+    */
 }
 }

+ 8 - 1
components/esp_hw_support/hw_random.c

@@ -14,6 +14,13 @@
 #include "soc/wdev_reg.h"
 #include "soc/wdev_reg.h"
 #include "esp_private/esp_clk.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)
 uint32_t IRAM_ATTR esp_random(void)
 {
 {
     /* The PRNG which implements WDEV_RANDOM register gets 2 bits
     /* The PRNG which implements WDEV_RANDOM register gets 2 bits
@@ -42,7 +49,7 @@ uint32_t IRAM_ATTR esp_random(void)
     do {
     do {
         ccount = cpu_hal_get_cycle_count();
         ccount = cpu_hal_get_cycle_count();
         result ^= REG_READ(WDEV_RND_REG);
         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;
     last_ccount = ccount;
     return result ^ REG_READ(WDEV_RND_REG);
     return result ^ REG_READ(WDEV_RND_REG);
 }
 }

+ 21 - 1
components/esp_hw_support/port/esp32s3/private_include/regi2c_saradc.h

@@ -16,7 +16,7 @@
  */
  */
 
 
 #define I2C_SAR_ADC            0X69
 #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 0x7
 #define ADC_SAR1_ENCAL_GND_ADDR_MSB 5
 #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 0x2
 #define ADC_SAR1_SAMPLE_CYCLE_ADDR_MSB 0x2
 #define ADC_SAR1_SAMPLE_CYCLE_ADDR_MSB 0x2
 #define ADC_SAR1_SAMPLE_CYCLE_ADDR_LSB 0x0
 #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