diff --git a/examples/noise.rs b/examples/noise.rs index f3d2eb8e8a049a403de54b64d597480ab11c91ea..1dca3b7b16c696c91b07153a4da148723d5ad03c 100644 --- a/examples/noise.rs +++ b/examples/noise.rs @@ -50,7 +50,7 @@ async fn main(_spawner: Spawner) { let mut hist = [0u32; 200]; - let PRINT = 1000; + let PRINT = 10000; // let PRINT = 50; // let mut gpios = [ @@ -67,17 +67,18 @@ async fn main(_spawner: Spawner) { // serial // p.PIN_0.degrade().into_ref(), // p.PIN_1.degrade().into_ref(), - p.PIN_2.degrade().into_ref(), - p.PIN_3.degrade().into_ref(), - p.PIN_4.degrade().into_ref(), - p.PIN_5.degrade().into_ref(), + + // p.PIN_2.degrade().into_ref(), + // p.PIN_3.degrade().into_ref(), + // p.PIN_4.degrade().into_ref(), + // p.PIN_5.degrade().into_ref(), p.PIN_6.degrade().into_ref(), - p.PIN_7.degrade().into_ref(), - p.PIN_8.degrade().into_ref(), - p.PIN_9.degrade().into_ref(), + // p.PIN_7.degrade().into_ref(), + // p.PIN_8.degrade().into_ref(), + // p.PIN_9.degrade().into_ref(), p.PIN_10.degrade().into_ref(), - p.PIN_11.degrade().into_ref(), - p.PIN_12.degrade().into_ref(), + // p.PIN_11.degrade().into_ref(), + // p.PIN_12.degrade().into_ref(), p.PIN_13.degrade().into_ref(), p.PIN_14.degrade().into_ref(), p.PIN_15.degrade().into_ref(), @@ -90,34 +91,37 @@ async fn main(_spawner: Spawner) { p.PIN_22.degrade().into_ref(), // p.PIN_23.degrade().into_ref(), // p.PIN_24.degrade().into_ref(), + // wl_cs, gate of vsys adc mosfet p.PIN_25.degrade().into_ref(), - p.PIN_26.degrade().into_ref(), - p.PIN_27.degrade().into_ref(), - p.PIN_28.degrade().into_ref(), + // p.PIN_26.degrade().into_ref(), + // p.PIN_27.degrade().into_ref(), + // p.PIN_28.degrade().into_ref(), // p.PIN_29.degrade().into_ref(), ]; for gpio in gpios.iter_mut() { - let pin = gpio.pin(); - let mut n = 0; - caprand::noise(gpio.reborrow(), &mut cp.SYST, - |v, overshoot| { - // info!("{}", v); - - let vu = v as usize; - hist[vu.min(hist.len()-1)] += 1; - n += 1; - if n % PRINT == 0 { - info!("gpio {} iter {}", pin, n); - for (p, h) in hist.iter_mut().enumerate() { - if *h > 0 { - info!("{}: {}", p, h); - *h = 0; + for low_delay in 0..1{ + let pin = gpio.pin(); + let mut n = 0; + caprand::noise(gpio.reborrow(), low_delay, + &mut cp.SYST, + |v, overshoot| { + // info!("{}", v); + + let vu = v as usize; + hist[vu.min(hist.len()-1)] += 1; + n += 1; + if n % PRINT == 0 { + info!("gpio {} delay {} iter {}", pin, low_delay, n); + for (p, h) in hist.iter_mut().enumerate() { + if *h > 0 { + info!("{}: {}", p, h); + *h = 0; + } } } - } - n < PRINT - }).unwrap(); + n < PRINT + }).unwrap(); + } } - } diff --git a/src/cap.rs b/src/cap.rs index 823ae68690ab605ebf46ed9a86ab172440045b4d..feb736e4e9beb5df0589904e084eefc8df3e2ec5 100644 --- a/src/cap.rs +++ b/src/cap.rs @@ -92,6 +92,10 @@ impl<'t> SyTi<'t> { } } + fn reset(&mut self) { + self.syst.clear_current(); + } + /// returns the duration, or failure on overflow fn done(self) -> Result<u32, ()> { let t2 = SYST::get_current(); @@ -103,39 +107,150 @@ impl<'t> SyTi<'t> { Ok(self.t1 - t2) } } -// Returns (ticks: u32, precise: bool) -fn time_rise(pin: PeripheralRef<AnyPin>, wait: &mut u32, rpos: &mut u32, syst: &mut SYST) -> Result<(u32, bool), ()> { - +// Returns (ticks: u32, pos: u8) +// `pos == 0` are less precise than other results +fn time_rise(pin: PeripheralRef<AnyPin>, low_delay: u32, syst: &mut SYST) -> Result<(u32, u8), ()> { let pin_num = pin.pin() as usize; let mask = 1u32 << pin_num; + unsafe { + pac::PADS_BANK0 + .gpio(pin_num) + .modify(|s| { + // Pullup + s.set_pue(true); + }); + }; + // bank 0 single cycle IO in let gpio_in = pac::SIO.gpio_in(0).ptr(); let so = pac::SIO.gpio_out(0); let soe = pac::SIO.gpio_oe(0); unsafe { so.value_clr().write_value(1 << pin_num); - soe.value_set().write_value(1 << pin_num); } - // // unsafe { - // // asm!( - // // "nop", - // // ) - // // } - // cortex_m::asm::delay(20); - // cortex_m::asm::delay(1000); - unsafe { - soe.value_clr().write_value(1 << pin_num); + + let soe_set = soe.value_set().ptr(); + let soe_clr = soe.value_clr().ptr(); + let mut t = SyTi::new(syst); + + // actual low time is low_delay+1 cycles + match (low_delay, low_delay % 3) { + (0, _) => unsafe { + asm!( + "str {mask}, [{soe_set}]", + // low for 1 cycle + "str {mask}, [{soe_clr}]", + + mask = in(reg) mask, + soe_set = in(reg) soe_set, + soe_clr = in(reg) soe_clr, + options(nostack, readonly), + ) + }, + (1, _) => unsafe { + asm!( + "str {mask}, [{soe_set}]", + // low for 2 cycles + "nop", + "str {mask}, [{soe_clr}]", + + mask = in(reg) mask, + soe_set = in(reg) soe_set, + soe_clr = in(reg) soe_clr, + options(nostack, readonly), + ) + }, + (_, 2) => unsafe { + // min delay of 2 + let mut d = low_delay + 1; + assert!(d % 3 == 0); + asm!( + "str {mask}, [{soe_set}]", + "000:", + // one cycle + "subs {d}, 3", + // two cycles bne taken + "bne 000b", + // one cycle for bne not taken + "str {mask}, [{soe_clr}]", + + mask = in(reg) mask, + soe_set = in(reg) soe_set, + soe_clr = in(reg) soe_clr, + d = inout(reg) d, + options(nostack, readonly), + ); + assert_eq!(d, 0); + }, + (_, 0) => unsafe { + // min delay of 3 + let mut d = low_delay + 1; + assert!(d % 3 == 1); + asm!( + "str {mask}, [{soe_set}]", + // one cycle + "subs {d}, 1", + "000:", + // one cycle + "subs {d}, 3", + // two cycles bne taken + "bne 000b", + // one cycle for bne not taken + "str {mask}, [{soe_clr}]", + + mask = in(reg) mask, + soe_set = in(reg) soe_set, + soe_clr = in(reg) soe_clr, + d = inout(reg) d, + options(nostack, readonly), + ); + assert_eq!(d, 0); + }, + (_, 1) => unsafe { + // min delay of 4 + let mut d = low_delay + 1; + assert!(d % 3 == 2); + asm!( + "str {mask}, [{soe_set}]", + // one cycle + "subs {d}, 1", + // one cycle + "subs {d}, 1", + "000:", + // one cycle + "subs {d}, 3", + // two cycles bne taken + "bne 000b", + // one cycle for bne not taken + "str {mask}, [{soe_clr}]", + + mask = in(reg) mask, + soe_set = in(reg) soe_set, + soe_clr = in(reg) soe_clr, + d = inout(reg) d, + options(nostack, readonly), + ); + assert_eq!(d, 0); + }, + // `match` doesn't understand modulo + _ => unreachable!() } - unsafe { - pac::PADS_BANK0 - .gpio(pin_num) - .modify(|s| { - // Pullup - s.set_pue(true); - }); - }; + t.reset(); + // unsafe { + // soe.value_set().write_value(1 << pin_num); + // } + // // // unsafe { + // // // asm!( + // // // "nop", + // // // ) + // // // } + // // cortex_m::asm::delay(20); + // // cortex_m::asm::delay(1000); + // unsafe { + // soe.value_clr().write_value(1 << pin_num); + // } // for testing with logic analyzer // let mut out = Flex::new(unsafe { embassy_rp::peripherals::PIN_16::steal() }); @@ -146,7 +261,6 @@ fn time_rise(pin: PeripheralRef<AnyPin>, wait: &mut u32, rpos: &mut u32, syst: & // cortex_m::asm::delay(900); // pin.set_pull(Pull::None); - let t = SyTi::new(syst); let x0: u32; let x1: u32; @@ -211,12 +325,6 @@ fn time_rise(pin: PeripheralRef<AnyPin>, wait: &mut u32, rpos: &mut u32, syst: & // first measurement is less precise. let precise = pos != 0; - if tick > 600 { - *wait = wait.saturating_sub(1); - } else if tick > 600 { - *wait = (*wait+1).max(10000); - } - unsafe { pac::PADS_BANK0 .gpio(pin_num) @@ -226,13 +334,13 @@ fn time_rise(pin: PeripheralRef<AnyPin>, wait: &mut u32, rpos: &mut u32, syst: & }); }; - *rpos = pos; - Ok((tick, precise)) + Ok((tick, pos as u8)) } // `f()` is called on each output `u32`. pub fn noise<'d, F>( mut pin: PeripheralRef<AnyPin>, + low_delay: u32, syst: &mut SYST, mut f: F, ) -> Result<(), ()> @@ -258,40 +366,46 @@ where // Long enough to drive the capacitor low cortex_m::asm::delay(10000); gpio.set_as_input(); - let del = critical_section::with(|_cs| { - gpio.set_pull(Pull::Up); - let t = SyTi::new(syst); - // Get it near the threshold to begin. - while gpio.is_low() {} - t.done() - })?; + // let del = critical_section::with(|_cs| { + // gpio.set_pull(Pull::Up); + // let t = SyTi::new(syst); + // // Get it near the threshold to begin. + // while gpio.is_low() {} + // t.done() + // })?; drop(gpio); - info!("Initial pullup del is {}", del); + // info!("Initial pullup del is {}", del); - if del < MIN_CAPACITOR_DEL { - error!("Capacitor seems small or missing?"); - return Err(()) - } + // if del < MIN_CAPACITOR_DEL { + // error!("Capacitor seems small or missing?"); + // return Err(()) + // } // The main loop let mut overshoot = 1u32; let mut warming = WARMUP; - let mut wait = 0; let mut pos = 0; unsafe { pac::PADS_BANK0 .gpio(pin_num) .modify(|s| { - // Disabling the Schmitt Trigger gives a clearer correlation between "overshoot" - // and measured values. - s.set_schmitt(false); + // // Disabling the Schmitt Trigger gives a clearer correlation between "overshoot" + // // and measured values. + // s.set_schmitt(false); // Input enable s.set_ie(true); }); + pac::SYSCFG + .proc_in_sync_bypass() + .modify(|s| { + let val = s.proc_in_sync_bypass(); + s.set_proc_in_sync_bypass(val | 1 << pin_num); + }); + // Use SIO pac::IO_BANK0 .gpio(pin_num) @@ -322,7 +436,8 @@ where // while pin.is_high() {} // let r = t.done().map(|t| (t, true)); - let (r, precise) = time_rise(pin.reborrow(), &mut wait, &mut pos, syst)?; + let (r, pos) = time_rise(pin.reborrow(), 0, syst)?; + let precise = pos == 0; // let mut gpio = Flex::<AnyPin>::new(pin.reborrow()); // gpio.set_pull(Pull::None); diff --git a/src/rng.rs b/src/rng.rs index 8120373badaff260b49cb9ef5dc3e21dfe108bab..00085373a9810792b1cd3a95cc7a58dbe0856a92 100644 --- a/src/rng.rs +++ b/src/rng.rs @@ -76,7 +76,7 @@ impl CapRng { ) -> Result<Self, getrandom::Error> { let mut h = Sha256::new(); let mut count = 0; - crate::cap::noise(pin, syst, |v, _over| { + crate::cap::noise(pin, 0, syst, |v, _over| { h.update(v.to_be_bytes()); count += 1; count < Self::SEED_SAMPLES