aboutsummaryrefslogtreecommitdiff
path: root/embassy-rp
diff options
context:
space:
mode:
authorpennae <[email protected]>2023-05-17 02:52:29 +0200
committerpennae <[email protected]>2023-05-17 21:36:19 +0200
commit053d5629ba88a67f4b126bd7ac4b478fbe00d17f (patch)
tree83b92e3755c67c26f785ddeb260d593b29b98bbc /embassy-rp
parent1b3d9a0aeffd9e0619126c3b2dc42520cc2b4209 (diff)
rp/clocks: require GpinPin for gpin config
we'll take static ownership of an entire pin (not just a limited reference), otherwise we cannot at all guarantee that the pin will not be reused for something else while still in use. in theory we could limit the liftime of this use, but that would require attaching lifetimes to ClockConfig (and subsequently the main config), passing those through init(), and returning an object that undoes the gpin configuration on drop. that's a lot unnecessary support code while we don't have runtime clock reconfig.
Diffstat (limited to 'embassy-rp')
-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