Files
esp-idf/components/bootloader_support/src/bootloader_random.c
Jakob Hasse d7ce04a5cd esp_hw_support: decrease RNG read frequency on C6 and H2
* The RNG reading frequency of 200 KHz has been too high for
  C6 and H2 since on these chips the RNG output is combined
  with the RTC slow clock which is only 150KHz. Reduced the max
  reading frequency via esp_random() from 200KHz to 62.5KHz,
  which show best results in tests.
  Also updated the bootloader_fill_random() max frequency to the
  same value to be in line, even though it was just 83KHz.
2023-05-30 19:16:53 +08:00

118 lines
3.4 KiB
C

/*
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
#include "bootloader_random.h"
#include "esp_cpu.h"
#include "soc/wdev_reg.h"
#if defined CONFIG_IDF_TARGET_ESP32C6
#include "hal/lp_timer_hal.h"
#endif
#ifndef BOOTLOADER_BUILD
#include "esp_random.h"
#include "esp_private/periph_ctrl.h"
__attribute__((weak)) void bootloader_fill_random(void *buffer, size_t length)
{
return esp_fill_random(buffer, length);
}
#else
#if !defined CONFIG_IDF_TARGET_ESP32S3
#if (defined CONFIG_IDF_TARGET_ESP32C6 || defined CONFIG_IDF_TARGET_ESP32H2)
#define RNG_CPU_WAIT_CYCLE_NUM (80 * 16) // Keep the byte sampling frequency in the ~62KHz range which has been
// tested.
#else
#define RNG_CPU_WAIT_CYCLE_NUM (80 * 32 * 2) /* extra factor of 2 is precautionary */
#endif
#else
#define RNG_CPU_WAIT_CYCLE_NUM (80 * 23) /* 45 KHz reading frequency is the maximum we have tested so far on S3 */
#endif
#if defined CONFIG_IDF_TARGET_ESP32H2
// TODO: temporary definition until IDF-6270 is implemented
#include "soc/lp_timer_reg.h"
static inline uint32_t lp_timer_hal_get_cycle_count(void)
{
REG_SET_BIT(LP_TIMER_UPDATE_REG, LP_TIMER_MAIN_TIMER_UPDATE);
uint32_t lo = REG_GET_FIELD(LP_TIMER_MAIN_BUF0_LOW_REG, LP_TIMER_MAIN_TIMER_BUF0_LOW);
return lo;
}
#endif
__attribute__((weak)) void bootloader_fill_random(void *buffer, size_t length)
{
uint8_t *buffer_bytes = (uint8_t *)buffer;
uint32_t random;
uint32_t start, now;
assert(buffer != NULL);
for (size_t i = 0; i < length; i++) {
#if (defined CONFIG_IDF_TARGET_ESP32C6 || defined CONFIG_IDF_TARGET_ESP32H2)
random = REG_READ(WDEV_RND_REG);
start = esp_cpu_get_cycle_count();
do {
random ^= REG_READ(WDEV_RND_REG);
now = esp_cpu_get_cycle_count();
} while (now - start < RNG_CPU_WAIT_CYCLE_NUM);
// XOR the RT slow clock, which is asynchronous, to add some entropy and improve
// the distribution
uint32_t current_rtc_timer_counter = (lp_timer_hal_get_cycle_count() & 0xFF);
random = random ^ current_rtc_timer_counter;
buffer_bytes[i] = random & 0xFF;
#else
if (i == 0 || i % 4 == 0) { /* redundant check is for a compiler warning */
/* in bootloader with ADC feeding HWRNG, we accumulate 1
bit of entropy per 40 APB cycles (==80 CPU cycles.)
To avoid reading the entire RNG hardware state out
as-is, we repeatedly read the RNG register and XOR all
values.
*/
random = REG_READ(WDEV_RND_REG);
start = esp_cpu_get_cycle_count();
do {
random ^= REG_READ(WDEV_RND_REG);
now = esp_cpu_get_cycle_count();
} while (now - start < RNG_CPU_WAIT_CYCLE_NUM);
}
buffer_bytes[i] = random >> ((i % 4) * 8);
#endif
}
}
#ifndef CONFIG_IDF_ENV_FPGA
#else // CONFIG_IDF_ENV_FPGA
#include "esp_log.h"
static void s_non_functional(const char *func)
{
ESP_EARLY_LOGW("rand", "%s non-functional for FPGA builds", func);
}
void bootloader_random_enable()
{
s_non_functional(__func__);
}
void bootloader_random_disable()
{
s_non_functional(__func__);
}
#endif // CONFIG_IDF_ENV_FPGA
#endif // BOOTLOADER_BUILD