aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-rp/src/clocks.rs61
1 files changed, 43 insertions, 18 deletions
diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs
index cfc94f844..7ab0ecd11 100644
--- a/embassy-rp/src/clocks.rs
+++ b/embassy-rp/src/clocks.rs
@@ -1,8 +1,11 @@
1use core::marker::PhantomData;
1use core::sync::atomic::{AtomicU16, AtomicU32, Ordering}; 2use core::sync::atomic::{AtomicU16, AtomicU32, Ordering};
2 3
3use embassy_hal_common::{into_ref, PeripheralRef}; 4use embassy_hal_common::{into_ref, PeripheralRef};
4use pac::clocks::vals::*; 5use pac::clocks::vals::*;
5 6
7use crate::gpio::sealed::Pin;
8use crate::gpio::AnyPin;
6use crate::{pac, reset, Peripheral}; 9use crate::{pac, reset, Peripheral};
7 10
8struct Clocks { 11struct Clocks {
@@ -58,8 +61,8 @@ pub struct ClockConfig {
58 pub usb_clk: Option<UsbClkConfig>, 61 pub usb_clk: Option<UsbClkConfig>,
59 pub adc_clk: Option<AdcClkConfig>, 62 pub adc_clk: Option<AdcClkConfig>,
60 pub rtc_clk: Option<RtcClkConfig>, 63 pub rtc_clk: Option<RtcClkConfig>,
61 pub gpin0_hz: Option<u32>, 64 gpin0: Option<(u32, Gpin<'static, AnyPin>)>,
62 pub gpin1_hz: Option<u32>, 65 gpin1: Option<(u32, Gpin<'static, AnyPin>)>,
63} 66}
64 67
65impl ClockConfig { 68impl ClockConfig {
@@ -115,8 +118,8 @@ impl ClockConfig {
115 div_frac: 0, 118 div_frac: 0,
116 phase: 0, 119 phase: 0,
117 }), 120 }),
118 gpin0_hz: None, 121 gpin0: None,
119 gpin1_hz: None, 122 gpin1: None,
120 } 123 }
121 } 124 }
122 125
@@ -153,10 +156,20 @@ impl ClockConfig {
153 div_frac: 171, 156 div_frac: 171,
154 phase: 0, 157 phase: 0,
155 }), 158 }),
156 gpin0_hz: None, 159 gpin0: None,
157 gpin1_hz: None, 160 gpin1: None,
158 } 161 }
159 } 162 }
163
164 pub fn bind_gpin<P: GpinPin>(&mut self, gpin: Gpin<'static, P>, hz: u32) {
165 match P::NR {
166 0 => self.gpin0 = Some((hz, gpin.map_into())),
167 1 => self.gpin1 = Some((hz, gpin.map_into())),
168 _ => unreachable!(),
169 }
170 // pin is now provisionally bound. if the config is applied it must be forgotten,
171 // or Gpin::drop will deconfigure the clock input.
172 }
160} 173}
161 174
162#[repr(u16)] 175#[repr(u16)]
@@ -319,9 +332,15 @@ pub(crate) unsafe fn init(config: ClockConfig) {
319 reset::reset(peris); 332 reset::reset(peris);
320 reset::unreset_wait(peris); 333 reset::unreset_wait(peris);
321 334
322 let gpin0_freq = config.gpin0_hz.unwrap_or(0); 335 let gpin0_freq = config.gpin0.map_or(0, |p| {
336 core::mem::forget(p.1);
337 p.0
338 });
323 CLOCKS.gpin0.store(gpin0_freq, Ordering::Relaxed); 339 CLOCKS.gpin0.store(gpin0_freq, Ordering::Relaxed);
324 let gpin1_freq = config.gpin1_hz.unwrap_or(0); 340 let gpin1_freq = config.gpin1.map_or(0, |p| {
341 core::mem::forget(p.1);
342 p.0
343 });
325 CLOCKS.gpin1.store(gpin1_freq, Ordering::Relaxed); 344 CLOCKS.gpin1.store(gpin1_freq, Ordering::Relaxed);
326 345
327 let rosc_freq = match config.rosc { 346 let rosc_freq = match config.rosc {
@@ -661,15 +680,13 @@ unsafe fn configure_pll(p: pac::pll::Pll, input_freq: u32, config: PllConfig) ->
661} 680}
662 681
663pub trait GpinPin: crate::gpio::Pin { 682pub trait GpinPin: crate::gpio::Pin {
664 fn number(&self) -> usize; 683 const NR: usize;
665} 684}
666 685
667macro_rules! impl_gpinpin { 686macro_rules! impl_gpinpin {
668 ($name:ident, $pin_num:expr, $gpin_num:expr) => { 687 ($name:ident, $pin_num:expr, $gpin_num:expr) => {
669 impl GpinPin for crate::peripherals::$name { 688 impl GpinPin for crate::peripherals::$name {
670 fn number(&self) -> usize { 689 const NR: usize = $gpin_num;
671 $gpin_num
672 }
673 } 690 }
674 }; 691 };
675} 692}
@@ -677,23 +694,31 @@ macro_rules! impl_gpinpin {
677impl_gpinpin!(PIN_20, 20, 0); 694impl_gpinpin!(PIN_20, 20, 0);
678impl_gpinpin!(PIN_22, 22, 1); 695impl_gpinpin!(PIN_22, 22, 1);
679 696
680pub struct Gpin<'d, T: GpinPin> { 697pub struct Gpin<'d, T: Pin> {
681 gpin: PeripheralRef<'d, T>, 698 gpin: PeripheralRef<'d, AnyPin>,
699 _phantom: PhantomData<T>,
682} 700}
683 701
684impl<'d, T: GpinPin> Gpin<'d, T> { 702impl<'d, T: Pin> Gpin<'d, T> {
685 pub fn new(gpin: impl Peripheral<P = T> + 'd) -> Self { 703 pub fn new<P: GpinPin>(gpin: impl Peripheral<P = P> + 'd) -> Gpin<'d, P> {
686 into_ref!(gpin); 704 into_ref!(gpin);
687 705
688 unsafe { 706 unsafe {
689 gpin.io().ctrl().write(|w| w.set_funcsel(0x08)); 707 gpin.io().ctrl().write(|w| w.set_funcsel(0x08));
690 } 708 }
691 709
692 Self { gpin } 710 Gpin {
711 gpin: gpin.map_into(),
712 _phantom: PhantomData,
713 }
714 }
715
716 fn map_into(self) -> Gpin<'d, AnyPin> {
717 unsafe { core::mem::transmute(self) }
693 } 718 }
694} 719}
695 720
696impl<'d, T: GpinPin> Drop for Gpin<'d, T> { 721impl<'d, T: Pin> Drop for Gpin<'d, T> {
697 fn drop(&mut self) { 722 fn drop(&mut self) {
698 unsafe { 723 unsafe {
699 self.gpin 724 self.gpin