diff options
| -rw-r--r-- | embassy-rp/src/clocks.rs | 61 |
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 @@ | |||
| 1 | use core::marker::PhantomData; | ||
| 1 | use core::sync::atomic::{AtomicU16, AtomicU32, Ordering}; | 2 | use core::sync::atomic::{AtomicU16, AtomicU32, Ordering}; |
| 2 | 3 | ||
| 3 | use embassy_hal_common::{into_ref, PeripheralRef}; | 4 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 4 | use pac::clocks::vals::*; | 5 | use pac::clocks::vals::*; |
| 5 | 6 | ||
| 7 | use crate::gpio::sealed::Pin; | ||
| 8 | use crate::gpio::AnyPin; | ||
| 6 | use crate::{pac, reset, Peripheral}; | 9 | use crate::{pac, reset, Peripheral}; |
| 7 | 10 | ||
| 8 | struct Clocks { | 11 | struct 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 | ||
| 65 | impl ClockConfig { | 68 | impl 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 | ||
| 663 | pub trait GpinPin: crate::gpio::Pin { | 682 | pub trait GpinPin: crate::gpio::Pin { |
| 664 | fn number(&self) -> usize; | 683 | const NR: usize; |
| 665 | } | 684 | } |
| 666 | 685 | ||
| 667 | macro_rules! impl_gpinpin { | 686 | macro_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 { | |||
| 677 | impl_gpinpin!(PIN_20, 20, 0); | 694 | impl_gpinpin!(PIN_20, 20, 0); |
| 678 | impl_gpinpin!(PIN_22, 22, 1); | 695 | impl_gpinpin!(PIN_22, 22, 1); |
| 679 | 696 | ||
| 680 | pub struct Gpin<'d, T: GpinPin> { | 697 | pub struct Gpin<'d, T: Pin> { |
| 681 | gpin: PeripheralRef<'d, T>, | 698 | gpin: PeripheralRef<'d, AnyPin>, |
| 699 | _phantom: PhantomData<T>, | ||
| 682 | } | 700 | } |
| 683 | 701 | ||
| 684 | impl<'d, T: GpinPin> Gpin<'d, T> { | 702 | impl<'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 | ||
| 696 | impl<'d, T: GpinPin> Drop for Gpin<'d, T> { | 721 | impl<'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 |
