commit
						3e83a495cb
					
				| @ -15,6 +15,7 @@ cortex-m-rt = { version = "0.6.13", features = ["device"] } | |||||||
| cortex-m = "0.7.1" | cortex-m = "0.7.1" | ||||||
| embedded-hal    = { version = "0.2.4" } | embedded-hal    = { version = "0.2.4" } | ||||||
| futures = { version = "0.3.5", default-features = false, features = ["async-await"] } | futures = { version = "0.3.5", default-features = false, features = ["async-await"] } | ||||||
|  | rand_core = { version = "0.6.2", optional=true} | ||||||
| 
 | 
 | ||||||
| [build-dependencies] | [build-dependencies] | ||||||
| regex = "1.4.6" | regex = "1.4.6" | ||||||
| @ -321,7 +322,7 @@ _exti = [] | |||||||
| _exti_v1 = [] | _exti_v1 = [] | ||||||
| _gpio = [] | _gpio = [] | ||||||
| _gpio_v2 = [] | _gpio_v2 = [] | ||||||
| _rng = [] | _rng = [ "rand_core",] | ||||||
| _rng_v1 = [] | _rng_v1 = [] | ||||||
| _stm32f4 = [] | _stm32f4 = [] | ||||||
| _stm32l4 = [] | _stm32l4 = [] | ||||||
|  | |||||||
| @ -201,6 +201,9 @@ for chip in chips.values(): | |||||||
| 
 | 
 | ||||||
| # ========= Update Cargo features | # ========= Update Cargo features | ||||||
| 
 | 
 | ||||||
|  | feature_optional_deps = {} | ||||||
|  | feature_optional_deps['_rng'] = ['rand_core'] | ||||||
|  | 
 | ||||||
| features = {} | features = {} | ||||||
| extra_features = set() | extra_features = set() | ||||||
| for name, chip in chips.items(): | for name, chip in chips.items(): | ||||||
| @ -208,7 +211,7 @@ for name, chip in chips.items(): | |||||||
|     for feature in chip['features']: |     for feature in chip['features']: | ||||||
|         extra_features.add(feature) |         extra_features.add(feature) | ||||||
| for feature in sorted(list(extra_features)): | for feature in sorted(list(extra_features)): | ||||||
|     features[feature] = [] |     features[feature] = feature_optional_deps.get(feature) or [] | ||||||
| 
 | 
 | ||||||
| SEPARATOR_START = '# BEGIN GENERATED FEATURES\n' | SEPARATOR_START = '# BEGIN GENERATED FEATURES\n' | ||||||
| SEPARATOR_END = '# END GENERATED FEATURES\n' | SEPARATOR_END = '# END GENERATED FEATURES\n' | ||||||
|  | |||||||
| @ -15,6 +15,7 @@ pub mod exti; | |||||||
| pub mod gpio; | pub mod gpio; | ||||||
| #[cfg(feature = "_rng")] | #[cfg(feature = "_rng")] | ||||||
| pub mod rng; | pub mod rng; | ||||||
|  | #[cfg(feature = "_usart")] | ||||||
| pub mod usart; | pub mod usart; | ||||||
| 
 | 
 | ||||||
| // This must go LAST so that it sees the `impl_foo!` macros
 | // 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] | #![macro_use] | ||||||
| use crate::pac::rng::{regs, Rng}; | 
 | ||||||
|  | //use crate::pac::rng::{regs, Rng};
 | ||||||
|  | use crate::pac; | ||||||
| use crate::peripherals; | 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 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> { | pub struct Random<T: Instance> { | ||||||
|     inner: T, |     inner: T, | ||||||
| @ -11,21 +29,112 @@ pub struct Random<T: Instance> { | |||||||
| impl<T: Instance> Random<T> { | impl<T: Instance> Random<T> { | ||||||
|     pub fn new(inner: impl Unborrow<Target=T>) -> Self { |     pub fn new(inner: impl Unborrow<Target=T>) -> Self { | ||||||
|         unborrow!(inner); |         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::future::Future; | ||||||
| use core::marker::PhantomData; | 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> { | pub enum Error { | ||||||
|     type Error = (); |     SeedError, | ||||||
|     #[rustfmt::skip] |     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>>; |     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> { |     fn fill_bytes<'a>(&'a mut self, dest: &'a mut [u8]) -> Self::RngFuture<'a> { | ||||||
|         async move { Ok(()) } |         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::*; |     use super::*; | ||||||
| 
 | 
 | ||||||
|     pub trait Instance { |     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 { | macro_rules! impl_rng { | ||||||
|     ($inst:ident) => { |     ($inst:ident) => { | ||||||
|         impl crate::rng::sealed::Instance for peripherals::$inst { |         impl crate::rng::sealed::Instance for peripherals::RNG { | ||||||
|             fn regs(&self) -> crate::pac::rng::Rng { |             fn regs() -> crate::pac::chip::rng::Rng { | ||||||
|                 crate::pac::$inst |                 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
 |     /// May result in delays if entropy is exhausted prior to completely
 | ||||||
|     /// filling the buffer. Upon completion, the buffer will be completely
 |     /// filling the buffer. Upon completion, the buffer will be completely
 | ||||||
|     /// filled or an error will have been reported.
 |     /// 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