aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2021-06-25 18:17:59 +0200
committerDario Nieuwenhuis <[email protected]>2021-06-30 22:43:15 +0200
commit749f4838d5457005ed23e69d7d7712aae90f8230 (patch)
tree0b50a78e2b661aada95e4756718f8b6f50aaf29f
parentda014afb89c73570bdcde4070b94c7e3de6e7446 (diff)
rp/gpio: add optional pins
-rw-r--r--embassy-rp/src/gpio.rs54
-rw-r--r--embassy-rp/src/spi.rs54
2 files changed, 87 insertions, 21 deletions
diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs
index 1eddce184..5edf47f52 100644
--- a/embassy-rp/src/gpio.rs
+++ b/embassy-rp/src/gpio.rs
@@ -223,9 +223,11 @@ pub(crate) mod sealed {
223 SIO.gpio_in(self.bank() as _) 223 SIO.gpio_in(self.bank() as _)
224 } 224 }
225 } 225 }
226
227 pub trait OptionalPin {}
226} 228}
227 229
228pub trait Pin: sealed::Pin { 230pub trait Pin: Unborrow<Target = Self> + sealed::Pin {
229 /// Degrade to a generic pin struct 231 /// Degrade to a generic pin struct
230 fn degrade(self) -> AnyPin { 232 fn degrade(self) -> AnyPin {
231 AnyPin { 233 AnyPin {
@@ -245,6 +247,56 @@ impl sealed::Pin for AnyPin {
245 } 247 }
246} 248}
247 249
250// ==========================
251
252pub trait OptionalPin: Unborrow<Target = Self> + sealed::OptionalPin + Sized {
253 type Pin: Pin;
254 fn pin(&self) -> Option<&Self::Pin>;
255 fn pin_mut(&mut self) -> Option<&mut Self::Pin>;
256
257 /// Convert from concrete pin type PIN_XX to type erased `Option<AnyPin>`.
258 #[inline]
259 fn degrade_optional(mut self) -> Option<AnyPin> {
260 self.pin_mut()
261 .map(|pin| unsafe { core::ptr::read(pin) }.degrade())
262 }
263}
264
265impl<T: Pin> sealed::OptionalPin for T {}
266impl<T: Pin> OptionalPin for T {
267 type Pin = T;
268
269 #[inline]
270 fn pin(&self) -> Option<&T> {
271 Some(self)
272 }
273
274 #[inline]
275 fn pin_mut(&mut self) -> Option<&mut T> {
276 Some(self)
277 }
278}
279
280#[derive(Clone, Copy, Debug)]
281pub struct NoPin;
282unsafe_impl_unborrow!(NoPin);
283impl sealed::OptionalPin for NoPin {}
284impl OptionalPin for NoPin {
285 type Pin = AnyPin;
286
287 #[inline]
288 fn pin(&self) -> Option<&AnyPin> {
289 None
290 }
291
292 #[inline]
293 fn pin_mut(&mut self) -> Option<&mut AnyPin> {
294 None
295 }
296}
297
298// ==========================
299
248macro_rules! impl_pin { 300macro_rules! impl_pin {
249 ($name:ident, $bank:expr, $pin_num:expr) => { 301 ($name:ident, $bank:expr, $pin_num:expr) => {
250 impl Pin for peripherals::$name {} 302 impl Pin for peripherals::$name {}
diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs
index fb8e84230..766f08616 100644
--- a/embassy-rp/src/spi.rs
+++ b/embassy-rp/src/spi.rs
@@ -3,9 +3,10 @@ use core::marker::PhantomData;
3use embassy::util::Unborrow; 3use embassy::util::Unborrow;
4use embassy_extras::unborrow; 4use embassy_extras::unborrow;
5use embedded_hal::blocking::spi as eh; 5use embedded_hal::blocking::spi as eh;
6use gpio::Pin;
7 6
8use crate::{gpio, pac, peripherals}; 7use crate::gpio::sealed::Pin as _;
8use crate::gpio::{NoPin, OptionalPin};
9use crate::{pac, peripherals};
9 10
10#[non_exhaustive] 11#[non_exhaustive]
11pub struct Config { 12pub struct Config {
@@ -31,9 +32,10 @@ impl<'d, T: Instance> Spi<'d, T> {
31 clk: impl Unborrow<Target = impl ClkPin<T>>, 32 clk: impl Unborrow<Target = impl ClkPin<T>>,
32 mosi: impl Unborrow<Target = impl MosiPin<T>>, 33 mosi: impl Unborrow<Target = impl MosiPin<T>>,
33 miso: impl Unborrow<Target = impl MisoPin<T>>, 34 miso: impl Unborrow<Target = impl MisoPin<T>>,
35 cs: impl Unborrow<Target = impl CsPin<T>>,
34 config: Config, 36 config: Config,
35 ) -> Self { 37 ) -> Self {
36 unborrow!(inner, clk, mosi, miso); 38 unborrow!(inner, clk, mosi, miso, cs);
37 39
38 unsafe { 40 unsafe {
39 let p = inner.regs(); 41 let p = inner.regs();
@@ -41,6 +43,8 @@ impl<'d, T: Instance> Spi<'d, T> {
41 let clk_peri = crate::clocks::clk_peri_freq(); 43 let clk_peri = crate::clocks::clk_peri_freq();
42 assert!(config.frequency <= clk_peri); 44 assert!(config.frequency <= clk_peri);
43 45
46 // TODO replace these trial-and-error loops with decent calculations.
47
44 // Find smallest prescale value which puts output frequency in range of 48 // Find smallest prescale value which puts output frequency in range of
45 // post-divide. Prescale is an even number from 2 to 254 inclusive. 49 // post-divide. Prescale is an even number from 2 to 254 inclusive.
46 let presc = (2u32..=254).step_by(2).find(|&presc| { 50 let presc = (2u32..=254).step_by(2).find(|&presc| {
@@ -52,7 +56,8 @@ impl<'d, T: Instance> Spi<'d, T> {
52 56
53 // Find largest post-divide which makes output <= baudrate. Post-divide is 57 // Find largest post-divide which makes output <= baudrate. Post-divide is
54 // an integer in the range 1 to 256 inclusive. 58 // an integer in the range 1 to 256 inclusive.
55 let postdiv = (1u32..=256) 59 // TODO figure what's up with postdiv=1, it is dividing by 0. Iterate down to 2 for now.
60 let postdiv = (2u32..=256)
56 .rev() 61 .rev()
57 .find(|&postdiv| clk_peri / (presc * (postdiv - 1)) > config.frequency); 62 .find(|&postdiv| clk_peri / (presc * (postdiv - 1)) > config.frequency);
58 let postdiv = unwrap!(postdiv); 63 let postdiv = unwrap!(postdiv);
@@ -70,9 +75,18 @@ impl<'d, T: Instance> Spi<'d, T> {
70 75
71 info!("SPI freq: {=u32}", clk_peri / (presc * postdiv)); 76 info!("SPI freq: {=u32}", clk_peri / (presc * postdiv));
72 77
73 clk.io().ctrl().write(|w| w.set_funcsel(1)); 78 if let Some(pin) = clk.pin_mut() {
74 mosi.io().ctrl().write(|w| w.set_funcsel(1)); 79 pin.io().ctrl().write(|w| w.set_funcsel(1));
75 miso.io().ctrl().write(|w| w.set_funcsel(1)); 80 }
81 if let Some(pin) = mosi.pin_mut() {
82 pin.io().ctrl().write(|w| w.set_funcsel(1));
83 }
84 if let Some(pin) = miso.pin_mut() {
85 pin.io().ctrl().write(|w| w.set_funcsel(1));
86 }
87 if let Some(pin) = cs.pin_mut() {
88 pin.io().ctrl().write(|w| w.set_funcsel(1));
89 }
76 } 90 }
77 Self { 91 Self {
78 inner, 92 inner,
@@ -97,15 +111,6 @@ impl<'d, T: Instance> Spi<'d, T> {
97 while p.sr().read().bsy() {} 111 while p.sr().read().bsy() {}
98 } 112 }
99 } 113 }
100
101 fn drain_rx(&mut self) {
102 unsafe {
103 let p = self.inner.regs();
104 while !p.sr().read().rne() {
105 p.dr().read();
106 }
107 }
108 }
109} 114}
110 115
111impl<'d, T: Instance> eh::Write<u8> for Spi<'d, T> { 116impl<'d, T: Instance> eh::Write<u8> for Spi<'d, T> {
@@ -145,10 +150,19 @@ macro_rules! impl_instance {
145impl_instance!(SPI0, Spi0); 150impl_instance!(SPI0, Spi0);
146impl_instance!(SPI1, Spi1); 151impl_instance!(SPI1, Spi1);
147 152
148pub trait ClkPin<T: Instance>: sealed::ClkPin<T> + Pin {} 153pub trait ClkPin<T: Instance>: sealed::ClkPin<T> + OptionalPin {}
149pub trait CsPin<T: Instance>: sealed::CsPin<T> + Pin {} 154pub trait CsPin<T: Instance>: sealed::CsPin<T> + OptionalPin {}
150pub trait MosiPin<T: Instance>: sealed::MosiPin<T> + Pin {} 155pub trait MosiPin<T: Instance>: sealed::MosiPin<T> + OptionalPin {}
151pub trait MisoPin<T: Instance>: sealed::MisoPin<T> + Pin {} 156pub trait MisoPin<T: Instance>: sealed::MisoPin<T> + OptionalPin {}
157
158impl<T: Instance> sealed::ClkPin<T> for NoPin {}
159impl<T: Instance> ClkPin<T> for NoPin {}
160impl<T: Instance> sealed::CsPin<T> for NoPin {}
161impl<T: Instance> CsPin<T> for NoPin {}
162impl<T: Instance> sealed::MosiPin<T> for NoPin {}
163impl<T: Instance> MosiPin<T> for NoPin {}
164impl<T: Instance> sealed::MisoPin<T> for NoPin {}
165impl<T: Instance> MisoPin<T> for NoPin {}
152 166
153macro_rules! impl_pin { 167macro_rules! impl_pin {
154 ($pin:ident, $instance:ident, $function:ident) => { 168 ($pin:ident, $instance:ident, $function:ident) => {