From 124501eb46287715209492830dc174b23098b96c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Fri, 18 Jul 2025 14:06:11 +0200 Subject: [PATCH] Rewrite RNG --- esp-hal/CHANGELOG.md | 3 + esp-hal/MIGRATING-1.0.0-rc.0.md | 26 + esp-hal/src/rng.rs | 271 ----------- esp-hal/src/rng/ll.rs | 87 ++++ esp-hal/src/rng/mod.rs | 459 ++++++++++++++++++ .../src/_build_script_utils.rs | 38 ++ .../src/_generated_esp32.rs | 6 + .../src/_generated_esp32c2.rs | 12 + .../src/_generated_esp32c3.rs | 12 + .../src/_generated_esp32c6.rs | 12 + .../src/_generated_esp32h2.rs | 12 + .../src/_generated_esp32s2.rs | 6 + .../src/_generated_esp32s3.rs | 6 + esp-metadata/devices/esp32.toml | 8 +- esp-metadata/devices/esp32c2.toml | 10 +- esp-metadata/devices/esp32c3.toml | 10 +- esp-metadata/devices/esp32c6.toml | 11 +- esp-metadata/devices/esp32h2.toml | 11 +- esp-metadata/devices/esp32s2.toml | 7 +- esp-metadata/devices/esp32s3.toml | 7 +- esp-metadata/src/cfg.rs | 11 +- esp-wifi/CHANGELOG.md | 1 + esp-wifi/MIGRATING-0.15.0.md | 10 + esp-wifi/src/ble/btdm.rs | 7 + esp-wifi/src/ble/npl.rs | 11 +- esp-wifi/src/common_adapter/mod.rs | 6 +- esp-wifi/src/lib.rs | 19 +- esp-wifi/src/wifi/mod.rs | 7 + examples/src/bin/hmac.rs | 2 +- examples/src/bin/wifi_80211_tx.rs | 11 +- examples/src/bin/wifi_access_point.rs | 5 +- .../src/bin/wifi_access_point_with_sta.rs | 5 +- examples/src/bin/wifi_bench.rs | 5 +- examples/src/bin/wifi_ble.rs | 3 +- examples/src/bin/wifi_coex.rs | 5 +- examples/src/bin/wifi_csi.rs | 5 +- examples/src/bin/wifi_dhcp.rs | 5 +- examples/src/bin/wifi_embassy_access_point.rs | 7 +- .../bin/wifi_embassy_access_point_with_sta.rs | 7 +- examples/src/bin/wifi_embassy_bench.rs | 7 +- examples/src/bin/wifi_embassy_ble.rs | 6 +- examples/src/bin/wifi_embassy_dhcp.rs | 7 +- examples/src/bin/wifi_embassy_esp_now.rs | 7 +- .../src/bin/wifi_embassy_esp_now_duplex.rs | 7 +- examples/src/bin/wifi_esp_now.rs | 3 +- examples/src/bin/wifi_sniffer.rs | 4 +- examples/src/bin/wifi_static_ip.rs | 5 +- hil-test/Cargo.toml | 4 + hil-test/tests/alloc_psram.rs | 2 +- hil-test/tests/ecc.rs | 39 +- hil-test/tests/esp_wifi_ble_controller.rs | 8 +- hil-test/tests/esp_wifi_floats.rs | 12 +- hil-test/tests/esp_wifi_init.rs | 25 +- hil-test/tests/rng.rs | 66 +++ hil-test/tests/sha.rs | 13 +- 55 files changed, 933 insertions(+), 428 deletions(-) create mode 100644 esp-hal/MIGRATING-1.0.0-rc.0.md delete mode 100644 esp-hal/src/rng.rs create mode 100644 esp-hal/src/rng/ll.rs create mode 100644 esp-hal/src/rng/mod.rs create mode 100644 esp-wifi/MIGRATING-0.15.0.md create mode 100644 hil-test/tests/rng.rs diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index c693ad560d8..f13d90452a8 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -10,9 +10,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - A reimplemntation of the `assign_resources!` macro (#3809) +- `TrngSource` to manage random number generator entropy (#3829) ### Changed +- The `rng` module has been rewritten (#3829) ### Fixed @@ -21,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Removed +- `Trng::new` (replaced by `Trng::try_new`) (#3829) ## [v1.0.0-rc.0] - 2025-07-16 diff --git a/esp-hal/MIGRATING-1.0.0-rc.0.md b/esp-hal/MIGRATING-1.0.0-rc.0.md new file mode 100644 index 00000000000..93ae4b91533 --- /dev/null +++ b/esp-hal/MIGRATING-1.0.0-rc.0.md @@ -0,0 +1,26 @@ +# Migration Guide from 1.0.0-rc.0 to {{currentVersion}} + +## RNG changes + +Random number generator objects can now be created anywhere. The `RNG` peripheral singleton +is only necessary to enable the cryptographically secure random number generator. + + - `Rng` can be constructed without any constraints. + - `Trng` can only be constructed when it can be ensured to generate true random numbers. + +A new `TrngSource` object has been added. Users can use `TrngSource::new` to create the object, +and as long as it is alive, `Trng::try_new` will return `Ok` and will provide a true random number +generator interface. + +The previous way to obtain RNG object has changed like so: + +```diff +-let mut rng = Rng::new(peripherals.RNG); ++let rng = Rng::new(); + +-let mut trng = Trng::new(peripherals.RNG, peripherals.ADC1); ++// Once: ++let trng_source = TrngSource::new(peripherals.RNG, peripherals.ADC1); ++// As long as `trng_source` is alive: ++let trng = Tnrg::try_new().unrwap(); +``` diff --git a/esp-hal/src/rng.rs b/esp-hal/src/rng.rs deleted file mode 100644 index 8e2ac280216..00000000000 --- a/esp-hal/src/rng.rs +++ /dev/null @@ -1,271 +0,0 @@ -#![cfg_attr(docsrs, procmacros::doc_replace( - "analog_pin" => { - cfg(esp32) => "let analog_pin = peripherals.GPIO32;", - cfg(not(esp32)) => "let analog_pin = peripherals.GPIO3;" - } -))] -//! # Random Number Generator (RNG) -//! -//! ## Overview -//! The Random Number Generator (RNG) module provides an interface to generate -//! random numbers using the RNG peripheral on ESP chips. This driver allows you -//! to generate random numbers that can be used for various cryptographic, -//! security, or general-purpose applications. -//! -//! There are certain pre-conditions which must be met in order for the RNG to -//! produce *true* random numbers. The hardware RNG produces true random numbers -//! under any of the following conditions: -//! -//! - RF subsystem is enabled (i.e. Wi-Fi or Bluetooth are enabled). -//! - An internal entropy source has been enabled by calling `bootloader_random_enable()` and not -//! yet disabled by calling `bootloader_random_disable()`. -//! - While the ESP-IDF Second stage bootloader is running. This is because the default ESP-IDF -//! bootloader implementation calls `bootloader_random_enable()` when the bootloader starts, and -//! `bootloader_random_disable()` before executing the app. -//! -//! When any of these conditions are true, samples of physical noise are -//! continuously mixed into the internal hardware RNG state to provide entropy. -//! If none of the above conditions are true, the output of the RNG should be -//! considered pseudo-random only. -//! -//! For more information, please refer to the -#![doc = concat!("[ESP-IDF documentation](https://docs.espressif.com/projects/esp-idf/en/latest/", chip!(), "/api-reference/system/random.html)")] -//! ## Configuration -//! To use the [Rng] Driver, you need to initialize it with the RNG peripheral. -//! Once initialized, you can generate random numbers by calling the `random` -//! method, which returns a 32-bit unsigned integer. -//! -//! ## Usage -//! The driver implements the traits from the [`rand_core`] crate. -//! -//! [`rand_core`]: https://crates.io/crates/rand_core -//! -//! ## Examples -//! -//! ### Basic RNG operation -//! -//! ```rust, no_run -//! # {before_snippet} -//! # use esp_hal::rng::Rng; -//! -//! let mut rng = Rng::new(peripherals.RNG); -//! -//! // Generate a random word (u32): -//! let rand_word = rng.random(); -//! -//! // Fill a buffer with random bytes: -//! let mut buf = [0u8; 16]; -//! rng.read(&mut buf); -//! -//! loop {} -//! # } -//! ``` -//! -//! ### TRNG operation -//! ```rust, no_run -//! # {before_snippet} -//! # use esp_hal::Blocking; -//! # use esp_hal::rng::Trng; -//! # use esp_hal::peripherals::Peripherals; -//! # use esp_hal::peripherals::ADC1; -//! # use esp_hal::analog::adc::{AdcConfig, Attenuation, Adc}; -//! -//! let mut buf = [0u8; 16]; -//! -//! // ADC is not available from now -//! let mut trng = Trng::new(peripherals.RNG, peripherals.ADC1.reborrow()); -//! trng.read(&mut buf); -//! let mut true_rand = trng.random(); -//! let mut rng = trng.downgrade(); -//! // ADC is available now -//! # {analog_pin} -//! let mut adc1_config = AdcConfig::new(); -//! let mut adc1_pin = adc1_config.enable_pin(analog_pin, Attenuation::_11dB); -//! let mut adc1 = Adc::::new(peripherals.ADC1, adc1_config); -//! let pin_value: u16 = nb::block!(adc1.read_oneshot(&mut adc1_pin))?; -//! rng.read(&mut buf); -//! true_rand = rng.random(); -//! let pin_value: u16 = nb::block!(adc1.read_oneshot(&mut adc1_pin))?; -//! # {after_snippet} -//! ``` - -use crate::{ - peripherals::{ADC1, RNG}, - private::Sealed, -}; - -/// Random number generator driver -#[derive(Clone, Copy)] -#[non_exhaustive] -pub struct Rng; - -impl Rng { - /// Create a new random number generator instance - pub fn new(_rng: RNG<'_>) -> Self { - Self - } - - #[inline] - /// Reads currently available `u32` integer from `RNG` - pub fn random(&mut self) -> u32 { - // SAFETY: read-only register access - RNG::regs().data().read().bits() - } - - #[inline] - /// Reads enough bytes from hardware random number generator to fill - /// `buffer`. - /// - /// If any error is encountered then this function immediately returns. The - /// contents of buf are unspecified in this case. - /// - /// If this function returns an error, it is unspecified how many bytes it - /// has read, but it will never read more than would be necessary to - /// completely fill the buffer. - pub fn read(&mut self, buffer: &mut [u8]) { - for chunk in buffer.chunks_mut(4) { - let bytes = self.random().to_le_bytes(); - chunk.copy_from_slice(&bytes[..chunk.len()]); - } - } -} - -impl Sealed for Rng {} - -#[instability::unstable] -impl rand_core_06::RngCore for Rng { - fn next_u32(&mut self) -> u32 { - self.random() - } - - fn next_u64(&mut self) -> u64 { - let upper = self.random() as u64; - let lower = self.random() as u64; - - (upper << 32) | lower - } - - fn fill_bytes(&mut self, dest: &mut [u8]) { - self.read(dest); - } - - fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core_06::Error> { - self.read(dest); - Ok(()) - } -} - -#[instability::unstable] -impl rand_core_09::RngCore for Rng { - fn next_u32(&mut self) -> u32 { - self.random() - } - fn next_u64(&mut self) -> u64 { - let upper = self.random() as u64; - let lower = self.random() as u64; - - (upper << 32) | lower - } - fn fill_bytes(&mut self, dest: &mut [u8]) { - self.read(dest); - } -} - -/// True Random Number Generator (TRNG) driver -/// -/// The `Trng` struct represents a true random number generator that combines -/// the randomness from the hardware RNG and an ADC. This struct provides -/// methods to generate random numbers and fill buffers with random bytes. -/// Due to pulling the entropy source from the ADC, it uses the associated -/// registers, so to use TRNG we need to "occupy" the ADC peripheral. -pub struct Trng<'d> { - /// The hardware random number generator instance. - pub rng: Rng, - /// A mutable reference to the ADC1 instance. - _adc: ADC1<'d>, -} - -impl<'d> Trng<'d> { - /// Creates a new True Random Number Generator (TRNG) instance. - /// - /// # Arguments - /// - /// * `rng` - A peripheral instance implementing the `RNG` trait. - /// * `adc` - A mutable reference to an `Adc` instance. - /// - /// # Returns - /// - /// Returns a new `Trng` instance. - pub fn new(rng: RNG<'_>, adc: ADC1<'d>) -> Self { - let r#gen = Rng::new(rng); - crate::soc::trng::ensure_randomness(); - Self { - rng: r#gen, - _adc: adc, - } - } - - /// Reads currently available `u32` integer from `TRNG` - pub fn random(&mut self) -> u32 { - self.rng.random() - } - - /// Fills the provided buffer with random bytes. - pub fn read(&mut self, buffer: &mut [u8]) { - self.rng.read(buffer); - } - - /// Downgrades the `Trng` instance to a `Rng` instance and releases the - /// ADC1. - pub fn downgrade(self) -> Rng { - self.rng - } -} - -impl Drop for Trng<'_> { - fn drop(&mut self) { - crate::soc::trng::revert_trng(); - } -} - -/// Implementing RngCore trait from rand_core for `Trng` structure -#[instability::unstable] -impl rand_core_06::RngCore for Trng<'_> { - fn next_u32(&mut self) -> u32 { - self.rng.next_u32() - } - - fn next_u64(&mut self) -> u64 { - self.rng.next_u64() - } - - fn fill_bytes(&mut self, dest: &mut [u8]) { - self.rng.fill_bytes(dest) - } - - fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core_06::Error> { - self.rng.try_fill_bytes(dest) - } -} - -#[instability::unstable] -impl rand_core_09::RngCore for Trng<'_> { - fn next_u32(&mut self) -> u32 { - self.rng.next_u32() - } - fn next_u64(&mut self) -> u64 { - self.rng.next_u64() - } - fn fill_bytes(&mut self, dest: &mut [u8]) { - self.rng.fill_bytes(dest) - } -} - -/// Implementing a CryptoRng marker trait that indicates that the generator is -/// cryptographically secure. -#[instability::unstable] -impl rand_core_06::CryptoRng for Trng<'_> {} -#[instability::unstable] -impl rand_core_09::CryptoRng for Trng<'_> {} - -impl Sealed for Trng<'_> {} diff --git a/esp-hal/src/rng/ll.rs b/esp-hal/src/rng/ll.rs new file mode 100644 index 00000000000..33b6e3d9841 --- /dev/null +++ b/esp-hal/src/rng/ll.rs @@ -0,0 +1,87 @@ +use crate::{clock::Clocks, peripherals::RNG, sync::Locked}; + +// TODO: find a better place for these +#[inline] +#[cfg(soc_cpu_has_prv_mode)] +fn tee_enabled() -> bool { + false +} + +#[inline] +fn current_cpu_cycles() -> usize { + cfg_if::cfg_if! { + if #[cfg(xtensa)] { + xtensa_lx::timer::get_cycle_count() as usize + } else if #[cfg(soc_cpu_has_csr_pc)] { + const PRV_M: usize = 3; + macro_rules! read_csr_fn { + ($fnname:ident, $csr:literal) => { + #[inline] + fn $fnname() -> usize { + riscv::read_csr!($csr); + + unsafe { _read() } + } + } + } + + read_csr_fn!(read_pccr_machine, 0x7e2); + read_csr_fn!(read_pccr_user, 0x802); + + fn read_prv_mode() -> usize { + #[cfg(soc_cpu_has_prv_mode)] + if tee_enabled() { + riscv::read_csr!(0x810); + return unsafe { _read() }; + } + + PRV_M + } + + if read_prv_mode() == PRV_M { + read_pccr_machine() + } else { + read_pccr_user() + } + } else { + riscv::register::mcycle::read() + } + } +} + +static LAST_READ: Locked = Locked::new(0); + +fn read_one(wait_cycles: usize) -> u32 { + loop { + let random = LAST_READ.with(|last_wait_start| { + let now: usize = current_cpu_cycles(); + if now.wrapping_sub(*last_wait_start) >= wait_cycles { + *last_wait_start = now; + Some(RNG::regs().data().read().bits()) + } else { + None + } + }); + if let Some(random) = random { + return random; + } + } +} + +pub(super) fn fill_ptr_range(data: *mut u8, len: usize) { + let clocks = Clocks::get(); + let cpu_to_apb_freq_ratio = clocks.cpu_clock / clocks.apb_clock; + let wait_cycles = cpu_to_apb_freq_ratio as usize * property!("rng.apb_cycle_wait_num"); + + let mut remaining = len; + let mut dst = data; + while remaining > 0 { + let random_bytes = read_one(wait_cycles).to_le_bytes(); + let bytes_to_copy = random_bytes.len().min(remaining); + unsafe { + dst.copy_from_nonoverlapping(random_bytes.as_ptr(), bytes_to_copy); + dst = dst.add(bytes_to_copy); + } + remaining -= bytes_to_copy; + } +} diff --git a/esp-hal/src/rng/mod.rs b/esp-hal/src/rng/mod.rs new file mode 100644 index 00000000000..f1895244ca0 --- /dev/null +++ b/esp-hal/src/rng/mod.rs @@ -0,0 +1,459 @@ +#![cfg_attr(docsrs, procmacros::doc_replace( + "analog_pin" => { + cfg(esp32) => "let analog_pin = peripherals.GPIO32;", + cfg(not(esp32)) => "let analog_pin = peripherals.GPIO3;" + }, + "documentation" => concat!("[ESP-IDF documentation](https://docs.espressif.com/projects/esp-idf/en/latest/", chip!(), "/api-reference/system/random.html)") +))] +//! # Random Number Generator (RNG) +//! +//! ## Overview +//! The Random Number Generator (RNG) module provides an interface to generate +//! random numbers using the RNG peripheral on ESP chips. This driver allows you +//! to generate random numbers that can be used for various cryptographic, +//! security, or general-purpose applications. +//! +//! There are certain pre-conditions which must be met in order for the RNG to +//! produce *true* random numbers. The hardware RNG produces true random numbers +//! under any of the following conditions: +//! +//! - RF subsystem is enabled (i.e. Wi-Fi or Bluetooth are enabled). +//! - An ADC is used to generate entropy. +//! - An internal entropy source has been enabled by calling `bootloader_random_enable()` and not +//! yet disabled by calling `bootloader_random_disable()`. As the default bootloader calls +//! `bootloader_random_disable()` automatically, this option requires a custom bootloader build. +//! +//! When any of these conditions are true, samples of physical noise are +//! continuously mixed into the internal hardware RNG state to provide entropy. +//! If none of the above conditions are true, the output of the RNG should be +//! considered pseudo-random only. +//! +//! > Note that, when the Wi-Fi module is enabled, the value read from the high-speed ADC can be +//! > saturated in some extreme cases, which lowers the entropy. Thus, it is advisable to also +//! > enable the SAR ADC as the noise source for the random number generator for such cases. +//! +//! For more information, please refer to the +//! # {documentation} +//! +//! ## Configuration +//! +//! To generate pseudo-random numbers, you can create [`Rng`] at any time. To generate +//! true random numbers, you need to create an instance of [`TrngSource`]. Once you've +//! done that, you can create [`Trng`] instances at any time, as long as the [`TrngSource`] +//! is alive. +//! +//! ## Compatibility with [`rand_core`] +//! +//! The [`Rng`] and [`Trng`] drivers implement the relevant +//! traits from versions `0.6` and `0.9` of the [`rand_core`] crate. +//! +//! [`rand_core`]: https://crates.io/crates/rand_core +//! +//! ## Compatibility with [`getrandom`] +//! The driver can be used to implement a custom backend for `getrandom`. +//! +//! ### Example +//! +//! The following example demonstrates how to set up a [custom backend] using `getrandom v0.3.3`: +//! +//! ```rust, ignore +//! use getrandom::Error; +//! +//! #[no_mangle] +//! unsafe extern "Rust" fn __getrandom_v03_custom( +//! dest: *mut u8, +//! len: usize, +//! ) -> Result<(), Error> { +//! unsafe { esp_hal::rng:Rng::new().read_into_raw() }; +//! Ok(()) +//! } +//! ``` +//! +//! [`getrandom`]: https://crates.io/crates/getrandom +//! [custom backend]: https://github.com/rust-random/getrandom/tree/v0.3.3?tab=readme-ov-file#custom-backend +//! +//! ## Examples +//! +//! ### Basic RNG operation +//! +//! ```rust, no_run +//! # {before_snippet} +//! # use esp_hal::rng::Rng; +//! +//! let rng = Rng::new(); +//! +//! // Generate a random word (u32): +//! let rand_word = rng.random(); +//! +//! // Fill a buffer with random bytes: +//! let mut buf = [0u8; 16]; +//! rng.read(&mut buf); +//! +//! loop {} +//! # } +//! ``` +//! +//! ### TRNG operation +//! ```rust, no_run +//! # {before_snippet} +//! # use esp_hal::Blocking; +//! # use esp_hal::peripherals::ADC1; +//! # use esp_hal::analog::adc::{AdcConfig, Attenuation, Adc}; +//! # +//! use esp_hal::rng::{Trng, TrngSource}; +//! +//! let mut buf = [0u8; 16]; +//! +//! // ADC is not available from now +//! let trng_source = TrngSource::new(peripherals.RNG, peripherals.ADC1.reborrow()); +//! +//! let trng = Trng::try_new().unwrap(); // Unwrap is safe as we have enabled TrngSource. +//! +//! // Generate true random numbers +//! trng.read(&mut buf); +//! let true_random_number = trng.random(); +//! +//! // Downgrade to Rng to allow disabling the TrngSource +//! let rng = trng.downgrade(); +//! +//! // Drop the true random number source. ADC is available now. +//! core::mem::drop(trng_source); +//! +//! # {analog_pin} +//! +//! let mut adc1_config = AdcConfig::new(); +//! let mut adc1_pin = adc1_config.enable_pin(analog_pin, Attenuation::_11dB); +//! let mut adc1 = Adc::::new(peripherals.ADC1, adc1_config); +//! let pin_value: u16 = nb::block!(adc1.read_oneshot(&mut adc1_pin))?; +//! +//! // Now we can only generate pseudo-random numbers... +//! rng.read(&mut buf); +//! let pseudo_random_number = rng.random(); +//! +//! // ... but the ADC is available for use. +//! let pin_value: u16 = nb::block!(adc1.read_oneshot(&mut adc1_pin))?; +//! # {after_snippet} +//! ``` + +mod ll; + +use portable_atomic::{AtomicUsize, Ordering}; + +static TRNG_ENABLED: AtomicUsize = AtomicUsize::new(0); +static TRNG_USERS: AtomicUsize = AtomicUsize::new(0); + +use crate::peripherals::{ADC1, RNG}; + +/// Ensures random numbers are cryptographically secure. +#[instability::unstable] +pub struct TrngSource<'d> { + _rng: RNG<'d>, + _adc: ADC1<'d>, +} + +impl<'d> TrngSource<'d> { + /// Enables the SAR ADC entropy source. + // TODO: this is not final. A single ADC channel should be sufficient. + #[instability::unstable] + pub fn new(_rng: RNG<'d>, _adc: ADC1<'d>) -> Self { + crate::soc::trng::ensure_randomness(); + unsafe { Self::increase_entropy_source_counter() } + Self { _rng, _adc } + } + + /// Increases the internal entropy source counter. + /// + /// # Panics + /// + /// This function panics if the internal counter overflows. + /// + /// # Safety + /// + /// This function must only be called after a new entropy source has been enabled. + #[instability::unstable] + pub unsafe fn increase_entropy_source_counter() { + if TRNG_ENABLED.fetch_add(1, Ordering::Relaxed) == usize::MAX { + panic!("TrngSource enable overflowed"); + } + } + + /// Decreases the internal entropy source counter. + /// + /// This function should only be called **before** disabling an entropy source (such as the + /// radio). + /// + /// This function should only be called as many times as + /// [`TrngSource::increase_entropy_source_counter`] was called. + /// + /// # Panics + /// + /// This function panics if the internal counter underflows. Dropping the `TrngSource` will + /// panic if this function is called more times than + /// [`TrngSource::increase_entropy_source_counter`]. + #[instability::unstable] + pub fn decrease_entropy_source_counter(_private: crate::private::Internal) { + match TRNG_ENABLED.fetch_sub(1, Ordering::Relaxed) { + 0 => panic!("TrngSource is not active"), + + 1 => assert!( + TRNG_USERS.load(Ordering::Acquire) == 0, + "TRNG cannot be disabled while it's in use" + ), + + _ => {} + } + } + + /// Returns whether the TRNG is currently enabled. + /// + /// Note that entropy sources can be disabled at any time. + #[instability::unstable] + pub fn is_enabled() -> bool { + TRNG_ENABLED.load(Ordering::Relaxed) > 0 + } + + /// Attempts to disable the TRNG. + /// + /// This function returns `Err(TrngSource)` if there are TRNG users. + /// + /// # Panics + /// + /// This function panics if the TRNG is not enabled (i.e. it has been disabled by calling + /// [`TrngSource::decrease_entropy_source_counter`] incorrectly). + #[instability::unstable] + pub fn try_disable(self) -> Result<(), Self> { + if TRNG_ENABLED + .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |enabled| { + assert!(enabled > 0, "TrngSource is not active"); + if TRNG_USERS.load(Ordering::Acquire) > 0 { + return None; + } + + Some(enabled - 1) + }) + .is_err() + { + // The TRNG is in use. + return Err(self); + } + + core::mem::forget(self); + Ok(()) + } +} + +impl Drop for TrngSource<'_> { + fn drop(&mut self) { + Self::decrease_entropy_source_counter(crate::private::Internal); + crate::soc::trng::revert_trng(); + } +} + +/// (Pseudo-)Random Number Generator +#[derive(Clone, Copy, Default, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[non_exhaustive] +#[instability::unstable] +pub struct Rng; + +impl Rng { + /// Creates a new random number generator instance. + #[inline] + #[instability::unstable] + pub fn new() -> Self { + Self + } + + /// Reads currently available `u32` integer from `RNG`. + #[inline] + #[instability::unstable] + pub fn random(&self) -> u32 { + let mut n = [0; 4]; + self.read(&mut n); + u32::from_le_bytes(n) + } + + /// Reads enough bytes from hardware random number generator to fill + /// `buffer`. + /// + /// If any error is encountered then this function immediately returns. The + /// contents of buf are unspecified in this case. + #[inline] + #[instability::unstable] + pub fn read(&self, buffer: &mut [u8]) { + unsafe { self.read_into_raw(buffer.as_mut_ptr(), buffer.len()) }; + } + + /// Reads enough bytes from hardware random number generator to fill + /// `buffer`. + /// + /// If any error is encountered then this function immediately returns. The + /// contents of buf are unspecified in this case. + /// + /// # Safety + /// + /// `ptr` must not be `null` and valid for writes for `len` bytes. + #[inline] + #[instability::unstable] + pub unsafe fn read_into_raw(&self, ptr: *mut u8, len: usize) { + ll::fill_ptr_range(ptr, len); + } +} + +/// Errors returned when constructing a [`Trng`]. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[non_exhaustive] +#[instability::unstable] +pub enum TrngError { + /// The [`TrngSource`] is not enabled. + /// + /// This error is returned by [`Trng::try_new`] when the RNG is not configured + /// to generate true random numbers. + TrngSourceNotEnabled, +} + +/// True Random Number Generator (TRNG) +/// +/// The `Trng` struct represents a true random number generator that combines +/// the randomness from the hardware RNG and an ADC. This struct provides +/// methods to generate random numbers and fill buffers with random bytes. +/// Due to pulling the entropy source from the ADC, it uses the associated +/// registers, so to use TRNG we need to "occupy" the ADC peripheral. +#[derive(Default, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[non_exhaustive] +#[instability::unstable] +pub struct Trng { + rng: Rng, +} + +impl Clone for Trng { + #[inline] + fn clone(&self) -> Self { + TRNG_USERS.fetch_add(1, Ordering::Acquire); + Self { rng: self.rng } + } +} + +impl Trng { + /// Attempts to create a new True Random Number Generator (TRNG) instance. + /// + /// This function returns a new `Trng` instance on success, or an error if the + /// [`TrngSource`] is not active. + #[inline] + #[instability::unstable] + pub fn try_new() -> Result { + TRNG_USERS.fetch_add(1, Ordering::Acquire); + let this = Self { rng: Rng::new() }; + if TRNG_ENABLED.load(Ordering::Acquire) == 0 { + // Dropping `this` reduces the TRNG_USERS count back (to 0 as it should be when TRNG is + // not enabled). + return Err(TrngError::TrngSourceNotEnabled); + } + Ok(this) + } + + /// Returns a new, random `u32` integer. + #[inline] + #[instability::unstable] + pub fn random(&self) -> u32 { + self.rng.random() + } + + /// Fills the provided buffer with random bytes. + #[inline] + #[instability::unstable] + pub fn read(&self, buffer: &mut [u8]) { + self.rng.read(buffer); + } + + /// Downgrades the `Trng` instance to a `Rng` instance. + #[inline] + #[instability::unstable] + pub fn downgrade(self) -> Rng { + Rng::new() + } +} + +impl Drop for Trng { + fn drop(&mut self) { + TRNG_USERS.fetch_sub(1, Ordering::Release); + } +} + +// Implement RngCore traits + +#[instability::unstable] +impl rand_core_06::RngCore for Rng { + fn next_u32(&mut self) -> u32 { + self.random() + } + + fn next_u64(&mut self) -> u64 { + let mut bytes = [0; 8]; + self.fill_bytes(&mut bytes); + u64::from_le_bytes(bytes) + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.read(dest); + } + + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core_06::Error> { + self.read(dest); + Ok(()) + } +} + +#[instability::unstable] +impl rand_core_09::RngCore for Rng { + fn next_u32(&mut self) -> u32 { + self.random() + } + fn next_u64(&mut self) -> u64 { + let mut bytes = [0; 8]; + self.fill_bytes(&mut bytes); + u64::from_le_bytes(bytes) + } + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.read(dest); + } +} + +#[instability::unstable] +impl rand_core_06::RngCore for Trng { + fn next_u32(&mut self) -> u32 { + self.rng.next_u32() + } + + fn next_u64(&mut self) -> u64 { + self.rng.next_u64() + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.rng.fill_bytes(dest) + } + + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core_06::Error> { + self.rng.try_fill_bytes(dest) + } +} + +#[instability::unstable] +impl rand_core_09::RngCore for Trng { + fn next_u32(&mut self) -> u32 { + self.rng.next_u32() + } + fn next_u64(&mut self) -> u64 { + self.rng.next_u64() + } + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.rng.fill_bytes(dest) + } +} + +#[instability::unstable] +impl rand_core_06::CryptoRng for Trng {} +#[instability::unstable] +impl rand_core_09::CryptoRng for Trng {} diff --git a/esp-metadata-generated/src/_build_script_utils.rs b/esp-metadata-generated/src/_build_script_utils.rs index 238532876af..8ef3b5313cc 100644 --- a/esp-metadata-generated/src/_build_script_utils.rs +++ b/esp-metadata-generated/src/_build_script_utils.rs @@ -277,6 +277,7 @@ impl Chip { "interrupts_status_registers=\"3\"", "rmt_ram_start=\"1073047552\"", "rmt_channel_ram_size=\"64\"", + "rng_apb_cycle_wait_num=\"16\"", "timergroup_timg_has_timer1", "uart_ram_size=\"128\"", "has_dram_region", @@ -419,6 +420,7 @@ impl Chip { "cargo:rustc-cfg=interrupts_status_registers=\"3\"", "cargo:rustc-cfg=rmt_ram_start=\"1073047552\"", "cargo:rustc-cfg=rmt_channel_ram_size=\"64\"", + "cargo:rustc-cfg=rng_apb_cycle_wait_num=\"16\"", "cargo:rustc-cfg=timergroup_timg_has_timer1", "cargo:rustc-cfg=uart_ram_size=\"128\"", "cargo:rustc-cfg=has_dram_region", @@ -481,6 +483,7 @@ impl Chip { "pm_support_bt_wakeup", "uart_support_wakeup_int", "gpio_support_deepsleep_wakeup", + "soc", "adc", "assist_debug", "dma", @@ -508,6 +511,7 @@ impl Chip { "timergroup_timg0", "uart_uart0", "uart_uart1", + "soc_cpu_has_csr_pc", "assist_debug_has_sp_monitor", "gpio_gpio_function=\"1\"", "gpio_constant_0_input=\"31\"", @@ -526,6 +530,7 @@ impl Chip { "i2c_master_ll_intr_mask=\"262143\"", "i2c_master_fifo_size=\"16\"", "interrupts_status_registers=\"2\"", + "rng_apb_cycle_wait_num=\"16\"", "timergroup_timg_has_divcnt_rst", "uart_ram_size=\"128\"", "has_dram_region", @@ -584,6 +589,7 @@ impl Chip { "cargo:rustc-cfg=pm_support_bt_wakeup", "cargo:rustc-cfg=uart_support_wakeup_int", "cargo:rustc-cfg=gpio_support_deepsleep_wakeup", + "cargo:rustc-cfg=soc", "cargo:rustc-cfg=adc", "cargo:rustc-cfg=assist_debug", "cargo:rustc-cfg=dma", @@ -611,6 +617,7 @@ impl Chip { "cargo:rustc-cfg=timergroup_timg0", "cargo:rustc-cfg=uart_uart0", "cargo:rustc-cfg=uart_uart1", + "cargo:rustc-cfg=soc_cpu_has_csr_pc", "cargo:rustc-cfg=assist_debug_has_sp_monitor", "cargo:rustc-cfg=gpio_gpio_function=\"1\"", "cargo:rustc-cfg=gpio_constant_0_input=\"31\"", @@ -629,6 +636,7 @@ impl Chip { "cargo:rustc-cfg=i2c_master_ll_intr_mask=\"262143\"", "cargo:rustc-cfg=i2c_master_fifo_size=\"16\"", "cargo:rustc-cfg=interrupts_status_registers=\"2\"", + "cargo:rustc-cfg=rng_apb_cycle_wait_num=\"16\"", "cargo:rustc-cfg=timergroup_timg_has_divcnt_rst", "cargo:rustc-cfg=uart_ram_size=\"128\"", "cargo:rustc-cfg=has_dram_region", @@ -700,6 +708,7 @@ impl Chip { "pm_support_bt_wakeup", "uart_support_wakeup_int", "gpio_support_deepsleep_wakeup", + "soc", "adc", "aes", "assist_debug", @@ -735,6 +744,7 @@ impl Chip { "timergroup_timg1", "uart_uart0", "uart_uart1", + "soc_cpu_has_csr_pc", "assist_debug_has_sp_monitor", "assist_debug_has_region_monitor", "gpio_gpio_function=\"1\"", @@ -756,6 +766,7 @@ impl Chip { "interrupts_status_registers=\"2\"", "rmt_ram_start=\"1610703872\"", "rmt_channel_ram_size=\"48\"", + "rng_apb_cycle_wait_num=\"16\"", "timergroup_timg_has_divcnt_rst", "uart_ram_size=\"128\"", "has_dram_region", @@ -823,6 +834,7 @@ impl Chip { "cargo:rustc-cfg=pm_support_bt_wakeup", "cargo:rustc-cfg=uart_support_wakeup_int", "cargo:rustc-cfg=gpio_support_deepsleep_wakeup", + "cargo:rustc-cfg=soc", "cargo:rustc-cfg=adc", "cargo:rustc-cfg=aes", "cargo:rustc-cfg=assist_debug", @@ -858,6 +870,7 @@ impl Chip { "cargo:rustc-cfg=timergroup_timg1", "cargo:rustc-cfg=uart_uart0", "cargo:rustc-cfg=uart_uart1", + "cargo:rustc-cfg=soc_cpu_has_csr_pc", "cargo:rustc-cfg=assist_debug_has_sp_monitor", "cargo:rustc-cfg=assist_debug_has_region_monitor", "cargo:rustc-cfg=gpio_gpio_function=\"1\"", @@ -879,6 +892,7 @@ impl Chip { "cargo:rustc-cfg=interrupts_status_registers=\"2\"", "cargo:rustc-cfg=rmt_ram_start=\"1610703872\"", "cargo:rustc-cfg=rmt_channel_ram_size=\"48\"", + "cargo:rustc-cfg=rng_apb_cycle_wait_num=\"16\"", "cargo:rustc-cfg=timergroup_timg_has_divcnt_rst", "cargo:rustc-cfg=uart_ram_size=\"128\"", "cargo:rustc-cfg=has_dram_region", @@ -991,6 +1005,7 @@ impl Chip { "gpio_support_deepsleep_wakeup", "uart_support_wakeup_int", "pm_support_ext1_wakeup", + "soc", "adc", "aes", "assist_debug", @@ -1035,6 +1050,8 @@ impl Chip { "timergroup_timg1", "uart_uart0", "uart_uart1", + "soc_cpu_has_csr_pc", + "soc_cpu_has_prv_mode", "assist_debug_has_sp_monitor", "assist_debug_has_region_monitor", "gpio_gpio_function=\"1\"", @@ -1059,6 +1076,7 @@ impl Chip { "interrupts_status_registers=\"3\"", "rmt_ram_start=\"1610638336\"", "rmt_channel_ram_size=\"48\"", + "rng_apb_cycle_wait_num=\"16\"", "timergroup_timg_has_divcnt_rst", "uart_ram_size=\"128\"", "lp_uart_ram_size=\"32\"", @@ -1169,6 +1187,7 @@ impl Chip { "cargo:rustc-cfg=gpio_support_deepsleep_wakeup", "cargo:rustc-cfg=uart_support_wakeup_int", "cargo:rustc-cfg=pm_support_ext1_wakeup", + "cargo:rustc-cfg=soc", "cargo:rustc-cfg=adc", "cargo:rustc-cfg=aes", "cargo:rustc-cfg=assist_debug", @@ -1213,6 +1232,8 @@ impl Chip { "cargo:rustc-cfg=timergroup_timg1", "cargo:rustc-cfg=uart_uart0", "cargo:rustc-cfg=uart_uart1", + "cargo:rustc-cfg=soc_cpu_has_csr_pc", + "cargo:rustc-cfg=soc_cpu_has_prv_mode", "cargo:rustc-cfg=assist_debug_has_sp_monitor", "cargo:rustc-cfg=assist_debug_has_region_monitor", "cargo:rustc-cfg=gpio_gpio_function=\"1\"", @@ -1237,6 +1258,7 @@ impl Chip { "cargo:rustc-cfg=interrupts_status_registers=\"3\"", "cargo:rustc-cfg=rmt_ram_start=\"1610638336\"", "cargo:rustc-cfg=rmt_channel_ram_size=\"48\"", + "cargo:rustc-cfg=rng_apb_cycle_wait_num=\"16\"", "cargo:rustc-cfg=timergroup_timg_has_divcnt_rst", "cargo:rustc-cfg=uart_ram_size=\"128\"", "cargo:rustc-cfg=lp_uart_ram_size=\"32\"", @@ -1332,6 +1354,7 @@ impl Chip { "rom_crc_le", "rom_crc_be", "rom_md5_bsd", + "soc", "adc", "aes", "assist_debug", @@ -1372,6 +1395,8 @@ impl Chip { "timergroup_timg1", "uart_uart0", "uart_uart1", + "soc_cpu_has_csr_pc", + "soc_cpu_has_prv_mode", "assist_debug_has_sp_monitor", "assist_debug_has_region_monitor", "gpio_gpio_function=\"1\"", @@ -1395,6 +1420,7 @@ impl Chip { "interrupts_status_registers=\"2\"", "rmt_ram_start=\"1610642432\"", "rmt_channel_ram_size=\"48\"", + "rng_apb_cycle_wait_num=\"16\"", "timergroup_timg_has_divcnt_rst", "uart_ram_size=\"128\"", "has_dram_region", @@ -1484,6 +1510,7 @@ impl Chip { "cargo:rustc-cfg=rom_crc_le", "cargo:rustc-cfg=rom_crc_be", "cargo:rustc-cfg=rom_md5_bsd", + "cargo:rustc-cfg=soc", "cargo:rustc-cfg=adc", "cargo:rustc-cfg=aes", "cargo:rustc-cfg=assist_debug", @@ -1524,6 +1551,8 @@ impl Chip { "cargo:rustc-cfg=timergroup_timg1", "cargo:rustc-cfg=uart_uart0", "cargo:rustc-cfg=uart_uart1", + "cargo:rustc-cfg=soc_cpu_has_csr_pc", + "cargo:rustc-cfg=soc_cpu_has_prv_mode", "cargo:rustc-cfg=assist_debug_has_sp_monitor", "cargo:rustc-cfg=assist_debug_has_region_monitor", "cargo:rustc-cfg=gpio_gpio_function=\"1\"", @@ -1547,6 +1576,7 @@ impl Chip { "cargo:rustc-cfg=interrupts_status_registers=\"2\"", "cargo:rustc-cfg=rmt_ram_start=\"1610642432\"", "cargo:rustc-cfg=rmt_channel_ram_size=\"48\"", + "cargo:rustc-cfg=rng_apb_cycle_wait_num=\"16\"", "cargo:rustc-cfg=timergroup_timg_has_divcnt_rst", "cargo:rustc-cfg=uart_ram_size=\"128\"", "cargo:rustc-cfg=has_dram_region", @@ -1693,6 +1723,7 @@ impl Chip { "interrupts_status_registers=\"3\"", "rmt_ram_start=\"1061250048\"", "rmt_channel_ram_size=\"64\"", + "rng_apb_cycle_wait_num=\"16\"", "spi_master_has_octal", "timergroup_timg_has_timer1", "uart_ram_size=\"128\"", @@ -1836,6 +1867,7 @@ impl Chip { "cargo:rustc-cfg=interrupts_status_registers=\"3\"", "cargo:rustc-cfg=rmt_ram_start=\"1061250048\"", "cargo:rustc-cfg=rmt_channel_ram_size=\"64\"", + "cargo:rustc-cfg=rng_apb_cycle_wait_num=\"16\"", "cargo:rustc-cfg=spi_master_has_octal", "cargo:rustc-cfg=timergroup_timg_has_timer1", "cargo:rustc-cfg=uart_ram_size=\"128\"", @@ -2003,6 +2035,7 @@ impl Chip { "interrupts_status_registers=\"4\"", "rmt_ram_start=\"1610704896\"", "rmt_channel_ram_size=\"48\"", + "rng_apb_cycle_wait_num=\"16\"", "spi_master_has_octal", "timergroup_timg_has_timer1", "uart_ram_size=\"128\"", @@ -2166,6 +2199,7 @@ impl Chip { "cargo:rustc-cfg=interrupts_status_registers=\"4\"", "cargo:rustc-cfg=rmt_ram_start=\"1610704896\"", "cargo:rustc-cfg=rmt_channel_ram_size=\"48\"", + "cargo:rustc-cfg=rng_apb_cycle_wait_num=\"16\"", "cargo:rustc-cfg=spi_master_has_octal", "cargo:rustc-cfg=timergroup_timg_has_timer1", "cargo:rustc-cfg=uart_ram_size=\"128\"", @@ -2337,9 +2371,11 @@ impl Config { println!("cargo:rustc-check-cfg=cfg(pm_support_bt_wakeup)"); println!("cargo:rustc-check-cfg=cfg(uart_support_wakeup_int)"); println!("cargo:rustc-check-cfg=cfg(gpio_support_deepsleep_wakeup)"); + println!("cargo:rustc-check-cfg=cfg(soc)"); println!("cargo:rustc-check-cfg=cfg(assist_debug)"); println!("cargo:rustc-check-cfg=cfg(ecc)"); println!("cargo:rustc-check-cfg=cfg(systimer)"); + println!("cargo:rustc-check-cfg=cfg(soc_cpu_has_csr_pc)"); println!("cargo:rustc-check-cfg=cfg(assist_debug_has_sp_monitor)"); println!("cargo:rustc-check-cfg=cfg(i2c_master_has_fsm_timeouts)"); println!("cargo:rustc-check-cfg=cfg(i2c_master_has_hw_bus_clear)"); @@ -2409,6 +2445,7 @@ impl Config { println!("cargo:rustc-check-cfg=cfg(lp_uart)"); println!("cargo:rustc-check-cfg=cfg(ulp_riscv)"); println!("cargo:rustc-check-cfg=cfg(ieee802154)"); + println!("cargo:rustc-check-cfg=cfg(soc_cpu_has_prv_mode)"); println!("cargo:rustc-check-cfg=cfg(i2c_master_can_estimate_nack_reason)"); println!("cargo:rustc-check-cfg=cfg(i2c_master_has_reliable_fsm_reset)"); println!("cargo:rustc-check-cfg=cfg(wifi_has_wifi6)"); @@ -2464,6 +2501,7 @@ impl Config { "cargo:rustc-check-cfg=cfg(rmt_ram_start, values(\"1073047552\",\"1610703872\",\"1610638336\",\"1610642432\",\"1061250048\",\"1610704896\"))" ); println!("cargo:rustc-check-cfg=cfg(rmt_channel_ram_size, values(\"64\",\"48\"))"); + println!("cargo:rustc-check-cfg=cfg(rng_apb_cycle_wait_num, values(\"16\"))"); println!("cargo:rustc-check-cfg=cfg(uart_ram_size, values(\"128\"))"); println!("cargo:rustc-check-cfg=cfg(lp_i2c_master_fifo_size, values(\"16\"))"); println!("cargo:rustc-check-cfg=cfg(lp_uart_ram_size, values(\"32\"))"); diff --git a/esp-metadata-generated/src/_generated_esp32.rs b/esp-metadata-generated/src/_generated_esp32.rs index ae950e80855..075eadb72ef 100644 --- a/esp-metadata-generated/src/_generated_esp32.rs +++ b/esp-metadata-generated/src/_generated_esp32.rs @@ -150,6 +150,12 @@ macro_rules! property { ("rmt.channel_ram_size", str) => { stringify!(64) }; + ("rng.apb_cycle_wait_num") => { + 16 + }; + ("rng.apb_cycle_wait_num", str) => { + stringify!(16) + }; ("spi_master.has_octal") => { false }; diff --git a/esp-metadata-generated/src/_generated_esp32c2.rs b/esp-metadata-generated/src/_generated_esp32c2.rs index 121642ab309..f2d3fe00e1a 100644 --- a/esp-metadata-generated/src/_generated_esp32c2.rs +++ b/esp-metadata-generated/src/_generated_esp32c2.rs @@ -36,6 +36,12 @@ macro_rules! property { ("trm") => { "https://www.espressif.com/sites/default/files/documentation/esp8684_technical_reference_manual_en.pdf" }; + ("soc.cpu_has_csr_pc") => { + true + }; + ("soc.cpu_has_prv_mode") => { + false + }; ("assist_debug.has_sp_monitor") => { true }; @@ -138,6 +144,12 @@ macro_rules! property { ("interrupts.status_registers", str) => { stringify!(2) }; + ("rng.apb_cycle_wait_num") => { + 16 + }; + ("rng.apb_cycle_wait_num", str) => { + stringify!(16) + }; ("spi_master.has_octal") => { false }; diff --git a/esp-metadata-generated/src/_generated_esp32c3.rs b/esp-metadata-generated/src/_generated_esp32c3.rs index 424519afdfc..41bd259a29c 100644 --- a/esp-metadata-generated/src/_generated_esp32c3.rs +++ b/esp-metadata-generated/src/_generated_esp32c3.rs @@ -36,6 +36,12 @@ macro_rules! property { ("trm") => { "https://www.espressif.com/sites/default/files/documentation/esp32-c3_technical_reference_manual_en.pdf" }; + ("soc.cpu_has_csr_pc") => { + true + }; + ("soc.cpu_has_prv_mode") => { + false + }; ("assist_debug.has_sp_monitor") => { true }; @@ -150,6 +156,12 @@ macro_rules! property { ("rmt.channel_ram_size", str) => { stringify!(48) }; + ("rng.apb_cycle_wait_num") => { + 16 + }; + ("rng.apb_cycle_wait_num", str) => { + stringify!(16) + }; ("spi_master.has_octal") => { false }; diff --git a/esp-metadata-generated/src/_generated_esp32c6.rs b/esp-metadata-generated/src/_generated_esp32c6.rs index 6ba50f2856c..1b5845dddaf 100644 --- a/esp-metadata-generated/src/_generated_esp32c6.rs +++ b/esp-metadata-generated/src/_generated_esp32c6.rs @@ -36,6 +36,12 @@ macro_rules! property { ("trm") => { "https://www.espressif.com/sites/default/files/documentation/esp32-c6_technical_reference_manual_en.pdf" }; + ("soc.cpu_has_csr_pc") => { + true + }; + ("soc.cpu_has_prv_mode") => { + true + }; ("assist_debug.has_sp_monitor") => { true }; @@ -156,6 +162,12 @@ macro_rules! property { ("rmt.channel_ram_size", str) => { stringify!(48) }; + ("rng.apb_cycle_wait_num") => { + 16 + }; + ("rng.apb_cycle_wait_num", str) => { + stringify!(16) + }; ("spi_master.has_octal") => { false }; diff --git a/esp-metadata-generated/src/_generated_esp32h2.rs b/esp-metadata-generated/src/_generated_esp32h2.rs index 7726386c8a6..748656de789 100644 --- a/esp-metadata-generated/src/_generated_esp32h2.rs +++ b/esp-metadata-generated/src/_generated_esp32h2.rs @@ -36,6 +36,12 @@ macro_rules! property { ("trm") => { "https://www.espressif.com/sites/default/files/documentation/esp32-h2_technical_reference_manual_en.pdf" }; + ("soc.cpu_has_csr_pc") => { + true + }; + ("soc.cpu_has_prv_mode") => { + true + }; ("assist_debug.has_sp_monitor") => { true }; @@ -150,6 +156,12 @@ macro_rules! property { ("rmt.channel_ram_size", str) => { stringify!(48) }; + ("rng.apb_cycle_wait_num") => { + 16 + }; + ("rng.apb_cycle_wait_num", str) => { + stringify!(16) + }; ("spi_master.has_octal") => { false }; diff --git a/esp-metadata-generated/src/_generated_esp32s2.rs b/esp-metadata-generated/src/_generated_esp32s2.rs index d772d23eb27..20374ba1d08 100644 --- a/esp-metadata-generated/src/_generated_esp32s2.rs +++ b/esp-metadata-generated/src/_generated_esp32s2.rs @@ -150,6 +150,12 @@ macro_rules! property { ("rmt.channel_ram_size", str) => { stringify!(64) }; + ("rng.apb_cycle_wait_num") => { + 16 + }; + ("rng.apb_cycle_wait_num", str) => { + stringify!(16) + }; ("spi_master.has_octal") => { true }; diff --git a/esp-metadata-generated/src/_generated_esp32s3.rs b/esp-metadata-generated/src/_generated_esp32s3.rs index 6132b686ea2..329bbb3c45a 100644 --- a/esp-metadata-generated/src/_generated_esp32s3.rs +++ b/esp-metadata-generated/src/_generated_esp32s3.rs @@ -150,6 +150,12 @@ macro_rules! property { ("rmt.channel_ram_size", str) => { stringify!(48) }; + ("rng.apb_cycle_wait_num") => { + 16 + }; + ("rng.apb_cycle_wait_num", str) => { + stringify!(16) + }; ("spi_master.has_octal") => { true }; diff --git a/esp-metadata/devices/esp32.toml b/esp-metadata/devices/esp32.toml index c7e4aac09d2..8d03f2f5a18 100644 --- a/esp-metadata/devices/esp32.toml +++ b/esp-metadata/devices/esp32.toml @@ -591,12 +591,14 @@ instances = [ ] [device.spi_slave] +support_status = "partial" instances = [ { name = "spi2", sys_instance = "Spi2", sclk = "HSPICLK", mosi = "HSPID", miso = "HSPIQ", cs = "HSPICS0" }, { name = "spi3", sys_instance = "Spi3", sclk = "VSPICLK", mosi = "VSPID", miso = "VSPIQ", cs = "VSPICS0" }, ] [device.timergroup] +support_status = "partial" timg_has_timer1 = true timg_has_divcnt_rst = false instances = [{ name = "timg0" }, { name = "timg1" }] @@ -616,6 +618,11 @@ support_status = "not_supported" [device.camera] support_status = "not_supported" [device.rgb_display] +support_status = "partial" + +[device.rng] +support_status = "partial" +apb_cycle_wait_num = 16 # TODO # Other drivers which are partially supported but have no other configuration: @@ -623,7 +630,6 @@ support_status = "not_supported" [device.aes] [device.rsa] [device.sha] -[device.rng] ## Interfaces [device.i2s] diff --git a/esp-metadata/devices/esp32c2.toml b/esp-metadata/devices/esp32c2.toml index b143043b2c5..7edec7a56ca 100644 --- a/esp-metadata/devices/esp32c2.toml +++ b/esp-metadata/devices/esp32c2.toml @@ -77,6 +77,9 @@ symbols = [ memory = [{ name = "dram", start = 0x3FCA_0000, end = 0x3FCE_0000 }] +[device.soc] +cpu_has_csr_pc = true + [device.adc] support_status = "partial" instances = [ @@ -248,11 +251,13 @@ instances = [ ] [device.spi_slave] +support_status = "partial" instances = [ { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", mosi = "FSPID", miso = "FSPIQ", cs = "FSPICS0" }, ] [device.timergroup] +support_status = "partial" instances = [{ name = "timg0" }] timg_has_divcnt_rst = true @@ -264,13 +269,16 @@ instances = [ ] ram_size = 128 +[device.rng] +support_status = "partial" +apb_cycle_wait_num = 16 # TODO + # Other drivers which are partially supported but have no other configuration: ## Crypto # [device.aes] Product portfolio lists AES, but TRM only has XTS_AES? [device.ecc] [device.sha] -[device.rng] ## Interfaces [device.ledc] diff --git a/esp-metadata/devices/esp32c3.toml b/esp-metadata/devices/esp32c3.toml index 6c2e099280f..0362ced1b02 100644 --- a/esp-metadata/devices/esp32c3.toml +++ b/esp-metadata/devices/esp32c3.toml @@ -86,6 +86,9 @@ symbols = [ memory = [{ name = "dram", start = 0x3FC8_0000, end = 0x3FCE_0000 }] +[device.soc] +cpu_has_csr_pc = true + [device.adc] support_status = "partial" instances = [ @@ -294,11 +297,13 @@ instances = [ ] [device.spi_slave] +support_status = "partial" instances = [ { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", mosi = "FSPID", miso = "FSPIQ", cs = "FSPICS0" }, ] [device.timergroup] +support_status = "partial" instances = [{ name = "timg0" }, { name = "timg1" }] timg_has_divcnt_rst = true @@ -313,6 +318,10 @@ ram_size = 128 [device.ds] support_status = "not_supported" +[device.rng] +support_status = "partial" +apb_cycle_wait_num = 16 # TODO + # Other drivers which are partially supported but have no other configuration: ## Crypto @@ -320,7 +329,6 @@ support_status = "not_supported" [device.rsa] [device.sha] [device.hmac] -[device.rng] ## Interfaces [device.i2s] diff --git a/esp-metadata/devices/esp32c6.toml b/esp-metadata/devices/esp32c6.toml index eaf9c9f89e0..20097ff2c73 100644 --- a/esp-metadata/devices/esp32c6.toml +++ b/esp-metadata/devices/esp32c6.toml @@ -127,6 +127,10 @@ symbols = [ memory = [{ name = "dram", start = 0x4080_0000, end = 0x4088_0000 }] +[device.soc] +cpu_has_csr_pc = true +cpu_has_prv_mode = true + [device.adc] support_status = "partial" instances = [ @@ -448,11 +452,13 @@ instances = [ ] [device.spi_slave] +support_status = "partial" instances = [ { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", mosi = "FSPID", miso = "FSPIQ", cs = "FSPICS0" }, ] [device.timergroup] +support_status = "partial" instances = [{ name = "timg0" }, { name = "timg1" }] timg_has_divcnt_rst = true @@ -475,6 +481,10 @@ support_status = "not_supported" support_status = "partial" has_wifi6 = true +[device.rng] +support_status = "partial" +apb_cycle_wait_num = 16 # TODO + # Other drivers which are partially supported but have no other configuration: ## Crypto @@ -483,7 +493,6 @@ has_wifi6 = true [device.rsa] [device.sha] [device.hmac] -[device.rng] ## Interfaces [device.i2s] diff --git a/esp-metadata/devices/esp32h2.toml b/esp-metadata/devices/esp32h2.toml index efb032d4fcc..71ee525251e 100644 --- a/esp-metadata/devices/esp32h2.toml +++ b/esp-metadata/devices/esp32h2.toml @@ -106,6 +106,10 @@ symbols = [ memory = [{ name = "dram", start = 0x4080_0000, end = 0x4085_0000 }] +[device.soc] +cpu_has_csr_pc = true +cpu_has_prv_mode = true + [device.adc] support_status = "partial" instances = [ @@ -365,11 +369,13 @@ instances = [ ] [device.spi_slave] +support_status = "partial" instances = [ { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", mosi = "FSPID", miso = "FSPIQ", cs = "FSPICS0" }, ] [device.timergroup] +support_status = "partial" instances = [{ name = "timg0" }, { name = "timg1" }] timg_has_divcnt_rst = true @@ -384,6 +390,10 @@ ram_size = 128 [device.ds] support_status = "not_supported" +[device.rng] +support_status = "partial" +apb_cycle_wait_num = 16 # TODO + # Other drivers which are partially supported but have no other configuration: ## Crypto @@ -392,7 +402,6 @@ support_status = "not_supported" [device.rsa] [device.sha] [device.hmac] -[device.rng] ## Interfaces [device.i2s] diff --git a/esp-metadata/devices/esp32s2.toml b/esp-metadata/devices/esp32s2.toml index e3f2b7c36ce..57e8f310c48 100644 --- a/esp-metadata/devices/esp32s2.toml +++ b/esp-metadata/devices/esp32s2.toml @@ -414,12 +414,14 @@ instances = [ ] [device.spi_slave] +support_status = "partial" instances = [ { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", mosi = "FSPID", miso = "FSPIQ", cs = "FSPICS0" }, { name = "spi3", sys_instance = "Spi3", sclk = "SPI3_CLK", mosi = "SPI3_D", miso = "SPI3_Q", cs = "SPI3_CS0" }, ] [device.timergroup] +support_status = "partial" timg_has_timer1 = true timg_has_divcnt_rst = false instances = [{ name = "timg0" }, { name = "timg1" }] @@ -444,6 +446,10 @@ support_status = "not_supported" [device.ds] support_status = "not_supported" +[device.rng] +support_status = "partial" +apb_cycle_wait_num = 16 # TODO + # Other drivers which are partially supported but have no other configuration: ## Crypto @@ -451,7 +457,6 @@ support_status = "not_supported" [device.rsa] [device.hmac] [device.sha] -[device.rng] ## Interfaces [device.i2s] diff --git a/esp-metadata/devices/esp32s3.toml b/esp-metadata/devices/esp32s3.toml index 4b97b1fa086..eaf0e107973 100644 --- a/esp-metadata/devices/esp32s3.toml +++ b/esp-metadata/devices/esp32s3.toml @@ -589,12 +589,14 @@ instances = [ ] [device.spi_slave] +support_status = "partial" instances = [ { name = "spi2", sys_instance = "Spi2", sclk = "FSPICLK", mosi = "FSPID", miso = "FSPIQ", cs = "FSPICS0" }, { name = "spi3", sys_instance = "Spi3", sclk = "SPI3_CLK", mosi = "SPI3_D", miso = "SPI3_Q", cs = "SPI3_CS0" }, ] [device.timergroup] +support_status = "partial" timg_has_timer1 = true timg_has_divcnt_rst = false instances = [{ name = "timg0" }, { name = "timg1" }] @@ -614,6 +616,10 @@ support_status = "not_supported" [device.ds] support_status = "not_supported" +[device.rng] +support_status = "partial" +apb_cycle_wait_num = 16 # TODO + # Other drivers which are partially supported but have no other configuration: ## Crypto @@ -621,7 +627,6 @@ support_status = "not_supported" [device.rsa] [device.hmac] [device.sha] -[device.rng] ## Interfaces [device.i2s] diff --git a/esp-metadata/src/cfg.rs b/esp-metadata/src/cfg.rs index c76a40667c6..3dca206566b 100644 --- a/esp-metadata/src/cfg.rs +++ b/esp-metadata/src/cfg.rs @@ -236,7 +236,12 @@ driver_configs![ driver: soc, name: "SOC", hide_from_peri_table: true, - properties: {} + properties: { + #[serde(default)] + cpu_has_csr_pc: bool, + #[serde(default)] + cpu_has_prv_mode: bool, + } }, AdcProperties { @@ -419,7 +424,9 @@ driver_configs![ RngProperties { driver: rng, name: "RNG", - properties: {} + properties: { + apb_cycle_wait_num: u32, + } }, RsaProperties { driver: rsa, diff --git a/esp-wifi/CHANGELOG.md b/esp-wifi/CHANGELOG.md index 0da4292bf13..1261db368f5 100644 --- a/esp-wifi/CHANGELOG.md +++ b/esp-wifi/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- `esp_wifi::init` no longer needs an `RNG` driver. (#3829) ### Fixed diff --git a/esp-wifi/MIGRATING-0.15.0.md b/esp-wifi/MIGRATING-0.15.0.md new file mode 100644 index 00000000000..80d38b8e564 --- /dev/null +++ b/esp-wifi/MIGRATING-0.15.0.md @@ -0,0 +1,10 @@ +# Migration Guide from 0.15.0 to {{currentVersion}} + +## Initialization + +`esp_wifi::init` no longer requires `RNG`. + +```diff +-let esp_wifi_ctrl = init(timg0.timer0, Rng::new()).unwrap(); ++let esp_wifi_ctrl = init(timg0.timer0).unwrap(); +``` diff --git a/esp-wifi/src/ble/btdm.rs b/esp-wifi/src/ble/btdm.rs index 7952c131691..7f6b6c9687f 100644 --- a/esp-wifi/src/ble/btdm.rs +++ b/esp-wifi/src/ble/btdm.rs @@ -452,9 +452,16 @@ pub(crate) fn ble_init() { API_vhci_host_register_callback(&VHCI_HOST_CALLBACK); } + + // At some point the "High-speed ADC" entropy source became available. + unsafe { esp_hal::rng::TrngSource::increase_entropy_source_counter() }; } pub(crate) fn ble_deinit() { + esp_hal::rng::TrngSource::decrease_entropy_source_counter(unsafe { + esp_hal::Internal::conjure() + }); + unsafe extern "C" { fn btdm_controller_deinit(); } diff --git a/esp-wifi/src/ble/npl.rs b/esp-wifi/src/ble/npl.rs index c2fd7245d02..e54c5ad672e 100644 --- a/esp-wifi/src/ble/npl.rs +++ b/esp-wifi/src/ble/npl.rs @@ -1217,12 +1217,19 @@ pub(crate) fn ble_init() { // this is to avoid (ASSERT r_ble_hci_ram_hs_cmd_tx:34 0 0) // we wait a bit to make sure the ble task initialized everything crate::compat::common::sleep(10); - - debug!("The ble_controller_init was initialized"); } + + // At some point the "High-speed ADC" entropy source became available. + unsafe { esp_hal::rng::TrngSource::increase_entropy_source_counter() }; + + debug!("The ble_controller_init was initialized"); } pub(crate) fn ble_deinit() { + esp_hal::rng::TrngSource::decrease_entropy_source_counter(unsafe { + esp_hal::Internal::conjure() + }); + unsafe { // HCI deinit npl::r_ble_hci_trans_cfg_hs(None, core::ptr::null(), None, core::ptr::null()); diff --git a/esp-wifi/src/common_adapter/mod.rs b/esp-wifi/src/common_adapter/mod.rs index f53376c62a1..e3c0706915b 100644 --- a/esp-wifi/src/common_adapter/mod.rs +++ b/esp-wifi/src/common_adapter/mod.rs @@ -122,8 +122,7 @@ pub unsafe extern "C" fn semphr_give(semphr: *mut crate::binary::c_types::c_void pub unsafe extern "C" fn random() -> crate::binary::c_types::c_ulong { trace!("random"); - // stealing RNG is safe since we own it (passed into `init`) - let mut rng = hal::rng::Rng::new(unsafe { hal::peripherals::RNG::steal() }); + let rng = hal::rng::Rng::new(); rng.random() } @@ -286,8 +285,7 @@ pub unsafe extern "C" fn esp_fill_random(dst: *mut u8, len: u32) { unsafe { let dst = core::slice::from_raw_parts_mut(dst, len as usize); - // stealing RNG is safe since we own it (passed into `init`) - let mut rng = esp_hal::rng::Rng::new(esp_hal::peripherals::RNG::steal()); + let rng = esp_hal::rng::Rng::new(); for chunk in dst.chunks_mut(4) { let bytes = rng.random().to_le_bytes(); chunk.copy_from_slice(&bytes[..chunk.len()]); diff --git a/esp-wifi/src/lib.rs b/esp-wifi/src/lib.rs index 0163fd40bd2..93e43cb2f7a 100644 --- a/esp-wifi/src/lib.rs +++ b/esp-wifi/src/lib.rs @@ -112,11 +112,10 @@ use core::marker::PhantomData; use common_adapter::chip_specific::phy_mem_init; use esp_config::*; -use esp_hal as hal; +use esp_hal::{self as hal}; use hal::{ Blocking, clock::{Clocks, init_radio_clocks}, - rng::{Rng, Trng}, time::Rate, timer::{AnyTimer, PeriodicTimer, timg::Timer as TimgTimer}, }; @@ -290,14 +289,6 @@ where } } -/// A marker trait for suitable Rng sources for esp-wifi -pub trait EspWifiRngSource: rand_core::RngCore + private::Sealed {} - -impl EspWifiRngSource for Rng {} -impl private::Sealed for Rng {} -impl EspWifiRngSource for Trng<'_> {} -impl private::Sealed for Trng<'_> {} - /// Initialize for using WiFi and or BLE. /// /// Make sure to **not** call this function while interrupts are disabled. @@ -318,17 +309,11 @@ impl private::Sealed for Trng<'_> {} /// use esp_hal::{rng::Rng, timer::timg::TimerGroup}; /// /// let timg0 = TimerGroup::new(peripherals.TIMG0); -/// let init = esp_wifi::init( -/// timg0.timer0, -/// Rng::new(peripherals.RNG), -/// peripherals.RADIO_CLK, -/// ) -/// .unwrap(); +/// let init = esp_wifi::init(timg0.timer0).unwrap(); /// # } /// ``` pub fn init<'d>( timer: impl EspWifiTimerSource + 'd, - _rng: impl EspWifiRngSource + 'd, ) -> Result, InitializationError> { if crate::is_interrupts_disabled() { return Err(InitializationError::InterruptsDisabled); diff --git a/esp-wifi/src/wifi/mod.rs b/esp-wifi/src/wifi/mod.rs index 90211ea1523..cdb8ba37430 100644 --- a/esp-wifi/src/wifi/mod.rs +++ b/esp-wifi/src/wifi/mod.rs @@ -2687,6 +2687,9 @@ pub fn new<'d>( esp_wifi_result!(esp_wifi_set_country(&country))?; } + // At some point the "High-speed ADC" entropy source became available. + unsafe { esp_hal::rng::TrngSource::increase_entropy_source_counter() }; + controller.set_power_saving(PowerSaveMode::default())?; Ok(( @@ -2718,6 +2721,10 @@ impl Drop for WifiController<'_> { if let Err(e) = crate::wifi::wifi_deinit() { warn!("Failed to cleanly deinit wifi: {:?}", e); } + + esp_hal::rng::TrngSource::decrease_entropy_source_counter(unsafe { + esp_hal::Internal::conjure() + }); } } diff --git a/examples/src/bin/hmac.rs b/examples/src/bin/hmac.rs index 7ba1cdff4f1..1bc1e624fcb 100644 --- a/examples/src/bin/hmac.rs +++ b/examples/src/bin/hmac.rs @@ -76,7 +76,7 @@ type HmacSha256 = HmacSw; fn main() -> ! { let peripherals = esp_hal::init(esp_hal::Config::default()); - let mut rng = Rng::new(peripherals.RNG); + let rng = Rng::new(); // Set sw key let key = [0_u8; 32].as_ref(); diff --git a/examples/src/bin/wifi_80211_tx.rs b/examples/src/bin/wifi_80211_tx.rs index 3adaf28177a..83d41bbcfdc 100644 --- a/examples/src/bin/wifi_80211_tx.rs +++ b/examples/src/bin/wifi_80211_tx.rs @@ -12,14 +12,7 @@ use core::marker::PhantomData; use esp_alloc as _; use esp_backtrace as _; -use esp_hal::{ - clock::CpuClock, - delay::Delay, - main, - rng::Rng, - time::Duration, - timer::timg::TimerGroup, -}; +use esp_hal::{clock::CpuClock, delay::Delay, main, time::Duration, timer::timg::TimerGroup}; use esp_println::println; use esp_wifi::{init, wifi}; use ieee80211::{ @@ -49,7 +42,7 @@ fn main() -> ! { let timg0 = TimerGroup::new(peripherals.TIMG0); - let esp_wifi_ctrl = init(timg0.timer0, Rng::new(peripherals.RNG)).unwrap(); + let esp_wifi_ctrl = init(timg0.timer0).unwrap(); // We must initialize some kind of interface and start it. let (mut controller, interfaces) = diff --git a/examples/src/bin/wifi_access_point.rs b/examples/src/bin/wifi_access_point.rs index 20457130146..ac7559cd1af 100644 --- a/examples/src/bin/wifi_access_point.rs +++ b/examples/src/bin/wifi_access_point.rs @@ -68,9 +68,7 @@ fn main() -> ! { ); }); - let mut rng = Rng::new(peripherals.RNG); - - let esp_wifi_ctrl = init(timg0.timer0, rng.clone()).unwrap(); + let esp_wifi_ctrl = init(timg0.timer0).unwrap(); let (mut controller, interfaces) = esp_wifi::wifi::new(&esp_wifi_ctrl, peripherals.WIFI).unwrap(); @@ -80,6 +78,7 @@ fn main() -> ! { let now = || time::Instant::now().duration_since_epoch().as_millis(); + let rng = Rng::new(); let mut socket_set_entries: [SocketStorage; 3] = Default::default(); let socket_set = SocketSet::new(&mut socket_set_entries[..]); let mut stack = Stack::new(iface, device, socket_set, now, rng.random()); diff --git a/examples/src/bin/wifi_access_point_with_sta.rs b/examples/src/bin/wifi_access_point_with_sta.rs index 4ebcddcc101..429dd49b964 100644 --- a/examples/src/bin/wifi_access_point_with_sta.rs +++ b/examples/src/bin/wifi_access_point_with_sta.rs @@ -54,9 +54,7 @@ fn main() -> ! { let timg0 = TimerGroup::new(peripherals.TIMG0); - let mut rng = Rng::new(peripherals.RNG); - - let esp_wifi_ctrl = init(timg0.timer0, rng.clone()).unwrap(); + let esp_wifi_ctrl = init(timg0.timer0).unwrap(); let (mut controller, interfaces) = esp_wifi::wifi::new(&esp_wifi_ctrl, peripherals.WIFI).unwrap(); @@ -67,6 +65,7 @@ fn main() -> ! { let mut sta_device = interfaces.sta; let sta_interface = create_interface(&mut sta_device); + let rng = Rng::new(); let now = || time::Instant::now().duration_since_epoch().as_millis(); let mut ap_socket_set_entries: [SocketStorage; 3] = Default::default(); let ap_socket_set = SocketSet::new(&mut ap_socket_set_entries[..]); diff --git a/examples/src/bin/wifi_bench.rs b/examples/src/bin/wifi_bench.rs index 69f51183dbc..e953d1d4b82 100644 --- a/examples/src/bin/wifi_bench.rs +++ b/examples/src/bin/wifi_bench.rs @@ -66,9 +66,7 @@ fn main() -> ! { let timg0 = TimerGroup::new(peripherals.TIMG0); - let mut rng = Rng::new(peripherals.RNG); - - let esp_wifi_ctrl = init(timg0.timer0, rng.clone()).unwrap(); + let esp_wifi_ctrl = init(timg0.timer0).unwrap(); let (mut controller, interfaces) = esp_wifi::wifi::new(&esp_wifi_ctrl, peripherals.WIFI).unwrap(); @@ -90,6 +88,7 @@ fn main() -> ! { }]); socket_set.add(dhcp_socket); + let rng = Rng::new(); let now = || time::Instant::now().duration_since_epoch().as_millis(); let stack = Stack::new(iface, device, socket_set, now, rng.random()); diff --git a/examples/src/bin/wifi_ble.rs b/examples/src/bin/wifi_ble.rs index 133861a5a67..ce1229840b8 100644 --- a/examples/src/bin/wifi_ble.rs +++ b/examples/src/bin/wifi_ble.rs @@ -29,7 +29,6 @@ use esp_hal::{ clock::CpuClock, gpio::{Input, InputConfig, Pull}, main, - rng::Rng, time, timer::timg::TimerGroup, }; @@ -48,7 +47,7 @@ fn main() -> ! { let timg0 = TimerGroup::new(peripherals.TIMG0); - let esp_wifi_ctrl = init(timg0.timer0, Rng::new(peripherals.RNG)).unwrap(); + let esp_wifi_ctrl = init(timg0.timer0).unwrap(); let config = InputConfig::default().with_pull(Pull::Down); cfg_if::cfg_if! { diff --git a/examples/src/bin/wifi_coex.rs b/examples/src/bin/wifi_coex.rs index 6e6c0387fe9..24d9d0baf94 100644 --- a/examples/src/bin/wifi_coex.rs +++ b/examples/src/bin/wifi_coex.rs @@ -74,9 +74,7 @@ fn main() -> ! { let timg0 = TimerGroup::new(peripherals.TIMG0); - let mut rng = Rng::new(peripherals.RNG); - - let esp_wifi_ctrl = init(timg0.timer0, rng.clone()).unwrap(); + let esp_wifi_ctrl = init(timg0.timer0).unwrap(); let now = || time::Instant::now().duration_since_epoch().as_millis(); @@ -123,6 +121,7 @@ fn main() -> ! { }]); socket_set.add(dhcp_socket); + let rng = Rng::new(); let stack = Stack::new(iface, device, socket_set, now, rng.random()); let client_config = Configuration::Client(ClientConfiguration { diff --git a/examples/src/bin/wifi_csi.rs b/examples/src/bin/wifi_csi.rs index 55cabfda81c..dfd35a208cf 100644 --- a/examples/src/bin/wifi_csi.rs +++ b/examples/src/bin/wifi_csi.rs @@ -38,10 +38,8 @@ fn main() -> ! { esp_alloc::heap_allocator!(size: 72 * 1024); - let mut rng = Rng::new(peripherals.RNG); - let timg0 = TimerGroup::new(peripherals.TIMG0); - let esp_wifi_ctrl = init(timg0.timer0, rng.clone()).unwrap(); + let esp_wifi_ctrl = init(timg0.timer0).unwrap(); let (mut controller, interfaces) = esp_wifi::wifi::new(&esp_wifi_ctrl, peripherals.WIFI).unwrap(); @@ -59,6 +57,7 @@ fn main() -> ! { }]); socket_set.add(dhcp_socket); + let rng = Rng::new(); let now = || time::Instant::now().duration_since_epoch().as_millis(); let stack = Stack::new(iface, device, socket_set, now, rng.random()); diff --git a/examples/src/bin/wifi_dhcp.rs b/examples/src/bin/wifi_dhcp.rs index d7283e18576..3e387b7a8d1 100644 --- a/examples/src/bin/wifi_dhcp.rs +++ b/examples/src/bin/wifi_dhcp.rs @@ -53,9 +53,7 @@ fn main() -> ! { let timg0 = TimerGroup::new(peripherals.TIMG0); - let mut rng = Rng::new(peripherals.RNG); - - let esp_wifi_ctrl = init(timg0.timer0, rng.clone()).unwrap(); + let esp_wifi_ctrl = init(timg0.timer0).unwrap(); let (mut controller, interfaces) = esp_wifi::wifi::new(&esp_wifi_ctrl, peripherals.WIFI).unwrap(); @@ -73,6 +71,7 @@ fn main() -> ! { }]); socket_set.add(dhcp_socket); + let rng = Rng::new(); let now = || time::Instant::now().duration_since_epoch().as_millis(); let stack = Stack::new(iface, device, socket_set, now, rng.random()); diff --git a/examples/src/bin/wifi_embassy_access_point.rs b/examples/src/bin/wifi_embassy_access_point.rs index 0582e346a3b..f860cbb0653 100644 --- a/examples/src/bin/wifi_embassy_access_point.rs +++ b/examples/src/bin/wifi_embassy_access_point.rs @@ -69,12 +69,8 @@ async fn main(spawner: Spawner) -> ! { esp_alloc::heap_allocator!(size: 72 * 1024); let timg0 = TimerGroup::new(peripherals.TIMG0); - let mut rng = Rng::new(peripherals.RNG); - let esp_wifi_ctrl = &*mk_static!( - EspWifiController<'static>, - init(timg0.timer0, rng.clone()).unwrap() - ); + let esp_wifi_ctrl = &*mk_static!(EspWifiController<'static>, init(timg0.timer0).unwrap()); let (controller, interfaces) = esp_wifi::wifi::new(&esp_wifi_ctrl, peripherals.WIFI).unwrap(); @@ -100,6 +96,7 @@ async fn main(spawner: Spawner) -> ! { dns_servers: Default::default(), }); + let rng = Rng::new(); let seed = (rng.random() as u64) << 32 | rng.random() as u64; // Init network stack diff --git a/examples/src/bin/wifi_embassy_access_point_with_sta.rs b/examples/src/bin/wifi_embassy_access_point_with_sta.rs index 4a6b08ba405..6d43c84339f 100644 --- a/examples/src/bin/wifi_embassy_access_point_with_sta.rs +++ b/examples/src/bin/wifi_embassy_access_point_with_sta.rs @@ -77,12 +77,8 @@ async fn main(spawner: Spawner) -> ! { esp_alloc::heap_allocator!(size: 72 * 1024); let timg0 = TimerGroup::new(peripherals.TIMG0); - let mut rng = Rng::new(peripherals.RNG); - let esp_wifi_ctrl = &*mk_static!( - EspWifiController<'static>, - init(timg0.timer0, rng.clone()).unwrap() - ); + let esp_wifi_ctrl = &*mk_static!(EspWifiController<'static>, init(timg0.timer0).unwrap()); let (mut controller, interfaces) = esp_wifi::wifi::new(&esp_wifi_ctrl, peripherals.WIFI).unwrap(); @@ -108,6 +104,7 @@ async fn main(spawner: Spawner) -> ! { }); let sta_config = embassy_net::Config::dhcpv4(Default::default()); + let rng = Rng::new(); let seed = (rng.random() as u64) << 32 | rng.random() as u64; // Init network stacks diff --git a/examples/src/bin/wifi_embassy_bench.rs b/examples/src/bin/wifi_embassy_bench.rs index 18004589b5d..24f33a773d9 100644 --- a/examples/src/bin/wifi_embassy_bench.rs +++ b/examples/src/bin/wifi_embassy_bench.rs @@ -77,12 +77,8 @@ async fn main(spawner: Spawner) -> ! { let server_address: Ipv4Addr = HOST_IP.parse().expect("Invalid HOST_IP address"); let timg0 = TimerGroup::new(peripherals.TIMG0); - let mut rng = Rng::new(peripherals.RNG); - let esp_wifi_ctrl = &*mk_static!( - EspWifiController<'static>, - init(timg0.timer0, rng.clone()).unwrap() - ); + let esp_wifi_ctrl = &*mk_static!(EspWifiController<'static>, init(timg0.timer0,).unwrap()); let (mut controller, interfaces) = esp_wifi::wifi::new(&esp_wifi_ctrl, peripherals.WIFI).unwrap(); @@ -106,6 +102,7 @@ async fn main(spawner: Spawner) -> ! { let config = embassy_net::Config::dhcpv4(Default::default()); + let rng = Rng::new(); let seed = (rng.random() as u64) << 32 | rng.random() as u64; // Init network stack diff --git a/examples/src/bin/wifi_embassy_ble.rs b/examples/src/bin/wifi_embassy_ble.rs index d31784a9edd..90c7e85a2ac 100644 --- a/examples/src/bin/wifi_embassy_ble.rs +++ b/examples/src/bin/wifi_embassy_ble.rs @@ -33,7 +33,6 @@ use esp_backtrace as _; use esp_hal::{ clock::CpuClock, gpio::{Input, InputConfig, Pull}, - rng::Rng, time, timer::timg::TimerGroup, }; @@ -62,10 +61,7 @@ async fn main(_spawner: Spawner) -> ! { let timg0 = TimerGroup::new(peripherals.TIMG0); - let esp_wifi_ctrl = &*mk_static!( - EspWifiController<'static>, - init(timg0.timer0, Rng::new(peripherals.RNG),).unwrap() - ); + let esp_wifi_ctrl = &*mk_static!(EspWifiController<'static>, init(timg0.timer0).unwrap()); let config = InputConfig::default().with_pull(Pull::Down); cfg_if::cfg_if! { diff --git a/examples/src/bin/wifi_embassy_dhcp.rs b/examples/src/bin/wifi_embassy_dhcp.rs index 4fbfb99543f..6e7f10bb2e0 100644 --- a/examples/src/bin/wifi_embassy_dhcp.rs +++ b/examples/src/bin/wifi_embassy_dhcp.rs @@ -53,12 +53,8 @@ async fn main(spawner: Spawner) -> ! { esp_alloc::heap_allocator!(size: 72 * 1024); let timg0 = TimerGroup::new(peripherals.TIMG0); - let mut rng = Rng::new(peripherals.RNG); - let esp_wifi_ctrl = &*mk_static!( - EspWifiController<'static>, - init(timg0.timer0, rng.clone()).unwrap() - ); + let esp_wifi_ctrl = &*mk_static!(EspWifiController<'static>, init(timg0.timer0).unwrap()); let (controller, interfaces) = esp_wifi::wifi::new(&esp_wifi_ctrl, peripherals.WIFI).unwrap(); @@ -77,6 +73,7 @@ async fn main(spawner: Spawner) -> ! { let config = embassy_net::Config::dhcpv4(Default::default()); + let rng = Rng::new(); let seed = (rng.random() as u64) << 32 | rng.random() as u64; // Init network stack diff --git a/examples/src/bin/wifi_embassy_esp_now.rs b/examples/src/bin/wifi_embassy_esp_now.rs index 29d4fd0c099..cc45de5cb4e 100644 --- a/examples/src/bin/wifi_embassy_esp_now.rs +++ b/examples/src/bin/wifi_embassy_esp_now.rs @@ -15,7 +15,7 @@ use embassy_futures::select::{Either, select}; use embassy_time::{Duration, Ticker}; use esp_alloc as _; use esp_backtrace as _; -use esp_hal::{clock::CpuClock, rng::Rng, timer::timg::TimerGroup}; +use esp_hal::{clock::CpuClock, timer::timg::TimerGroup}; use esp_println::println; use esp_wifi::{ EspWifiController, @@ -45,10 +45,7 @@ async fn main(_spawner: Spawner) -> ! { let timg0 = TimerGroup::new(peripherals.TIMG0); - let esp_wifi_ctrl = &*mk_static!( - EspWifiController<'static>, - init(timg0.timer0, Rng::new(peripherals.RNG),).unwrap() - ); + let esp_wifi_ctrl = &*mk_static!(EspWifiController<'static>, init(timg0.timer0).unwrap()); let wifi = peripherals.WIFI; let (mut controller, interfaces) = esp_wifi::wifi::new(&esp_wifi_ctrl, wifi).unwrap(); diff --git a/examples/src/bin/wifi_embassy_esp_now_duplex.rs b/examples/src/bin/wifi_embassy_esp_now_duplex.rs index 41f34603eb0..e95616e132a 100644 --- a/examples/src/bin/wifi_embassy_esp_now_duplex.rs +++ b/examples/src/bin/wifi_embassy_esp_now_duplex.rs @@ -16,7 +16,7 @@ use embassy_sync::{blocking_mutex::raw::NoopRawMutex, mutex::Mutex}; use embassy_time::{Duration, Ticker}; use esp_alloc as _; use esp_backtrace as _; -use esp_hal::{clock::CpuClock, rng::Rng, timer::timg::TimerGroup}; +use esp_hal::{clock::CpuClock, timer::timg::TimerGroup}; use esp_println::println; use esp_wifi::{ EspWifiController, @@ -46,10 +46,7 @@ async fn main(spawner: Spawner) -> ! { let timg0 = TimerGroup::new(peripherals.TIMG0); - let esp_wifi_ctrl = &*mk_static!( - EspWifiController<'static>, - init(timg0.timer0, Rng::new(peripherals.RNG)).unwrap() - ); + let esp_wifi_ctrl = &*mk_static!(EspWifiController<'static>, init(timg0.timer0).unwrap()); let wifi = peripherals.WIFI; let (mut controller, interfaces) = esp_wifi::wifi::new(&esp_wifi_ctrl, wifi).unwrap(); diff --git a/examples/src/bin/wifi_esp_now.rs b/examples/src/bin/wifi_esp_now.rs index e3d43798c33..5e24e744627 100644 --- a/examples/src/bin/wifi_esp_now.rs +++ b/examples/src/bin/wifi_esp_now.rs @@ -13,7 +13,6 @@ use esp_backtrace as _; use esp_hal::{ clock::CpuClock, main, - rng::Rng, time::{self, Duration}, timer::timg::TimerGroup, }; @@ -35,7 +34,7 @@ fn main() -> ! { let timg0 = TimerGroup::new(peripherals.TIMG0); - let esp_wifi_ctrl = init(timg0.timer0, Rng::new(peripherals.RNG)).unwrap(); + let esp_wifi_ctrl = init(timg0.timer0).unwrap(); let wifi = peripherals.WIFI; let (mut controller, interfaces) = esp_wifi::wifi::new(&esp_wifi_ctrl, wifi).unwrap(); diff --git a/examples/src/bin/wifi_sniffer.rs b/examples/src/bin/wifi_sniffer.rs index 74ae7c37f12..adf593b76df 100644 --- a/examples/src/bin/wifi_sniffer.rs +++ b/examples/src/bin/wifi_sniffer.rs @@ -18,7 +18,7 @@ use core::cell::RefCell; use critical_section::Mutex; use esp_backtrace as _; -use esp_hal::{clock::CpuClock, main, rng::Rng, timer::timg::TimerGroup}; +use esp_hal::{clock::CpuClock, main, timer::timg::TimerGroup}; use esp_println::println; use esp_wifi::{init, wifi}; use ieee80211::{match_frames, mgmt_frame::BeaconFrame}; @@ -36,7 +36,7 @@ fn main() -> ! { esp_alloc::heap_allocator!(size: 72 * 1024); let timg0 = TimerGroup::new(peripherals.TIMG0); - let esp_wifi_ctrl = init(timg0.timer0, Rng::new(peripherals.RNG)).unwrap(); + let esp_wifi_ctrl = init(timg0.timer0).unwrap(); // We must initialize some kind of interface and start it. let (mut controller, interfaces) = diff --git a/examples/src/bin/wifi_static_ip.rs b/examples/src/bin/wifi_static_ip.rs index 4b7efdbf138..42ac95367cd 100644 --- a/examples/src/bin/wifi_static_ip.rs +++ b/examples/src/bin/wifi_static_ip.rs @@ -47,9 +47,7 @@ fn main() -> ! { let timg0 = TimerGroup::new(peripherals.TIMG0); - let mut rng = Rng::new(peripherals.RNG); - - let esp_wifi_ctrl = init(timg0.timer0, rng.clone()).unwrap(); + let esp_wifi_ctrl = init(timg0.timer0).unwrap(); let (mut controller, interfaces) = esp_wifi::wifi::new(&esp_wifi_ctrl, peripherals.WIFI).unwrap(); @@ -64,6 +62,7 @@ fn main() -> ! { let mut socket_set_entries: [SocketStorage; 3] = Default::default(); let socket_set = SocketSet::new(&mut socket_set_entries[..]); + let rng = Rng::new(); let now = || time::Instant::now().duration_since_epoch().as_millis(); let mut stack = Stack::new(iface, device, socket_set, now, rng.random()); diff --git a/hil-test/Cargo.toml b/hil-test/Cargo.toml index 20e2431cb7a..d3231e2c1e9 100644 --- a/hil-test/Cargo.toml +++ b/hil-test/Cargo.toml @@ -104,6 +104,10 @@ harness = false name = "qspi" harness = false +[[test]] +name = "rng" +harness = false + [[test]] name = "spi_full_duplex" harness = false diff --git a/hil-test/tests/alloc_psram.rs b/hil-test/tests/alloc_psram.rs index e5b3dd5c0da..63e0111f140 100644 --- a/hil-test/tests/alloc_psram.rs +++ b/hil-test/tests/alloc_psram.rs @@ -175,7 +175,7 @@ mod tests { #[repr(C, align(4))] struct AlignedBuf([u8; N]); - let mut rng = esp_hal::rng::Rng::new(unsafe { esp_hal::peripherals::RNG::steal() }); + let rng = esp_hal::rng::Rng::new(); for _ in 0..100 { let mut buf = [0u8; 1024]; diff --git a/hil-test/tests/ecc.rs b/hil-test/tests/ecc.rs index 0e649b4fc4f..7c3702b062e 100644 --- a/hil-test/tests/ecc.rs +++ b/hil-test/tests/ecc.rs @@ -21,7 +21,7 @@ use esp_hal::{ Blocking, clock::CpuClock, ecc::{Ecc, EllipticCurve, Error}, - rng::Rng, + rng::{Rng, TrngSource}, }; use hex_literal::hex; use hil_test as _; @@ -47,7 +47,7 @@ const TEST_PARAMS_VECTOR: TestParams = TestParams { struct Context<'a> { ecc: Ecc<'a, Blocking>, - rng: Rng, + _rng_source: TrngSource<'a>, } #[cfg(test)] @@ -58,16 +58,17 @@ mod tests { #[init] fn init() -> Context<'static> { let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max()); - let peripherals = esp_hal::init(config); + let p = esp_hal::init(config); - let ecc = Ecc::new(peripherals.ECC); - let rng = Rng::new(peripherals.RNG); - - Context { ecc, rng } + Context { + ecc: Ecc::new(p.ECC), + _rng_source: TrngSource::new(p.RNG, p.ADC1), + } } #[test] fn test_ecc_affine_point_multiplication(mut ctx: Context<'static>) { + let rng = Rng::new(); for &prime_field in TEST_PARAMS_VECTOR.prime_fields { match prime_field.len() { 24 => (), @@ -79,7 +80,7 @@ mod tests { let (y, _) = y.split_at_mut(prime_field.len()); for _ in 0..TEST_PARAMS_VECTOR.nb_loop_mul { loop { - ctx.rng.read(k); + rng.read(k); let is_zero = k.iter().all(|&elt| elt == 0); let is_modulus = k.iter().zip(prime_field).all(|(&a, &b)| a == b); if is_zero == false && is_modulus == false { @@ -168,6 +169,7 @@ mod tests { #[test] fn test_ecc_affine_point_verification(mut ctx: Context<'static>) { + let rng = Rng::new(); for &prime_field in TEST_PARAMS_VECTOR.prime_fields { let t1 = &mut [0_u8; 96]; let (k, x) = t1.split_at_mut(prime_field.len()); @@ -175,7 +177,7 @@ mod tests { let (y, _) = y.split_at_mut(prime_field.len()); for _ in 0..TEST_PARAMS_VECTOR.nb_loop_mul { loop { - ctx.rng.read(k); + rng.read(k); let is_zero = k.iter().all(|&elt| elt == 0); let is_modulus = k.iter().zip(prime_field).all(|(&a, &b)| a == b); if is_zero == false && is_modulus == false { @@ -228,6 +230,7 @@ mod tests { #[test] fn test_ecc_afine_point_verification_multiplication(mut ctx: Context<'static>) { + let rng = Rng::new(); for &prime_field in TEST_PARAMS_VECTOR.prime_fields { let t1 = &mut [0_u8; 96]; let (k, px) = t1.split_at_mut(prime_field.len()); @@ -241,7 +244,7 @@ mod tests { let qz = &mut [0u8; 8]; for _ in 0..TEST_PARAMS_VECTOR.nb_loop_mul { loop { - ctx.rng.read(k); + rng.read(k); let is_zero = k.iter().all(|&elt| elt == 0); let is_modulus = k.iter().zip(prime_field).all(|(&a, &b)| a == b); if is_zero == false && is_modulus == false { @@ -345,6 +348,7 @@ mod tests { } #[test] fn test_ecc_jacobian_point_multiplication(mut ctx: Context<'static>) { + let rng = Rng::new(); for &prime_field in TEST_PARAMS_VECTOR.prime_fields { let t1 = &mut [0_u8; 96]; let (k, x) = t1.split_at_mut(prime_field.len()); @@ -358,7 +362,7 @@ mod tests { let (sw_k, _) = sw_k.split_at_mut(prime_field.len()); loop { - ctx.rng.read(k); + rng.read(k); let is_zero = k.iter().all(|&elt| elt == 0); let is_modulus = k.iter().zip(prime_field).all(|(&a, &b)| a == b); if is_zero == false && is_modulus == false { @@ -466,6 +470,7 @@ mod tests { #[test] fn test_jacobian_point_verification(mut ctx: Context<'static>) { + let rng = Rng::new(); for &prime_field in TEST_PARAMS_VECTOR.prime_fields { let t1 = &mut [0_u8; 128]; let (k, x) = t1.split_at_mut(prime_field.len()); @@ -474,8 +479,8 @@ mod tests { let (z, _) = z.split_at_mut(prime_field.len()); for _ in 0..TEST_PARAMS_VECTOR.nb_loop_mul { loop { - ctx.rng.read(k); - ctx.rng.read(z); + rng.read(k); + rng.read(z); let is_zero = k.iter().all(|&elt| elt == 0) || z.iter().all(|&elt| elt == 0); let is_modulus = k.iter().zip(prime_field).all(|(&a, &b)| a == b) || z.iter().zip(prime_field).all(|(&a, &b)| a == b); @@ -553,6 +558,7 @@ mod tests { #[test] fn test_ecc_afine_point_verification_jacobian_multiplication(mut ctx: Context<'static>) { + let rng = Rng::new(); for &prime_field in TEST_PARAMS_VECTOR.prime_fields { let t1 = &mut [0_u8; 96]; let (k, x) = t1.split_at_mut(prime_field.len()); @@ -566,7 +572,7 @@ mod tests { let (sw_k, _) = sw_k.split_at_mut(prime_field.len()); loop { - ctx.rng.read(k); + rng.read(k); let is_zero = k.iter().all(|&elt| elt == 0); let is_modulus = k.iter().zip(prime_field).all(|(&a, &b)| a == b); if is_zero == false && is_modulus == false { @@ -687,14 +693,15 @@ mod tests { #[test] #[cfg(feature = "esp32c2")] fn test_ecc_finite_field_division(mut ctx: Context<'static>) { + let rng = Rng::new(); for &prime_field in TEST_PARAMS_VECTOR.prime_fields { let t1 = &mut [0_u8; 64]; let (k, y) = t1.split_at_mut(prime_field.len()); let (y, _) = y.split_at_mut(prime_field.len()); for _ in 0..TEST_PARAMS_VECTOR.nb_loop_inv { loop { - ctx.rng.read(k); - ctx.rng.read(y); + rng.read(k); + rng.read(y); let is_zero = k.iter().all(|&elt| elt == 0) || y.iter().all(|&elt| elt == 0); let is_modulus = k.iter().zip(prime_field).all(|(&a, &b)| a == b) || y.iter().zip(prime_field).all(|(&a, &b)| a == b); diff --git a/hil-test/tests/esp_wifi_ble_controller.rs b/hil-test/tests/esp_wifi_ble_controller.rs index 74886a102f4..113c3868513 100644 --- a/hil-test/tests/esp_wifi_ble_controller.rs +++ b/hil-test/tests/esp_wifi_ble_controller.rs @@ -17,7 +17,7 @@ #![no_main] use embedded_io::{Read, Write}; -use esp_hal::{clock::CpuClock, peripherals::Peripherals, rng::Rng, timer::timg::TimerGroup}; +use esp_hal::{clock::CpuClock, peripherals::Peripherals, timer::timg::TimerGroup}; use esp_wifi::ble::controller::BleConnector; use hil_test as _; @@ -29,12 +29,12 @@ fn _esp_wifi_can_be_reinited() { { let timg0: TimerGroup<'_, _> = TimerGroup::new(p.TIMG0.reborrow()); - let _init = esp_wifi::init(timg0.timer0, Rng::new(p.RNG.reborrow())).unwrap(); + let _init = esp_wifi::init(timg0.timer0).unwrap(); } { let timg0 = TimerGroup::new(p.TIMG0.reborrow()); - let _init = esp_wifi::init(timg0.timer0, Rng::new(p.RNG.reborrow())).unwrap(); + let _init = esp_wifi::init(timg0.timer0).unwrap(); } } @@ -59,7 +59,7 @@ mod tests { #[test] fn test_controller_comms(peripherals: Peripherals) { let timg0 = TimerGroup::new(peripherals.TIMG0); - let init = esp_wifi::init(timg0.timer0, Rng::new(peripherals.RNG)).unwrap(); + let init = esp_wifi::init(timg0.timer0).unwrap(); let mut connector = BleConnector::new(&init, peripherals.BT); diff --git a/hil-test/tests/esp_wifi_floats.rs b/hil-test/tests/esp_wifi_floats.rs index fabdf505c38..3e8be3fb571 100644 --- a/hil-test/tests/esp_wifi_floats.rs +++ b/hil-test/tests/esp_wifi_floats.rs @@ -15,7 +15,6 @@ use esp_hal::{ handler, interrupt::software::{SoftwareInterrupt, SoftwareInterruptControl}, peripherals::Peripherals, - rng::Rng, timer::timg::TimerGroup, }; use hil_test as _; @@ -97,7 +96,7 @@ mod tests { #[test] fn fpu_stays_enabled_with_wifi(peripherals: Peripherals) { let timg0 = TimerGroup::new(peripherals.TIMG0); - let _init = esp_wifi::init(timg0.timer1, Rng::new(peripherals.RNG)).unwrap(); + let _init = esp_wifi::init(timg0.timer1).unwrap(); let mut sw_ints = SoftwareInterruptControl::new(peripherals.SW_INTERRUPT); @@ -140,7 +139,7 @@ mod tests { } let timg0 = TimerGroup::new(peripherals.TIMG0); - let _init = esp_wifi::init(timg0.timer1, Rng::new(peripherals.RNG)).unwrap(); + let _init = esp_wifi::init(timg0.timer1).unwrap(); let mut sw_ints = SoftwareInterruptControl::new(peripherals.SW_INTERRUPT); @@ -177,9 +176,6 @@ mod tests { // creating a new test suite is not necessary as we don't want to flash/run // anything. #[allow(unused)] // compile test -fn esp_wifi_can_be_initialized_with_any_timer( - timer: esp_hal::timer::AnyTimer<'static>, - rng: esp_hal::rng::Rng, -) { - esp_wifi::init(timer, rng); +fn esp_wifi_can_be_initialized_with_any_timer(timer: esp_hal::timer::AnyTimer<'static>) { + esp_wifi::init(timer); } diff --git a/hil-test/tests/esp_wifi_init.rs b/hil-test/tests/esp_wifi_init.rs index baf2f5fb412..7cddcde5285 100644 --- a/hil-test/tests/esp_wifi_init.rs +++ b/hil-test/tests/esp_wifi_init.rs @@ -15,8 +15,7 @@ use esp_hal::xtensa_lx::interrupt::free as interrupt_free; use esp_hal::{ clock::CpuClock, interrupt::{Priority, software::SoftwareInterruptControl}, - peripherals::{Peripherals, RNG, TIMG0}, - rng::Rng, + peripherals::{Peripherals, TIMG0}, timer::timg::TimerGroup, }; use esp_hal_embassy::InterruptExecutor; @@ -30,19 +29,12 @@ esp_bootloader_esp_idf::esp_app_desc!(); async fn try_init( signal: &'static Signal>, timer: TIMG0<'static>, - rng: RNG<'static>, ) { let timg0 = TimerGroup::new(timer); - let init = esp_wifi::init(timg0.timer0, Rng::new(rng)); - - match init { - Ok(_) => { - signal.signal(None); - } - Err(err) => { - signal.signal(Some(err)); - } + match esp_wifi::init(timg0.timer0) { + Ok(_) => signal.signal(None), + Err(err) => signal.signal(Some(err)), } } @@ -62,8 +54,7 @@ mod tests { #[test] fn test_init_fails_cs(peripherals: Peripherals) { let timg0 = TimerGroup::new(peripherals.TIMG0); - let init = - critical_section::with(|_| esp_wifi::init(timg0.timer0, Rng::new(peripherals.RNG))); + let init = critical_section::with(|_| esp_wifi::init(timg0.timer0)); assert!(matches!( init, @@ -74,7 +65,7 @@ mod tests { #[test] fn test_init_fails_interrupt_free(peripherals: Peripherals) { let timg0 = TimerGroup::new(peripherals.TIMG0); - let init = interrupt_free(|| esp_wifi::init(timg0.timer0, Rng::new(peripherals.RNG))); + let init = interrupt_free(|| esp_wifi::init(timg0.timer0)); assert!(matches!( init, @@ -95,9 +86,7 @@ mod tests { let signal = mk_static!(Signal>, Signal::new()); - spawner - .spawn(try_init(signal, peripherals.TIMG0, peripherals.RNG)) - .ok(); + spawner.spawn(try_init(signal, peripherals.TIMG0)).ok(); let res = signal.wait().await; diff --git a/hil-test/tests/rng.rs b/hil-test/tests/rng.rs new file mode 100644 index 00000000000..ff82366fd3f --- /dev/null +++ b/hil-test/tests/rng.rs @@ -0,0 +1,66 @@ +//! RNG Tests + +//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 +//% FEATURES: unstable + +#![no_std] +#![no_main] + +use hil_test as _; + +esp_bootloader_esp_idf::esp_app_desc!(); + +#[cfg(test)] +#[embedded_test::tests(default_timeout = 5)] +mod tests { + use esp_hal::rng::{Rng, Trng, TrngSource}; + + #[test] + fn test_trng_without_source_is_error() { + assert!(Trng::try_new().is_err()); + + // Rng can be created anyway: + let _rng = Rng::new(); + } + + #[test] + fn test_trng_source_cannot_be_disabled_while_in_use() { + let p = esp_hal::init(Default::default()); + let source = TrngSource::new(p.RNG, p.ADC1); + + let trng = Trng::try_new().unwrap(); + + let _source = source.try_disable().unwrap_err(); + + // Need to drop trng first + core::mem::drop(trng); + + // Rng will not prevent disabling the TrngSource + let _rng = Rng::new(); + } + + #[test] + #[should_panic] + fn test_trng_source_cannot_be_dropped_while_in_use() { + let p = esp_hal::init(Default::default()); + let source = TrngSource::new(p.RNG, p.ADC1); + + let _trng = Trng::try_new().unwrap(); + + core::mem::drop(source); + } + + #[test] + fn test_trng_source_can_be_dropped_if_unsafely_enabled() { + let p = esp_hal::init(Default::default()); + + let source = TrngSource::new(p.RNG, p.ADC1); + + // Unsafely increase the counter. Practically, this may be done in esp-wifi. + unsafe { TrngSource::increase_entropy_source_counter() }; + + let _trng = Trng::try_new().unwrap(); + + core::mem::drop(source); + } +} diff --git a/hil-test/tests/sha.rs b/hil-test/tests/sha.rs index 81684a7120a..7c3627e5cf3 100644 --- a/hil-test/tests/sha.rs +++ b/hil-test/tests/sha.rs @@ -16,7 +16,7 @@ use esp_hal::sha::{Sha384, Sha512}; #[cfg(any(feature = "esp32s2", feature = "esp32s3"))] use esp_hal::sha::{Sha512_224, Sha512_256}; use esp_hal::{ - rng::Rng, + rng::{Rng, TrngSource}, sha::{Sha, Sha1, Sha256, ShaAlgorithm, ShaDigest}, }; use hil_test as _; @@ -88,7 +88,6 @@ fn assert_digest<'a, S: ShaAlgorithm, const N: usize>(sha: &'a mut Sha<'static>, #[allow(unused_mut)] fn with_random_data( - mut rng: Rng, mut f: impl FnMut( (&[u8], &mut [u8]), (&[u8], &mut [u8]), @@ -105,6 +104,8 @@ fn with_random_data( let mut sha384_random = [0u8; BUFFER_LEN]; let mut sha512_random = [0u8; BUFFER_LEN]; + let rng = Rng::new(); + // Fill source data with random data rng.read(&mut sha1_random); #[cfg(not(feature = "esp32"))] @@ -157,7 +158,7 @@ fn with_random_data( } pub struct Context { - rng: Rng, + _rng_source: TrngSource<'static>, sha: Sha<'static>, } @@ -179,7 +180,7 @@ mod tests { let peripherals = esp_hal::init(config); Context { - rng: Rng::new(peripherals.RNG), + _rng_source: TrngSource::new(peripherals.RNG, peripherals.ADC1), sha: Sha::new(peripherals.SHA), } } @@ -252,7 +253,7 @@ mod tests { #[test] fn test_sha_rolling(mut ctx: Context) { #[allow(unused)] - with_random_data(ctx.rng, |sha1_p, sha224_p, sha256_p, sha384_p, sha512_p| { + with_random_data(|sha1_p, sha224_p, sha256_p, sha384_p, sha512_p| { let mut sha1_remaining = sha1_p.0; let mut sha224_remaining = sha224_p.0; let mut sha256_remaining = sha256_p.0; @@ -335,7 +336,7 @@ mod tests { #[test] fn test_for_digest_rolling(mut ctx: Context) { #[allow(unused)] - with_random_data(ctx.rng, |sha1_p, sha224_p, sha256_p, sha384_p, sha512_p| { + with_random_data(|sha1_p, sha224_p, sha256_p, sha384_p, sha512_p| { // The Digest::update will consume the entirety of remaining. We don't need to // loop until remaining is fully consumed.