nrf/rng: add Blocking/Async Mode param.
This allows avoiding creating the irq handler if you're only going to use it in blocking mode.
This commit is contained in:
		
							parent
							
								
									7cbc9058bc
								
							
						
					
					
						commit
						0e47478f01
					
				| @ -1039,3 +1039,27 @@ pub fn init(config: config::Config) -> Peripherals { | |||||||
| 
 | 
 | ||||||
|     peripherals |     peripherals | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | /// Operating modes for peripherals.
 | ||||||
|  | pub mod mode { | ||||||
|  |     trait SealedMode {} | ||||||
|  | 
 | ||||||
|  |     /// Operating mode for a peripheral.
 | ||||||
|  |     #[allow(private_bounds)] | ||||||
|  |     pub trait Mode: SealedMode {} | ||||||
|  | 
 | ||||||
|  |     macro_rules! impl_mode { | ||||||
|  |         ($name:ident) => { | ||||||
|  |             impl SealedMode for $name {} | ||||||
|  |             impl Mode for $name {} | ||||||
|  |         }; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Blocking mode.
 | ||||||
|  |     pub struct Blocking; | ||||||
|  |     /// Async mode.
 | ||||||
|  |     pub struct Async; | ||||||
|  | 
 | ||||||
|  |     impl_mode!(Blocking); | ||||||
|  |     impl_mode!(Async); | ||||||
|  | } | ||||||
|  | |||||||
| @ -14,6 +14,7 @@ use embassy_hal_internal::{Peri, PeripheralType}; | |||||||
| use embassy_sync::waitqueue::WakerRegistration; | use embassy_sync::waitqueue::WakerRegistration; | ||||||
| 
 | 
 | ||||||
| use crate::interrupt::typelevel::Interrupt; | use crate::interrupt::typelevel::Interrupt; | ||||||
|  | use crate::mode::{Async, Blocking, Mode}; | ||||||
| use crate::{interrupt, pac}; | use crate::{interrupt, pac}; | ||||||
| 
 | 
 | ||||||
| /// Interrupt handler.
 | /// Interrupt handler.
 | ||||||
| @ -55,11 +56,31 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl | |||||||
| /// A wrapper around an nRF RNG peripheral.
 | /// A wrapper around an nRF RNG peripheral.
 | ||||||
| ///
 | ///
 | ||||||
| /// It has a non-blocking API, and a blocking api through `rand`.
 | /// It has a non-blocking API, and a blocking api through `rand`.
 | ||||||
| pub struct Rng<'d, T: Instance> { | pub struct Rng<'d, T: Instance, M: Mode> { | ||||||
|     _peri: Peri<'d, T>, |     _peri: Peri<'d, T>, | ||||||
|  |     _phantom: PhantomData<M>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<'d, T: Instance> Rng<'d, T> { | impl<'d, T: Instance> Rng<'d, T, Blocking> { | ||||||
|  |     /// Creates a new RNG driver from the `RNG` peripheral and interrupt.
 | ||||||
|  |     ///
 | ||||||
|  |     /// SAFETY: The future returned from `fill_bytes` must not have its lifetime end without running its destructor,
 | ||||||
|  |     /// e.g. using `mem::forget`.
 | ||||||
|  |     ///
 | ||||||
|  |     /// The synchronous API is safe.
 | ||||||
|  |     pub fn new_blocking(rng: Peri<'d, T>) -> Self { | ||||||
|  |         let this = Self { | ||||||
|  |             _peri: rng, | ||||||
|  |             _phantom: PhantomData, | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         this.stop(); | ||||||
|  | 
 | ||||||
|  |         this | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<'d, T: Instance> Rng<'d, T, Async> { | ||||||
|     /// Creates a new RNG driver from the `RNG` peripheral and interrupt.
 |     /// Creates a new RNG driver from the `RNG` peripheral and interrupt.
 | ||||||
|     ///
 |     ///
 | ||||||
|     /// SAFETY: The future returned from `fill_bytes` must not have its lifetime end without running its destructor,
 |     /// SAFETY: The future returned from `fill_bytes` must not have its lifetime end without running its destructor,
 | ||||||
| @ -70,7 +91,10 @@ impl<'d, T: Instance> Rng<'d, T> { | |||||||
|         rng: Peri<'d, T>, |         rng: Peri<'d, T>, | ||||||
|         _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |         _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | ||||||
|     ) -> Self { |     ) -> Self { | ||||||
|         let this = Self { _peri: rng }; |         let this = Self { | ||||||
|  |             _peri: rng, | ||||||
|  |             _phantom: PhantomData, | ||||||
|  |         }; | ||||||
| 
 | 
 | ||||||
|         this.stop(); |         this.stop(); | ||||||
|         this.disable_irq(); |         this.disable_irq(); | ||||||
| @ -81,14 +105,6 @@ impl<'d, T: Instance> Rng<'d, T> { | |||||||
|         this |         this | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn stop(&self) { |  | ||||||
|         T::regs().tasks_stop().write_value(1) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn start(&self) { |  | ||||||
|         T::regs().tasks_start().write_value(1) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn enable_irq(&self) { |     fn enable_irq(&self) { | ||||||
|         T::regs().intenset().write(|w| w.set_valrdy(true)); |         T::regs().intenset().write(|w| w.set_valrdy(true)); | ||||||
|     } |     } | ||||||
| @ -97,16 +113,6 @@ impl<'d, T: Instance> Rng<'d, T> { | |||||||
|         T::regs().intenclr().write(|w| w.set_valrdy(true)); |         T::regs().intenclr().write(|w| w.set_valrdy(true)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Enable or disable the RNG's bias correction.
 |  | ||||||
|     ///
 |  | ||||||
|     /// Bias correction removes any bias towards a '1' or a '0' in the bits generated.
 |  | ||||||
|     /// However, this makes the generation of numbers slower.
 |  | ||||||
|     ///
 |  | ||||||
|     /// Defaults to disabled.
 |  | ||||||
|     pub fn set_bias_correction(&self, enable: bool) { |  | ||||||
|         T::regs().config().write(|w| w.set_dercen(enable)) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /// Fill the buffer with random bytes.
 |     /// Fill the buffer with random bytes.
 | ||||||
|     pub async fn fill_bytes(&mut self, dest: &mut [u8]) { |     pub async fn fill_bytes(&mut self, dest: &mut [u8]) { | ||||||
|         if dest.is_empty() { |         if dest.is_empty() { | ||||||
| @ -153,6 +159,26 @@ impl<'d, T: Instance> Rng<'d, T> { | |||||||
|         // Trigger the teardown
 |         // Trigger the teardown
 | ||||||
|         drop(on_drop); |         drop(on_drop); | ||||||
|     } |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<'d, T: Instance, M: Mode> Rng<'d, T, M> { | ||||||
|  |     fn stop(&self) { | ||||||
|  |         T::regs().tasks_stop().write_value(1) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn start(&self) { | ||||||
|  |         T::regs().tasks_start().write_value(1) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Enable or disable the RNG's bias correction.
 | ||||||
|  |     ///
 | ||||||
|  |     /// Bias correction removes any bias towards a '1' or a '0' in the bits generated.
 | ||||||
|  |     /// However, this makes the generation of numbers slower.
 | ||||||
|  |     ///
 | ||||||
|  |     /// Defaults to disabled.
 | ||||||
|  |     pub fn set_bias_correction(&self, enable: bool) { | ||||||
|  |         T::regs().config().write(|w| w.set_dercen(enable)) | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /// Fill the buffer with random bytes, blocking version.
 |     /// Fill the buffer with random bytes, blocking version.
 | ||||||
|     pub fn blocking_fill_bytes(&mut self, dest: &mut [u8]) { |     pub fn blocking_fill_bytes(&mut self, dest: &mut [u8]) { | ||||||
| @ -184,7 +210,7 @@ impl<'d, T: Instance> Rng<'d, T> { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<'d, T: Instance> Drop for Rng<'d, T> { | impl<'d, T: Instance, M: Mode> Drop for Rng<'d, T, M> { | ||||||
|     fn drop(&mut self) { |     fn drop(&mut self) { | ||||||
|         self.stop(); |         self.stop(); | ||||||
|         critical_section::with(|cs| { |         critical_section::with(|cs| { | ||||||
| @ -195,7 +221,7 @@ impl<'d, T: Instance> Drop for Rng<'d, T> { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<'d, T: Instance> rand_core_06::RngCore for Rng<'d, T> { | impl<'d, T: Instance, M: Mode> rand_core_06::RngCore for Rng<'d, T, M> { | ||||||
|     fn fill_bytes(&mut self, dest: &mut [u8]) { |     fn fill_bytes(&mut self, dest: &mut [u8]) { | ||||||
|         self.blocking_fill_bytes(dest); |         self.blocking_fill_bytes(dest); | ||||||
|     } |     } | ||||||
| @ -211,9 +237,9 @@ impl<'d, T: Instance> rand_core_06::RngCore for Rng<'d, T> { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<'d, T: Instance> rand_core_06::CryptoRng for Rng<'d, T> {} | impl<'d, T: Instance, M: Mode> rand_core_06::CryptoRng for Rng<'d, T, M> {} | ||||||
| 
 | 
 | ||||||
| impl<'d, T: Instance> rand_core_09::RngCore for Rng<'d, T> { | impl<'d, T: Instance, M: Mode> rand_core_09::RngCore for Rng<'d, T, M> { | ||||||
|     fn fill_bytes(&mut self, dest: &mut [u8]) { |     fn fill_bytes(&mut self, dest: &mut [u8]) { | ||||||
|         self.blocking_fill_bytes(dest); |         self.blocking_fill_bytes(dest); | ||||||
|     } |     } | ||||||
| @ -225,7 +251,7 @@ impl<'d, T: Instance> rand_core_09::RngCore for Rng<'d, T> { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<'d, T: Instance> rand_core_09::CryptoRng for Rng<'d, T> {} | impl<'d, T: Instance, M: Mode> rand_core_09::CryptoRng for Rng<'d, T, M> {} | ||||||
| 
 | 
 | ||||||
| /// Peripheral static state
 | /// Peripheral static state
 | ||||||
| pub(crate) struct State { | pub(crate) struct State { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user