commit
						3e83a495cb
					
				| @ -15,6 +15,7 @@ cortex-m-rt = { version = "0.6.13", features = ["device"] } | ||||
| cortex-m = "0.7.1" | ||||
| embedded-hal    = { version = "0.2.4" } | ||||
| futures = { version = "0.3.5", default-features = false, features = ["async-await"] } | ||||
| rand_core = { version = "0.6.2", optional=true} | ||||
| 
 | ||||
| [build-dependencies] | ||||
| regex = "1.4.6" | ||||
| @ -321,7 +322,7 @@ _exti = [] | ||||
| _exti_v1 = [] | ||||
| _gpio = [] | ||||
| _gpio_v2 = [] | ||||
| _rng = [] | ||||
| _rng = [ "rand_core",] | ||||
| _rng_v1 = [] | ||||
| _stm32f4 = [] | ||||
| _stm32l4 = [] | ||||
|  | ||||
| @ -201,6 +201,9 @@ for chip in chips.values(): | ||||
| 
 | ||||
| # ========= Update Cargo features | ||||
| 
 | ||||
| feature_optional_deps = {} | ||||
| feature_optional_deps['_rng'] = ['rand_core'] | ||||
| 
 | ||||
| features = {} | ||||
| extra_features = set() | ||||
| for name, chip in chips.items(): | ||||
| @ -208,7 +211,7 @@ for name, chip in chips.items(): | ||||
|     for feature in chip['features']: | ||||
|         extra_features.add(feature) | ||||
| for feature in sorted(list(extra_features)): | ||||
|     features[feature] = [] | ||||
|     features[feature] = feature_optional_deps.get(feature) or [] | ||||
| 
 | ||||
| SEPARATOR_START = '# BEGIN GENERATED FEATURES\n' | ||||
| SEPARATOR_END = '# END GENERATED FEATURES\n' | ||||
|  | ||||
| @ -15,6 +15,7 @@ pub mod exti; | ||||
| pub mod gpio; | ||||
| #[cfg(feature = "_rng")] | ||||
| pub mod rng; | ||||
| #[cfg(feature = "_usart")] | ||||
| pub mod usart; | ||||
| 
 | ||||
| // This must go LAST so that it sees the `impl_foo!` macros
 | ||||
|  | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -1,8 +1,26 @@ | ||||
| #![macro_use] | ||||
| use crate::pac::rng::{regs, Rng}; | ||||
| 
 | ||||
| //use crate::pac::rng::{regs, Rng};
 | ||||
| use crate::pac; | ||||
| use crate::peripherals; | ||||
| use embassy::util::Unborrow; | ||||
| use crate::interrupt; | ||||
| use futures::future::poll_fn; | ||||
| use embassy::util::{Unborrow, AtomicWaker}; | ||||
| use embassy_extras::unborrow; | ||||
| use rand_core::{RngCore, CryptoRng}; | ||||
| 
 | ||||
| use defmt::*; | ||||
| 
 | ||||
| static RNG_WAKER: AtomicWaker = AtomicWaker::new(); | ||||
| 
 | ||||
