diff options
| author | Dario Nieuwenhuis <[email protected]> | 2021-03-19 04:08:44 +0100 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2021-03-29 00:58:57 +0200 |
| commit | fcf6a63b5cf1d1505ec01ea42a1a75f33794b038 (patch) | |
| tree | cc8acfe57060d25979d13820cebaf49959b6d025 | |
| parent | d9aaa0edf88e822b9e5d6deb5f4a133dd32449fa (diff) | |
nrf: add owned Peripherals struct, migrate gpio and spim
| -rw-r--r-- | embassy-nrf-examples/src/bin/spim.rs | 18 | ||||
| -rw-r--r-- | embassy-nrf/src/gpio.rs | 307 | ||||
| -rw-r--r-- | embassy-nrf/src/lib.rs | 2 | ||||
| -rw-r--r-- | embassy-nrf/src/peripherals.rs | 144 | ||||
| -rw-r--r-- | embassy-nrf/src/spim.rs | 88 |
5 files changed, 516 insertions, 43 deletions
diff --git a/embassy-nrf-examples/src/bin/spim.rs b/embassy-nrf-examples/src/bin/spim.rs index d3d942e4e..8eaac5e15 100644 --- a/embassy-nrf-examples/src/bin/spim.rs +++ b/embassy-nrf-examples/src/bin/spim.rs | |||
| @@ -6,6 +6,8 @@ | |||
| 6 | 6 | ||
| 7 | #[path = "../example_common.rs"] | 7 | #[path = "../example_common.rs"] |
| 8 | mod example_common; | 8 | mod example_common; |
| 9 | use embassy_nrf::gpio::{Level, Output}; | ||
| 10 | use embassy_nrf::peripherals::Peripherals; | ||
| 9 | use embassy_traits::spi::FullDuplex; | 11 | use embassy_traits::spi::FullDuplex; |
| 10 | use example_common::*; | 12 | use example_common::*; |
| 11 | 13 | ||
| @@ -16,7 +18,6 @@ use embassy::util::Forever; | |||
| 16 | use embedded_hal::digital::v2::*; | 18 | use embedded_hal::digital::v2::*; |
| 17 | use futures::pin_mut; | 19 | use futures::pin_mut; |
| 18 | use nrf52840_hal::clocks; | 20 | use nrf52840_hal::clocks; |
| 19 | use nrf52840_hal::gpio; | ||
| 20 | 21 | ||
| 21 | use embassy_nrf::{interrupt, pac, rtc, spim}; | 22 | use embassy_nrf::{interrupt, pac, rtc, spim}; |
| 22 | 23 | ||
| @@ -24,25 +25,20 @@ use embassy_nrf::{interrupt, pac, rtc, spim}; | |||
| 24 | async fn run() { | 25 | async fn run() { |
| 25 | info!("running!"); | 26 | info!("running!"); |
| 26 | 27 | ||
| 27 | let p = unsafe { embassy_nrf::pac::Peripherals::steal() }; | 28 | let mut p = unsafe { Peripherals::steal() }; |
| 28 | let p0 = gpio::p0::Parts::new(p.P0); | ||
| 29 | 29 | ||
| 30 | let pins = spim::Pins { | ||
| 31 | sck: p0.p0_29.into_push_pull_output(gpio::Level::Low).degrade(), | ||
| 32 | miso: Some(p0.p0_28.into_floating_input().degrade()), | ||
| 33 | mosi: Some(p0.p0_30.into_push_pull_output(gpio::Level::Low).degrade()), | ||
| 34 | }; | ||
| 35 | let config = spim::Config { | 30 | let config = spim::Config { |
| 36 | pins, | ||
| 37 | frequency: spim::Frequency::M16, | 31 | frequency: spim::Frequency::M16, |
| 38 | mode: spim::MODE_0, | 32 | mode: spim::MODE_0, |
| 39 | orc: 0x00, | 33 | orc: 0x00, |
| 40 | }; | 34 | }; |
| 41 | 35 | ||
| 42 | let mut ncs = p0.p0_31.into_push_pull_output(gpio::Level::High); | 36 | let mut irq = interrupt::take!(SPIM3); |
| 43 | let spim = spim::Spim::new(p.SPIM3, interrupt::take!(SPIM3), config); | 37 | let spim = spim::Spim::new(p.spim3, irq, p.p0_29, p.p0_28, p.p0_30, config); |
| 44 | pin_mut!(spim); | 38 | pin_mut!(spim); |
| 45 | 39 | ||
| 40 | let mut ncs = Output::new(p.p0_31, Level::High); | ||
| 41 | |||
| 46 | // Example on how to talk to an ENC28J60 chip | 42 | // Example on how to talk to an ENC28J60 chip |
| 47 | 43 | ||
| 48 | // softreset | 44 | // softreset |
diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs new file mode 100644 index 000000000..9f4604b0a --- /dev/null +++ b/embassy-nrf/src/gpio.rs | |||
| @@ -0,0 +1,307 @@ | |||
| 1 | use core::convert::Infallible; | ||
| 2 | use core::hint::unreachable_unchecked; | ||
| 3 | |||
| 4 | use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin}; | ||
| 5 | |||
| 6 | use crate::pac; | ||
| 7 | use crate::pac::p0 as gpio; | ||
| 8 | use crate::peripherals; | ||
| 9 | |||
| 10 | /// Represents a digital input or output level. | ||
| 11 | #[derive(Debug, Eq, PartialEq)] | ||
| 12 | pub enum Level { | ||
| 13 | Low, | ||
| 14 | High, | ||
| 15 | } | ||
| 16 | |||
| 17 | /// Represents a pull setting for an input. | ||
| 18 | #[derive(Debug, Eq, PartialEq)] | ||
| 19 | pub enum Pull { | ||
| 20 | None, | ||
| 21 | Up, | ||
| 22 | Down, | ||
| 23 | } | ||
| 24 | |||
| 25 | /// A GPIO port with up to 32 pins. | ||
| 26 | #[derive(Debug, Eq, PartialEq)] | ||
| 27 | pub enum Port { | ||
| 28 | /// Port 0, available on all nRF52 and nRF51 MCUs. | ||
| 29 | Port0, | ||
| 30 | |||
| 31 | /// Port 1, only available on some nRF52 MCUs. | ||
| 32 | #[cfg(any(feature = "52833", feature = "52840"))] | ||
| 33 | Port1, | ||
| 34 | } | ||
| 35 | |||
| 36 | pub struct Input<T: Pin> { | ||
| 37 | pin: T, | ||
| 38 | } | ||
| 39 | |||
| 40 | impl<T: Pin> Input<T> { | ||
| 41 | pub fn new(pin: T, pull: Pull) -> Self { | ||
| 42 | pin.conf().write(|w| { | ||
| 43 | w.dir().input(); | ||
| 44 | w.input().connect(); | ||
| 45 | match pull { | ||
| 46 | Pull::None => { | ||
| 47 | w.pull().disabled(); | ||
| 48 | } | ||
| 49 | Pull::Up => { | ||
| 50 | w.pull().pullup(); | ||
| 51 | } | ||
| 52 | Pull::Down => { | ||
| 53 | w.pull().pulldown(); | ||
| 54 | } | ||
| 55 | } | ||
| 56 | w.drive().s0s1(); | ||
| 57 | w.sense().disabled(); | ||
| 58 | w | ||
| 59 | }); | ||
| 60 | |||
| 61 | Self { pin } | ||
| 62 | } | ||
| 63 | } | ||
| 64 | |||
| 65 | impl<T: Pin> Drop for Input<T> { | ||
| 66 | fn drop(&mut self) { | ||
| 67 | self.pin.conf().reset(); | ||
| 68 | } | ||
| 69 | } | ||
| 70 | |||
| 71 | impl<T: Pin> InputPin for Input<T> { | ||
| 72 | type Error = Infallible; | ||
| 73 | |||
| 74 | fn is_high(&self) -> Result<bool, Self::Error> { | ||
| 75 | self.is_low().map(|v| !v) | ||
| 76 | } | ||
| 77 | |||
| 78 | fn is_low(&self) -> Result<bool, Self::Error> { | ||
| 79 | Ok(self.pin.block().in_.read().bits() & (1 << self.pin.pin()) == 0) | ||
| 80 | } | ||
| 81 | } | ||
| 82 | |||
| 83 | pub struct Output<T: Pin> { | ||
| 84 | pin: T, | ||
| 85 | } | ||
| 86 | |||
| 87 | impl<T: Pin> Output<T> { | ||
| 88 | // TODO opendrain | ||
| 89 | pub fn new(pin: T, initial_output: Level) -> Self { | ||
| 90 | pin.conf().write(|w| { | ||
| 91 | w.dir().output(); | ||
| 92 | w.input().disconnect(); | ||
| 93 | w.pull().disabled(); | ||
| 94 | w.drive().s0s1(); | ||
| 95 | w.sense().disabled(); | ||
| 96 | w | ||
| 97 | }); | ||
| 98 | |||
| 99 | Self { pin } | ||
| 100 | } | ||
| 101 | } | ||
| 102 | |||
| 103 | impl<T: Pin> Drop for Output<T> { | ||
| 104 | fn drop(&mut self) { | ||
| 105 | self.pin.conf().reset(); | ||
| 106 | } | ||
| 107 | } | ||
| 108 | |||
| 109 | impl<T: Pin> OutputPin for Output<T> { | ||
| 110 | type Error = Infallible; | ||
| 111 | |||
| 112 | /// Set the output as high. | ||
| 113 | fn set_high(&mut self) -> Result<(), Self::Error> { | ||
| 114 | unsafe { | ||
| 115 | self.pin | ||
| 116 | .block() | ||
| 117 | .outset | ||
| 118 | .write(|w| w.bits(1u32 << self.pin.pin())); | ||
| 119 | } | ||
| 120 | Ok(()) | ||
| 121 | } | ||
| 122 | |||
| 123 | /// Set the output as low. | ||
| 124 | fn set_low(&mut self) -> Result<(), Self::Error> { | ||
| 125 | unsafe { | ||
| 126 | self.pin | ||
| 127 | .block() | ||
| 128 | .outclr | ||
| 129 | .write(|w| w.bits(1u32 << self.pin.pin())); | ||
| 130 | } | ||
| 131 | Ok(()) | ||
| 132 | } | ||
| 133 | } | ||
| 134 | |||
| 135 | impl<T: Pin> StatefulOutputPin for Output<T> { | ||
| 136 | /// Is the output pin set as high? | ||
| 137 | fn is_set_high(&self) -> Result<bool, Self::Error> { | ||
| 138 | self.is_set_low().map(|v| !v) | ||
| 139 | } | ||
| 140 | |||
| 141 | /// Is the output pin set as low? | ||
| 142 | fn is_set_low(&self) -> Result<bool, Self::Error> { | ||
| 143 | Ok(self.pin.block().out.read().bits() & (1 << self.pin.pin()) == 0) | ||
| 144 | } | ||
| 145 | } | ||
| 146 | |||
| 147 | pub(crate) mod sealed { | ||
| 148 | use super::*; | ||
| 149 | |||
| 150 | pub trait Pin { | ||
| 151 | fn pin_port(&self) -> u8; | ||
| 152 | |||
| 153 | #[inline] | ||
| 154 | fn _pin(&self) -> u8 { | ||
| 155 | #[cfg(any(feature = "52833", feature = "52840"))] | ||
| 156 | { | ||
| 157 | self.pin_port() % 32 | ||
| 158 | } | ||
| 159 | |||
| 160 | #[cfg(not(any(feature = "52833", feature = "52840")))] | ||
| 161 | { | ||
| 162 | self.pin_port() | ||
| 163 | } | ||
| 164 | } | ||
| 165 | |||
| 166 | fn block(&self) -> &gpio::RegisterBlock { | ||
| 167 | unsafe { | ||
| 168 | match self.pin_port() / 32 { | ||
| 169 | 0 => &*pac::P0::ptr(), | ||
| 170 | #[cfg(any(feature = "52833", feature = "52840"))] | ||
| 171 | 1 => &*pac::P1::ptr(), | ||
| 172 | _ => unreachable_unchecked(), | ||
| 173 | } | ||
| 174 | } | ||
| 175 | } | ||
| 176 | |||
| 177 | fn conf(&self) -> &gpio::PIN_CNF { | ||
| 178 | &self.block().pin_cnf[self._pin() as usize] | ||
| 179 | } | ||
| 180 | |||
| 181 | /// Set the output as high. | ||
| 182 | fn set_high(&self) { | ||
| 183 | unsafe { | ||
| 184 | self.block().outset.write(|w| w.bits(1u32 << self._pin())); | ||
| 185 | } | ||
| 186 | } | ||
| 187 | |||
| 188 | /// Set the output as low. | ||
| 189 | fn set_low(&self) { | ||
| 190 | unsafe { | ||
| 191 | self.block().outclr.write(|w| w.bits(1u32 << self._pin())); | ||
| 192 | } | ||
| 193 | } | ||
| 194 | } | ||
| 195 | } | ||
| 196 | |||
| 197 | pub trait Pin: sealed::Pin + Sized { | ||
| 198 | #[inline] | ||
| 199 | fn pin(&self) -> u8 { | ||
| 200 | self._pin() | ||
| 201 | } | ||
| 202 | |||
| 203 | #[inline] | ||
| 204 | fn port(&self) -> Port { | ||
| 205 | match self.pin_port() / 32 { | ||
| 206 | 1 => Port::Port0, | ||
| 207 | #[cfg(any(feature = "52833", feature = "52840"))] | ||
| 208 | 1 => Port::Port1, | ||
| 209 | _ => unsafe { unreachable_unchecked() }, | ||
| 210 | } | ||
| 211 | } | ||
| 212 | |||
| 213 | #[inline] | ||
| 214 | fn psel_bits(&self) -> u32 { | ||
| 215 | self.pin_port() as u32 | ||
| 216 | } | ||
| 217 | |||
| 218 | fn degrade(self) -> AnyPin { | ||
| 219 | AnyPin { | ||
| 220 | pin_port: self.pin_port(), | ||
| 221 | } | ||
| 222 | } | ||
| 223 | } | ||
| 224 | |||
| 225 | pub struct AnyPin { | ||
| 226 | pin_port: u8, | ||
| 227 | } | ||
| 228 | |||
| 229 | impl AnyPin { | ||
| 230 | pub unsafe fn from_psel_bits(psel_bits: u32) -> Self { | ||
| 231 | Self { | ||
| 232 | pin_port: psel_bits as u8, | ||
| 233 | } | ||
| 234 | } | ||
| 235 | } | ||
| 236 | |||
| 237 | impl Pin for AnyPin {} | ||
| 238 | impl sealed::Pin for AnyPin { | ||
| 239 | fn pin_port(&self) -> u8 { | ||
| 240 | self.pin_port | ||
| 241 | } | ||
| 242 | } | ||
| 243 | |||
| 244 | macro_rules! make_impl { | ||
| 245 | ($type:ident, $port_num:expr, $pin_num:expr) => { | ||
| 246 | impl Pin for peripherals::$type {} | ||
| 247 | impl sealed::Pin for peripherals::$type { | ||
| 248 | fn pin_port(&self) -> u8 { | ||
| 249 | $port_num * 32 + $pin_num | ||
| 250 | } | ||
| 251 | } | ||
| 252 | }; | ||
| 253 | } | ||
| 254 | |||
| 255 | make_impl!(P0_00, 0, 0); | ||
| 256 | make_impl!(P0_01, 0, 1); | ||
| 257 | make_impl!(P0_02, 0, 2); | ||
| 258 | make_impl!(P0_03, 0, 3); | ||
| 259 | make_impl!(P0_04, 0, 4); | ||
| 260 | make_impl!(P0_05, 0, 5); | ||
| 261 | make_impl!(P0_06, 0, 6); | ||
| 262 | make_impl!(P0_07, 0, 7); | ||
| 263 | make_impl!(P0_08, 0, 8); | ||
| 264 | make_impl!(P0_09, 0, 9); | ||
| 265 | make_impl!(P0_10, 0, 10); | ||
| 266 | make_impl!(P0_11, 0, 11); | ||
| 267 | make_impl!(P0_12, 0, 12); | ||
| 268 | make_impl!(P0_13, 0, 13); | ||
| 269 | make_impl!(P0_14, 0, 14); | ||
| 270 | make_impl!(P0_15, 0, 15); | ||
| 271 | make_impl!(P0_16, 0, 16); | ||
| 272 | make_impl!(P0_17, 0, 17); | ||
| 273 | make_impl!(P0_18, 0, 18); | ||
| 274 | make_impl!(P0_19, 0, 19); | ||
| 275 | make_impl!(P0_20, 0, 20); | ||
| 276 | make_impl!(P0_21, 0, 21); | ||
| 277 | make_impl!(P0_22, 0, 22); | ||
| 278 | make_impl!(P0_23, 0, 23); | ||
| 279 | make_impl!(P0_24, 0, 24); | ||
| 280 | make_impl!(P0_25, 0, 25); | ||
| 281 | make_impl!(P0_26, 0, 26); | ||
| 282 | make_impl!(P0_27, 0, 27); | ||
| 283 | make_impl!(P0_28, 0, 28); | ||
| 284 | make_impl!(P0_29, 0, 29); | ||
| 285 | make_impl!(P0_30, 0, 30); | ||
| 286 | make_impl!(P0_31, 0, 31); | ||
| 287 | |||
| 288 | #[cfg(any(feature = "52833", feature = "52840"))] | ||
| 289 | mod _p1 { | ||
| 290 | use super::*; | ||
| 291 | make_impl!(P1_00, 1, 0); | ||
| 292 | make_impl!(P1_01, 1, 1); | ||
| 293 | make_impl!(P1_02, 1, 2); | ||
| 294 | make_impl!(P1_03, 1, 3); | ||
| 295 | make_impl!(P1_04, 1, 4); | ||
| 296 | make_impl!(P1_05, 1, 5); | ||
| 297 | make_impl!(P1_06, 1, 6); | ||
| 298 | make_impl!(P1_07, 1, 7); | ||
| 299 | make_impl!(P1_08, 1, 8); | ||
| 300 | make_impl!(P1_09, 1, 9); | ||
| 301 | make_impl!(P1_10, 1, 10); | ||
| 302 | make_impl!(P1_11, 1, 11); | ||
| 303 | make_impl!(P1_12, 1, 12); | ||
| 304 | make_impl!(P1_13, 1, 13); | ||
| 305 | make_impl!(P1_14, 1, 14); | ||
| 306 | make_impl!(P1_15, 1, 15); | ||
| 307 | } | ||
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index 2c72b912c..07759996c 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs | |||
| @@ -94,8 +94,10 @@ pub(crate) fn slice_in_ram_or<T>(slice: &[u8], err: T) -> Result<(), T> { | |||
| 94 | pub(crate) mod fmt; | 94 | pub(crate) mod fmt; |
| 95 | 95 | ||
| 96 | pub mod buffered_uarte; | 96 | pub mod buffered_uarte; |
| 97 | pub mod gpio; | ||
| 97 | pub mod gpiote; | 98 | pub mod gpiote; |
| 98 | pub mod interrupt; | 99 | pub mod interrupt; |
| 100 | pub mod peripherals; | ||
| 99 | #[cfg(feature = "52840")] | 101 | #[cfg(feature = "52840")] |
| 100 | pub mod qspi; | 102 | pub mod qspi; |
| 101 | pub mod rtc; | 103 | pub mod rtc; |
diff --git a/embassy-nrf/src/peripherals.rs b/embassy-nrf/src/peripherals.rs new file mode 100644 index 000000000..bc2ed8810 --- /dev/null +++ b/embassy-nrf/src/peripherals.rs | |||
| @@ -0,0 +1,144 @@ | |||
| 1 | use embassy::util::PeripheralBorrow; | ||
| 2 | |||
| 3 | macro_rules! peripherals { | ||
| 4 | ($($(#[$cfg:meta])? $name:ident: $type:ident),*$(,)?) => { | ||
| 5 | $( | ||
| 6 | $(#[$cfg])? | ||
| 7 | pub struct $type { _private: () } | ||
| 8 | |||
| 9 | $(#[$cfg])? | ||
| 10 | impl PeripheralBorrow for $type { | ||
| 11 | type Target = $type; | ||
| 12 | unsafe fn unborrow(self) -> $type { | ||
| 13 | self | ||
| 14 | } | ||
| 15 | } | ||
| 16 | |||
| 17 | $(#[$cfg])? | ||
| 18 | impl PeripheralBorrow for &mut $type { | ||
| 19 | type Target = $type; | ||
| 20 | unsafe fn unborrow(self) -> $type { | ||
| 21 | ::core::ptr::read(self) | ||
| 22 | } | ||
| 23 | } | ||
| 24 | )* | ||
| 25 | |||
| 26 | pub struct Peripherals { | ||
| 27 | $( | ||
| 28 | $(#[$cfg])? | ||
| 29 | pub $name: $type, | ||
| 30 | )* | ||
| 31 | } | ||
| 32 | |||
| 33 | impl Peripherals { | ||
| 34 | pub unsafe fn steal() -> Self { | ||
| 35 | Self { | ||
| 36 | $( | ||
| 37 | $(#[$cfg])? | ||
| 38 | $name: $type { _private: () }, | ||
| 39 | )* | ||
| 40 | } | ||
| 41 | } | ||
| 42 | } | ||
| 43 | |||
| 44 | }; | ||
| 45 | } | ||
| 46 | |||
| 47 | peripherals! { | ||
| 48 | // RTC | ||
| 49 | rtc0: RTC0, | ||
| 50 | rtc1: RTC1, | ||
| 51 | #[cfg(any(feature = "52832", feature = "52833", feature = "52840"))] | ||
| 52 | rtc2: RTC2, | ||
| 53 | |||
| 54 | // QSPI | ||
| 55 | #[cfg(feature = "52840")] | ||
| 56 | qspi: QSPI, | ||
| 57 | |||
| 58 | // UARTE | ||
| 59 | uarte0: UARTE0, | ||
| 60 | #[cfg(any(feature = "52833", feature = "52840", feature = "9160"))] | ||
| 61 | uarte1: UARTE1, | ||
| 62 | |||
| 63 | // SPIM | ||
| 64 | // TODO this is actually shared with SPI, SPIM, SPIS, TWI, TWIS, TWIS. | ||
| 65 | // When they're all implemented, they should be only one peripheral here. | ||
| 66 | spim0: SPIM0, | ||
| 67 | #[cfg(any(feature = "52832", feature = "52833", feature = "52840"))] | ||
| 68 | spim1: SPIM1, | ||
| 69 | #[cfg(any(feature = "52832", feature = "52833", feature = "52840"))] | ||
| 70 | spim2: SPIM2, | ||
| 71 | #[cfg(any(feature = "52833", feature = "52840"))] | ||
| 72 | spim3: SPIM3, | ||
| 73 | |||
| 74 | // GPIOTE | ||
| 75 | gpiote: GPIOTE, | ||
| 76 | |||
| 77 | // GPIO port 0 | ||
| 78 | p0_00: P0_00, | ||
| 79 | p0_01: P0_01, | ||
| 80 | p0_02: P0_02, | ||
| 81 | p0_03: P0_03, | ||
| 82 | p0_04: P0_04, | ||
| 83 | p0_05: P0_05, | ||
| 84 | p0_06: P0_06, | ||
| 85 | p0_07: P0_07, | ||
| 86 | p0_08: P0_08, | ||
| 87 | p0_09: P0_09, | ||
| 88 | p0_10: P0_10, | ||
| 89 | p0_11: P0_11, | ||
| 90 | p0_12: P0_12, | ||
| 91 | p0_13: P0_13, | ||
| 92 | p0_14: P0_14, | ||
| 93 | p0_15: P0_15, | ||
| 94 | p0_16: P0_16, | ||
| 95 | p0_17: P0_17, | ||
| 96 | p0_18: P0_18, | ||
| 97 | p0_19: P0_19, | ||
| 98 | p0_20: P0_20, | ||
| 99 | p0_21: P0_21, | ||
| 100 | p0_22: P0_22, | ||
| 101 | p0_23: P0_23, | ||
| 102 | p0_24: P0_24, | ||
| 103 | p0_25: P0_25, | ||
| 104 | p0_26: P0_26, | ||
| 105 | p0_27: P0_27, | ||
| 106 | p0_28: P0_28, | ||
| 107 | p0_29: P0_29, | ||
| 108 | p0_30: P0_30, | ||
| 109 | p0_31: P0_31, | ||
| 110 | |||
| 111 | // GPIO port 1 | ||
| 112 | #[cfg(any(feature = "52833", feature = "52840"))] | ||
| 113 | p1_00: P1_00, | ||
| 114 | #[cfg(any(feature = "52833", feature = "52840"))] | ||
| 115 | p1_01: P1_01, | ||
| 116 | #[cfg(any(feature = "52833", feature = "52840"))] | ||
| 117 | p1_02: P1_02, | ||
| 118 | #[cfg(any(feature = "52833", feature = "52840"))] | ||
| 119 | p1_03: P1_03, | ||
| 120 | #[cfg(any(feature = "52833", feature = "52840"))] | ||
| 121 | p1_04: P1_04, | ||
| 122 | #[cfg(any(feature = "52833", feature = "52840"))] | ||
| 123 | p1_05: P1_05, | ||
| 124 | #[cfg(any(feature = "52833", feature = "52840"))] | ||
| 125 | p1_06: P1_06, | ||
| 126 | #[cfg(any(feature = "52833", feature = "52840"))] | ||
| 127 | p1_07: P1_07, | ||
| 128 | #[cfg(any(feature = "52833", feature = "52840"))] | ||
| 129 | p1_08: P1_08, | ||
| 130 | #[cfg(any(feature = "52833", feature = "52840"))] | ||
| 131 | p1_09: P1_09, | ||
| 132 | #[cfg(any(feature = "52833", feature = "52840"))] | ||
| 133 | p1_10: P1_10, | ||
| 134 | #[cfg(any(feature = "52833", feature = "52840"))] | ||
| 135 | p1_11: P1_11, | ||
| 136 | #[cfg(any(feature = "52833", feature = "52840"))] | ||
| 137 | p1_12: P1_12, | ||
| 138 | #[cfg(any(feature = "52833", feature = "52840"))] | ||
| 139 | p1_13: P1_13, | ||
| 140 | #[cfg(any(feature = "52833", feature = "52840"))] | ||
| 141 | p1_14: P1_14, | ||
| 142 | #[cfg(any(feature = "52833", feature = "52840"))] | ||
| 143 | p1_15: P1_15, | ||
| 144 | } | ||
diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs index b236f5387..38cfa0052 100644 --- a/embassy-nrf/src/spim.rs +++ b/embassy-nrf/src/spim.rs | |||
| @@ -1,19 +1,20 @@ | |||
| 1 | use core::future::Future; | 1 | use core::future::Future; |
| 2 | use core::marker::PhantomData; | ||
| 2 | use core::pin::Pin; | 3 | use core::pin::Pin; |
| 3 | use core::sync::atomic::{compiler_fence, Ordering}; | 4 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 4 | use core::task::Poll; | 5 | use core::task::Poll; |
| 5 | use embassy::traits; | 6 | use embassy::traits; |
| 6 | use embassy::util::WakerRegistration; | 7 | use embassy::util::{PeripheralBorrow, WakerRegistration}; |
| 7 | use embassy_extras::peripheral::{PeripheralMutex, PeripheralState}; | 8 | use embassy_extras::peripheral::{PeripheralMutex, PeripheralState}; |
| 8 | use futures::future::poll_fn; | 9 | use futures::future::poll_fn; |
| 9 | use traits::spi::FullDuplex; | 10 | use traits::spi::FullDuplex; |
| 10 | 11 | ||
| 12 | use crate::gpio::Pin as GpioPin; | ||
| 11 | use crate::interrupt::{self, Interrupt}; | 13 | use crate::interrupt::{self, Interrupt}; |
| 12 | use crate::{pac, slice_in_ram_or}; | 14 | use crate::{pac, peripherals, slice_in_ram_or}; |
| 13 | 15 | ||
| 14 | pub use crate::hal::spim::{ | 16 | pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; |
| 15 | Frequency, Mode, Phase, Pins, Polarity, MODE_0, MODE_1, MODE_2, MODE_3, | 17 | pub use pac::spim0::frequency::FREQUENCY_A as Frequency; |
| 16 | }; | ||
| 17 | 18 | ||
| 18 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | 19 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
| 19 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 20 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| @@ -30,41 +31,63 @@ struct State<T: Instance> { | |||
| 30 | waker: WakerRegistration, | 31 | waker: WakerRegistration, |
| 31 | } | 32 | } |
| 32 | 33 | ||
| 33 | pub struct Spim<T: Instance> { | 34 | pub struct Spim<'d, T: Instance> { |
| 34 | inner: PeripheralMutex<State<T>>, | 35 | inner: PeripheralMutex<State<T>>, |
| 36 | phantom: PhantomData<&'d mut T>, | ||
| 35 | } | 37 | } |
| 36 | 38 | ||
| 37 | pub struct Config { | 39 | pub struct Config { |
| 38 | pub pins: Pins, | ||
| 39 | pub frequency: Frequency, | 40 | pub frequency: Frequency, |
| 40 | pub mode: Mode, | 41 | pub mode: Mode, |
| 41 | pub orc: u8, | 42 | pub orc: u8, |
| 42 | } | 43 | } |
| 43 | 44 | ||
| 44 | impl<T: Instance> Spim<T> { | 45 | impl<'d, T: Instance> Spim<'d, T> { |
| 45 | pub fn new(mut spim: T, irq: T::Interrupt, config: Config) -> Self { | 46 | pub fn new( |
| 47 | spim: impl PeripheralBorrow<Target = T> + 'd, | ||
| 48 | irq: impl PeripheralBorrow<Target = T::Interrupt> + 'd, | ||
| 49 | sck: impl PeripheralBorrow<Target = impl GpioPin> + 'd, | ||
| 50 | miso: impl PeripheralBorrow<Target = impl GpioPin> + 'd, | ||
| 51 | mosi: impl PeripheralBorrow<Target = impl GpioPin> + 'd, | ||
| 52 | config: Config, | ||
| 53 | ) -> Self { | ||
| 54 | let mut spim = unsafe { spim.unborrow() }; | ||
| 55 | let irq = unsafe { irq.unborrow() }; | ||
| 56 | let sck = unsafe { sck.unborrow() }; | ||
| 57 | let miso = unsafe { miso.unborrow() }; | ||
| 58 | let mosi = unsafe { mosi.unborrow() }; | ||
| 59 | |||
| 46 | let r = spim.regs(); | 60 | let r = spim.regs(); |
| 47 | 61 | ||
| 62 | // Configure pins | ||
| 63 | sck.conf().write(|w| w.dir().output()); | ||
| 64 | mosi.conf().write(|w| w.dir().output()); | ||
| 65 | miso.conf().write(|w| w.input().connect()); | ||
| 66 | |||
| 67 | match config.mode.polarity { | ||
| 68 | Polarity::IdleHigh => { | ||
| 69 | sck.set_high(); | ||
| 70 | mosi.set_high(); | ||
| 71 | } | ||
| 72 | Polarity::IdleLow => { | ||
| 73 | sck.set_low(); | ||
| 74 | mosi.set_low(); | ||
| 75 | } | ||
| 76 | } | ||
| 77 | |||
| 48 | // Select pins. | 78 | // Select pins. |
| 49 | r.psel.sck.write(|w| { | 79 | r.psel.sck.write(|w| { |
| 50 | unsafe { w.bits(config.pins.sck.psel_bits()) }; | 80 | unsafe { w.bits(sck.psel_bits()) }; |
| 81 | w.connect().connected() | ||
| 82 | }); | ||
| 83 | r.psel.mosi.write(|w| { | ||
| 84 | unsafe { w.bits(mosi.psel_bits()) }; | ||
| 85 | w.connect().connected() | ||
| 86 | }); | ||
| 87 | r.psel.miso.write(|w| { | ||
| 88 | unsafe { w.bits(miso.psel_bits()) }; | ||
| 51 | w.connect().connected() | 89 | w.connect().connected() |
| 52 | }); | 90 | }); |
| 53 | |||
| 54 | match config.pins.mosi { | ||
| 55 | Some(mosi) => r.psel.mosi.write(|w| { | ||
| 56 | unsafe { w.bits(mosi.psel_bits()) }; | ||
| 57 | w.connect().connected() | ||
| 58 | }), | ||
| 59 | None => r.psel.mosi.write(|w| w.connect().disconnected()), | ||
| 60 | } | ||
| 61 | match config.pins.miso { | ||
| 62 | Some(miso) => r.psel.miso.write(|w| { | ||
| 63 | unsafe { w.bits(miso.psel_bits()) }; | ||
| 64 | w.connect().connected() | ||
| 65 | }), | ||
| 66 | None => r.psel.miso.write(|w| w.connect().disconnected()), | ||
| 67 | } | ||
| 68 | 91 | ||
| 69 | // Enable SPIM instance. | 92 | // Enable SPIM instance. |
| 70 | r.enable.write(|w| w.enable().enabled()); | 93 | r.enable.write(|w| w.enable().enabled()); |
| @@ -114,6 +137,7 @@ impl<T: Instance> Spim<T> { | |||
| 114 | }, | 137 | }, |
| 115 | irq, | 138 | irq, |
| 116 | ), | 139 | ), |
| 140 | phantom: PhantomData, | ||
| 117 | } | 141 | } |
| 118 | } | 142 | } |
| 119 | 143 | ||
| @@ -122,7 +146,7 @@ impl<T: Instance> Spim<T> { | |||
| 122 | } | 146 | } |
| 123 | } | 147 | } |
| 124 | 148 | ||
| 125 | impl<T: Instance> FullDuplex<u8> for Spim<T> { | 149 | impl<'d, T: Instance> FullDuplex<u8> for Spim<'d, T> { |
| 126 | type Error = Error; | 150 | type Error = Error; |
| 127 | 151 | ||
| 128 | #[rustfmt::skip] | 152 | #[rustfmt::skip] |
| @@ -222,19 +246,19 @@ mod sealed { | |||
| 222 | } | 246 | } |
| 223 | } | 247 | } |
| 224 | 248 | ||
| 225 | pub trait Instance: sealed::Instance { | 249 | pub trait Instance: sealed::Instance + 'static { |
| 226 | type Interrupt: Interrupt; | 250 | type Interrupt: Interrupt; |
| 227 | } | 251 | } |
| 228 | 252 | ||
| 229 | macro_rules! make_impl { | 253 | macro_rules! make_impl { |
| 230 | ($SPIMx:ident, $IRQ:ident) => { | 254 | ($type:ident, $irq:ident) => { |
| 231 | impl sealed::Instance for pac::$SPIMx { | 255 | impl sealed::Instance for peripherals::$type { |
| 232 | fn regs(&mut self) -> &pac::spim0::RegisterBlock { | 256 | fn regs(&mut self) -> &pac::spim0::RegisterBlock { |
| 233 | self | 257 | unsafe { &*pac::$type::ptr() } |
| 234 | } | 258 | } |
| 235 | } | 259 | } |
| 236 | impl Instance for pac::$SPIMx { | 260 | impl Instance for peripherals::$type { |
| 237 | type Interrupt = interrupt::$IRQ; | 261 | type Interrupt = interrupt::$irq; |
| 238 | } | 262 | } |
| 239 | }; | 263 | }; |
| 240 | } | 264 | } |
