diff --git a/drivers/entropy/entropy_esp32.c b/drivers/entropy/entropy_esp32.c index ddcf961fe4a..ab0c4e81c26 100644 --- a/drivers/entropy/entropy_esp32.c +++ b/drivers/entropy/entropy_esp32.c @@ -20,6 +20,26 @@ LOG_MODULE_REGISTER(entropy, CONFIG_ENTROPY_LOG_LEVEL); +#if SOC_LP_TIMER_SUPPORTED +#include "hal/lp_timer_hal.h" +#endif + +#if defined CONFIG_SOC_SERIES_ESP32S3 +/* If APB clock is 80 MHz, the maximum sampling frequency is around 45 KHz */ +/* 45 KHz reading frequency is the maximum we have tested so far on S3 */ +#define APB_CYCLE_WAIT_NUM (1778) +#elif defined CONFIG_SOC_SERIES_ESP32C6 +/* On ESP32C6, we only read one byte at a time, then XOR the value with + * an asynchronous timer (see code below). + * The current value translates to a sampling frequency of around 62.5 KHz + * for reading 8 bit samples, which is the rate at which the RNG was tested, + * plus additional overhead for the calculation, making it slower. + */ +#define APB_CYCLE_WAIT_NUM (160 * 16) +#else +#define APB_CYCLE_WAIT_NUM (16) +#endif + static inline uint32_t entropy_esp32_get_u32(void) { /* The PRNG which implements WDEV_RANDOM register gets 2 bits @@ -30,18 +50,29 @@ static inline uint32_t entropy_esp32_get_u32(void) * wait a bit longer due to extra time spent in arithmetic and branch statements. */ - uint32_t cpu_to_apb_freq_ratio = - esp_clk_cpu_freq() / esp_clk_apb_freq(); + uint32_t cpu_to_apb_freq_ratio = esp_clk_cpu_freq() / esp_clk_apb_freq(); static uint32_t last_ccount; uint32_t ccount; - + uint32_t result = 0; +#if SOC_LP_TIMER_SUPPORTED + for (size_t i = 0; i < sizeof(result); i++) { + do { + ccount = esp_cpu_get_cycle_count(); + result ^= REG_READ(WDEV_RND_REG); + } while (ccount - last_ccount < cpu_to_apb_freq_ratio * APB_CYCLE_WAIT_NUM); + uint32_t current_rtc_timer_counter = (lp_timer_hal_get_cycle_count() & 0xFF); + + result ^= ((result ^ current_rtc_timer_counter) & 0xFF) << (i * 8); + } +#else do { ccount = esp_cpu_get_cycle_count(); - } while (ccount - last_ccount < cpu_to_apb_freq_ratio * 16); + result ^= REG_READ(WDEV_RND_REG); + } while (ccount - last_ccount < cpu_to_apb_freq_ratio * APB_CYCLE_WAIT_NUM); +#endif last_ccount = ccount; - - return REG_READ(WDEV_RND_REG); + return result ^ REG_READ(WDEV_RND_REG); } static int entropy_esp32_get_entropy(const struct device *dev, uint8_t *buf,