| #[interrupt] | ||||
| unsafe fn RNG() { | ||||
|     let bits = crate::pac::RNG.sr().read(); | ||||
|     if bits.drdy() || bits.seis() || bits.ceis() { | ||||
|         crate::pac::RNG.cr().write(|reg| reg.set_ie(false)); | ||||
|         RNG_WAKER.wake(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub struct Random<T: Instance> { | ||||
|     inner: T, | ||||
| @ -11,21 +29,112 @@ pub struct Random<T: Instance> { | ||||
| impl<T: Instance> Random<T> { | ||||
|     pub fn new(inner: impl Unborrow<Target=T>) -> Self { | ||||
|         unborrow!(inner); | ||||
|         Self { inner } | ||||
|         let mut random = Self { inner }; | ||||
|         random.reset(); | ||||
|         random | ||||
|     } | ||||
| 
 | ||||
|     pub fn reset(&mut self) { | ||||
|         unsafe { | ||||
|             T::regs().cr().modify(|reg| { | ||||
|                 reg.set_rngen(true); | ||||
|                 reg.set_ie(true); | ||||
|             }); | ||||
|             T::regs().sr().modify(|reg| { | ||||
|                 reg.set_seis(false); | ||||
|                 reg.set_ceis(false); | ||||
|             }); | ||||
|         } | ||||
|         // Reference manual says to discard the first.
 | ||||
|         let _ = self.next_u32(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<T: Instance> RngCore for Random<T> { | ||||
|     fn next_u32(&mut self) -> u32 { | ||||
|         loop { | ||||
|             let bits = unsafe { T::regs().sr().read() }; | ||||
|             if bits.drdy() { | ||||
|                 return unsafe{ T::regs().dr().read() } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn next_u64(&mut self) -> u64 { | ||||
|         let mut rand = self.next_u32() as u64; | ||||
|         rand |= (self.next_u32() as u64) << 32; | ||||
|         rand | ||||
|     } | ||||
| 
 | ||||
|     fn fill_bytes(&mut self, dest: &mut [u8]) { | ||||
|         for chunk in dest.chunks_mut(4) { | ||||
|             let rand = self.next_u32(); | ||||
|             for (slot, num) in chunk.iter_mut().zip(rand.to_be_bytes().iter()) { | ||||
|                 *slot = *num | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> { | ||||
|         self.fill_bytes( dest ); | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<T: Instance> CryptoRng for Random<T> { } | ||||
| 
 | ||||
| use core::future::Future; | ||||
| use core::marker::PhantomData; | ||||
| use embassy::traits::rng::Rng as RngTrait; | ||||
| use embassy::traits; | ||||
| use core::task::{Poll, Context}; | ||||
| use core::pin::Pin; | ||||
| 
 | ||||
| impl<T: Instance> RngTrait for Random<T> { | ||||
|     type Error = (); | ||||
|     #[rustfmt::skip] | ||||
| pub enum Error { | ||||
|     SeedError, | ||||
|     ClockError, | ||||
| } | ||||
| 
 | ||||
| impl<T: Instance> traits::rng::Rng for Random<T> { | ||||
|     type Error = Error; | ||||
|     type RngFuture<'a> where Self: 'a = impl Future<Output=Result<(), Self::Error>>; | ||||
| 
 | ||||
|     fn fill<'a>(&'a mut self, dest: &'a mut [u8]) -> Self::RngFuture<'a> { | ||||
|         async move { Ok(()) } | ||||
|     fn fill_bytes<'a>(&'a mut self, dest: &'a mut [u8]) -> Self::RngFuture<'a> { | ||||
|         unsafe { | ||||
|             T::regs().cr().modify(|reg| { | ||||
|                 reg.set_rngen(true); | ||||
|             }); | ||||
|         } | ||||
|         async move { | ||||
|             for chunk in dest.chunks_mut(4) { | ||||
|                 poll_fn(|cx| { | ||||
|                     RNG_WAKER.register(cx.waker()); | ||||
|                     unsafe { | ||||
|                         T::regs().cr().modify(|reg| { | ||||
|                             reg.set_ie(true); | ||||
|                         }); | ||||
|                     } | ||||
| 
 | ||||
|                     let bits = unsafe { T::regs().sr().read() }; | ||||
| 
 | ||||
|                     if bits.drdy() { | ||||
|                         Poll::Ready(Ok(())) | ||||
|                     } else if bits.seis() { | ||||
|                         self.reset(); | ||||
|                         Poll::Ready(Err(Error::SeedError)) | ||||
|                     } else if bits.ceis() { | ||||
|                         self.reset(); | ||||
|                         Poll::Ready(Err(Error::ClockError)) | ||||
|                     } else { | ||||
|                         Poll::Pending | ||||
|                     } | ||||
|                 } ).await?; | ||||
|                 let random_bytes = unsafe { T::regs().dr().read() }.to_be_bytes(); | ||||
|                 for (dest, src) in chunk.iter_mut().zip(random_bytes.iter()) { | ||||
|                     *dest = *src | ||||
|                 } | ||||
|             } | ||||
|             Ok(()) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -33,7 +142,7 @@ pub(crate) mod sealed { | ||||
|     use super::*; | ||||
| 
 | ||||
|     pub trait Instance { | ||||
|         fn regs(&self) -> Rng; | ||||
|         fn regs() -> pac::rng::Rng; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -41,12 +150,12 @@ pub trait Instance: sealed::Instance {} | ||||
| 
 | ||||
| macro_rules! impl_rng { | ||||
|     ($inst:ident) => { | ||||
|         impl crate::rng::sealed::Instance for peripherals::$inst { | ||||
|             fn regs(&self) -> crate::pac::rng::Rng { | ||||
|                 crate::pac::$inst | ||||
|         impl crate::rng::sealed::Instance for peripherals::RNG { | ||||
|             fn regs() -> crate::pac::chip::rng::Rng { | ||||
|                 crate::pac::RNG | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         impl crate::rng::Instance for peripherals::$inst {} | ||||
|         impl crate::rng::Instance for peripherals::RNG {} | ||||
|     }; | ||||
| } | ||||
|  | ||||
| @ -13,5 +13,5 @@ pub trait Rng { | ||||
|     /// May result in delays if entropy is exhausted prior to completely
 | ||||
|     /// filling the buffer. Upon completion, the buffer will be completely
 | ||||
|     /// filled or an error will have been reported.
 | ||||
|     fn fill<'a>(&'a mut self, dest: &'a mut [u8]) -> Self::RngFuture<'a>; | ||||
|     fn fill_bytes<'a>(&'a mut self, dest: &'a mut [u8]) -> Self::RngFuture<'a>; | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user