diff options
| author | Dario Nieuwenhuis <[email protected]> | 2021-06-25 18:17:59 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2021-06-30 22:43:15 +0200 |
| commit | 749f4838d5457005ed23e69d7d7712aae90f8230 (patch) | |
| tree | 0b50a78e2b661aada95e4756718f8b6f50aaf29f | |
| parent | da014afb89c73570bdcde4070b94c7e3de6e7446 (diff) | |
rp/gpio: add optional pins
| -rw-r--r-- | embassy-rp/src/gpio.rs | 54 | ||||
| -rw-r--r-- | embassy-rp/src/spi.rs | 54 |
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 | ||
| 228 | pub trait Pin: sealed::Pin { | 230 | pub 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 | |||
| 252 | pub 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 | |||
| 265 | impl<T: Pin> sealed::OptionalPin for T {} | ||
| 266 | impl<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)] | ||
| 281 | pub struct NoPin; | ||
| 282 | unsafe_impl_unborrow!(NoPin); | ||
| 283 | impl sealed::OptionalPin for NoPin {} | ||
| 284 | impl 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 | |||
| 248 | macro_rules! impl_pin { | 300 | macro_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; | |||
| 3 | use embassy::util::Unborrow; | 3 | use embassy::util::Unborrow; |
| 4 | use embassy_extras::unborrow; | 4 | use embassy_extras::unborrow; |
| 5 | use embedded_hal::blocking::spi as eh; | 5 | use embedded_hal::blocking::spi as eh; |
| 6 | use gpio::Pin; | ||
| 7 | 6 | ||
| 8 | use crate::{gpio, pac, peripherals}; | 7 | use crate::gpio::sealed::Pin as _; |
| 8 | use crate::gpio::{NoPin, OptionalPin}; | ||
| 9 | use crate::{pac, peripherals}; | ||
| 9 | 10 | ||
| 10 | #[non_exhaustive] | 11 | #[non_exhaustive] |
| 11 | pub struct Config { | 12 | pub 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 | ||
| 111 | impl<'d, T: Instance> eh::Write<u8> for Spi<'d, T> { | 116 | impl<'d, T: Instance> eh::Write<u8> for Spi<'d, T> { |
| @@ -145,10 +150,19 @@ macro_rules! impl_instance { | |||
| 145 | impl_instance!(SPI0, Spi0); | 150 | impl_instance!(SPI0, Spi0); |
| 146 | impl_instance!(SPI1, Spi1); | 151 | impl_instance!(SPI1, Spi1); |
| 147 | 152 | ||
| 148 | pub trait ClkPin<T: Instance>: sealed::ClkPin<T> + Pin {} | 153 | pub trait ClkPin<T: Instance>: sealed::ClkPin<T> + OptionalPin {} |
| 149 | pub trait CsPin<T: Instance>: sealed::CsPin<T> + Pin {} | 154 | pub trait CsPin<T: Instance>: sealed::CsPin<T> + OptionalPin {} |
| 150 | pub trait MosiPin<T: Instance>: sealed::MosiPin<T> + Pin {} | 155 | pub trait MosiPin<T: Instance>: sealed::MosiPin<T> + OptionalPin {} |
| 151 | pub trait MisoPin<T: Instance>: sealed::MisoPin<T> + Pin {} | 156 | pub trait MisoPin<T: Instance>: sealed::MisoPin<T> + OptionalPin {} |
| 157 | |||
| 158 | impl<T: Instance> sealed::ClkPin<T> for NoPin {} | ||
| 159 | impl<T: Instance> ClkPin<T> for NoPin {} | ||
| 160 | impl<T: Instance> sealed::CsPin<T> for NoPin {} | ||
| 161 | impl<T: Instance> CsPin<T> for NoPin {} | ||
| 162 | impl<T: Instance> sealed::MosiPin<T> for NoPin {} | ||
| 163 | impl<T: Instance> MosiPin<T> for NoPin {} | ||
| 164 | impl<T: Instance> sealed::MisoPin<T> for NoPin {} | ||
| 165 | impl<T: Instance> MisoPin<T> for NoPin {} | ||
| 152 | 166 | ||
| 153 | macro_rules! impl_pin { | 167 | macro_rules! impl_pin { |
| 154 | ($pin:ident, $instance:ident, $function:ident) => { | 168 | ($pin:ident, $instance:ident, $function:ident) => { |
