diff --git a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_random.c b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_random.c index 81f7707718..ba7469c4b2 100644 --- a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_random.c +++ b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_random.c @@ -1,13 +1,24 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include #include +#include +#include +#include "sdkconfig.h" +#include "soc/soc_caps.h" #include "unity.h" #include "esp_random.h" +#if SOC_LIGHT_SLEEP_SUPPORTED +#include "esp_sleep.h" +#include "esp_private/esp_sleep_internal.h" +#include "esp_private/sleep_cpu.h" +#include "esp_private/esp_pmu.h" +#endif + /* Note: these are just sanity tests, not the same as entropy tests */ @@ -69,3 +80,57 @@ TEST_CASE("call esp_fill_random()", "[random]") TEST_ASSERT_EQUAL_HEX8(0xFF, one_buf[x]); } } + +TEST_CASE("verify esp_random() bit balance 0/1 ratio", "[random]") +{ +#if SOC_LIGHT_SLEEP_SUPPORTED + esp_sleep_context_t sleep_ctx; + esp_sleep_set_sleep_context(&sleep_ctx); + printf("go to light sleep for 1 seconds\r\n"); +#if CONFIG_PM_ESP_SLEEP_POWER_DOWN_CPU + TEST_ESP_OK(sleep_cpu_configure(true)); +#endif + TEST_ESP_OK(esp_sleep_enable_timer_wakeup(1 * 1000 * 1000)); + TEST_ESP_OK(esp_light_sleep_start()); +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && !SOC_PM_TOP_PD_NOT_ALLOWED + // check if the power domain also is powered down + TEST_ASSERT_EQUAL(PMU_SLEEP_PD_TOP, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP); +#endif + esp_sleep_set_sleep_context(NULL); + printf("Waked up! Let's see if esp_random can still work correctly...\r\n"); +#if CONFIG_PM_ESP_SLEEP_POWER_DOWN_CPU + TEST_ESP_OK(sleep_cpu_configure(false)); +#endif +#endif + + const size_t NUM_RANDOM = 50000; /* Need enough samples for statistical significance */ + const float EXPECTED_RATIO = 0.5f; /* Expected ratio of 1s */ + const float TOLERANCE = 0.01f; /* Allow 1% deviation (49%-51%) */ + uint32_t bit_counts[32] = {0}; /* Count of 1s for each bit position */ + /* Collect random numbers and count 1s in each bit position */ + for (int i = 0; i < NUM_RANDOM; i++) { + uint32_t r = esp_random(); + for (int bit = 0; bit < 32; bit++) { + if (r & (1U << bit)) { + bit_counts[bit]++; + } + } + } + /* Verify each bit position has approximately 50% ones */ + printf("\nBit balance statistics (total samples: %zu):\n", NUM_RANDOM); + printf("Bit | 1s count | 0s count | 1s ratio | 0s ratio | Deviation\n"); + printf("----|----------|----------|----------|----------|----------\n"); + for (int bit = 0; bit < 32; bit++) { + uint32_t ones_count = bit_counts[bit]; + uint32_t zeros_count = NUM_RANDOM - ones_count; + float ratio_ones = (float)ones_count / NUM_RANDOM; + float ratio_zeros = (float)zeros_count / NUM_RANDOM; + float deviation = fabs(ratio_ones - EXPECTED_RATIO); + + printf("%3d | %8" PRIu32 " | %8" PRIu32 " | %8.4f | %8.4f | %9.4f\n", + bit, ones_count, zeros_count, ratio_ones, ratio_zeros, deviation); + + /* Check if ratio is within tolerance */ + TEST_ASSERT_LESS_THAN_FLOAT(TOLERANCE, deviation); + } +} diff --git a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/sdkconfig.ci.release b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/sdkconfig.ci.release index 8b0a31a9bc..c7a5959d40 100644 --- a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/sdkconfig.ci.release +++ b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/sdkconfig.ci.release @@ -4,3 +4,5 @@ CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y # we can silent the assertion to save the binary footprint CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y + +CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y diff --git a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/sdkconfig.defaults b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/sdkconfig.defaults index cc85282c55..c8801945ed 100644 --- a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/sdkconfig.defaults +++ b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/sdkconfig.defaults @@ -6,3 +6,6 @@ CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y # we can silent the assertion to save the binary footprint CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y + +# primitives for checking sleep internal state +CONFIG_ESP_SLEEP_DEBUG=y