diff options
| -rw-r--r-- | embassy-nrf/Cargo.toml | 8 | ||||
| -rw-r--r-- | embassy-nrf/src/buffered_uarte.rs | 14 | ||||
| -rw-r--r-- | embassy-nrf/src/gpio.rs | 253 | ||||
| -rw-r--r-- | embassy-nrf/src/gpiote.rs | 224 | ||||
| -rw-r--r-- | embassy-nrf/src/qspi.rs | 208 | ||||
| -rw-r--r-- | embassy-nrf/src/rng.rs | 115 | ||||
| -rw-r--r-- | embassy-nrf/src/spim.rs | 460 | ||||
| -rw-r--r-- | embassy-nrf/src/twim.rs | 687 | ||||
| -rw-r--r-- | embassy-nrf/src/uarte.rs | 644 | ||||
| -rw-r--r-- | embassy-nrf/src/util.rs | 22 | ||||
| -rw-r--r-- | examples/nrf/Cargo.toml | 1 | ||||
| -rw-r--r-- | examples/nrf/src/bin/gpiote_port.rs | 1 | ||||
| -rw-r--r-- | examples/nrf/src/bin/qspi.rs | 1 | ||||
| -rw-r--r-- | examples/nrf/src/bin/qspi_lowpower.rs | 1 | ||||
| -rw-r--r-- | examples/nrf/src/bin/rng.rs | 6 | ||||
| -rw-r--r-- | examples/nrf/src/bin/spim.rs | 9 | ||||
| -rw-r--r-- | examples/nrf/src/bin/twim.rs | 2 | ||||
| -rw-r--r-- | examples/nrf/src/bin/twim_lowpower.rs | 2 | ||||
| -rw-r--r-- | examples/nrf/src/bin/uart.rs | 1 | ||||
| -rw-r--r-- | examples/nrf/src/bin/uart_idle.rs | 10 | ||||
| -rw-r--r-- | examples/nrf/src/bin/uart_split.rs | 9 | ||||
| -rw-r--r-- | examples/nrf/src/bin/wdt.rs | 1 |
22 files changed, 1594 insertions, 1085 deletions
diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index 3d0c171f3..c9bd2bc14 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml | |||
| @@ -12,6 +12,9 @@ edition = "2018" | |||
| 12 | # There are no plans to make this stable. | 12 | # There are no plans to make this stable. |
| 13 | unstable-pac = [] | 13 | unstable-pac = [] |
| 14 | 14 | ||
| 15 | # Implement embedded-hal 1.0 alpha and embedded-hal-async traits. | ||
| 16 | unstable-traits = ["embedded-hal-1", "embedded-hal-async"] | ||
| 17 | |||
| 15 | nrf52805 = ["nrf52805-pac", "_ppi"] | 18 | nrf52805 = ["nrf52805-pac", "_ppi"] |
| 16 | nrf52810 = ["nrf52810-pac", "_ppi"] | 19 | nrf52810 = ["nrf52810-pac", "_ppi"] |
| 17 | nrf52811 = ["nrf52811-pac", "_ppi"] | 20 | nrf52811 = ["nrf52811-pac", "_ppi"] |
| @@ -47,11 +50,14 @@ embassy = { version = "0.1.0", path = "../embassy" } | |||
| 47 | embassy-macros = { version = "0.1.0", path = "../embassy-macros", features = ["nrf"]} | 50 | embassy-macros = { version = "0.1.0", path = "../embassy-macros", features = ["nrf"]} |
| 48 | embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" } | 51 | embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" } |
| 49 | 52 | ||
| 53 | embedded-hal-02 = { package = "embedded-hal", version = "0.2.6" } | ||
| 54 | embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.6", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy", optional = true} | ||
| 55 | embedded-hal-async = { version = "0.0.1", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy", optional = true} | ||
| 56 | |||
| 50 | defmt = { version = "0.3", optional = true } | 57 | defmt = { version = "0.3", optional = true } |
| 51 | log = { version = "0.4.14", optional = true } | 58 | log = { version = "0.4.14", optional = true } |
| 52 | cortex-m-rt = ">=0.6.15,<0.8" | 59 | cortex-m-rt = ">=0.6.15,<0.8" |
| 53 | cortex-m = "0.7.3" | 60 | cortex-m = "0.7.3" |
| 54 | embedded-hal = "0.2.6" | ||
| 55 | embedded-dma = "0.1.2" | 61 | embedded-dma = "0.1.2" |
| 56 | futures = { version = "0.3.17", default-features = false } | 62 | futures = { version = "0.3.17", default-features = false } |
| 57 | critical-section = "0.2.5" | 63 | critical-section = "0.2.5" |
diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs index 45e8afc4b..2880c84f6 100644 --- a/embassy-nrf/src/buffered_uarte.rs +++ b/embassy-nrf/src/buffered_uarte.rs | |||
| @@ -213,9 +213,6 @@ impl<'d, U: UarteInstance, T: TimerInstance> AsyncBufRead for BufferedUarte<'d, | |||
| 213 | cx: &mut Context<'_>, | 213 | cx: &mut Context<'_>, |
| 214 | ) -> Poll<embassy::io::Result<&[u8]>> { | 214 | ) -> Poll<embassy::io::Result<&[u8]>> { |
| 215 | self.inner.with(|state| { | 215 | self.inner.with(|state| { |
| 216 | // Conservative compiler fence to prevent optimizations that do not | ||
| 217 | // take in to account actions by DMA. The fence has been placed here, | ||
| 218 | // before any DMA action has started | ||
| 219 | compiler_fence(Ordering::SeqCst); | 216 | compiler_fence(Ordering::SeqCst); |
| 220 | trace!("poll_read"); | 217 | trace!("poll_read"); |
| 221 | 218 | ||
| @@ -265,9 +262,6 @@ impl<'d, U: UarteInstance, T: TimerInstance> AsyncWrite for BufferedUarte<'d, U, | |||
| 265 | 262 | ||
| 266 | trace!("poll_write: queued {:?}", n); | 263 | trace!("poll_write: queued {:?}", n); |
| 267 | 264 | ||
| 268 | // Conservative compiler fence to prevent optimizations that do not | ||
| 269 | // take in to account actions by DMA. The fence has been placed here, | ||
| 270 | // before any DMA action has started | ||
| 271 | compiler_fence(Ordering::SeqCst); | 265 | compiler_fence(Ordering::SeqCst); |
| 272 | 266 | ||
| 273 | Poll::Ready(Ok(n)) | 267 | Poll::Ready(Ok(n)) |
| @@ -347,9 +341,7 @@ impl<'a, U: UarteInstance, T: TimerInstance> PeripheralState for StateInner<'a, | |||
| 347 | trace!(" irq_rx: buf {:?} {:?}", buf.as_ptr() as u32, buf.len()); | 341 | trace!(" irq_rx: buf {:?} {:?}", buf.as_ptr() as u32, buf.len()); |
| 348 | 342 | ||
| 349 | // Start UARTE Receive transaction | 343 | // Start UARTE Receive transaction |
| 350 | r.tasks_startrx.write(|w| | 344 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); |
| 351 | // `1` is a valid value to write to task registers. | ||
| 352 | unsafe { w.bits(1) }); | ||
| 353 | } | 345 | } |
| 354 | break; | 346 | break; |
| 355 | } | 347 | } |
| @@ -397,9 +389,7 @@ impl<'a, U: UarteInstance, T: TimerInstance> PeripheralState for StateInner<'a, | |||
| 397 | unsafe { w.maxcnt().bits(buf.len() as _) }); | 389 | unsafe { w.maxcnt().bits(buf.len() as _) }); |
| 398 | 390 | ||
| 399 | // Start UARTE Transmit transaction | 391 | // Start UARTE Transmit transaction |
| 400 | r.tasks_starttx.write(|w| | 392 | r.tasks_starttx.write(|w| unsafe { w.bits(1) }); |
| 401 | // `1` is a valid value to write to task registers. | ||
| 402 | unsafe { w.bits(1) }); | ||
| 403 | } | 393 | } |
| 404 | break; | 394 | break; |
| 405 | } | 395 | } |
diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs index ddc84cf5d..3f204d564 100644 --- a/embassy-nrf/src/gpio.rs +++ b/embassy-nrf/src/gpio.rs | |||
| @@ -7,7 +7,6 @@ use core::marker::PhantomData; | |||
| 7 | use cfg_if::cfg_if; | 7 | use cfg_if::cfg_if; |
| 8 | use embassy::util::Unborrow; | 8 | use embassy::util::Unborrow; |
| 9 | use embassy_hal_common::{unborrow, unsafe_impl_unborrow}; | 9 | use embassy_hal_common::{unborrow, unsafe_impl_unborrow}; |
| 10 | use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin}; | ||
| 11 | use gpio::pin_cnf::DRIVE_A; | 10 | use gpio::pin_cnf::DRIVE_A; |
| 12 | 11 | ||
| 13 | use crate::pac; | 12 | use crate::pac; |
| @@ -37,12 +36,12 @@ pub enum Pull { | |||
| 37 | 36 | ||
| 38 | /// GPIO input driver. | 37 | /// GPIO input driver. |
| 39 | pub struct Input<'d, T: Pin> { | 38 | pub struct Input<'d, T: Pin> { |
| 40 | pub(crate) pin: FlexPin<'d, T>, | 39 | pub(crate) pin: Flex<'d, T>, |
| 41 | } | 40 | } |
| 42 | 41 | ||
| 43 | impl<'d, T: Pin> Input<'d, T> { | 42 | impl<'d, T: Pin> Input<'d, T> { |
| 44 | pub fn new(pin: impl Unborrow<Target = T> + 'd, pull: Pull) -> Self { | 43 | pub fn new(pin: impl Unborrow<Target = T> + 'd, pull: Pull) -> Self { |
| 45 | let mut pin = FlexPin::new(pin); | 44 | let mut pin = Flex::new(pin); |
| 46 | pin.set_as_input(pull); | 45 | pin.set_as_input(pull); |
| 47 | 46 | ||
| 48 | Self { pin } | 47 | Self { pin } |
| @@ -57,18 +56,6 @@ impl<'d, T: Pin> Input<'d, T> { | |||
| 57 | } | 56 | } |
| 58 | } | 57 | } |
| 59 | 58 | ||
| 60 | impl<'d, T: Pin> InputPin for Input<'d, T> { | ||
| 61 | type Error = Infallible; | ||
| 62 | |||
| 63 | fn is_high(&self) -> Result<bool, Self::Error> { | ||
| 64 | Ok(self.is_high()) | ||
| 65 | } | ||
| 66 | |||
| 67 | fn is_low(&self) -> Result<bool, Self::Error> { | ||
| 68 | Ok(self.is_low()) | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 72 | /// Digital input or output level. | 59 | /// Digital input or output level. |
| 73 | #[derive(Debug, Eq, PartialEq)] | 60 | #[derive(Debug, Eq, PartialEq)] |
| 74 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 61 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| @@ -102,7 +89,7 @@ pub enum OutputDrive { | |||
| 102 | 89 | ||
| 103 | /// GPIO output driver. | 90 | /// GPIO output driver. |
| 104 | pub struct Output<'d, T: Pin> { | 91 | pub struct Output<'d, T: Pin> { |
| 105 | pub(crate) pin: FlexPin<'d, T>, | 92 | pub(crate) pin: Flex<'d, T>, |
| 106 | } | 93 | } |
| 107 | 94 | ||
| 108 | impl<'d, T: Pin> Output<'d, T> { | 95 | impl<'d, T: Pin> Output<'d, T> { |
| @@ -111,7 +98,7 @@ impl<'d, T: Pin> Output<'d, T> { | |||
| 111 | initial_output: Level, | 98 | initial_output: Level, |
| 112 | drive: OutputDrive, | 99 | drive: OutputDrive, |
| 113 | ) -> Self { | 100 | ) -> Self { |
| 114 | let mut pin = FlexPin::new(pin); | 101 | let mut pin = Flex::new(pin); |
| 115 | match initial_output { | 102 | match initial_output { |
| 116 | Level::High => pin.set_high(), | 103 | Level::High => pin.set_high(), |
| 117 | Level::Low => pin.set_low(), | 104 | Level::Low => pin.set_low(), |
| @@ -142,40 +129,18 @@ impl<'d, T: Pin> Output<'d, T> { | |||
| 142 | } | 129 | } |
| 143 | } | 130 | } |
| 144 | 131 | ||
| 145 | impl<'d, T: Pin> OutputPin for Output<'d, T> { | ||
| 146 | type Error = Infallible; | ||
| 147 | |||
| 148 | fn set_high(&mut self) -> Result<(), Self::Error> { | ||
| 149 | Ok(self.set_high()) | ||
| 150 | } | ||
| 151 | |||
| 152 | fn set_low(&mut self) -> Result<(), Self::Error> { | ||
| 153 | Ok(self.set_low()) | ||
| 154 | } | ||
| 155 | } | ||
| 156 | |||
| 157 | impl<'d, T: Pin> StatefulOutputPin for Output<'d, T> { | ||
| 158 | fn is_set_high(&self) -> Result<bool, Self::Error> { | ||
| 159 | Ok(self.is_set_high()) | ||
| 160 | } | ||
| 161 | |||
| 162 | fn is_set_low(&self) -> Result<bool, Self::Error> { | ||
| 163 | Ok(self.is_set_low()) | ||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 167 | /// GPIO flexible pin. | 132 | /// GPIO flexible pin. |
| 168 | /// | 133 | /// |
| 169 | /// This pin can either be a disconnected, input, or output pin. The level register bit will remain | 134 | /// This pin can either be a disconnected, input, or output pin. The level register bit will remain |
| 170 | /// set while not in output mode, so the pin's level will be 'remembered' when it is not in output | 135 | /// set while not in output mode, so the pin's level will be 'remembered' when it is not in output |
| 171 | /// mode. | 136 | /// mode. |
| 172 | pub struct FlexPin<'d, T: Pin> { | 137 | pub struct Flex<'d, T: Pin> { |
| 173 | pub(crate) pin: T, | 138 | pub(crate) pin: T, |
| 174 | phantom: PhantomData<&'d mut T>, | 139 | phantom: PhantomData<&'d mut T>, |
| 175 | } | 140 | } |
| 176 | 141 | ||
| 177 | impl<'d, T: Pin> FlexPin<'d, T> { | 142 | impl<'d, T: Pin> Flex<'d, T> { |
| 178 | /// Wrap the pin in a `FlexPin`. | 143 | /// Wrap the pin in a `Flex`. |
| 179 | /// | 144 | /// |
| 180 | /// The pin remains disconnected. The initial output level is unspecified, but can be changed | 145 | /// The pin remains disconnected. The initial output level is unspecified, but can be changed |
| 181 | /// before the pin is put into output mode. | 146 | /// before the pin is put into output mode. |
| @@ -270,49 +235,12 @@ impl<'d, T: Pin> FlexPin<'d, T> { | |||
| 270 | } | 235 | } |
| 271 | } | 236 | } |
| 272 | 237 | ||
| 273 | impl<'d, T: Pin> Drop for FlexPin<'d, T> { | 238 | impl<'d, T: Pin> Drop for Flex<'d, T> { |
| 274 | fn drop(&mut self) { | 239 | fn drop(&mut self) { |
| 275 | self.pin.conf().reset(); | 240 | self.pin.conf().reset(); |
| 276 | } | 241 | } |
| 277 | } | 242 | } |
| 278 | 243 | ||
| 279 | /// Implement [`InputPin`] for [`FlexPin`]; | ||
| 280 | /// | ||
| 281 | /// If the pin is not in input mode the result is unspecified. | ||
| 282 | impl<'d, T: Pin> InputPin for FlexPin<'d, T> { | ||
| 283 | type Error = Infallible; | ||
| 284 | |||
| 285 | fn is_high(&self) -> Result<bool, Self::Error> { | ||
| 286 | Ok(self.is_high()) | ||
| 287 | } | ||
| 288 | |||
| 289 | fn is_low(&self) -> Result<bool, Self::Error> { | ||
| 290 | Ok(self.is_low()) | ||
| 291 | } | ||
| 292 | } | ||
| 293 | |||
| 294 | impl<'d, T: Pin> OutputPin for FlexPin<'d, T> { | ||
| 295 | type Error = Infallible; | ||
| 296 | |||
| 297 | fn set_high(&mut self) -> Result<(), Self::Error> { | ||
| 298 | Ok(self.set_high()) | ||
| 299 | } | ||
| 300 | |||
| 301 | fn set_low(&mut self) -> Result<(), Self::Error> { | ||
| 302 | Ok(self.set_low()) | ||
| 303 | } | ||
| 304 | } | ||
| 305 | |||
| 306 | impl<'d, T: Pin> StatefulOutputPin for FlexPin<'d, T> { | ||
| 307 | fn is_set_high(&self) -> Result<bool, Self::Error> { | ||
| 308 | Ok(self.is_set_high()) | ||
| 309 | } | ||
| 310 | |||
| 311 | fn is_set_low(&self) -> Result<bool, Self::Error> { | ||
| 312 | Ok(self.is_set_low()) | ||
| 313 | } | ||
| 314 | } | ||
| 315 | |||
| 316 | pub(crate) mod sealed { | 244 | pub(crate) mod sealed { |
| 317 | use super::*; | 245 | use super::*; |
| 318 | 246 | ||
| @@ -350,17 +278,13 @@ pub(crate) mod sealed { | |||
| 350 | /// Set the output as high. | 278 | /// Set the output as high. |
| 351 | #[inline] | 279 | #[inline] |
| 352 | fn set_high(&self) { | 280 | fn set_high(&self) { |
| 353 | unsafe { | 281 | unsafe { self.block().outset.write(|w| w.bits(1u32 << self._pin())) } |
| 354 | self.block().outset.write(|w| w.bits(1u32 << self._pin())); | ||
| 355 | } | ||
| 356 | } | 282 | } |
| 357 | 283 | ||
| 358 | /// Set the output as low. | 284 | /// Set the output as low. |
| 359 | #[inline] | 285 | #[inline] |
| 360 | fn set_low(&self) { | 286 | fn set_low(&self) { |
| 361 | unsafe { | 287 | unsafe { self.block().outclr.write(|w| w.bits(1u32 << self._pin())) } |
| 362 | self.block().outclr.write(|w| w.bits(1u32 << self._pin())); | ||
| 363 | } | ||
| 364 | } | 288 | } |
| 365 | } | 289 | } |
| 366 | 290 | ||
| @@ -495,3 +419,160 @@ macro_rules! impl_pin { | |||
| 495 | } | 419 | } |
| 496 | }; | 420 | }; |
| 497 | } | 421 | } |
| 422 | |||
| 423 | // ==================== | ||
| 424 | |||
| 425 | mod eh02 { | ||
| 426 | use super::*; | ||
| 427 | |||
| 428 | impl<'d, T: Pin> embedded_hal_02::digital::v2::InputPin for Input<'d, T> { | ||
| 429 | type Error = Infallible; | ||
| 430 | |||
| 431 | fn is_high(&self) -> Result<bool, Self::Error> { | ||
| 432 | Ok(self.is_high()) | ||
| 433 | } | ||
| 434 | |||
| 435 | fn is_low(&self) -> Result<bool, Self::Error> { | ||
| 436 | Ok(self.is_low()) | ||
| 437 | } | ||
| 438 | } | ||
| 439 | |||
| 440 | impl<'d, T: Pin> embedded_hal_02::digital::v2::OutputPin for Output<'d, T> { | ||
| 441 | type Error = Infallible; | ||
| 442 | |||
| 443 | fn set_high(&mut self) -> Result<(), Self::Error> { | ||
| 444 | Ok(self.set_high()) | ||
| 445 | } | ||
| 446 | |||
| 447 | fn set_low(&mut self) -> Result<(), Self::Error> { | ||
| 448 | Ok(self.set_low()) | ||
| 449 | } | ||
| 450 | } | ||
| 451 | |||
| 452 | impl<'d, T: Pin> embedded_hal_02::digital::v2::StatefulOutputPin for Output<'d, T> { | ||
| 453 | fn is_set_high(&self) -> Result<bool, Self::Error> { | ||
| 454 | Ok(self.is_set_high()) | ||
| 455 | } | ||
| 456 | |||
| 457 | fn is_set_low(&self) -> Result<bool, Self::Error> { | ||
| 458 | Ok(self.is_set_low()) | ||
| 459 | } | ||
| 460 | } | ||
| 461 | |||
| 462 | /// Implement [`InputPin`] for [`Flex`]; | ||
| 463 | /// | ||
| 464 | /// If the pin is not in input mode the result is unspecified. | ||
| 465 | impl<'d, T: Pin> embedded_hal_02::digital::v2::InputPin for Flex<'d, T> { | ||
| 466 | type Error = Infallible; | ||
| 467 | |||
| 468 | fn is_high(&self) -> Result<bool, Self::Error> { | ||
| 469 | Ok(self.is_high()) | ||
| 470 | } | ||
| 471 | |||
| 472 | fn is_low(&self) -> Result<bool, Self::Error> { | ||
| 473 | Ok(self.is_low()) | ||
| 474 | } | ||
| 475 | } | ||
| 476 | |||
| 477 | impl<'d, T: Pin> embedded_hal_02::digital::v2::OutputPin for Flex<'d, T> { | ||
| 478 | type Error = Infallible; | ||
| 479 | |||
| 480 | fn set_high(&mut self) -> Result<(), Self::Error> { | ||
| 481 | Ok(self.set_high()) | ||
| 482 | } | ||
| 483 | |||
| 484 | fn set_low(&mut self) -> Result<(), Self::Error> { | ||
| 485 | Ok(self.set_low()) | ||
| 486 | } | ||
| 487 | } | ||
| 488 | |||
| 489 | impl<'d, T: Pin> embedded_hal_02::digital::v2::StatefulOutputPin for Flex<'d, T> { | ||
| 490 | fn is_set_high(&self) -> Result<bool, Self::Error> { | ||
| 491 | Ok(self.is_set_high()) | ||
| 492 | } | ||
| 493 | |||
| 494 | fn is_set_low(&self) -> Result<bool, Self::Error> { | ||
| 495 | Ok(self.is_set_low()) | ||
| 496 | } | ||
| 497 | } | ||
| 498 | } | ||
| 499 | |||
| 500 | #[cfg(feature = "unstable-traits")] | ||
| 501 | mod eh1 { | ||
| 502 | use super::*; | ||
| 503 | |||
| 504 | impl<'d, T: Pin> embedded_hal_1::digital::ErrorType for Input<'d, T> { | ||
| 505 | type Error = Infallible; | ||
| 506 | } | ||
| 507 | |||
| 508 | impl<'d, T: Pin> embedded_hal_1::digital::blocking::InputPin for Input<'d, T> { | ||
| 509 | fn is_high(&self) -> Result<bool, Self::Error> { | ||
| 510 | Ok(self.is_high()) | ||
| 511 | } | ||
| 512 | |||
| 513 | fn is_low(&self) -> Result<bool, Self::Error> { | ||
| 514 | Ok(self.is_low()) | ||
| 515 | } | ||
| 516 | } | ||
| 517 | |||
| 518 | impl<'d, T: Pin> embedded_hal_1::digital::ErrorType for Output<'d, T> { | ||
| 519 | type Error = Infallible; | ||
| 520 | } | ||
| 521 | |||
| 522 | impl<'d, T: Pin> embedded_hal_1::digital::blocking::OutputPin for Output<'d, T> { | ||
| 523 | fn set_high(&mut self) -> Result<(), Self::Error> { | ||
| 524 | Ok(self.set_high()) | ||
| 525 | } | ||
| 526 | |||
| 527 | fn set_low(&mut self) -> Result<(), Self::Error> { | ||
| 528 | Ok(self.set_low()) | ||
| 529 | } | ||
| 530 | } | ||
| 531 | |||
| 532 | impl<'d, T: Pin> embedded_hal_1::digital::blocking::StatefulOutputPin for Output<'d, T> { | ||
| 533 | fn is_set_high(&self) -> Result<bool, Self::Error> { | ||
| 534 | Ok(self.is_set_high()) | ||
| 535 | } | ||
| 536 | |||
| 537 | fn is_set_low(&self) -> Result<bool, Self::Error> { | ||
| 538 | Ok(self.is_set_low()) | ||
| 539 | } | ||
| 540 | } | ||
| 541 | |||
| 542 | impl<'d, T: Pin> embedded_hal_1::digital::ErrorType for Flex<'d, T> { | ||
| 543 | type Error = Infallible; | ||
| 544 | } | ||
| 545 | |||
| 546 | /// Implement [`InputPin`] for [`Flex`]; | ||
| 547 | /// | ||
| 548 | /// If the pin is not in input mode the result is unspecified. | ||
| 549 | impl<'d, T: Pin> embedded_hal_1::digital::blocking::InputPin for Flex<'d, T> { | ||
| 550 | fn is_high(&self) -> Result<bool, Self::Error> { | ||
| 551 | Ok(self.is_high()) | ||
| 552 | } | ||
| 553 | |||
| 554 | fn is_low(&self) -> Result<bool, Self::Error> { | ||
| 555 | Ok(self.is_low()) | ||
| 556 | } | ||
| 557 | } | ||
| 558 | |||
| 559 | impl<'d, T: Pin> embedded_hal_1::digital::blocking::OutputPin for Flex<'d, T> { | ||
| 560 | fn set_high(&mut self) -> Result<(), Self::Error> { | ||
| 561 | Ok(self.set_high()) | ||
| 562 | } | ||
| 563 | |||
| 564 | fn set_low(&mut self) -> Result<(), Self::Error> { | ||
| 565 | Ok(self.set_low()) | ||
| 566 | } | ||
| 567 | } | ||
| 568 | |||
| 569 | impl<'d, T: Pin> embedded_hal_1::digital::blocking::StatefulOutputPin for Flex<'d, T> { | ||
| 570 | fn is_set_high(&self) -> Result<bool, Self::Error> { | ||
| 571 | Ok(self.is_set_high()) | ||
| 572 | } | ||
| 573 | |||
| 574 | fn is_set_low(&self) -> Result<bool, Self::Error> { | ||
| 575 | Ok(self.is_set_low()) | ||
| 576 | } | ||
| 577 | } | ||
| 578 | } | ||
diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs index 99dfd1ebd..a4c24058c 100644 --- a/embassy-nrf/src/gpiote.rs +++ b/embassy-nrf/src/gpiote.rs | |||
| @@ -5,11 +5,10 @@ use core::task::{Context, Poll}; | |||
| 5 | use embassy::interrupt::{Interrupt, InterruptExt}; | 5 | use embassy::interrupt::{Interrupt, InterruptExt}; |
| 6 | use embassy::waitqueue::AtomicWaker; | 6 | use embassy::waitqueue::AtomicWaker; |
| 7 | use embassy_hal_common::unsafe_impl_unborrow; | 7 | use embassy_hal_common::unsafe_impl_unborrow; |
| 8 | use embedded_hal::digital::v2::InputPin; | ||
| 9 | use futures::future::poll_fn; | 8 | use futures::future::poll_fn; |
| 10 | 9 | ||
| 11 | use crate::gpio::sealed::Pin as _; | 10 | use crate::gpio::sealed::Pin as _; |
| 12 | use crate::gpio::{AnyPin, FlexPin, Input, Output, Pin as GpioPin}; | 11 | use crate::gpio::{AnyPin, Flex, Input, Output, Pin as GpioPin}; |
| 13 | use crate::pac; | 12 | use crate::pac; |
| 14 | use crate::ppi::{Event, Task}; | 13 | use crate::ppi::{Event, Task}; |
| 15 | use crate::{interrupt, peripherals}; | 14 | use crate::{interrupt, peripherals}; |
| @@ -216,18 +215,6 @@ impl<'d, C: Channel, T: GpioPin> InputChannel<'d, C, T> { | |||
| 216 | } | 215 | } |
| 217 | } | 216 | } |
| 218 | 217 | ||
| 219 | impl<'d, C: Channel, T: GpioPin> InputPin for InputChannel<'d, C, T> { | ||
| 220 | type Error = Infallible; | ||
| 221 | |||
| 222 | fn is_high(&self) -> Result<bool, Self::Error> { | ||
| 223 | self.pin.is_high() | ||
| 224 | } | ||
| 225 | |||
| 226 | fn is_low(&self) -> Result<bool, Self::Error> { | ||
| 227 | self.pin.is_low() | ||
| 228 | } | ||
| 229 | } | ||
| 230 | |||
| 231 | /// GPIOTE channel driver in output mode | 218 | /// GPIOTE channel driver in output mode |
| 232 | pub struct OutputChannel<'d, C: Channel, T: GpioPin> { | 219 | pub struct OutputChannel<'d, C: Channel, T: GpioPin> { |
| 233 | ch: C, | 220 | ch: C, |
| @@ -342,78 +329,60 @@ impl<'a> Future for PortInputFuture<'a> { | |||
| 342 | } | 329 | } |
| 343 | } | 330 | } |
| 344 | 331 | ||
| 345 | impl<'d, T: GpioPin> embassy::traits::gpio::WaitForHigh for Input<'d, T> { | 332 | impl<'d, T: GpioPin> Input<'d, T> { |
| 346 | type Future<'a> | 333 | pub async fn wait_for_high(&mut self) { |
| 347 | where | 334 | self.pin.wait_for_high().await |
| 348 | Self: 'a, | ||
| 349 | = impl Future<Output = ()> + Unpin + 'a; | ||
| 350 | |||
| 351 | fn wait_for_high<'a>(&'a mut self) -> Self::Future<'a> { | ||
| 352 | self.pin.wait_for_high() | ||
| 353 | } | 335 | } |
| 354 | } | ||
| 355 | 336 | ||
| 356 | impl<'d, T: GpioPin> embassy::traits::gpio::WaitForLow for Input<'d, T> { | 337 | pub async fn wait_for_low(&mut self) { |
| 357 | type Future<'a> | 338 | self.pin.wait_for_low().await |
| 358 | where | 339 | } |
| 359 | Self: 'a, | ||
| 360 | = impl Future<Output = ()> + Unpin + 'a; | ||
| 361 | 340 | ||
| 362 | fn wait_for_low<'a>(&'a mut self) -> Self::Future<'a> { | 341 | pub async fn wait_for_rising_edge(&mut self) { |
| 363 | self.pin.wait_for_low() | 342 | self.pin.wait_for_rising_edge().await |
| 364 | } | 343 | } |
| 365 | } | ||
| 366 | 344 | ||
| 367 | impl<'d, T: GpioPin> embassy::traits::gpio::WaitForAnyEdge for Input<'d, T> { | 345 | pub async fn wait_for_falling_edge(&mut self) { |
| 368 | type Future<'a> | 346 | self.pin.wait_for_falling_edge().await |
| 369 | where | 347 | } |
| 370 | Self: 'a, | ||
| 371 | = impl Future<Output = ()> + Unpin + 'a; | ||
| 372 | 348 | ||
| 373 | fn wait_for_any_edge<'a>(&'a mut self) -> Self::Future<'a> { | 349 | pub async fn wait_for_any_edge(&mut self) { |
| 374 | self.pin.wait_for_any_edge() | 350 | self.pin.wait_for_any_edge().await |
| 375 | } | 351 | } |
| 376 | } | 352 | } |
| 377 | 353 | ||
| 378 | impl<'d, T: GpioPin> embassy::traits::gpio::WaitForHigh for FlexPin<'d, T> { | 354 | impl<'d, T: GpioPin> Flex<'d, T> { |
| 379 | type Future<'a> | 355 | pub async fn wait_for_high(&mut self) { |
| 380 | where | ||
| 381 | Self: 'a, | ||
| 382 | = impl Future<Output = ()> + Unpin + 'a; | ||
| 383 | |||
| 384 | fn wait_for_high<'a>(&'a mut self) -> Self::Future<'a> { | ||
| 385 | self.pin.conf().modify(|_, w| w.sense().high()); | 356 | self.pin.conf().modify(|_, w| w.sense().high()); |
| 386 | 357 | ||
| 387 | PortInputFuture { | 358 | PortInputFuture { |
| 388 | pin_port: self.pin.pin_port(), | 359 | pin_port: self.pin.pin_port(), |
| 389 | phantom: PhantomData, | 360 | phantom: PhantomData, |
| 390 | } | 361 | } |
| 362 | .await | ||
| 391 | } | 363 | } |
| 392 | } | ||
| 393 | 364 | ||
| 394 | impl<'d, T: GpioPin> embassy::traits::gpio::WaitForLow for FlexPin<'d, T> { | 365 | pub async fn wait_for_low(&mut self) { |
| 395 | type Future<'a> | ||
| 396 | where | ||
| 397 | Self: 'a, | ||
| 398 | = impl Future<Output = ()> + Unpin + 'a; | ||
| 399 | |||
| 400 | fn wait_for_low<'a>(&'a mut self) -> Self::Future<'a> { | ||
| 401 | self.pin.conf().modify(|_, w| w.sense().low()); | 366 | self.pin.conf().modify(|_, w| w.sense().low()); |
| 402 | 367 | ||
| 403 | PortInputFuture { | 368 | PortInputFuture { |
| 404 | pin_port: self.pin.pin_port(), | 369 | pin_port: self.pin.pin_port(), |
| 405 | phantom: PhantomData, | 370 | phantom: PhantomData, |
| 406 | } | 371 | } |
| 372 | .await | ||
| 373 | } | ||
| 374 | |||
| 375 | pub async fn wait_for_rising_edge(&mut self) { | ||
| 376 | self.wait_for_low().await; | ||
| 377 | self.wait_for_high().await; | ||
| 407 | } | 378 | } |
| 408 | } | ||
| 409 | 379 | ||
| 410 | impl<'d, T: GpioPin> embassy::traits::gpio::WaitForAnyEdge for FlexPin<'d, T> { | 380 | pub async fn wait_for_falling_edge(&mut self) { |
| 411 | type Future<'a> | 381 | self.wait_for_high().await; |
| 412 | where | 382 | self.wait_for_low().await; |
| 413 | Self: 'a, | 383 | } |
| 414 | = impl Future<Output = ()> + Unpin + 'a; | ||
| 415 | 384 | ||
| 416 | fn wait_for_any_edge<'a>(&'a mut self) -> Self::Future<'a> { | 385 | pub async fn wait_for_any_edge(&mut self) { |
| 417 | if self.is_high() { | 386 | if self.is_high() { |
| 418 | self.pin.conf().modify(|_, w| w.sense().low()); | 387 | self.pin.conf().modify(|_, w| w.sense().low()); |
| 419 | } else { | 388 | } else { |
| @@ -423,6 +392,7 @@ impl<'d, T: GpioPin> embassy::traits::gpio::WaitForAnyEdge for FlexPin<'d, T> { | |||
| 423 | pin_port: self.pin.pin_port(), | 392 | pin_port: self.pin.pin_port(), |
| 424 | phantom: PhantomData, | 393 | phantom: PhantomData, |
| 425 | } | 394 | } |
| 395 | .await | ||
| 426 | } | 396 | } |
| 427 | } | 397 | } |
| 428 | 398 | ||
| @@ -471,3 +441,137 @@ impl_channel!(GPIOTE_CH4, 4); | |||
| 471 | impl_channel!(GPIOTE_CH5, 5); | 441 | impl_channel!(GPIOTE_CH5, 5); |
| 472 | impl_channel!(GPIOTE_CH6, 6); | 442 | impl_channel!(GPIOTE_CH6, 6); |
| 473 | impl_channel!(GPIOTE_CH7, 7); | 443 | impl_channel!(GPIOTE_CH7, 7); |
| 444 | |||
| 445 | // ==================== | ||
| 446 | |||
| 447 | mod eh02 { | ||
| 448 | use super::*; | ||
| 449 | |||
| 450 | impl<'d, C: Channel, T: GpioPin> embedded_hal_02::digital::v2::InputPin for InputChannel<'d, C, T> { | ||
| 451 | type Error = Infallible; | ||
| 452 | |||
| 453 | fn is_high(&self) -> Result<bool, Self::Error> { | ||
| 454 | self.pin.is_high() | ||
| 455 | } | ||
| 456 | |||
| 457 | fn is_low(&self) -> Result<bool, Self::Error> { | ||
| 458 | self.pin.is_low() | ||
| 459 | } | ||
| 460 | } | ||
| 461 | } | ||
| 462 | |||
| 463 | #[cfg(feature = "unstable-traits")] | ||
| 464 | mod eh1 { | ||
| 465 | use super::*; | ||
| 466 | use futures::FutureExt; | ||
| 467 | |||
| 468 | impl<'d, C: Channel, T: GpioPin> embedded_hal_1::digital::ErrorType for InputChannel<'d, C, T> { | ||
| 469 | type Error = Infallible; | ||
| 470 | } | ||
| 471 | |||
| 472 | impl<'d, C: Channel, T: GpioPin> embedded_hal_1::digital::blocking::InputPin | ||
| 473 | for InputChannel<'d, C, T> | ||
| 474 | { | ||
| 475 | fn is_high(&self) -> Result<bool, Self::Error> { | ||
| 476 | self.pin.is_high() | ||
| 477 | } | ||
| 478 | |||
| 479 | fn is_low(&self) -> Result<bool, Self::Error> { | ||
| 480 | self.pin.is_low() | ||
| 481 | } | ||
| 482 | } | ||
| 483 | |||
| 484 | impl<'d, T: GpioPin> embedded_hal_async::digital::Wait for Input<'d, T> { | ||
| 485 | type WaitForHighFuture<'a> | ||
| 486 | where | ||
| 487 | Self: 'a, | ||
| 488 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 489 | |||
| 490 | fn wait_for_high<'a>(&'a mut self) -> Self::WaitForHighFuture<'a> { | ||
| 491 | self.wait_for_high().map(Ok) | ||
| 492 | } | ||
| 493 | |||
| 494 | type WaitForLowFuture<'a> | ||
| 495 | where | ||
| 496 | Self: 'a, | ||
| 497 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 498 | |||
| 499 | fn wait_for_low<'a>(&'a mut self) -> Self::WaitForLowFuture<'a> { | ||
| 500 | self.wait_for_low().map(Ok) | ||
| 501 | } | ||
| 502 | |||
| 503 | type WaitForRisingEdgeFuture<'a> | ||
| 504 | where | ||
| 505 | Self: 'a, | ||
| 506 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 507 | |||
| 508 | fn wait_for_rising_edge<'a>(&'a mut self) -> Self::WaitForRisingEdgeFuture<'a> { | ||
| 509 | self.wait_for_rising_edge().map(Ok) | ||
| 510 | } | ||
| 511 | |||
| 512 | type WaitForFallingEdgeFuture<'a> | ||
| 513 | where | ||
| 514 | Self: 'a, | ||
| 515 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 516 | |||
| 517 | fn wait_for_falling_edge<'a>(&'a mut self) -> Self::WaitForFallingEdgeFuture<'a> { | ||
| 518 | self.wait_for_falling_edge().map(Ok) | ||
| 519 | } | ||
| 520 | |||
| 521 | type WaitForAnyEdgeFuture<'a> | ||
| 522 | where | ||
| 523 | Self: 'a, | ||
| 524 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 525 | |||
| 526 | fn wait_for_any_edge<'a>(&'a mut self) -> Self::WaitForAnyEdgeFuture<'a> { | ||
| 527 | self.wait_for_any_edge().map(Ok) | ||
| 528 | } | ||
| 529 | } | ||
| 530 | |||
| 531 | impl<'d, T: GpioPin> embedded_hal_async::digital::Wait for Flex<'d, T> { | ||
| 532 | type WaitForHighFuture<'a> | ||
| 533 | where | ||
| 534 | Self: 'a, | ||
| 535 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 536 | |||
| 537 | fn wait_for_high<'a>(&'a mut self) -> Self::WaitForHighFuture<'a> { | ||
| 538 | self.wait_for_high().map(Ok) | ||
| 539 | } | ||
| 540 | |||
| 541 | type WaitForLowFuture<'a> | ||
| 542 | where | ||
| 543 | Self: 'a, | ||
| 544 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 545 | |||
| 546 | fn wait_for_low<'a>(&'a mut self) -> Self::WaitForLowFuture<'a> { | ||
| 547 | self.wait_for_low().map(Ok) | ||
| 548 | } | ||
| 549 | |||
| 550 | type WaitForRisingEdgeFuture<'a> | ||
| 551 | where | ||
| 552 | Self: 'a, | ||
| 553 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 554 | |||
| 555 | fn wait_for_rising_edge<'a>(&'a mut self) -> Self::WaitForRisingEdgeFuture<'a> { | ||
| 556 | self.wait_for_rising_edge().map(Ok) | ||
| 557 | } | ||
| 558 | |||
| 559 | type WaitForFallingEdgeFuture<'a> | ||
| 560 | where | ||
| 561 | Self: 'a, | ||
| 562 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 563 | |||
| 564 | fn wait_for_falling_edge<'a>(&'a mut self) -> Self::WaitForFallingEdgeFuture<'a> { | ||
| 565 | self.wait_for_falling_edge().map(Ok) | ||
| 566 | } | ||
| 567 | |||
| 568 | type WaitForAnyEdgeFuture<'a> | ||
| 569 | where | ||
| 570 | Self: 'a, | ||
| 571 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 572 | |||
| 573 | fn wait_for_any_edge<'a>(&'a mut self) -> Self::WaitForAnyEdgeFuture<'a> { | ||
| 574 | self.wait_for_any_edge().map(Ok) | ||
| 575 | } | ||
| 576 | } | ||
| 577 | } | ||
diff --git a/embassy-nrf/src/qspi.rs b/embassy-nrf/src/qspi.rs index 6afba4931..89262ac05 100644 --- a/embassy-nrf/src/qspi.rs +++ b/embassy-nrf/src/qspi.rs | |||
| @@ -1,11 +1,9 @@ | |||
| 1 | #![macro_use] | 1 | #![macro_use] |
| 2 | 2 | ||
| 3 | use core::future::Future; | ||
| 4 | use core::marker::PhantomData; | 3 | use core::marker::PhantomData; |
| 5 | use core::ptr; | 4 | use core::ptr; |
| 6 | use core::task::Poll; | 5 | use core::task::Poll; |
| 7 | use embassy::interrupt::{Interrupt, InterruptExt}; | 6 | use embassy::interrupt::{Interrupt, InterruptExt}; |
| 8 | use embassy::traits::flash::{Error, Flash}; | ||
| 9 | use embassy::util::Unborrow; | 7 | use embassy::util::Unborrow; |
| 10 | use embassy_hal_common::drop::DropBomb; | 8 | use embassy_hal_common::drop::DropBomb; |
| 11 | use embassy_hal_common::unborrow; | 9 | use embassy_hal_common::unborrow; |
| @@ -58,6 +56,13 @@ impl Default for Config { | |||
| 58 | } | 56 | } |
| 59 | } | 57 | } |
| 60 | 58 | ||
| 59 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] | ||
| 60 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 61 | #[non_exhaustive] | ||
| 62 | pub enum Error { | ||
| 63 | // TODO add "not in data memory" error and check for it | ||
| 64 | } | ||
| 65 | |||
| 61 | pub struct Qspi<'d, T: Instance> { | 66 | pub struct Qspi<'d, T: Instance> { |
| 62 | dpm_enabled: bool, | 67 | dpm_enabled: bool, |
| 63 | phantom: PhantomData<&'d mut T>, | 68 | phantom: PhantomData<&'d mut T>, |
| @@ -240,6 +245,87 @@ impl<'d, T: Instance> Qspi<'d, T> { | |||
| 240 | }) | 245 | }) |
| 241 | .await | 246 | .await |
| 242 | } | 247 | } |
| 248 | |||
| 249 | pub async fn read(&mut self, address: usize, data: &mut [u8]) -> Result<(), Error> { | ||
| 250 | let bomb = DropBomb::new(); | ||
| 251 | |||
| 252 | assert_eq!(data.as_ptr() as u32 % 4, 0); | ||
| 253 | assert_eq!(data.len() as u32 % 4, 0); | ||
| 254 | assert_eq!(address as u32 % 4, 0); | ||
| 255 | |||
| 256 | let r = T::regs(); | ||
| 257 | |||
| 258 | r.read | ||
| 259 | .src | ||
| 260 | .write(|w| unsafe { w.src().bits(address as u32) }); | ||
| 261 | r.read | ||
| 262 | .dst | ||
| 263 | .write(|w| unsafe { w.dst().bits(data.as_ptr() as u32) }); | ||
| 264 | r.read | ||
| 265 | .cnt | ||
| 266 | .write(|w| unsafe { w.cnt().bits(data.len() as u32) }); | ||
| 267 | |||
| 268 | r.events_ready.reset(); | ||
| 269 | r.intenset.write(|w| w.ready().set()); | ||
| 270 | r.tasks_readstart.write(|w| w.tasks_readstart().bit(true)); | ||
| 271 | |||
| 272 | self.wait_ready().await; | ||
| 273 | |||
| 274 | bomb.defuse(); | ||
| 275 | |||
| 276 | Ok(()) | ||
| 277 | } | ||
| 278 | |||
| 279 | pub async fn write(&mut self, address: usize, data: &[u8]) -> Result<(), Error> { | ||
| 280 | let bomb = DropBomb::new(); | ||
| 281 | |||
| 282 | assert_eq!(data.as_ptr() as u32 % 4, 0); | ||
| 283 | assert_eq!(data.len() as u32 % 4, 0); | ||
| 284 | assert_eq!(address as u32 % 4, 0); | ||
| 285 | |||
| 286 | let r = T::regs(); | ||
| 287 | r.write | ||
| 288 | .src | ||
| 289 | .write(|w| unsafe { w.src().bits(data.as_ptr() as u32) }); | ||
| 290 | r.write | ||
| 291 | .dst | ||
| 292 | .write(|w| unsafe { w.dst().bits(address as u32) }); | ||
| 293 | r.write | ||
| 294 | .cnt | ||
| 295 | .write(|w| unsafe { w.cnt().bits(data.len() as u32) }); | ||
| 296 | |||
| 297 | r.events_ready.reset(); | ||
| 298 | r.intenset.write(|w| w.ready().set()); | ||
| 299 | r.tasks_writestart.write(|w| w.tasks_writestart().bit(true)); | ||
| 300 | |||
| 301 | self.wait_ready().await; | ||
| 302 | |||
| 303 | bomb.defuse(); | ||
| 304 | |||
| 305 | Ok(()) | ||
| 306 | } | ||
| 307 | |||
| 308 | pub async fn erase(&mut self, address: usize) -> Result<(), Error> { | ||
| 309 | let bomb = DropBomb::new(); | ||
| 310 | |||
| 311 | assert_eq!(address as u32 % 4096, 0); | ||
| 312 | |||
| 313 | let r = T::regs(); | ||
| 314 | r.erase | ||
| 315 | .ptr | ||
| 316 | .write(|w| unsafe { w.ptr().bits(address as u32) }); | ||
| 317 | r.erase.len.write(|w| w.len()._4kb()); | ||
| 318 | |||
| 319 | r.events_ready.reset(); | ||
| 320 | r.intenset.write(|w| w.ready().set()); | ||
| 321 | r.tasks_erasestart.write(|w| w.tasks_erasestart().bit(true)); | ||
| 322 | |||
| 323 | self.wait_ready().await; | ||
| 324 | |||
| 325 | bomb.defuse(); | ||
| 326 | |||
| 327 | Ok(()) | ||
| 328 | } | ||
| 243 | } | 329 | } |
| 244 | 330 | ||
| 245 | impl<'d, T: Instance> Drop for Qspi<'d, T> { | 331 | impl<'d, T: Instance> Drop for Qspi<'d, T> { |
| @@ -285,124 +371,6 @@ impl<'d, T: Instance> Drop for Qspi<'d, T> { | |||
| 285 | } | 371 | } |
| 286 | } | 372 | } |
| 287 | 373 | ||
| 288 | impl<'d, T: Instance> Flash for Qspi<'d, T> { | ||
| 289 | type ReadFuture<'a> | ||
| 290 | where | ||
| 291 | Self: 'a, | ||
| 292 | = impl Future<Output = Result<(), Error>> + 'a; | ||
| 293 | type WriteFuture<'a> | ||
| 294 | where | ||
| 295 | Self: 'a, | ||
| 296 | = impl Future<Output = Result<(), Error>> + 'a; | ||
| 297 | type ErasePageFuture<'a> | ||
| 298 | where | ||
| 299 | Self: 'a, | ||
| 300 | = impl Future<Output = Result<(), Error>> + 'a; | ||
| 301 | |||
| 302 | fn read<'a>(&'a mut self, address: usize, data: &'a mut [u8]) -> Self::ReadFuture<'a> { | ||
| 303 | async move { | ||
| 304 | let bomb = DropBomb::new(); | ||
| 305 | |||
| 306 | assert_eq!(data.as_ptr() as u32 % 4, 0); | ||
| 307 | assert_eq!(data.len() as u32 % 4, 0); | ||
| 308 | assert_eq!(address as u32 % 4, 0); | ||
| 309 | |||
| 310 | let r = T::regs(); | ||
| 311 | |||
| 312 | r.read | ||
| 313 | .src | ||
| 314 | .write(|w| unsafe { w.src().bits(address as u32) }); | ||
| 315 | r.read | ||
| 316 | .dst | ||
| 317 | .write(|w| unsafe { w.dst().bits(data.as_ptr() as u32) }); | ||
| 318 | r.read | ||
| 319 | .cnt | ||
| 320 | .write(|w| unsafe { w.cnt().bits(data.len() as u32) }); | ||
| 321 | |||
| 322 | r.events_ready.reset(); | ||
| 323 | r.intenset.write(|w| w.ready().set()); | ||
| 324 | r.tasks_readstart.write(|w| w.tasks_readstart().bit(true)); | ||
| 325 | |||
| 326 | self.wait_ready().await; | ||
| 327 | |||
| 328 | bomb.defuse(); | ||
| 329 | |||
| 330 | Ok(()) | ||
| 331 | } | ||
| 332 | } | ||
| 333 | |||
| 334 | fn write<'a>(&'a mut self, address: usize, data: &'a [u8]) -> Self::WriteFuture<'a> { | ||
| 335 | async move { | ||
| 336 | let bomb = DropBomb::new(); | ||
| 337 | |||
| 338 | assert_eq!(data.as_ptr() as u32 % 4, 0); | ||
| 339 | assert_eq!(data.len() as u32 % 4, 0); | ||
| 340 | assert_eq!(address as u32 % 4, 0); | ||
| 341 | |||
| 342 | let r = T::regs(); | ||
| 343 | r.write | ||
| 344 | .src | ||
| 345 | .write(|w| unsafe { w.src().bits(data.as_ptr() as u32) }); | ||
| 346 | r.write | ||
| 347 | .dst | ||
| 348 | .write(|w| unsafe { w.dst().bits(address as u32) }); | ||
| 349 | r.write | ||
| 350 | .cnt | ||
| 351 | .write(|w| unsafe { w.cnt().bits(data.len() as u32) }); | ||
| 352 | |||
| 353 | r.events_ready.reset(); | ||
| 354 | r.intenset.write(|w| w.ready().set()); | ||
| 355 | r.tasks_writestart.write(|w| w.tasks_writestart().bit(true)); | ||
| 356 | |||
| 357 | self.wait_ready().await; | ||
| 358 | |||
| 359 | bomb.defuse(); | ||
| 360 | |||
| 361 | Ok(()) | ||
| 362 | } | ||
| 363 | } | ||
| 364 | |||
| 365 | fn erase<'a>(&'a mut self, address: usize) -> Self::ErasePageFuture<'a> { | ||
| 366 | async move { | ||
| 367 | let bomb = DropBomb::new(); | ||
| 368 | |||
| 369 | assert_eq!(address as u32 % 4096, 0); | ||
| 370 | |||
| 371 | let r = T::regs(); | ||
| 372 | r.erase | ||
| 373 | .ptr | ||
| 374 | .write(|w| unsafe { w.ptr().bits(address as u32) }); | ||
| 375 | r.erase.len.write(|w| w.len()._4kb()); | ||
| 376 | |||
| 377 | r.events_ready.reset(); | ||
| 378 | r.intenset.write(|w| w.ready().set()); | ||
| 379 | r.tasks_erasestart.write(|w| w.tasks_erasestart().bit(true)); | ||
| 380 | |||
| 381 | self.wait_ready().await; | ||
| 382 | |||
| 383 | bomb.defuse(); | ||
| 384 | |||
| 385 | Ok(()) | ||
| 386 | } | ||
| 387 | } | ||
| 388 | |||
| 389 | fn size(&self) -> usize { | ||
| 390 | 256 * 4096 // TODO | ||
| 391 | } | ||
| 392 | |||
| 393 | fn read_size(&self) -> usize { | ||
| 394 | 4 // TODO | ||
| 395 | } | ||
| 396 | |||
| 397 | fn write_size(&self) -> usize { | ||
| 398 | 4 // TODO | ||
| 399 | } | ||
| 400 | |||
| 401 | fn erase_size(&self) -> usize { | ||
| 402 | 4096 // TODO | ||
| 403 | } | ||
| 404 | } | ||
| 405 | |||
| 406 | pub(crate) mod sealed { | 374 | pub(crate) mod sealed { |
| 407 | use embassy::waitqueue::AtomicWaker; | 375 | use embassy::waitqueue::AtomicWaker; |
| 408 | 376 | ||
diff --git a/embassy-nrf/src/rng.rs b/embassy-nrf/src/rng.rs index 6b36cbb88..98833c52b 100644 --- a/embassy-nrf/src/rng.rs +++ b/embassy-nrf/src/rng.rs | |||
| @@ -1,5 +1,3 @@ | |||
| 1 | use core::convert::Infallible; | ||
| 2 | use core::future::Future; | ||
| 3 | use core::marker::PhantomData; | 1 | use core::marker::PhantomData; |
| 4 | use core::ptr; | 2 | use core::ptr; |
| 5 | use core::sync::atomic::AtomicPtr; | 3 | use core::sync::atomic::AtomicPtr; |
| @@ -7,13 +5,11 @@ use core::sync::atomic::Ordering; | |||
| 7 | use core::task::Poll; | 5 | use core::task::Poll; |
| 8 | 6 | ||
| 9 | use embassy::interrupt::InterruptExt; | 7 | use embassy::interrupt::InterruptExt; |
| 10 | use embassy::traits; | ||
| 11 | use embassy::util::Unborrow; | 8 | use embassy::util::Unborrow; |
| 12 | use embassy::waitqueue::AtomicWaker; | 9 | use embassy::waitqueue::AtomicWaker; |
| 13 | use embassy_hal_common::drop::OnDrop; | 10 | use embassy_hal_common::drop::OnDrop; |
| 14 | use embassy_hal_common::unborrow; | 11 | use embassy_hal_common::unborrow; |
| 15 | use futures::future::poll_fn; | 12 | use futures::future::poll_fn; |
| 16 | use rand_core::RngCore; | ||
| 17 | 13 | ||
| 18 | use crate::interrupt; | 14 | use crate::interrupt; |
| 19 | use crate::pac; | 15 | use crate::pac; |
| @@ -39,7 +35,7 @@ struct State { | |||
| 39 | 35 | ||
| 40 | /// A wrapper around an nRF RNG peripheral. | 36 | /// A wrapper around an nRF RNG peripheral. |
| 41 | /// | 37 | /// |
| 42 | /// It has a non-blocking API, through `embassy::traits::Rng`, and a blocking api through `rand`. | 38 | /// It has a non-blocking API, and a blocking api through `rand`. |
| 43 | pub struct Rng<'d> { | 39 | pub struct Rng<'d> { |
| 44 | irq: interrupt::RNG, | 40 | irq: interrupt::RNG, |
| 45 | phantom: PhantomData<(&'d mut RNG, &'d mut interrupt::RNG)>, | 41 | phantom: PhantomData<(&'d mut RNG, &'d mut interrupt::RNG)>, |
| @@ -146,72 +142,51 @@ impl<'d> Rng<'d> { | |||
| 146 | pub fn bias_correction(&self, enable: bool) { | 142 | pub fn bias_correction(&self, enable: bool) { |
| 147 | RNG::regs().config.write(|w| w.dercen().bit(enable)) | 143 | RNG::regs().config.write(|w| w.dercen().bit(enable)) |
| 148 | } | 144 | } |
| 149 | } | ||
| 150 | |||
| 151 | impl<'d> Drop for Rng<'d> { | ||
| 152 | fn drop(&mut self) { | ||
| 153 | self.irq.disable() | ||
| 154 | } | ||
| 155 | } | ||
| 156 | |||
| 157 | impl<'d> traits::rng::Rng for Rng<'d> { | ||
| 158 | type Error = Infallible; | ||
| 159 | 145 | ||
| 160 | type RngFuture<'a> | 146 | pub async fn fill_bytes(&mut self, dest: &mut [u8]) { |
| 161 | where | 147 | if dest.len() == 0 { |
| 162 | 'd: 'a, | 148 | return; // Nothing to fill |
| 163 | = impl Future<Output = Result<(), Self::Error>> + 'a; | 149 | } |
| 164 | |||
| 165 | fn fill_bytes<'a>(&'a mut self, dest: &'a mut [u8]) -> Self::RngFuture<'a> { | ||
| 166 | async move { | ||
| 167 | if dest.len() == 0 { | ||
| 168 | return Ok(()); // Nothing to fill | ||
| 169 | } | ||
| 170 | |||
| 171 | let range = dest.as_mut_ptr_range(); | ||
| 172 | // Even if we've preempted the interrupt, it can't preempt us again, | ||
| 173 | // so we don't need to worry about the order we write these in. | ||
| 174 | STATE.ptr.store(range.start, Ordering::Relaxed); | ||
| 175 | STATE.end.store(range.end, Ordering::Relaxed); | ||
| 176 | 150 | ||
| 177 | self.enable_irq(); | 151 | let range = dest.as_mut_ptr_range(); |
| 178 | self.start(); | 152 | // Even if we've preempted the interrupt, it can't preempt us again, |
| 153 | // so we don't need to worry about the order we write these in. | ||
| 154 | STATE.ptr.store(range.start, Ordering::Relaxed); | ||
| 155 | STATE.end.store(range.end, Ordering::Relaxed); | ||
| 179 | 156 | ||
| 180 | let on_drop = OnDrop::new(|| { | 157 | self.enable_irq(); |
| 181 | self.stop(); | 158 | self.start(); |
| 182 | self.disable_irq(); | ||
| 183 | 159 | ||
| 184 | // The interrupt is now disabled and can't preempt us anymore, so the order doesn't matter here. | 160 | let on_drop = OnDrop::new(|| { |
| 185 | STATE.ptr.store(ptr::null_mut(), Ordering::Relaxed); | 161 | self.stop(); |
| 186 | STATE.end.store(ptr::null_mut(), Ordering::Relaxed); | 162 | self.disable_irq(); |
| 187 | }); | ||
| 188 | 163 | ||
| 189 | poll_fn(|cx| { | 164 | // The interrupt is now disabled and can't preempt us anymore, so the order doesn't matter here. |
| 190 | STATE.waker.register(cx.waker()); | 165 | STATE.ptr.store(ptr::null_mut(), Ordering::Relaxed); |
| 166 | STATE.end.store(ptr::null_mut(), Ordering::Relaxed); | ||
| 167 | }); | ||
| 191 | 168 | ||
| 192 | // The interrupt will never modify `end`, so load it first and then get the most up-to-date `ptr`. | 169 | poll_fn(|cx| { |
| 193 | let end = STATE.end.load(Ordering::Relaxed); | 170 | STATE.waker.register(cx.waker()); |
| 194 | let ptr = STATE.ptr.load(Ordering::Relaxed); | ||
| 195 | 171 | ||
| 196 | if ptr == end { | 172 | // The interrupt will never modify `end`, so load it first and then get the most up-to-date `ptr`. |
| 197 | // We're done. | 173 | let end = STATE.end.load(Ordering::Relaxed); |
| 198 | Poll::Ready(()) | 174 | let ptr = STATE.ptr.load(Ordering::Relaxed); |
| 199 | } else { | ||
| 200 | Poll::Pending | ||
| 201 | } | ||
| 202 | }) | ||
| 203 | .await; | ||
| 204 | 175 | ||
| 205 | // Trigger the teardown | 176 | if ptr == end { |
| 206 | drop(on_drop); | 177 | // We're done. |
| 178 | Poll::Ready(()) | ||
| 179 | } else { | ||
| 180 | Poll::Pending | ||
| 181 | } | ||
| 182 | }) | ||
| 183 | .await; | ||
| 207 | 184 | ||
| 208 | Ok(()) | 185 | // Trigger the teardown |
| 209 | } | 186 | drop(on_drop); |
| 210 | } | 187 | } |
| 211 | } | ||
| 212 | 188 | ||
| 213 | impl<'d> RngCore for Rng<'d> { | 189 | pub fn blocking_fill_bytes(&mut self, dest: &mut [u8]) { |
| 214 | fn fill_bytes(&mut self, dest: &mut [u8]) { | ||
| 215 | self.start(); | 190 | self.start(); |
| 216 | 191 | ||
| 217 | for byte in dest.iter_mut() { | 192 | for byte in dest.iter_mut() { |
| @@ -223,24 +198,36 @@ impl<'d> RngCore for Rng<'d> { | |||
| 223 | 198 | ||
| 224 | self.stop(); | 199 | self.stop(); |
| 225 | } | 200 | } |
| 201 | } | ||
| 202 | |||
| 203 | impl<'d> Drop for Rng<'d> { | ||
| 204 | fn drop(&mut self) { | ||
| 205 | self.irq.disable() | ||
| 206 | } | ||
| 207 | } | ||
| 208 | |||
| 209 | impl<'d> rand_core::RngCore for Rng<'d> { | ||
| 210 | fn fill_bytes(&mut self, dest: &mut [u8]) { | ||
| 211 | self.blocking_fill_bytes(dest); | ||
| 212 | } | ||
| 226 | 213 | ||
| 227 | fn next_u32(&mut self) -> u32 { | 214 | fn next_u32(&mut self) -> u32 { |
| 228 | let mut bytes = [0; 4]; | 215 | let mut bytes = [0; 4]; |
| 229 | self.fill_bytes(&mut bytes); | 216 | self.blocking_fill_bytes(&mut bytes); |
| 230 | // We don't care about the endianness, so just use the native one. | 217 | // We don't care about the endianness, so just use the native one. |
| 231 | u32::from_ne_bytes(bytes) | 218 | u32::from_ne_bytes(bytes) |
| 232 | } | 219 | } |
| 233 | 220 | ||
| 234 | fn next_u64(&mut self) -> u64 { | 221 | fn next_u64(&mut self) -> u64 { |
| 235 | let mut bytes = [0; 8]; | 222 | let mut bytes = [0; 8]; |
| 236 | self.fill_bytes(&mut bytes); | 223 | self.blocking_fill_bytes(&mut bytes); |
| 237 | u64::from_ne_bytes(bytes) | 224 | u64::from_ne_bytes(bytes) |
| 238 | } | 225 | } |
| 239 | 226 | ||
| 240 | fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> { | 227 | fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> { |
| 241 | self.fill_bytes(dest); | 228 | self.blocking_fill_bytes(dest); |
| 242 | Ok(()) | 229 | Ok(()) |
| 243 | } | 230 | } |
| 244 | } | 231 | } |
| 245 | 232 | ||
| 246 | // TODO: Should `Rng` implement `CryptoRng`? It's 'suitable for cryptographic purposes' according to the specification. | 233 | impl<'d> rand_core::CryptoRng for Rng<'d> {} |
diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs index bc5823f6a..cd43b26e6 100644 --- a/embassy-nrf/src/spim.rs +++ b/embassy-nrf/src/spim.rs | |||
| @@ -1,23 +1,21 @@ | |||
| 1 | #![macro_use] | 1 | #![macro_use] |
| 2 | 2 | ||
| 3 | use core::future::Future; | ||
| 4 | use core::marker::PhantomData; | 3 | use core::marker::PhantomData; |
| 5 | use core::sync::atomic::{compiler_fence, Ordering}; | 4 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 6 | use core::task::Poll; | 5 | use core::task::Poll; |
| 7 | use embassy::interrupt::InterruptExt; | 6 | use embassy::interrupt::InterruptExt; |
| 8 | use embassy::traits; | ||
| 9 | use embassy::util::Unborrow; | 7 | use embassy::util::Unborrow; |
| 10 | use embassy_hal_common::unborrow; | 8 | use embassy_hal_common::unborrow; |
| 11 | use futures::future::poll_fn; | 9 | use futures::future::poll_fn; |
| 12 | use traits::spi::{FullDuplex, Read, Spi, Write}; | ||
| 13 | 10 | ||
| 14 | use crate::gpio; | 11 | use crate::gpio; |
| 15 | use crate::gpio::sealed::Pin as _; | 12 | use crate::gpio::sealed::Pin as _; |
| 16 | use crate::gpio::{OptionalPin, Pin as GpioPin}; | 13 | use crate::gpio::{OptionalPin, Pin as GpioPin}; |
| 17 | use crate::interrupt::Interrupt; | 14 | use crate::interrupt::Interrupt; |
| 15 | use crate::util::{slice_ptr_parts, slice_ptr_parts_mut}; | ||
| 18 | use crate::{pac, util::slice_in_ram_or}; | 16 | use crate::{pac, util::slice_in_ram_or}; |
| 19 | 17 | ||
| 20 | pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; | 18 | pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; |
| 21 | pub use pac::spim0::frequency::FREQUENCY_A as Frequency; | 19 | pub use pac::spim0::frequency::FREQUENCY_A as Frequency; |
| 22 | 20 | ||
| 23 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | 21 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
| @@ -132,9 +130,7 @@ impl<'d, T: Instance> Spim<'d, T> { | |||
| 132 | 130 | ||
| 133 | // Set over-read character | 131 | // Set over-read character |
| 134 | let orc = config.orc; | 132 | let orc = config.orc; |
| 135 | r.orc.write(|w| | 133 | r.orc.write(|w| unsafe { w.orc().bits(orc) }); |
| 136 | // The ORC field is 8 bits long, so any u8 is a valid value to write. | ||
| 137 | unsafe { w.orc().bits(orc) }); | ||
| 138 | 134 | ||
| 139 | // Disable all events interrupts | 135 | // Disable all events interrupts |
| 140 | r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); | 136 | r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); |
| @@ -157,210 +153,114 @@ impl<'d, T: Instance> Spim<'d, T> { | |||
| 157 | r.intenclr.write(|w| w.end().clear()); | 153 | r.intenclr.write(|w| w.end().clear()); |
| 158 | } | 154 | } |
| 159 | } | 155 | } |
| 160 | } | ||
| 161 | 156 | ||
| 162 | impl<'d, T: Instance> Drop for Spim<'d, T> { | 157 | fn prepare(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> { |
| 163 | fn drop(&mut self) { | 158 | slice_in_ram_or(tx, Error::DMABufferNotInDataMemory)?; |
| 164 | trace!("spim drop"); | 159 | // NOTE: RAM slice check for rx is not necessary, as a mutable |
| 160 | // slice can only be built from data located in RAM. | ||
| 165 | 161 | ||
| 166 | // TODO check for abort, wait for xxxstopped | 162 | compiler_fence(Ordering::SeqCst); |
| 167 | 163 | ||
| 168 | // disable! | ||
| 169 | let r = T::regs(); | 164 | let r = T::regs(); |
| 170 | r.enable.write(|w| w.enable().disabled()); | ||
| 171 | 165 | ||
| 172 | gpio::deconfigure_pin(r.psel.sck.read().bits()); | 166 | // Set up the DMA write. |
| 173 | gpio::deconfigure_pin(r.psel.miso.read().bits()); | 167 | let (ptr, len) = slice_ptr_parts(tx); |
| 174 | gpio::deconfigure_pin(r.psel.mosi.read().bits()); | 168 | r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as _) }); |
| 169 | r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); | ||
| 175 | 170 | ||
| 176 | trace!("spim drop: done"); | 171 | // Set up the DMA read. |
| 177 | } | 172 | let (ptr, len) = slice_ptr_parts_mut(rx); |
| 178 | } | 173 | r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as _) }); |
| 174 | r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); | ||
| 179 | 175 | ||
| 180 | impl<'d, T: Instance> Spi<u8> for Spim<'d, T> { | 176 | // Reset and enable the event |
| 181 | type Error = Error; | 177 | r.events_end.reset(); |
| 182 | } | 178 | r.intenset.write(|w| w.end().set()); |
| 183 | 179 | ||
| 184 | impl<'d, T: Instance> Read<u8> for Spim<'d, T> { | 180 | // Start SPI transaction. |
| 185 | type ReadFuture<'a> | 181 | r.tasks_start.write(|w| unsafe { w.bits(1) }); |
| 186 | where | ||
| 187 | Self: 'a, | ||
| 188 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 189 | 182 | ||
| 190 | fn read<'a>(&'a mut self, data: &'a mut [u8]) -> Self::ReadFuture<'a> { | 183 | Ok(()) |
| 191 | self.read_write(data, &[]) | ||
| 192 | } | 184 | } |
| 193 | } | ||
| 194 | 185 | ||
| 195 | impl<'d, T: Instance> Write<u8> for Spim<'d, T> { | 186 | fn blocking_inner(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> { |
| 196 | type WriteFuture<'a> | 187 | self.prepare(rx, tx)?; |
| 197 | where | ||
| 198 | Self: 'a, | ||
| 199 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 200 | |||
| 201 | fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> { | ||
| 202 | self.read_write(&mut [], data) | ||
| 203 | } | ||
| 204 | } | ||
| 205 | 188 | ||
| 206 | impl<'d, T: Instance> FullDuplex<u8> for Spim<'d, T> { | 189 | // Wait for 'end' event. |
| 207 | type WriteReadFuture<'a> | 190 | while T::regs().events_end.read().bits() == 0 {} |
| 208 | where | ||
| 209 | Self: 'a, | ||
| 210 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 211 | |||
| 212 | fn read_write<'a>(&'a mut self, rx: &'a mut [u8], tx: &'a [u8]) -> Self::WriteReadFuture<'a> { | ||
| 213 | async move { | ||
| 214 | slice_in_ram_or(tx, Error::DMABufferNotInDataMemory)?; | ||
| 215 | // NOTE: RAM slice check for rx is not necessary, as a mutable | ||
| 216 | // slice can only be built from data located in RAM. | ||
| 217 | |||
| 218 | // Conservative compiler fence to prevent optimizations that do not | ||
| 219 | // take in to account actions by DMA. The fence has been placed here, | ||
| 220 | // before any DMA action has started. | ||
| 221 | compiler_fence(Ordering::SeqCst); | ||
| 222 | |||
| 223 | let r = T::regs(); | ||
| 224 | let s = T::state(); | ||
| 225 | |||
| 226 | // Set up the DMA write. | ||
| 227 | r.txd | ||
| 228 | .ptr | ||
| 229 | .write(|w| unsafe { w.ptr().bits(tx.as_ptr() as u32) }); | ||
| 230 | r.txd | ||
| 231 | .maxcnt | ||
| 232 | .write(|w| unsafe { w.maxcnt().bits(tx.len() as _) }); | ||
| 233 | |||
| 234 | // Set up the DMA read. | ||
| 235 | r.rxd | ||
| 236 | .ptr | ||
| 237 | .write(|w| unsafe { w.ptr().bits(rx.as_mut_ptr() as u32) }); | ||
| 238 | r.rxd | ||
| 239 | .maxcnt | ||
| 240 | .write(|w| unsafe { w.maxcnt().bits(rx.len() as _) }); | ||
| 241 | |||
| 242 | // Reset and enable the event | ||
| 243 | r.events_end.reset(); | ||
| 244 | r.intenset.write(|w| w.end().set()); | ||
| 245 | |||
| 246 | // Start SPI transaction. | ||
| 247 | r.tasks_start.write(|w| unsafe { w.bits(1) }); | ||
| 248 | |||
| 249 | // Conservative compiler fence to prevent optimizations that do not | ||
| 250 | // take in to account actions by DMA. The fence has been placed here, | ||
| 251 | // after all possible DMA actions have completed. | ||
| 252 | compiler_fence(Ordering::SeqCst); | ||
| 253 | |||
| 254 | // Wait for 'end' event. | ||
| 255 | poll_fn(|cx| { | ||
| 256 | s.end_waker.register(cx.waker()); | ||
| 257 | if r.events_end.read().bits() != 0 { | ||
| 258 | return Poll::Ready(()); | ||
| 259 | } | ||
| 260 | 191 | ||
| 261 | Poll::Pending | 192 | compiler_fence(Ordering::SeqCst); |
| 262 | }) | ||
| 263 | .await; | ||
| 264 | 193 | ||
| 265 | Ok(()) | 194 | Ok(()) |
| 266 | } | ||
| 267 | } | 195 | } |
| 268 | } | ||
| 269 | 196 | ||
| 270 | // Blocking functions are provided by implementing `embedded_hal` traits. | 197 | async fn async_inner(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> { |
| 271 | // | 198 | self.prepare(rx, tx)?; |
| 272 | // Code could be shared between traits to reduce code size. | ||
| 273 | impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u8> for Spim<'d, T> { | ||
| 274 | type Error = Error; | ||
| 275 | fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> { | ||
| 276 | slice_in_ram_or(words, Error::DMABufferNotInDataMemory)?; | ||
| 277 | |||
| 278 | // Conservative compiler fence to prevent optimizations that do not | ||
| 279 | // take in to account actions by DMA. The fence has been placed here, | ||
| 280 | // before any DMA action has started. | ||
| 281 | compiler_fence(Ordering::SeqCst); | ||
| 282 | 199 | ||
| 283 | let r = T::regs(); | 200 | // Wait for 'end' event. |
| 201 | poll_fn(|cx| { | ||
| 202 | T::state().end_waker.register(cx.waker()); | ||
| 203 | if T::regs().events_end.read().bits() != 0 { | ||
| 204 | return Poll::Ready(()); | ||
| 205 | } | ||
| 284 | 206 | ||
| 285 | // Set up the DMA write. | 207 | Poll::Pending |
| 286 | r.txd | 208 | }) |
| 287 | .ptr | 209 | .await; |
| 288 | .write(|w| unsafe { w.ptr().bits(words.as_ptr() as u32) }); | ||
| 289 | r.txd | ||
| 290 | .maxcnt | ||
| 291 | .write(|w| unsafe { w.maxcnt().bits(words.len() as _) }); | ||
| 292 | 210 | ||
| 293 | // Set up the DMA read. | 211 | compiler_fence(Ordering::SeqCst); |
| 294 | r.rxd | ||
| 295 | .ptr | ||
| 296 | .write(|w| unsafe { w.ptr().bits(words.as_mut_ptr() as u32) }); | ||
| 297 | r.rxd | ||
| 298 | .maxcnt | ||
| 299 | .write(|w| unsafe { w.maxcnt().bits(words.len() as _) }); | ||
| 300 | |||
| 301 | // Disable the end event since we are busy-polling. | ||
| 302 | r.events_end.reset(); | ||
| 303 | 212 | ||
| 304 | // Start SPI transaction. | 213 | Ok(()) |
| 305 | r.tasks_start.write(|w| unsafe { w.bits(1) }); | 214 | } |
| 306 | 215 | ||
| 307 | // Wait for 'end' event. | 216 | pub fn blocking_read(&mut self, data: &mut [u8]) -> Result<(), Error> { |
| 308 | while r.events_end.read().bits() == 0 {} | 217 | self.blocking_inner(data, &[]) |
| 218 | } | ||
| 309 | 219 | ||
| 310 | // Conservative compiler fence to prevent optimizations that do not | 220 | pub fn blocking_transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> { |
| 311 | // take in to account actions by DMA. The fence has been placed here, | 221 | self.blocking_inner(read, write) |
| 312 | // after all possible DMA actions have completed. | 222 | } |
| 313 | compiler_fence(Ordering::SeqCst); | ||
| 314 | 223 | ||
| 315 | Ok(words) | 224 | pub fn blocking_transfer_in_place(&mut self, data: &mut [u8]) -> Result<(), Error> { |
| 225 | self.blocking_inner(data, data) | ||
| 316 | } | 226 | } |
| 317 | } | ||
| 318 | 227 | ||
| 319 | impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u8> for Spim<'d, T> { | 228 | pub fn blocking_write(&mut self, data: &[u8]) -> Result<(), Error> { |
| 320 | type Error = Error; | 229 | self.blocking_inner(&mut [], data) |
| 230 | } | ||
| 321 | 231 | ||
| 322 | fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { | 232 | pub async fn read(&mut self, data: &mut [u8]) -> Result<(), Error> { |
| 323 | slice_in_ram_or(words, Error::DMABufferNotInDataMemory)?; | 233 | self.async_inner(data, &[]).await |
| 324 | let recv: &mut [u8] = &mut []; | 234 | } |
| 325 | 235 | ||
| 326 | // Conservative compiler fence to prevent optimizations that do not | 236 | pub async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> { |
| 327 | // take in to account actions by DMA. The fence has been placed here, | 237 | self.async_inner(read, write).await |
| 328 | // before any DMA action has started. | 238 | } |
| 329 | compiler_fence(Ordering::SeqCst); | ||
| 330 | 239 | ||
| 331 | let r = T::regs(); | 240 | pub async fn transfer_in_place(&mut self, data: &mut [u8]) -> Result<(), Error> { |
| 241 | self.async_inner(data, data).await | ||
| 242 | } | ||
| 332 | 243 | ||
| 333 | // Set up the DMA write. | 244 | pub async fn write(&mut self, data: &[u8]) -> Result<(), Error> { |
| 334 | r.txd | 245 | self.async_inner(&mut [], data).await |
| 335 | .ptr | 246 | } |
| 336 | .write(|w| unsafe { w.ptr().bits(words.as_ptr() as u32) }); | 247 | } |
| 337 | r.txd | ||
| 338 | .maxcnt | ||
| 339 | .write(|w| unsafe { w.maxcnt().bits(words.len() as _) }); | ||
| 340 | 248 | ||
| 341 | // Set up the DMA read. | 249 | impl<'d, T: Instance> Drop for Spim<'d, T> { |
| 342 | r.rxd | 250 | fn drop(&mut self) { |
| 343 | .ptr | 251 | trace!("spim drop"); |
| 344 | .write(|w| unsafe { w.ptr().bits(recv.as_mut_ptr() as u32) }); | ||
| 345 | r.rxd | ||
| 346 | .maxcnt | ||
| 347 | .write(|w| unsafe { w.maxcnt().bits(recv.len() as _) }); | ||
| 348 | |||
| 349 | // Disable the end event since we are busy-polling. | ||
| 350 | r.events_end.reset(); | ||
| 351 | 252 | ||
| 352 | // Start SPI transaction. | 253 | // TODO check for abort, wait for xxxstopped |
| 353 | r.tasks_start.write(|w| unsafe { w.bits(1) }); | ||
| 354 | 254 | ||
| 355 | // Wait for 'end' event. | 255 | // disable! |
| 356 | while r.events_end.read().bits() == 0 {} | 256 | let r = T::regs(); |
| 257 | r.enable.write(|w| w.enable().disabled()); | ||
| 357 | 258 | ||
| 358 | // Conservative compiler fence to prevent optimizations that do not | 259 | gpio::deconfigure_pin(r.psel.sck.read().bits()); |
| 359 | // take in to account actions by DMA. The fence has been placed here, | 260 | gpio::deconfigure_pin(r.psel.miso.read().bits()); |
| 360 | // after all possible DMA actions have completed. | 261 | gpio::deconfigure_pin(r.psel.mosi.read().bits()); |
| 361 | compiler_fence(Ordering::SeqCst); | ||
| 362 | 262 | ||
| 363 | Ok(()) | 263 | trace!("spim drop: done"); |
| 364 | } | 264 | } |
| 365 | } | 265 | } |
| 366 | 266 | ||
| @@ -407,3 +307,209 @@ macro_rules! impl_spim { | |||
| 407 | } | 307 | } |
| 408 | }; | 308 | }; |
| 409 | } | 309 | } |
| 310 | |||
| 311 | // ==================== | ||
| 312 | |||
| 313 | mod eh02 { | ||
| 314 | use super::*; | ||
| 315 | |||
| 316 | impl<'d, T: Instance> embedded_hal_02::blocking::spi::Transfer<u8> for Spim<'d, T> { | ||
| 317 | type Error = Error; | ||
| 318 | fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> { | ||
| 319 | self.blocking_transfer_in_place(words)?; | ||
| 320 | Ok(words) | ||
| 321 | } | ||
| 322 | } | ||
| 323 | |||
| 324 | impl<'d, T: Instance> embedded_hal_02::blocking::spi::Write<u8> for Spim<'d, T> { | ||
| 325 | type Error = Error; | ||
| 326 | |||
| 327 | fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { | ||
| 328 | self.blocking_write(words) | ||
| 329 | } | ||
| 330 | } | ||
| 331 | } | ||
| 332 | |||
| 333 | #[cfg(feature = "unstable-traits")] | ||
| 334 | mod eh1 { | ||
| 335 | use super::*; | ||
| 336 | use core::future::Future; | ||
| 337 | |||
| 338 | impl embedded_hal_1::spi::Error for Error { | ||
| 339 | fn kind(&self) -> embedded_hal_1::spi::ErrorKind { | ||
| 340 | match *self { | ||
| 341 | Self::TxBufferTooLong => embedded_hal_1::spi::ErrorKind::Other, | ||
| 342 | Self::RxBufferTooLong => embedded_hal_1::spi::ErrorKind::Other, | ||
| 343 | Self::DMABufferNotInDataMemory => embedded_hal_1::spi::ErrorKind::Other, | ||
| 344 | } | ||
| 345 | } | ||
| 346 | } | ||
| 347 | |||
| 348 | impl<'d, T: Instance> embedded_hal_1::spi::ErrorType for Spim<'d, T> { | ||
| 349 | type Error = Error; | ||
| 350 | } | ||
| 351 | |||
| 352 | impl<'d, T: Instance> embedded_hal_1::spi::blocking::Read<u8> for Spim<'d, T> { | ||
| 353 | fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { | ||
| 354 | self.blocking_transfer(words, &[]) | ||
| 355 | } | ||
| 356 | |||
| 357 | fn read_transaction(&mut self, words: &mut [&mut [u8]]) -> Result<(), Self::Error> { | ||
| 358 | for buf in words { | ||
| 359 | self.blocking_read(buf)? | ||
| 360 | } | ||
| 361 | Ok(()) | ||
| 362 | } | ||
| 363 | } | ||
| 364 | |||
| 365 | impl<'d, T: Instance> embedded_hal_1::spi::blocking::Write<u8> for Spim<'d, T> { | ||
| 366 | fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { | ||
| 367 | self.blocking_write(words) | ||
| 368 | } | ||
| 369 | |||
| 370 | fn write_transaction(&mut self, words: &[&[u8]]) -> Result<(), Self::Error> { | ||
| 371 | for buf in words { | ||
| 372 | self.blocking_write(buf)? | ||
| 373 | } | ||
| 374 | Ok(()) | ||
| 375 | } | ||
| 376 | |||
| 377 | fn write_iter<WI>(&mut self, words: WI) -> Result<(), Self::Error> | ||
| 378 | where | ||
| 379 | WI: IntoIterator<Item = u8>, | ||
| 380 | { | ||
| 381 | for w in words { | ||
| 382 | self.blocking_write(&[w])?; | ||
| 383 | } | ||
| 384 | Ok(()) | ||
| 385 | } | ||
| 386 | } | ||
| 387 | |||
| 388 | impl<'d, T: Instance> embedded_hal_1::spi::blocking::ReadWrite<u8> for Spim<'d, T> { | ||
| 389 | fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> { | ||
| 390 | self.blocking_transfer(read, write) | ||
| 391 | } | ||
| 392 | |||
| 393 | fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { | ||
| 394 | self.blocking_transfer_in_place(words) | ||
| 395 | } | ||
| 396 | |||
| 397 | fn transaction<'a>( | ||
| 398 | &mut self, | ||
| 399 | operations: &mut [embedded_hal_async::spi::Operation<'a, u8>], | ||
| 400 | ) -> Result<(), Self::Error> { | ||
| 401 | use embedded_hal_1::spi::blocking::Operation; | ||
| 402 | for o in operations { | ||
| 403 | match o { | ||
| 404 | Operation::Read(b) => self.blocking_read(b)?, | ||
| 405 | Operation::Write(b) => self.blocking_write(b)?, | ||
| 406 | Operation::Transfer(r, w) => self.blocking_transfer(r, w)?, | ||
| 407 | Operation::TransferInPlace(b) => self.blocking_transfer_in_place(b)?, | ||
| 408 | } | ||
| 409 | } | ||
| 410 | Ok(()) | ||
| 411 | } | ||
| 412 | } | ||
| 413 | |||
| 414 | impl<'d, T: Instance> embedded_hal_async::spi::Read<u8> for Spim<'d, T> { | ||
| 415 | type ReadFuture<'a> | ||
| 416 | where | ||
| 417 | Self: 'a, | ||
| 418 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 419 | |||
| 420 | fn read<'a>(&'a mut self, words: &'a mut [u8]) -> Self::ReadFuture<'a> { | ||
| 421 | self.read(words) | ||
| 422 | } | ||
| 423 | |||
| 424 | type ReadTransactionFuture<'a> | ||
| 425 | where | ||
| 426 | Self: 'a, | ||
| 427 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 428 | |||
| 429 | fn read_transaction<'a>( | ||
| 430 | &'a mut self, | ||
| 431 | words: &'a mut [&'a mut [u8]], | ||
| 432 | ) -> Self::ReadTransactionFuture<'a> { | ||
| 433 | async move { | ||
| 434 | for buf in words { | ||
| 435 | self.read(buf).await? | ||
| 436 | } | ||
| 437 | Ok(()) | ||
| 438 | } | ||
| 439 | } | ||
| 440 | } | ||
| 441 | |||
| 442 | impl<'d, T: Instance> embedded_hal_async::spi::Write<u8> for Spim<'d, T> { | ||
| 443 | type WriteFuture<'a> | ||
| 444 | where | ||
| 445 | Self: 'a, | ||
| 446 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 447 | |||
| 448 | fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> { | ||
| 449 | self.write(data) | ||
| 450 | } | ||
| 451 | |||
| 452 | type WriteTransactionFuture<'a> | ||
| 453 | where | ||
| 454 | Self: 'a, | ||
| 455 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 456 | |||
| 457 | fn write_transaction<'a>( | ||
| 458 | &'a mut self, | ||
| 459 | words: &'a [&'a [u8]], | ||
| 460 | ) -> Self::WriteTransactionFuture<'a> { | ||
| 461 | async move { | ||
| 462 | for buf in words { | ||
| 463 | self.write(buf).await? | ||
| 464 | } | ||
| 465 | Ok(()) | ||
| 466 | } | ||
| 467 | } | ||
| 468 | } | ||
| 469 | |||
| 470 | impl<'d, T: Instance> embedded_hal_async::spi::ReadWrite<u8> for Spim<'d, T> { | ||
| 471 | type TransferFuture<'a> | ||
| 472 | where | ||
| 473 | Self: 'a, | ||
| 474 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 475 | |||
| 476 | fn transfer<'a>(&'a mut self, rx: &'a mut [u8], tx: &'a [u8]) -> Self::TransferFuture<'a> { | ||
| 477 | self.transfer(rx, tx) | ||
| 478 | } | ||
| 479 | |||
| 480 | type TransferInPlaceFuture<'a> | ||
| 481 | where | ||
| 482 | Self: 'a, | ||
| 483 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 484 | |||
| 485 | fn transfer_in_place<'a>( | ||
| 486 | &'a mut self, | ||
| 487 | words: &'a mut [u8], | ||
| 488 | ) -> Self::TransferInPlaceFuture<'a> { | ||
| 489 | self.transfer_in_place(words) | ||
| 490 | } | ||
| 491 | |||
| 492 | type TransactionFuture<'a> | ||
| 493 | where | ||
| 494 | Self: 'a, | ||
| 495 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 496 | |||
| 497 | fn transaction<'a>( | ||
| 498 | &'a mut self, | ||
| 499 | operations: &'a mut [embedded_hal_async::spi::Operation<'a, u8>], | ||
| 500 | ) -> Self::TransactionFuture<'a> { | ||
| 501 | use embedded_hal_1::spi::blocking::Operation; | ||
| 502 | async move { | ||
| 503 | for o in operations { | ||
| 504 | match o { | ||
| 505 | Operation::Read(b) => self.read(b).await?, | ||
| 506 | Operation::Write(b) => self.write(b).await?, | ||
| 507 | Operation::Transfer(r, w) => self.transfer(r, w).await?, | ||
| 508 | Operation::TransferInPlace(b) => self.transfer_in_place(b).await?, | ||
| 509 | } | ||
| 510 | } | ||
| 511 | Ok(()) | ||
| 512 | } | ||
| 513 | } | ||
| 514 | } | ||
| 515 | } | ||
diff --git a/embassy-nrf/src/twim.rs b/embassy-nrf/src/twim.rs index 3cc79227e..4cd47c897 100644 --- a/embassy-nrf/src/twim.rs +++ b/embassy-nrf/src/twim.rs | |||
| @@ -11,12 +11,10 @@ use core::marker::PhantomData; | |||
| 11 | use core::sync::atomic::{compiler_fence, Ordering::SeqCst}; | 11 | use core::sync::atomic::{compiler_fence, Ordering::SeqCst}; |
| 12 | use core::task::Poll; | 12 | use core::task::Poll; |
| 13 | use embassy::interrupt::{Interrupt, InterruptExt}; | 13 | use embassy::interrupt::{Interrupt, InterruptExt}; |
| 14 | use embassy::traits; | ||
| 15 | use embassy::util::Unborrow; | 14 | use embassy::util::Unborrow; |
| 16 | use embassy::waitqueue::AtomicWaker; | 15 | use embassy::waitqueue::AtomicWaker; |
| 17 | use embassy_hal_common::unborrow; | 16 | use embassy_hal_common::unborrow; |
| 18 | use futures::future::poll_fn; | 17 | use futures::future::poll_fn; |
| 19 | use traits::i2c::I2c; | ||
| 20 | 18 | ||
| 21 | use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; | 19 | use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; |
| 22 | use crate::gpio; | 20 | use crate::gpio; |
| @@ -50,6 +48,22 @@ impl Default for Config { | |||
| 50 | } | 48 | } |
| 51 | } | 49 | } |
| 52 | 50 | ||
| 51 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] | ||
| 52 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 53 | #[non_exhaustive] | ||
| 54 | pub enum Error { | ||
| 55 | TxBufferTooLong, | ||
| 56 | RxBufferTooLong, | ||
| 57 | TxBufferZeroLength, | ||
| 58 | RxBufferZeroLength, | ||
| 59 | Transmit, | ||
| 60 | Receive, | ||
| 61 | DMABufferNotInDataMemory, | ||
| 62 | AddressNack, | ||
| 63 | DataNack, | ||
| 64 | Overrun, | ||
| 65 | } | ||
| 66 | |||
| 53 | /// Interface to a TWIM instance. | 67 | /// Interface to a TWIM instance. |
| 54 | pub struct Twim<'d, T: Instance> { | 68 | pub struct Twim<'d, T: Instance> { |
| 55 | phantom: PhantomData<&'d mut T>, | 69 | phantom: PhantomData<&'d mut T>, |
| @@ -201,7 +215,7 @@ impl<'d, T: Instance> Twim<'d, T> { | |||
| 201 | } | 215 | } |
| 202 | 216 | ||
| 203 | /// Get Error instance, if any occurred. | 217 | /// Get Error instance, if any occurred. |
| 204 | fn read_errorsrc(&self) -> Result<(), Error> { | 218 | fn check_errorsrc(&self) -> Result<(), Error> { |
| 205 | let r = T::regs(); | 219 | let r = T::regs(); |
| 206 | 220 | ||
| 207 | let err = r.errorsrc.read(); | 221 | let err = r.errorsrc.read(); |
| @@ -217,8 +231,26 @@ impl<'d, T: Instance> Twim<'d, T> { | |||
| 217 | Ok(()) | 231 | Ok(()) |
| 218 | } | 232 | } |
| 219 | 233 | ||
| 234 | fn check_rx(&self, len: usize) -> Result<(), Error> { | ||
| 235 | let r = T::regs(); | ||
| 236 | if r.rxd.amount.read().bits() != len as u32 { | ||
| 237 | Err(Error::Receive) | ||
| 238 | } else { | ||
| 239 | Ok(()) | ||
| 240 | } | ||
| 241 | } | ||
| 242 | |||
| 243 | fn check_tx(&self, len: usize) -> Result<(), Error> { | ||
| 244 | let r = T::regs(); | ||
| 245 | if r.txd.amount.read().bits() != len as u32 { | ||
| 246 | Err(Error::Transmit) | ||
| 247 | } else { | ||
| 248 | Ok(()) | ||
| 249 | } | ||
| 250 | } | ||
| 251 | |||
| 220 | /// Wait for stop or error | 252 | /// Wait for stop or error |
| 221 | fn wait(&mut self) { | 253 | fn blocking_wait(&mut self) { |
| 222 | let r = T::regs(); | 254 | let r = T::regs(); |
| 223 | loop { | 255 | loop { |
| 224 | if r.events_stopped.read().bits() != 0 { | 256 | if r.events_stopped.read().bits() != 0 { |
| @@ -232,16 +264,32 @@ impl<'d, T: Instance> Twim<'d, T> { | |||
| 232 | } | 264 | } |
| 233 | } | 265 | } |
| 234 | 266 | ||
| 235 | /// Write to an I2C slave. | 267 | /// Wait for stop or error |
| 236 | /// | 268 | fn async_wait(&mut self) -> impl Future<Output = ()> { |
| 237 | /// The buffer must have a length of at most 255 bytes on the nRF52832 | 269 | poll_fn(move |cx| { |
| 238 | /// and at most 65535 bytes on the nRF52840. | 270 | let r = T::regs(); |
| 239 | pub fn write(&mut self, address: u8, buffer: &[u8]) -> Result<(), Error> { | 271 | let s = T::state(); |
| 272 | |||
| 273 | s.end_waker.register(cx.waker()); | ||
| 274 | if r.events_stopped.read().bits() != 0 { | ||
| 275 | r.events_stopped.reset(); | ||
| 276 | |||
| 277 | return Poll::Ready(()); | ||
| 278 | } | ||
| 279 | |||
| 280 | // stop if an error occured | ||
| 281 | if r.events_error.read().bits() != 0 { | ||
| 282 | r.events_error.reset(); | ||
| 283 | r.tasks_stop.write(|w| unsafe { w.bits(1) }); | ||
| 284 | } | ||
| 285 | |||
| 286 | Poll::Pending | ||
| 287 | }) | ||
| 288 | } | ||
| 289 | |||
| 290 | fn setup_write(&mut self, address: u8, buffer: &[u8], inten: bool) -> Result<(), Error> { | ||
| 240 | let r = T::regs(); | 291 | let r = T::regs(); |
| 241 | 292 | ||
| 242 | // Conservative compiler fence to prevent optimizations that do not | ||
| 243 | // take in to account actions by DMA. The fence has been placed here, | ||
| 244 | // before any DMA action has started. | ||
| 245 | compiler_fence(SeqCst); | 293 | compiler_fence(SeqCst); |
| 246 | 294 | ||
| 247 | r.address.write(|w| unsafe { w.address().bits(address) }); | 295 | r.address.write(|w| unsafe { w.address().bits(address) }); |
| @@ -255,38 +303,21 @@ impl<'d, T: Instance> Twim<'d, T> { | |||
| 255 | r.events_lasttx.reset(); | 303 | r.events_lasttx.reset(); |
| 256 | self.clear_errorsrc(); | 304 | self.clear_errorsrc(); |
| 257 | 305 | ||
| 258 | // Start write operation. | 306 | if inten { |
| 259 | r.shorts.write(|w| w.lasttx_stop().enabled()); | 307 | r.intenset.write(|w| w.stopped().set().error().set()); |
| 260 | r.tasks_starttx.write(|w| | 308 | } else { |
| 261 | // `1` is a valid value to write to task registers. | 309 | r.intenclr.write(|w| w.stopped().clear().error().clear()); |
| 262 | unsafe { w.bits(1) }); | ||
| 263 | |||
| 264 | self.wait(); | ||
| 265 | |||
| 266 | // Conservative compiler fence to prevent optimizations that do not | ||
| 267 | // take in to account actions by DMA. The fence has been placed here, | ||
| 268 | // after all possible DMA actions have completed. | ||
| 269 | compiler_fence(SeqCst); | ||
| 270 | |||
| 271 | self.read_errorsrc()?; | ||
| 272 | |||
| 273 | if r.txd.amount.read().bits() != buffer.len() as u32 { | ||
| 274 | return Err(Error::Transmit); | ||
| 275 | } | 310 | } |
| 276 | 311 | ||
| 312 | // Start write operation. | ||
| 313 | r.shorts.write(|w| w.lasttx_stop().enabled()); | ||
| 314 | r.tasks_starttx.write(|w| unsafe { w.bits(1) }); | ||
| 277 | Ok(()) | 315 | Ok(()) |
| 278 | } | 316 | } |
| 279 | 317 | ||
| 280 | /// Read from an I2C slave. | 318 | fn setup_read(&mut self, address: u8, buffer: &mut [u8], inten: bool) -> Result<(), Error> { |
| 281 | /// | ||
| 282 | /// The buffer must have a length of at most 255 bytes on the nRF52832 | ||
| 283 | /// and at most 65535 bytes on the nRF52840. | ||
| 284 | pub fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> { | ||
| 285 | let r = T::regs(); | 319 | let r = T::regs(); |
| 286 | 320 | ||
| 287 | // Conservative compiler fence to prevent optimizations that do not | ||
| 288 | // take in to account actions by DMA. The fence has been placed here, | ||
| 289 | // before any DMA action has started. | ||
| 290 | compiler_fence(SeqCst); | 321 | compiler_fence(SeqCst); |
| 291 | 322 | ||
| 292 | r.address.write(|w| unsafe { w.address().bits(address) }); | 323 | r.address.write(|w| unsafe { w.address().bits(address) }); |
| @@ -299,44 +330,27 @@ impl<'d, T: Instance> Twim<'d, T> { | |||
| 299 | r.events_error.reset(); | 330 | r.events_error.reset(); |
| 300 | self.clear_errorsrc(); | 331 | self.clear_errorsrc(); |
| 301 | 332 | ||
| 302 | // Start read operation. | 333 | if inten { |
| 303 | r.shorts.write(|w| w.lastrx_stop().enabled()); | 334 | r.intenset.write(|w| w.stopped().set().error().set()); |
| 304 | r.tasks_startrx.write(|w| | 335 | } else { |
| 305 | // `1` is a valid value to write to task registers. | 336 | r.intenclr.write(|w| w.stopped().clear().error().clear()); |
| 306 | unsafe { w.bits(1) }); | ||
| 307 | |||
| 308 | self.wait(); | ||
| 309 | |||
| 310 | // Conservative compiler fence to prevent optimizations that do not | ||
| 311 | // take in to account actions by DMA. The fence has been placed here, | ||
| 312 | // after all possible DMA actions have completed. | ||
| 313 | compiler_fence(SeqCst); | ||
| 314 | |||
| 315 | self.read_errorsrc()?; | ||
| 316 | |||
| 317 | if r.rxd.amount.read().bits() != buffer.len() as u32 { | ||
| 318 | return Err(Error::Receive); | ||
| 319 | } | 337 | } |
| 320 | 338 | ||
| 339 | // Start read operation. | ||
| 340 | r.shorts.write(|w| w.lastrx_stop().enabled()); | ||
| 341 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); | ||
| 321 | Ok(()) | 342 | Ok(()) |
| 322 | } | 343 | } |
| 323 | 344 | ||
| 324 | /// Write data to an I2C slave, then read data from the slave without | 345 | fn setup_write_read( |
| 325 | /// triggering a stop condition between the two. | ||
| 326 | /// | ||
| 327 | /// The buffers must have a length of at most 255 bytes on the nRF52832 | ||
| 328 | /// and at most 65535 bytes on the nRF52840. | ||
| 329 | pub fn write_then_read( | ||
| 330 | &mut self, | 346 | &mut self, |
| 331 | address: u8, | 347 | address: u8, |
| 332 | wr_buffer: &[u8], | 348 | wr_buffer: &[u8], |
| 333 | rd_buffer: &mut [u8], | 349 | rd_buffer: &mut [u8], |
| 350 | inten: bool, | ||
| 334 | ) -> Result<(), Error> { | 351 | ) -> Result<(), Error> { |
| 335 | let r = T::regs(); | 352 | let r = T::regs(); |
| 336 | 353 | ||
| 337 | // Conservative compiler fence to prevent optimizations that do not | ||
| 338 | // take in to account actions by DMA. The fence has been placed here, | ||
| 339 | // before any DMA action has started. | ||
| 340 | compiler_fence(SeqCst); | 354 | compiler_fence(SeqCst); |
| 341 | 355 | ||
| 342 | r.address.write(|w| unsafe { w.address().bits(address) }); | 356 | r.address.write(|w| unsafe { w.address().bits(address) }); |
| @@ -352,35 +366,65 @@ impl<'d, T: Instance> Twim<'d, T> { | |||
| 352 | r.events_error.reset(); | 366 | r.events_error.reset(); |
| 353 | self.clear_errorsrc(); | 367 | self.clear_errorsrc(); |
| 354 | 368 | ||
| 369 | if inten { | ||
| 370 | r.intenset.write(|w| w.stopped().set().error().set()); | ||
| 371 | } else { | ||
| 372 | r.intenclr.write(|w| w.stopped().clear().error().clear()); | ||
| 373 | } | ||
| 374 | |||
| 355 | // Start write+read operation. | 375 | // Start write+read operation. |
| 356 | r.shorts.write(|w| { | 376 | r.shorts.write(|w| { |
| 357 | w.lasttx_startrx().enabled(); | 377 | w.lasttx_startrx().enabled(); |
| 358 | w.lastrx_stop().enabled(); | 378 | w.lastrx_stop().enabled(); |
| 359 | w | 379 | w |
| 360 | }); | 380 | }); |
| 361 | // `1` is a valid value to write to task registers. | ||
| 362 | r.tasks_starttx.write(|w| unsafe { w.bits(1) }); | 381 | r.tasks_starttx.write(|w| unsafe { w.bits(1) }); |
| 382 | Ok(()) | ||
| 383 | } | ||
| 363 | 384 | ||
| 364 | self.wait(); | 385 | /// Write to an I2C slave. |
| 365 | 386 | /// | |
| 366 | // Conservative compiler fence to prevent optimizations that do not | 387 | /// The buffer must have a length of at most 255 bytes on the nRF52832 |
| 367 | // take in to account actions by DMA. The fence has been placed here, | 388 | /// and at most 65535 bytes on the nRF52840. |
| 368 | // after all possible DMA actions have completed. | 389 | pub fn blocking_write(&mut self, address: u8, buffer: &[u8]) -> Result<(), Error> { |
| 390 | self.setup_write(address, buffer, false)?; | ||
| 391 | self.blocking_wait(); | ||
| 369 | compiler_fence(SeqCst); | 392 | compiler_fence(SeqCst); |
| 393 | self.check_errorsrc()?; | ||
| 394 | self.check_tx(buffer.len())?; | ||
| 395 | Ok(()) | ||
| 396 | } | ||
| 370 | 397 | ||
| 371 | self.read_errorsrc()?; | 398 | /// Read from an I2C slave. |
| 372 | 399 | /// | |
| 373 | let bad_write = r.txd.amount.read().bits() != wr_buffer.len() as u32; | 400 | /// The buffer must have a length of at most 255 bytes on the nRF52832 |
| 374 | let bad_read = r.rxd.amount.read().bits() != rd_buffer.len() as u32; | 401 | /// and at most 65535 bytes on the nRF52840. |
| 375 | 402 | pub fn blocking_read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> { | |
| 376 | if bad_write { | 403 | self.setup_read(address, buffer, false)?; |
| 377 | return Err(Error::Transmit); | 404 | self.blocking_wait(); |
| 378 | } | 405 | compiler_fence(SeqCst); |
| 379 | 406 | self.check_errorsrc()?; | |
| 380 | if bad_read { | 407 | self.check_rx(buffer.len())?; |
| 381 | return Err(Error::Receive); | 408 | Ok(()) |
| 382 | } | 409 | } |
| 383 | 410 | ||
| 411 | /// Write data to an I2C slave, then read data from the slave without | ||
| 412 | /// triggering a stop condition between the two. | ||
| 413 | /// | ||
| 414 | /// The buffers must have a length of at most 255 bytes on the nRF52832 | ||
| 415 | /// and at most 65535 bytes on the nRF52840. | ||
| 416 | pub fn blocking_write_read( | ||
| 417 | &mut self, | ||
| 418 | address: u8, | ||
| 419 | wr_buffer: &[u8], | ||
| 420 | rd_buffer: &mut [u8], | ||
| 421 | ) -> Result<(), Error> { | ||
| 422 | self.setup_write_read(address, wr_buffer, rd_buffer, false)?; | ||
| 423 | self.blocking_wait(); | ||
| 424 | compiler_fence(SeqCst); | ||
| 425 | self.check_errorsrc()?; | ||
| 426 | self.check_tx(wr_buffer.len())?; | ||
| 427 | self.check_rx(rd_buffer.len())?; | ||
| 384 | Ok(()) | 428 | Ok(()) |
| 385 | } | 429 | } |
| 386 | 430 | ||
| @@ -388,7 +432,7 @@ impl<'d, T: Instance> Twim<'d, T> { | |||
| 388 | /// | 432 | /// |
| 389 | /// The write buffer must have a length of at most 255 bytes on the nRF52832 | 433 | /// The write buffer must have a length of at most 255 bytes on the nRF52832 |
| 390 | /// and at most 1024 bytes on the nRF52840. | 434 | /// and at most 1024 bytes on the nRF52840. |
| 391 | pub fn copy_write(&mut self, address: u8, wr_buffer: &[u8]) -> Result<(), Error> { | 435 | pub fn blocking_copy_write(&mut self, address: u8, wr_buffer: &[u8]) -> Result<(), Error> { |
| 392 | if wr_buffer.len() > FORCE_COPY_BUFFER_SIZE { | 436 | if wr_buffer.len() > FORCE_COPY_BUFFER_SIZE { |
| 393 | return Err(Error::TxBufferTooLong); | 437 | return Err(Error::TxBufferTooLong); |
| 394 | } | 438 | } |
| @@ -397,7 +441,7 @@ impl<'d, T: Instance> Twim<'d, T> { | |||
| 397 | let wr_ram_buffer = &mut [0; FORCE_COPY_BUFFER_SIZE][..wr_buffer.len()]; | 441 | let wr_ram_buffer = &mut [0; FORCE_COPY_BUFFER_SIZE][..wr_buffer.len()]; |
| 398 | wr_ram_buffer.copy_from_slice(wr_buffer); | 442 | wr_ram_buffer.copy_from_slice(wr_buffer); |
| 399 | 443 | ||
| 400 | self.write(address, wr_ram_buffer) | 444 | self.blocking_write(address, wr_ram_buffer) |
| 401 | } | 445 | } |
| 402 | 446 | ||
| 403 | /// Copy data into RAM and write to an I2C slave, then read data from the slave without | 447 | /// Copy data into RAM and write to an I2C slave, then read data from the slave without |
| @@ -408,7 +452,7 @@ impl<'d, T: Instance> Twim<'d, T> { | |||
| 408 | /// | 452 | /// |
| 409 | /// The read buffer must have a length of at most 255 bytes on the nRF52832 | 453 | /// The read buffer must have a length of at most 255 bytes on the nRF52832 |
| 410 | /// and at most 65535 bytes on the nRF52840. | 454 | /// and at most 65535 bytes on the nRF52840. |
| 411 | pub fn copy_write_then_read( | 455 | pub fn blocking_copy_write_read( |
| 412 | &mut self, | 456 | &mut self, |
| 413 | address: u8, | 457 | address: u8, |
| 414 | wr_buffer: &[u8], | 458 | wr_buffer: &[u8], |
| @@ -422,27 +466,40 @@ impl<'d, T: Instance> Twim<'d, T> { | |||
| 422 | let wr_ram_buffer = &mut [0; FORCE_COPY_BUFFER_SIZE][..wr_buffer.len()]; | 466 | let wr_ram_buffer = &mut [0; FORCE_COPY_BUFFER_SIZE][..wr_buffer.len()]; |
| 423 | wr_ram_buffer.copy_from_slice(wr_buffer); | 467 | wr_ram_buffer.copy_from_slice(wr_buffer); |
| 424 | 468 | ||
| 425 | self.write_then_read(address, wr_ram_buffer, rd_buffer) | 469 | self.blocking_write_read(address, wr_ram_buffer, rd_buffer) |
| 426 | } | 470 | } |
| 427 | 471 | ||
| 428 | fn wait_for_stopped_event(cx: &mut core::task::Context) -> Poll<()> { | 472 | pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> { |
| 429 | let r = T::regs(); | 473 | self.setup_read(address, buffer, true)?; |
| 430 | let s = T::state(); | 474 | self.async_wait().await; |
| 431 | 475 | compiler_fence(SeqCst); | |
| 432 | s.end_waker.register(cx.waker()); | 476 | self.check_errorsrc()?; |
| 433 | if r.events_stopped.read().bits() != 0 { | 477 | self.check_rx(buffer.len())?; |
| 434 | r.events_stopped.reset(); | 478 | Ok(()) |
| 435 | 479 | } | |
| 436 | return Poll::Ready(()); | ||
| 437 | } | ||
| 438 | 480 | ||
| 439 | // stop if an error occured | 481 | pub async fn write(&mut self, address: u8, buffer: &[u8]) -> Result<(), Error> { |
| 440 | if r.events_error.read().bits() != 0 { | 482 | self.setup_write(address, buffer, true)?; |
| 441 | r.events_error.reset(); | 483 | self.async_wait().await; |
| 442 | r.tasks_stop.write(|w| unsafe { w.bits(1) }); | 484 | compiler_fence(SeqCst); |
| 443 | } | 485 | self.check_errorsrc()?; |
| 486 | self.check_tx(buffer.len())?; | ||
| 487 | Ok(()) | ||
| 488 | } | ||
| 444 | 489 | ||
| 445 | Poll::Pending | 490 | pub async fn write_read( |
| 491 | &mut self, | ||
| 492 | address: u8, | ||
| 493 | wr_buffer: &[u8], | ||
| 494 | rd_buffer: &mut [u8], | ||
| 495 | ) -> Result<(), Error> { | ||
| 496 | self.setup_write_read(address, wr_buffer, rd_buffer, true)?; | ||
| 497 | self.async_wait().await; | ||
| 498 | compiler_fence(SeqCst); | ||
| 499 | self.check_errorsrc()?; | ||
| 500 | self.check_tx(wr_buffer.len())?; | ||
| 501 | self.check_rx(rd_buffer.len())?; | ||
| 502 | Ok(()) | ||
| 446 | } | 503 | } |
| 447 | } | 504 | } |
| 448 | 505 | ||
| @@ -450,7 +507,7 @@ impl<'a, T: Instance> Drop for Twim<'a, T> { | |||
| 450 | fn drop(&mut self) { | 507 | fn drop(&mut self) { |
| 451 | trace!("twim drop"); | 508 | trace!("twim drop"); |
| 452 | 509 | ||
| 453 | // TODO when implementing async here, check for abort | 510 | // TODO: check for abort |
| 454 | 511 | ||
| 455 | // disable! | 512 | // disable! |
| 456 | let r = T::regs(); | 513 | let r = T::regs(); |
| @@ -463,292 +520,228 @@ impl<'a, T: Instance> Drop for Twim<'a, T> { | |||
| 463 | } | 520 | } |
| 464 | } | 521 | } |
| 465 | 522 | ||
| 466 | impl<'d, T> I2c for Twim<'d, T> | 523 | pub(crate) mod sealed { |
| 467 | where | 524 | use super::*; |
| 468 | T: Instance, | ||
| 469 | { | ||
| 470 | type Error = Error; | ||
| 471 | |||
| 472 | type WriteFuture<'a> | ||
| 473 | where | ||
| 474 | Self: 'a, | ||
| 475 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 476 | type ReadFuture<'a> | ||
| 477 | where | ||
| 478 | Self: 'a, | ||
| 479 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 480 | type WriteReadFuture<'a> | ||
| 481 | where | ||
| 482 | Self: 'a, | ||
| 483 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 484 | |||
| 485 | fn read<'a>(&'a mut self, address: u8, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { | ||
| 486 | async move { | ||
| 487 | // NOTE: RAM slice check for buffer is not necessary, as a mutable | ||
| 488 | // slice can only be built from data located in RAM. | ||
| 489 | |||
| 490 | let r = T::regs(); | ||
| 491 | |||
| 492 | // Conservative compiler fence to prevent optimizations that do not | ||
| 493 | // take in to account actions by DMA. The fence has been placed here, | ||
| 494 | // before any DMA action has started. | ||
| 495 | compiler_fence(SeqCst); | ||
| 496 | |||
| 497 | r.address.write(|w| unsafe { w.address().bits(address) }); | ||
| 498 | |||
| 499 | // Set up the DMA read. | ||
| 500 | unsafe { self.set_rx_buffer(buffer)? }; | ||
| 501 | |||
| 502 | // Reset events | ||
| 503 | r.events_stopped.reset(); | ||
| 504 | r.events_error.reset(); | ||
| 505 | self.clear_errorsrc(); | ||
| 506 | |||
| 507 | // Enable events | ||
| 508 | r.intenset.write(|w| w.stopped().set().error().set()); | ||
| 509 | |||
| 510 | // Start read operation. | ||
| 511 | r.shorts.write(|w| w.lastrx_stop().enabled()); | ||
| 512 | r.tasks_startrx.write(|w| | ||
| 513 | // `1` is a valid value to write to task registers. | ||
| 514 | unsafe { w.bits(1) }); | ||
| 515 | |||
| 516 | // Conservative compiler fence to prevent optimizations that do not | ||
| 517 | // take in to account actions by DMA. The fence has been placed here, | ||
| 518 | // after all possible DMA actions have completed. | ||
| 519 | compiler_fence(SeqCst); | ||
| 520 | |||
| 521 | // Wait for 'stopped' event. | ||
| 522 | poll_fn(Self::wait_for_stopped_event).await; | ||
| 523 | 525 | ||
| 524 | self.read_errorsrc()?; | 526 | pub struct State { |
| 527 | pub end_waker: AtomicWaker, | ||
| 528 | } | ||
| 525 | 529 | ||
| 526 | if r.rxd.amount.read().bits() != buffer.len() as u32 { | 530 | impl State { |
| 527 | return Err(Error::Receive); | 531 | pub const fn new() -> Self { |
| 532 | Self { | ||
| 533 | end_waker: AtomicWaker::new(), | ||
| 528 | } | 534 | } |
| 529 | |||
| 530 | Ok(()) | ||
| 531 | } | 535 | } |
| 532 | } | 536 | } |
| 533 | 537 | ||
| 534 | fn write<'a>(&'a mut self, address: u8, bytes: &'a [u8]) -> Self::WriteFuture<'a> { | 538 | pub trait Instance { |
| 535 | async move { | 539 | fn regs() -> &'static pac::twim0::RegisterBlock; |
| 536 | slice_in_ram_or(bytes, Error::DMABufferNotInDataMemory)?; | 540 | fn state() -> &'static State; |
| 537 | 541 | } | |
| 538 | // Conservative compiler fence to prevent optimizations that do not | 542 | } |
| 539 | // take in to account actions by DMA. The fence has been placed here, | ||
| 540 | // before any DMA action has started. | ||
| 541 | compiler_fence(SeqCst); | ||
| 542 | |||
| 543 | let r = T::regs(); | ||
| 544 | 543 | ||
| 545 | // Set up current address we're trying to talk to | 544 | pub trait Instance: Unborrow<Target = Self> + sealed::Instance + 'static { |
| 546 | r.address.write(|w| unsafe { w.address().bits(address) }); | 545 | type Interrupt: Interrupt; |
| 546 | } | ||
| 547 | 547 | ||
| 548 | // Set up DMA write. | 548 | macro_rules! impl_twim { |
| 549 | unsafe { | 549 | ($type:ident, $pac_type:ident, $irq:ident) => { |
| 550 | self.set_tx_buffer(bytes)?; | 550 | impl crate::twim::sealed::Instance for peripherals::$type { |
| 551 | fn regs() -> &'static pac::twim0::RegisterBlock { | ||
| 552 | unsafe { &*pac::$pac_type::ptr() } | ||
| 551 | } | 553 | } |
| 552 | 554 | fn state() -> &'static crate::twim::sealed::State { | |
| 553 | // Reset events | 555 | static STATE: crate::twim::sealed::State = crate::twim::sealed::State::new(); |
| 554 | r.events_stopped.reset(); | 556 | &STATE |
| 555 | r.events_error.reset(); | ||
| 556 | r.events_lasttx.reset(); | ||
| 557 | self.clear_errorsrc(); | ||
| 558 | |||
| 559 | // Enable events | ||
| 560 | r.intenset.write(|w| w.stopped().set().error().set()); | ||
| 561 | |||
| 562 | // Start write operation. | ||
| 563 | r.shorts.write(|w| w.lasttx_stop().enabled()); | ||
| 564 | r.tasks_starttx.write(|w| | ||
| 565 | // `1` is a valid value to write to task registers. | ||
| 566 | unsafe { w.bits(1) }); | ||
| 567 | |||
| 568 | // Conservative compiler fence to prevent optimizations that do not | ||
| 569 | // take in to account actions by DMA. The fence has been placed here, | ||
| 570 | // after all possible DMA actions have completed. | ||
| 571 | compiler_fence(SeqCst); | ||
| 572 | |||
| 573 | // Wait for 'stopped' event. | ||
| 574 | poll_fn(Self::wait_for_stopped_event).await; | ||
| 575 | |||
| 576 | self.read_errorsrc()?; | ||
| 577 | |||
| 578 | if r.txd.amount.read().bits() != bytes.len() as u32 { | ||
| 579 | return Err(Error::Transmit); | ||
| 580 | } | 557 | } |
| 581 | |||
| 582 | Ok(()) | ||
| 583 | } | 558 | } |
| 584 | } | 559 | impl crate::twim::Instance for peripherals::$type { |
| 585 | 560 | type Interrupt = crate::interrupt::$irq; | |
| 586 | fn write_read<'a>( | 561 | } |
| 587 | &'a mut self, | 562 | }; |
| 588 | address: u8, | 563 | } |
| 589 | bytes: &'a [u8], | ||
| 590 | buffer: &'a mut [u8], | ||
| 591 | ) -> Self::WriteReadFuture<'a> { | ||
| 592 | async move { | ||
| 593 | slice_in_ram_or(bytes, Error::DMABufferNotInDataMemory)?; | ||
| 594 | // NOTE: RAM slice check for buffer is not necessary, as a mutable | ||
| 595 | // slice can only be built from data located in RAM. | ||
| 596 | |||
| 597 | // Conservative compiler fence to prevent optimizations that do not | ||
| 598 | // take in to account actions by DMA. The fence has been placed here, | ||
| 599 | // before any DMA action has started. | ||
| 600 | compiler_fence(SeqCst); | ||
| 601 | 564 | ||
| 602 | let r = T::regs(); | 565 | // ==================== |
| 603 | 566 | ||
| 604 | // Set up current address we're trying to talk to | 567 | mod eh02 { |
| 605 | r.address.write(|w| unsafe { w.address().bits(address) }); | 568 | use super::*; |
| 606 | 569 | ||
| 607 | // Set up DMA buffers. | 570 | impl<'a, T: Instance> embedded_hal_02::blocking::i2c::Write for Twim<'a, T> { |
| 608 | unsafe { | 571 | type Error = Error; |
| 609 | self.set_tx_buffer(bytes)?; | 572 | |
| 610 | self.set_rx_buffer(buffer)?; | 573 | fn write<'w>(&mut self, addr: u8, bytes: &'w [u8]) -> Result<(), Error> { |
| 574 | if slice_in_ram(bytes) { | ||
| 575 | self.blocking_write(addr, bytes) | ||
| 576 | } else { | ||
| 577 | let buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..]; | ||
| 578 | for chunk in bytes.chunks(FORCE_COPY_BUFFER_SIZE) { | ||
| 579 | buf[..chunk.len()].copy_from_slice(chunk); | ||
| 580 | self.blocking_write(addr, &buf[..chunk.len()])?; | ||
| 581 | } | ||
| 582 | Ok(()) | ||
| 611 | } | 583 | } |
| 584 | } | ||
| 585 | } | ||
| 612 | 586 | ||
| 613 | // Reset events | 587 | impl<'a, T: Instance> embedded_hal_02::blocking::i2c::Read for Twim<'a, T> { |
| 614 | r.events_stopped.reset(); | 588 | type Error = Error; |
| 615 | r.events_error.reset(); | ||
| 616 | r.events_lasttx.reset(); | ||
| 617 | self.clear_errorsrc(); | ||
| 618 | |||
| 619 | // Enable events | ||
| 620 | r.intenset.write(|w| w.stopped().set().error().set()); | ||
| 621 | |||
| 622 | // Start write+read operation. | ||
| 623 | r.shorts.write(|w| { | ||
| 624 | w.lasttx_startrx().enabled(); | ||
| 625 | w.lastrx_stop().enabled(); | ||
| 626 | w | ||
| 627 | }); | ||
| 628 | // `1` is a valid value to write to task registers. | ||
| 629 | r.tasks_starttx.write(|w| unsafe { w.bits(1) }); | ||
| 630 | |||
| 631 | // Conservative compiler fence to prevent optimizations that do not | ||
| 632 | // take in to account actions by DMA. The fence has been placed here, | ||
| 633 | // after all possible DMA actions have completed. | ||
| 634 | compiler_fence(SeqCst); | ||
| 635 | |||
| 636 | // Wait for 'stopped' event. | ||
| 637 | poll_fn(Self::wait_for_stopped_event).await; | ||
| 638 | |||
| 639 | self.read_errorsrc()?; | ||
| 640 | |||
| 641 | let bad_write = r.txd.amount.read().bits() != bytes.len() as u32; | ||
| 642 | let bad_read = r.rxd.amount.read().bits() != buffer.len() as u32; | ||
| 643 | 589 | ||
| 644 | if bad_write { | 590 | fn read<'w>(&mut self, addr: u8, bytes: &'w mut [u8]) -> Result<(), Error> { |
| 645 | return Err(Error::Transmit); | 591 | self.blocking_read(addr, bytes) |
| 646 | } | 592 | } |
| 593 | } | ||
| 647 | 594 | ||
| 648 | if bad_read { | 595 | impl<'a, T: Instance> embedded_hal_02::blocking::i2c::WriteRead for Twim<'a, T> { |
| 649 | return Err(Error::Receive); | 596 | type Error = Error; |
| 597 | |||
| 598 | fn write_read<'w>( | ||
| 599 | &mut self, | ||
| 600 | addr: u8, | ||
| 601 | bytes: &'w [u8], | ||
| 602 | buffer: &'w mut [u8], | ||
| 603 | ) -> Result<(), Error> { | ||
| 604 | if slice_in_ram(bytes) { | ||
| 605 | self.blocking_write_read(addr, bytes, buffer) | ||
| 606 | } else { | ||
| 607 | self.blocking_copy_write_read(addr, bytes, buffer) | ||
| 650 | } | 608 | } |
| 651 | |||
| 652 | Ok(()) | ||
| 653 | } | 609 | } |
| 654 | } | 610 | } |
| 655 | } | 611 | } |
| 656 | 612 | ||
| 657 | impl<'a, T: Instance> embedded_hal::blocking::i2c::Write for Twim<'a, T> { | 613 | #[cfg(feature = "unstable-traits")] |
| 658 | type Error = Error; | 614 | mod eh1 { |
| 615 | use super::*; | ||
| 659 | 616 | ||
| 660 | fn write<'w>(&mut self, addr: u8, bytes: &'w [u8]) -> Result<(), Error> { | 617 | impl embedded_hal_1::i2c::Error for Error { |
| 661 | if slice_in_ram(bytes) { | 618 | fn kind(&self) -> embedded_hal_1::i2c::ErrorKind { |
| 662 | self.write(addr, bytes) | 619 | match *self { |
| 663 | } else { | 620 | Self::TxBufferTooLong => embedded_hal_1::i2c::ErrorKind::Other, |
| 664 | let buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..]; | 621 | Self::RxBufferTooLong => embedded_hal_1::i2c::ErrorKind::Other, |
| 665 | for chunk in bytes.chunks(FORCE_COPY_BUFFER_SIZE) { | 622 | Self::TxBufferZeroLength => embedded_hal_1::i2c::ErrorKind::Other, |
| 666 | buf[..chunk.len()].copy_from_slice(chunk); | 623 | Self::RxBufferZeroLength => embedded_hal_1::i2c::ErrorKind::Other, |
| 667 | self.write(addr, &buf[..chunk.len()])?; | 624 | Self::Transmit => embedded_hal_1::i2c::ErrorKind::Other, |
| 625 | Self::Receive => embedded_hal_1::i2c::ErrorKind::Other, | ||
| 626 | Self::DMABufferNotInDataMemory => embedded_hal_1::i2c::ErrorKind::Other, | ||
| 627 | Self::AddressNack => embedded_hal_1::i2c::ErrorKind::NoAcknowledge( | ||
| 628 | embedded_hal_1::i2c::NoAcknowledgeSource::Address, | ||
| 629 | ), | ||
| 630 | Self::DataNack => embedded_hal_1::i2c::ErrorKind::NoAcknowledge( | ||
| 631 | embedded_hal_1::i2c::NoAcknowledgeSource::Data, | ||
| 632 | ), | ||
| 633 | Self::Overrun => embedded_hal_1::i2c::ErrorKind::Overrun, | ||
| 668 | } | 634 | } |
| 669 | Ok(()) | ||
| 670 | } | 635 | } |
| 671 | } | 636 | } |
| 672 | } | ||
| 673 | 637 | ||
| 674 | impl<'a, T: Instance> embedded_hal::blocking::i2c::Read for Twim<'a, T> { | 638 | impl<'d, T: Instance> embedded_hal_1::i2c::ErrorType for Twim<'d, T> { |
| 675 | type Error = Error; | 639 | type Error = Error; |
| 676 | |||
| 677 | fn read<'w>(&mut self, addr: u8, bytes: &'w mut [u8]) -> Result<(), Error> { | ||
| 678 | self.read(addr, bytes) | ||
| 679 | } | 640 | } |
| 680 | } | ||
| 681 | 641 | ||
| 682 | impl<'a, T: Instance> embedded_hal::blocking::i2c::WriteRead for Twim<'a, T> { | 642 | impl<'d, T: Instance> embedded_hal_1::i2c::blocking::I2c for Twim<'d, T> { |
| 683 | type Error = Error; | 643 | fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { |
| 644 | self.blocking_read(address, buffer) | ||
| 645 | } | ||
| 684 | 646 | ||
| 685 | fn write_read<'w>( | 647 | fn write(&mut self, address: u8, buffer: &[u8]) -> Result<(), Self::Error> { |
| 686 | &mut self, | 648 | self.blocking_write(address, buffer) |
| 687 | addr: u8, | ||
| 688 | bytes: &'w [u8], | ||
| 689 | buffer: &'w mut [u8], | ||
| 690 | ) -> Result<(), Error> { | ||
| 691 | if slice_in_ram(bytes) { | ||
| 692 | self.write_then_read(addr, bytes, buffer) | ||
| 693 | } else { | ||
| 694 | self.copy_write_then_read(addr, bytes, buffer) | ||
| 695 | } | 649 | } |
| 696 | } | ||
| 697 | } | ||
| 698 | 650 | ||
| 699 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] | 651 | fn write_iter<B>(&mut self, _address: u8, _bytes: B) -> Result<(), Self::Error> |
| 700 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 652 | where |
| 701 | pub enum Error { | 653 | B: IntoIterator<Item = u8>, |
| 702 | TxBufferTooLong, | 654 | { |
| 703 | RxBufferTooLong, | 655 | todo!(); |
| 704 | TxBufferZeroLength, | 656 | } |
| 705 | RxBufferZeroLength, | ||
| 706 | Transmit, | ||
| 707 | Receive, | ||
| 708 | DMABufferNotInDataMemory, | ||
| 709 | AddressNack, | ||
| 710 | DataNack, | ||
| 711 | Overrun, | ||
| 712 | } | ||
| 713 | 657 | ||
| 714 | pub(crate) mod sealed { | 658 | fn write_iter_read<B>( |
| 715 | use super::*; | 659 | &mut self, |
| 660 | _address: u8, | ||
| 661 | _bytes: B, | ||
| 662 | _buffer: &mut [u8], | ||
| 663 | ) -> Result<(), Self::Error> | ||
| 664 | where | ||
| 665 | B: IntoIterator<Item = u8>, | ||
| 666 | { | ||
| 667 | todo!(); | ||
| 668 | } | ||
| 716 | 669 | ||
| 717 | pub struct State { | 670 | fn write_read( |
| 718 | pub end_waker: AtomicWaker, | 671 | &mut self, |
| 719 | } | 672 | address: u8, |
| 673 | wr_buffer: &[u8], | ||
| 674 | rd_buffer: &mut [u8], | ||
| 675 | ) -> Result<(), Self::Error> { | ||
| 676 | self.blocking_write_read(address, wr_buffer, rd_buffer) | ||
| 677 | } | ||
| 720 | 678 | ||
| 721 | impl State { | 679 | fn transaction<'a>( |
| 722 | pub const fn new() -> Self { | 680 | &mut self, |
| 723 | Self { | 681 | _address: u8, |
| 724 | end_waker: AtomicWaker::new(), | 682 | _operations: &mut [embedded_hal_async::i2c::Operation<'a>], |
| 725 | } | 683 | ) -> Result<(), Self::Error> { |
| 684 | todo!(); | ||
| 726 | } | 685 | } |
| 727 | } | ||
| 728 | 686 | ||
| 729 | pub trait Instance { | 687 | fn transaction_iter<'a, O>( |
| 730 | fn regs() -> &'static pac::twim0::RegisterBlock; | 688 | &mut self, |
| 731 | fn state() -> &'static State; | 689 | _address: u8, |
| 690 | _operations: O, | ||
| 691 | ) -> Result<(), Self::Error> | ||
| 692 | where | ||
| 693 | O: IntoIterator<Item = embedded_hal_async::i2c::Operation<'a>>, | ||
| 694 | { | ||
| 695 | todo!(); | ||
| 696 | } | ||
| 732 | } | 697 | } |
| 733 | } | ||
| 734 | 698 | ||
| 735 | pub trait Instance: Unborrow<Target = Self> + sealed::Instance + 'static { | 699 | impl<'d, T: Instance> embedded_hal_async::i2c::I2c for Twim<'d, T> { |
| 736 | type Interrupt: Interrupt; | 700 | type ReadFuture<'a> |
| 737 | } | 701 | where |
| 702 | Self: 'a, | ||
| 703 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 738 | 704 | ||
| 739 | macro_rules! impl_twim { | 705 | fn read<'a>(&'a mut self, address: u8, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { |
| 740 | ($type:ident, $pac_type:ident, $irq:ident) => { | 706 | self.read(address, buffer) |
| 741 | impl crate::twim::sealed::Instance for peripherals::$type { | ||
| 742 | fn regs() -> &'static pac::twim0::RegisterBlock { | ||
| 743 | unsafe { &*pac::$pac_type::ptr() } | ||
| 744 | } | ||
| 745 | fn state() -> &'static crate::twim::sealed::State { | ||
| 746 | static STATE: crate::twim::sealed::State = crate::twim::sealed::State::new(); | ||
| 747 | &STATE | ||
| 748 | } | ||
| 749 | } | 707 | } |
| 750 | impl crate::twim::Instance for peripherals::$type { | 708 | |
| 751 | type Interrupt = crate::interrupt::$irq; | 709 | type WriteFuture<'a> |
| 710 | where | ||
| 711 | Self: 'a, | ||
| 712 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 713 | |||
| 714 | fn write<'a>(&'a mut self, address: u8, bytes: &'a [u8]) -> Self::WriteFuture<'a> { | ||
| 715 | self.write(address, bytes) | ||
| 752 | } | 716 | } |
| 753 | }; | 717 | |
| 718 | type WriteReadFuture<'a> | ||
| 719 | where | ||
| 720 | Self: 'a, | ||
| 721 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 722 | |||
| 723 | fn write_read<'a>( | ||
| 724 | &'a mut self, | ||
| 725 | address: u8, | ||
| 726 | wr_buffer: &'a [u8], | ||
| 727 | rd_buffer: &'a mut [u8], | ||
| 728 | ) -> Self::WriteReadFuture<'a> { | ||
| 729 | self.write_read(address, wr_buffer, rd_buffer) | ||
| 730 | } | ||
| 731 | |||
| 732 | type TransactionFuture<'a> | ||
| 733 | where | ||
| 734 | Self: 'a, | ||
| 735 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 736 | |||
| 737 | fn transaction<'a>( | ||
| 738 | &'a mut self, | ||
| 739 | address: u8, | ||
| 740 | operations: &mut [embedded_hal_async::i2c::Operation<'a>], | ||
| 741 | ) -> Self::TransactionFuture<'a> { | ||
| 742 | let _ = address; | ||
| 743 | let _ = operations; | ||
| 744 | async move { todo!() } | ||
| 745 | } | ||
| 746 | } | ||
| 754 | } | 747 | } |
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs index 38480ecca..b10e55a05 100644 --- a/embassy-nrf/src/uarte.rs +++ b/embassy-nrf/src/uarte.rs | |||
| @@ -13,12 +13,10 @@ | |||
| 13 | //! memory may be used given that buffers are passed in directly to its read and write | 13 | //! memory may be used given that buffers are passed in directly to its read and write |
| 14 | //! methods. | 14 | //! methods. |
| 15 | 15 | ||
| 16 | use core::future::Future; | ||
| 17 | use core::marker::PhantomData; | 16 | use core::marker::PhantomData; |
| 18 | use core::sync::atomic::{compiler_fence, Ordering}; | 17 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 19 | use core::task::Poll; | 18 | use core::task::Poll; |
| 20 | use embassy::interrupt::InterruptExt; | 19 | use embassy::interrupt::InterruptExt; |
| 21 | use embassy::traits::uart::{Error as TraitError, Read, ReadUntilIdle, Write}; | ||
| 22 | use embassy::util::Unborrow; | 20 | use embassy::util::Unborrow; |
| 23 | use embassy_hal_common::drop::OnDrop; | 21 | use embassy_hal_common::drop::OnDrop; |
| 24 | use embassy_hal_common::unborrow; | 22 | use embassy_hal_common::unborrow; |
| @@ -32,6 +30,7 @@ use crate::pac; | |||
| 32 | use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; | 30 | use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; |
| 33 | use crate::timer::Instance as TimerInstance; | 31 | use crate::timer::Instance as TimerInstance; |
| 34 | use crate::timer::{Frequency, Timer}; | 32 | use crate::timer::{Frequency, Timer}; |
| 33 | use crate::util::slice_in_ram_or; | ||
| 35 | 34 | ||
| 36 | // Re-export SVD variants to allow user to directly set values. | 35 | // Re-export SVD variants to allow user to directly set values. |
| 37 | pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; | 36 | pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; |
| @@ -51,6 +50,16 @@ impl Default for Config { | |||
| 51 | } | 50 | } |
| 52 | } | 51 | } |
| 53 | 52 | ||
| 53 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
| 54 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 55 | #[non_exhaustive] | ||
| 56 | pub enum Error { | ||
| 57 | BufferTooLong, | ||
| 58 | BufferZeroLength, | ||
| 59 | DMABufferNotInDataMemory, | ||
| 60 | // TODO: add other error variants. | ||
| 61 | } | ||
| 62 | |||
| 54 | /// Interface to the UARTE peripheral | 63 | /// Interface to the UARTE peripheral |
| 55 | pub struct Uarte<'d, T: Instance> { | 64 | pub struct Uarte<'d, T: Instance> { |
| 56 | phantom: PhantomData<&'d mut T>, | 65 | phantom: PhantomData<&'d mut T>, |
| @@ -139,8 +148,12 @@ impl<'d, T: Instance> Uarte<'d, T> { | |||
| 139 | 148 | ||
| 140 | Self { | 149 | Self { |
| 141 | phantom: PhantomData, | 150 | phantom: PhantomData, |
| 142 | tx: UarteTx::new(), | 151 | tx: UarteTx { |
| 143 | rx: UarteRx::new(), | 152 | phantom: PhantomData, |
| 153 | }, | ||
| 154 | rx: UarteRx { | ||
| 155 | phantom: PhantomData, | ||
| 156 | }, | ||
| 144 | } | 157 | } |
| 145 | } | 158 | } |
| 146 | 159 | ||
| @@ -170,92 +183,110 @@ impl<'d, T: Instance> Uarte<'d, T> { | |||
| 170 | r.intenclr.write(|w| w.endtx().clear()); | 183 | r.intenclr.write(|w| w.endtx().clear()); |
| 171 | } | 184 | } |
| 172 | } | 185 | } |
| 173 | } | ||
| 174 | 186 | ||
| 175 | impl<'d, T: Instance> Read for Uarte<'d, T> { | 187 | pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { |
| 176 | type ReadFuture<'a> | 188 | self.rx.read(buffer).await |
| 177 | where | 189 | } |
| 178 | Self: 'a, | ||
| 179 | = impl Future<Output = Result<(), TraitError>> + 'a; | ||
| 180 | 190 | ||
| 181 | fn read<'a>(&'a mut self, rx_buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { | 191 | pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { |
| 182 | self.rx.read(rx_buffer) | 192 | self.tx.write(buffer).await |
| 183 | } | 193 | } |
| 184 | } | ||
| 185 | 194 | ||
| 186 | impl<'d, T: Instance> Write for Uarte<'d, T> { | 195 | pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { |
| 187 | type WriteFuture<'a> | 196 | self.rx.blocking_read(buffer) |
| 188 | where | 197 | } |
| 189 | Self: 'a, | ||
| 190 | = impl Future<Output = Result<(), TraitError>> + 'a; | ||
| 191 | 198 | ||
| 192 | fn write<'a>(&'a mut self, tx_buffer: &'a [u8]) -> Self::WriteFuture<'a> { | 199 | pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { |
| 193 | self.tx.write(tx_buffer) | 200 | self.tx.blocking_write(buffer) |
| 194 | } | 201 | } |
| 195 | } | 202 | } |
| 196 | 203 | ||
| 197 | impl<'d, T: Instance> UarteTx<'d, T> { | 204 | impl<'d, T: Instance> UarteTx<'d, T> { |
| 198 | pub fn new() -> Self { | 205 | pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { |
| 199 | Self { | 206 | slice_in_ram_or(buffer, Error::DMABufferNotInDataMemory)?; |
| 200 | phantom: PhantomData, | 207 | if buffer.len() == 0 { |
| 208 | return Err(Error::BufferZeroLength); | ||
| 209 | } | ||
| 210 | if buffer.len() > EASY_DMA_SIZE { | ||
| 211 | return Err(Error::BufferTooLong); | ||
| 201 | } | 212 | } |
| 202 | } | ||
| 203 | } | ||
| 204 | 213 | ||
| 205 | impl<'d, T: Instance> Write for UarteTx<'d, T> { | 214 | let ptr = buffer.as_ptr(); |
| 206 | type WriteFuture<'a> | 215 | let len = buffer.len(); |
| 207 | where | ||
| 208 | Self: 'a, | ||
| 209 | = impl Future<Output = Result<(), TraitError>> + 'a; | ||
| 210 | 216 | ||
| 211 | fn write<'a>(&'a mut self, tx_buffer: &'a [u8]) -> Self::WriteFuture<'a> { | 217 | let r = T::regs(); |
| 212 | async move { | 218 | let s = T::state(); |
| 213 | let ptr = tx_buffer.as_ptr(); | ||
| 214 | let len = tx_buffer.len(); | ||
| 215 | assert!(len <= EASY_DMA_SIZE); | ||
| 216 | // TODO: panic if buffer is not in SRAM | ||
| 217 | 219 | ||
| 218 | let r = T::regs(); | 220 | let drop = OnDrop::new(move || { |
| 219 | let s = T::state(); | 221 | trace!("write drop: stopping"); |
| 220 | 222 | ||
| 221 | let drop = OnDrop::new(move || { | 223 | r.intenclr.write(|w| w.endtx().clear()); |
| 222 | trace!("write drop: stopping"); | 224 | r.events_txstopped.reset(); |
| 225 | r.tasks_stoptx.write(|w| unsafe { w.bits(1) }); | ||
| 223 | 226 | ||
| 224 | r.intenclr.write(|w| w.endtx().clear()); | 227 | // TX is stopped almost instantly, spinning is fine. |
| 225 | r.events_txstopped.reset(); | 228 | while r.events_endtx.read().bits() == 0 {} |
| 226 | r.tasks_stoptx.write(|w| unsafe { w.bits(1) }); | 229 | trace!("write drop: stopped"); |
| 230 | }); | ||
| 227 | 231 | ||
| 228 | // TX is stopped almost instantly, spinning is fine. | 232 | r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); |
| 229 | while r.events_endtx.read().bits() == 0 {} | 233 | r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); |
| 230 | trace!("write drop: stopped"); | ||
| 231 | }); | ||
| 232 | 234 | ||
| 233 | r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); | 235 | r.events_endtx.reset(); |
| 234 | r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); | 236 | r.intenset.write(|w| w.endtx().set()); |
| 235 | 237 | ||
| 236 | r.events_endtx.reset(); | 238 | compiler_fence(Ordering::SeqCst); |
| 237 | r.intenset.write(|w| w.endtx().set()); | ||
| 238 | 239 | ||
| 239 | compiler_fence(Ordering::SeqCst); | 240 | trace!("starttx"); |
| 241 | r.tasks_starttx.write(|w| unsafe { w.bits(1) }); | ||
| 240 | 242 | ||
| 241 | trace!("starttx"); | 243 | poll_fn(|cx| { |
| 242 | r.tasks_starttx.write(|w| unsafe { w.bits(1) }); | 244 | s.endtx_waker.register(cx.waker()); |
| 245 | if r.events_endtx.read().bits() != 0 { | ||
| 246 | return Poll::Ready(()); | ||
| 247 | } | ||
| 248 | Poll::Pending | ||
| 249 | }) | ||
| 250 | .await; | ||
| 243 | 251 | ||
| 244 | poll_fn(|cx| { | 252 | compiler_fence(Ordering::SeqCst); |
| 245 | s.endtx_waker.register(cx.waker()); | 253 | r.events_txstarted.reset(); |
| 246 | if r.events_endtx.read().bits() != 0 { | 254 | drop.defuse(); |
| 247 | return Poll::Ready(()); | ||
| 248 | } | ||
| 249 | Poll::Pending | ||
| 250 | }) | ||
| 251 | .await; | ||
| 252 | 255 | ||
| 253 | compiler_fence(Ordering::SeqCst); | 256 | Ok(()) |
| 254 | r.events_txstarted.reset(); | 257 | } |
| 255 | drop.defuse(); | ||
| 256 | 258 | ||
| 257 | Ok(()) | 259 | pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { |
| 260 | slice_in_ram_or(buffer, Error::DMABufferNotInDataMemory)?; | ||
| 261 | if buffer.len() == 0 { | ||
| 262 | return Err(Error::BufferZeroLength); | ||
| 263 | } | ||
| 264 | if buffer.len() > EASY_DMA_SIZE { | ||
| 265 | return Err(Error::BufferTooLong); | ||
| 258 | } | 266 | } |
| 267 | |||
| 268 | let ptr = buffer.as_ptr(); | ||
| 269 | let len = buffer.len(); | ||
| 270 | |||
| 271 | let r = T::regs(); | ||
| 272 | |||
| 273 | r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); | ||
| 274 | r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); | ||
| 275 | |||
| 276 | r.events_endtx.reset(); | ||
| 277 | r.intenclr.write(|w| w.endtx().clear()); | ||
| 278 | |||
| 279 | compiler_fence(Ordering::SeqCst); | ||
| 280 | |||
| 281 | trace!("starttx"); | ||
| 282 | r.tasks_starttx.write(|w| unsafe { w.bits(1) }); | ||
| 283 | |||
| 284 | while r.events_endtx.read().bits() == 0 {} | ||
| 285 | |||
| 286 | compiler_fence(Ordering::SeqCst); | ||
| 287 | r.events_txstarted.reset(); | ||
| 288 | |||
| 289 | Ok(()) | ||
| 259 | } | 290 | } |
| 260 | } | 291 | } |
| 261 | 292 | ||
| @@ -278,66 +309,89 @@ impl<'a, T: Instance> Drop for UarteTx<'a, T> { | |||
| 278 | } | 309 | } |
| 279 | 310 | ||
| 280 | impl<'d, T: Instance> UarteRx<'d, T> { | 311 | impl<'d, T: Instance> UarteRx<'d, T> { |
| 281 | pub fn new() -> Self { | 312 | pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { |
| 282 | Self { | 313 | if buffer.len() == 0 { |
| 283 | phantom: PhantomData, | 314 | return Err(Error::BufferZeroLength); |
| 315 | } | ||
| 316 | if buffer.len() > EASY_DMA_SIZE { | ||
| 317 | return Err(Error::BufferTooLong); | ||
| 284 | } | 318 | } |
| 285 | } | ||
| 286 | } | ||
| 287 | 319 | ||
| 288 | impl<'d, T: Instance> Read for UarteRx<'d, T> { | 320 | let ptr = buffer.as_ptr(); |
| 289 | type ReadFuture<'a> | 321 | let len = buffer.len(); |
| 290 | where | ||
| 291 | Self: 'a, | ||
| 292 | = impl Future<Output = Result<(), TraitError>> + 'a; | ||
| 293 | 322 | ||
| 294 | fn read<'a>(&'a mut self, rx_buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { | 323 | let r = T::regs(); |
| 295 | async move { | 324 | let s = T::state(); |
| 296 | let ptr = rx_buffer.as_ptr(); | ||
| 297 | let len = rx_buffer.len(); | ||
| 298 | assert!(len <= EASY_DMA_SIZE); | ||
| 299 | 325 | ||
| 300 | let r = T::regs(); | 326 | let drop = OnDrop::new(move || { |
| 301 | let s = T::state(); | 327 | trace!("read drop: stopping"); |
| 302 | 328 | ||
| 303 | let drop = OnDrop::new(move || { | 329 | r.intenclr.write(|w| w.endrx().clear()); |
| 304 | trace!("read drop: stopping"); | 330 | r.events_rxto.reset(); |
| 331 | r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); | ||
| 305 | 332 | ||
| 306 | r.intenclr.write(|w| w.endrx().clear()); | 333 | while r.events_endrx.read().bits() == 0 {} |
| 307 | r.events_rxto.reset(); | ||
| 308 | r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); | ||
| 309 | 334 | ||
| 310 | while r.events_endrx.read().bits() == 0 {} | 335 | trace!("read drop: stopped"); |
| 336 | }); | ||
| 311 | 337 | ||
| 312 | trace!("read drop: stopped"); | 338 | r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); |
| 313 | }); | 339 | r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); |
| 314 | 340 | ||
| 315 | r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); | 341 | r.events_endrx.reset(); |
| 316 | r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); | 342 | r.intenset.write(|w| w.endrx().set()); |
| 317 | 343 | ||
| 318 | r.events_endrx.reset(); | 344 | compiler_fence(Ordering::SeqCst); |
| 319 | r.intenset.write(|w| w.endrx().set()); | ||
| 320 | 345 | ||
| 321 | compiler_fence(Ordering::SeqCst); | 346 | trace!("startrx"); |
| 347 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); | ||
| 322 | 348 | ||
| 323 | trace!("startrx"); | 349 | poll_fn(|cx| { |
| 324 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); | 350 | s.endrx_waker.register(cx.waker()); |
| 351 | if r.events_endrx.read().bits() != 0 { | ||
| 352 | return Poll::Ready(()); | ||
| 353 | } | ||
| 354 | Poll::Pending | ||
| 355 | }) | ||
| 356 | .await; | ||
| 325 | 357 | ||
| 326 | poll_fn(|cx| { | 358 | compiler_fence(Ordering::SeqCst); |
| 327 | s.endrx_waker.register(cx.waker()); | 359 | r.events_rxstarted.reset(); |
| 328 | if r.events_endrx.read().bits() != 0 { | 360 | drop.defuse(); |
| 329 | return Poll::Ready(()); | ||
| 330 | } | ||
| 331 | Poll::Pending | ||
| 332 | }) | ||
| 333 | .await; | ||
| 334 | 361 | ||
| 335 | compiler_fence(Ordering::SeqCst); | 362 | Ok(()) |
| 336 | r.events_rxstarted.reset(); | 363 | } |
| 337 | drop.defuse(); | ||
| 338 | 364 | ||
| 339 | Ok(()) | 365 | pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { |
| 366 | if buffer.len() == 0 { | ||
| 367 | return Err(Error::BufferZeroLength); | ||
| 368 | } | ||
| 369 | if buffer.len() > EASY_DMA_SIZE { | ||
| 370 | return Err(Error::BufferTooLong); | ||
| 340 | } | 371 | } |
| 372 | |||
| 373 | let ptr = buffer.as_ptr(); | ||
| 374 | let len = buffer.len(); | ||
| 375 | |||
| 376 | let r = T::regs(); | ||
| 377 | |||
| 378 | r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); | ||
| 379 | r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); | ||
| 380 | |||
| 381 | r.events_endrx.reset(); | ||
| 382 | r.intenclr.write(|w| w.endrx().clear()); | ||
| 383 | |||
| 384 | compiler_fence(Ordering::SeqCst); | ||
| 385 | |||
| 386 | trace!("startrx"); | ||
| 387 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); | ||
| 388 | |||
| 389 | while r.events_endrx.read().bits() == 0 {} | ||
| 390 | |||
| 391 | compiler_fence(Ordering::SeqCst); | ||
| 392 | r.events_rxstarted.reset(); | ||
| 393 | |||
| 394 | Ok(()) | ||
| 341 | } | 395 | } |
| 342 | } | 396 | } |
| 343 | 397 | ||
| @@ -439,14 +493,7 @@ pub struct UarteWithIdle<'d, U: Instance, T: TimerInstance> { | |||
| 439 | impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> { | 493 | impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> { |
| 440 | /// Creates the interface to a UARTE instance. | 494 | /// Creates the interface to a UARTE instance. |
| 441 | /// Sets the baud rate, parity and assigns the pins to the UARTE peripheral. | 495 | /// Sets the baud rate, parity and assigns the pins to the UARTE peripheral. |
| 442 | /// | 496 | pub fn new( |
| 443 | /// # Safety | ||
| 444 | /// | ||
| 445 | /// The returned API is safe unless you use `mem::forget` (or similar safe mechanisms) | ||
| 446 | /// on stack allocated buffers which which have been passed to [`send()`](Uarte::send) | ||
| 447 | /// or [`receive`](Uarte::receive). | ||
| 448 | #[allow(unused_unsafe)] | ||
| 449 | pub unsafe fn new( | ||
| 450 | uarte: impl Unborrow<Target = U> + 'd, | 497 | uarte: impl Unborrow<Target = U> + 'd, |
| 451 | timer: impl Unborrow<Target = T> + 'd, | 498 | timer: impl Unborrow<Target = T> + 'd, |
| 452 | ppi_ch1: impl Unborrow<Target = impl ConfigurableChannel + 'd> + 'd, | 499 | ppi_ch1: impl Unborrow<Target = impl ConfigurableChannel + 'd> + 'd, |
| @@ -501,93 +548,119 @@ impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> { | |||
| 501 | _ppi_ch2: ppi_ch2, | 548 | _ppi_ch2: ppi_ch2, |
| 502 | } | 549 | } |
| 503 | } | 550 | } |
| 504 | } | ||
| 505 | 551 | ||
| 506 | impl<'d, U: Instance, T: TimerInstance> ReadUntilIdle for UarteWithIdle<'d, U, T> { | 552 | pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { |
| 507 | type ReadUntilIdleFuture<'a> | 553 | self.ppi_ch1.disable(); |
| 508 | where | 554 | self.uarte.read(buffer).await |
| 509 | Self: 'a, | 555 | } |
| 510 | = impl Future<Output = Result<usize, TraitError>> + 'a; | ||
| 511 | fn read_until_idle<'a>(&'a mut self, rx_buffer: &'a mut [u8]) -> Self::ReadUntilIdleFuture<'a> { | ||
| 512 | async move { | ||
| 513 | let ptr = rx_buffer.as_ptr(); | ||
| 514 | let len = rx_buffer.len(); | ||
| 515 | assert!(len <= EASY_DMA_SIZE); | ||
| 516 | 556 | ||
| 517 | let r = U::regs(); | 557 | pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { |
| 518 | let s = U::state(); | 558 | self.uarte.write(buffer).await |
| 559 | } | ||
| 519 | 560 | ||
| 520 | let drop = OnDrop::new(|| { | 561 | pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { |
| 521 | trace!("read drop: stopping"); | 562 | self.ppi_ch1.disable(); |
| 563 | self.uarte.blocking_read(buffer) | ||
| 564 | } | ||
| 522 | 565 | ||
| 523 | self.timer.stop(); | 566 | pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { |
| 567 | self.uarte.blocking_write(buffer) | ||
| 568 | } | ||
| 524 | 569 | ||
| 525 | r.intenclr.write(|w| w.endrx().clear()); | 570 | pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> { |
| 526 | r.events_rxto.reset(); | 571 | if buffer.len() == 0 { |
| 527 | r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); | 572 | return Err(Error::BufferZeroLength); |
| 573 | } | ||
| 574 | if buffer.len() > EASY_DMA_SIZE { | ||
| 575 | return Err(Error::BufferTooLong); | ||
| 576 | } | ||
| 528 | 577 | ||
| 529 | while r.events_endrx.read().bits() == 0 {} | 578 | let ptr = buffer.as_ptr(); |
| 579 | let len = buffer.len(); | ||
| 530 | 580 | ||
| 531 | trace!("read drop: stopped"); | 581 | let r = U::regs(); |
| 532 | }); | 582 | let s = U::state(); |
| 533 | 583 | ||
| 534 | r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); | 584 | self.ppi_ch1.enable(); |
| 535 | r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); | ||
| 536 | 585 | ||
| 537 | r.events_endrx.reset(); | 586 | let drop = OnDrop::new(|| { |
| 538 | r.intenset.write(|w| w.endrx().set()); | 587 | trace!("read drop: stopping"); |
| 539 | 588 | ||
| 540 | compiler_fence(Ordering::SeqCst); | 589 | self.timer.stop(); |
| 541 | 590 | ||
| 542 | trace!("startrx"); | 591 | r.intenclr.write(|w| w.endrx().clear()); |
| 543 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); | 592 | r.events_rxto.reset(); |
| 593 | r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); | ||
| 544 | 594 | ||
| 545 | poll_fn(|cx| { | 595 | while r.events_endrx.read().bits() == 0 {} |
| 546 | s.endrx_waker.register(cx.waker()); | ||
| 547 | if r.events_endrx.read().bits() != 0 { | ||
| 548 | return Poll::Ready(()); | ||
| 549 | } | ||
| 550 | Poll::Pending | ||
| 551 | }) | ||
| 552 | .await; | ||
| 553 | 596 | ||
| 554 | compiler_fence(Ordering::SeqCst); | 597 | trace!("read drop: stopped"); |
| 555 | let n = r.rxd.amount.read().amount().bits() as usize; | 598 | }); |
| 556 | 599 | ||
| 557 | // Stop timer | 600 | r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); |
| 558 | self.timer.stop(); | 601 | r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); |
| 559 | r.events_rxstarted.reset(); | ||
| 560 | 602 | ||
| 561 | drop.defuse(); | 603 | r.events_endrx.reset(); |
| 604 | r.intenset.write(|w| w.endrx().set()); | ||
| 562 | 605 | ||
| 563 | Ok(n) | 606 | compiler_fence(Ordering::SeqCst); |
| 564 | } | 607 | |
| 608 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); | ||
| 609 | |||
| 610 | poll_fn(|cx| { | ||
| 611 | s.endrx_waker.register(cx.waker()); | ||
| 612 | if r.events_endrx.read().bits() != 0 { | ||
| 613 | return Poll::Ready(()); | ||
| 614 | } | ||
| 615 | Poll::Pending | ||
| 616 | }) | ||
| 617 | .await; | ||
| 618 | |||
| 619 | compiler_fence(Ordering::SeqCst); | ||
| 620 | let n = r.rxd.amount.read().amount().bits() as usize; | ||
| 621 | |||
| 622 | self.timer.stop(); | ||
| 623 | r.events_rxstarted.reset(); | ||
| 624 | |||
| 625 | drop.defuse(); | ||
| 626 | |||
| 627 | Ok(n) | ||
| 565 | } | 628 | } |
| 566 | } | ||
| 567 | 629 | ||
| 568 | impl<'d, U: Instance, T: TimerInstance> Read for UarteWithIdle<'d, U, T> { | 630 | pub fn blocking_read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> { |
| 569 | type ReadFuture<'a> | 631 | if buffer.len() == 0 { |
| 570 | where | 632 | return Err(Error::BufferZeroLength); |
| 571 | Self: 'a, | ||
| 572 | = impl Future<Output = Result<(), TraitError>> + 'a; | ||
| 573 | fn read<'a>(&'a mut self, rx_buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { | ||
| 574 | async move { | ||
| 575 | self.ppi_ch1.disable(); | ||
| 576 | let result = self.uarte.read(rx_buffer).await; | ||
| 577 | self.ppi_ch1.enable(); | ||
| 578 | result | ||
| 579 | } | 633 | } |
| 580 | } | 634 | if buffer.len() > EASY_DMA_SIZE { |
| 581 | } | 635 | return Err(Error::BufferTooLong); |
| 636 | } | ||
| 637 | |||
| 638 | let ptr = buffer.as_ptr(); | ||
| 639 | let len = buffer.len(); | ||
| 640 | |||
| 641 | let r = U::regs(); | ||
| 642 | |||
| 643 | self.ppi_ch1.enable(); | ||
| 644 | |||
| 645 | r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); | ||
| 646 | r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); | ||
| 647 | |||
| 648 | r.events_endrx.reset(); | ||
| 649 | r.intenclr.write(|w| w.endrx().clear()); | ||
| 650 | |||
| 651 | compiler_fence(Ordering::SeqCst); | ||
| 652 | |||
| 653 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); | ||
| 582 | 654 | ||
| 583 | impl<'d, U: Instance, T: TimerInstance> Write for UarteWithIdle<'d, U, T> { | 655 | while r.events_endrx.read().bits() == 0 {} |
| 584 | type WriteFuture<'a> | ||
| 585 | where | ||
| 586 | Self: 'a, | ||
| 587 | = impl Future<Output = Result<(), TraitError>> + 'a; | ||
| 588 | 656 | ||
| 589 | fn write<'a>(&'a mut self, tx_buffer: &'a [u8]) -> Self::WriteFuture<'a> { | 657 | compiler_fence(Ordering::SeqCst); |
| 590 | self.uarte.write(tx_buffer) | 658 | let n = r.rxd.amount.read().amount().bits() as usize; |
| 659 | |||
| 660 | self.timer.stop(); | ||
| 661 | r.events_rxstarted.reset(); | ||
| 662 | |||
| 663 | Ok(n) | ||
| 591 | } | 664 | } |
| 592 | } | 665 | } |
| 593 | 666 | ||
| @@ -639,3 +712,206 @@ macro_rules! impl_uarte { | |||
| 639 | } | 712 | } |
| 640 | }; | 713 | }; |
| 641 | } | 714 | } |
| 715 | |||
| 716 | // ==================== | ||
| 717 | |||
| 718 | mod eh02 { | ||
| 719 | use super::*; | ||
| 720 | |||
| 721 | impl<'d, T: Instance> embedded_hal_02::blocking::serial::Write<u8> for Uarte<'d, T> { | ||
| 722 | type Error = Error; | ||
| 723 | |||
| 724 | fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { | ||
| 725 | self.blocking_write(buffer) | ||
| 726 | } | ||
| 727 | |||
| 728 | fn bflush(&mut self) -> Result<(), Self::Error> { | ||
| 729 | Ok(()) | ||
| 730 | } | ||
| 731 | } | ||
| 732 | |||
| 733 | impl<'d, T: Instance> embedded_hal_02::blocking::serial::Write<u8> for UarteTx<'d, T> { | ||
| 734 | type Error = Error; | ||
| 735 | |||
| 736 | fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { | ||
| 737 | self.blocking_write(buffer) | ||
| 738 | } | ||
| 739 | |||
| 740 | fn bflush(&mut self) -> Result<(), Self::Error> { | ||
| 741 | Ok(()) | ||
| 742 | } | ||
| 743 | } | ||
| 744 | |||
| 745 | impl<'d, U: Instance, T: TimerInstance> embedded_hal_02::blocking::serial::Write<u8> | ||
| 746 | for UarteWithIdle<'d, U, T> | ||
| 747 | { | ||
| 748 | type Error = Error; | ||
| 749 | |||
| 750 | fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { | ||
| 751 | self.blocking_write(buffer) | ||
| 752 | } | ||
| 753 | |||
| 754 | fn bflush(&mut self) -> Result<(), Self::Error> { | ||
| 755 | Ok(()) | ||
| 756 | } | ||
| 757 | } | ||
| 758 | } | ||
| 759 | |||
| 760 | #[cfg(feature = "unstable-traits")] | ||
| 761 | mod eh1 { | ||
| 762 | use super::*; | ||
| 763 | use core::future::Future; | ||
| 764 | |||
| 765 | impl embedded_hal_1::serial::Error for Error { | ||
| 766 | fn kind(&self) -> embedded_hal_1::serial::ErrorKind { | ||
| 767 | match *self { | ||
| 768 | Self::BufferTooLong => embedded_hal_1::serial::ErrorKind::Other, | ||
| 769 | Self::BufferZeroLength => embedded_hal_1::serial::ErrorKind::Other, | ||
| 770 | Self::DMABufferNotInDataMemory => embedded_hal_1::serial::ErrorKind::Other, | ||
| 771 | } | ||
| 772 | } | ||
| 773 | } | ||
| 774 | |||
| 775 | // ===================== | ||
| 776 | |||
| 777 | impl<'d, T: Instance> embedded_hal_1::serial::ErrorType for Uarte<'d, T> { | ||
| 778 | type Error = Error; | ||
| 779 | } | ||
| 780 | |||
| 781 | impl<'d, T: Instance> embedded_hal_1::serial::blocking::Write for Uarte<'d, T> { | ||
| 782 | fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { | ||
| 783 | self.blocking_write(buffer) | ||
| 784 | } | ||
| 785 | |||
| 786 | fn flush(&mut self) -> Result<(), Self::Error> { | ||
| 787 | Ok(()) | ||
| 788 | } | ||
| 789 | } | ||
| 790 | |||
| 791 | impl<'d, T: Instance> embedded_hal_async::serial::Read for Uarte<'d, T> { | ||
| 792 | type ReadFuture<'a> | ||
| 793 | where | ||
| 794 | Self: 'a, | ||
| 795 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 796 | |||
| 797 | fn read<'a>(&'a mut self, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { | ||
| 798 | self.read(buffer) | ||
| 799 | } | ||
| 800 | } | ||
| 801 | |||
| 802 | impl<'d, T: Instance> embedded_hal_async::serial::Write for Uarte<'d, T> { | ||
| 803 | type WriteFuture<'a> | ||
| 804 | where | ||
| 805 | Self: 'a, | ||
| 806 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 807 | |||
| 808 | fn write<'a>(&'a mut self, buffer: &'a [u8]) -> Self::WriteFuture<'a> { | ||
| 809 | self.write(buffer) | ||
| 810 | } | ||
| 811 | |||
| 812 | type FlushFuture<'a> | ||
| 813 | where | ||
| 814 | Self: 'a, | ||
| 815 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 816 | |||
| 817 | fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> { | ||
| 818 | async move { Ok(()) } | ||
| 819 | } | ||
| 820 | } | ||
| 821 | |||
| 822 | // ===================== | ||
| 823 | |||
| 824 | impl<'d, T: Instance> embedded_hal_1::serial::ErrorType for UarteTx<'d, T> { | ||
| 825 | type Error = Error; | ||
| 826 | } | ||
| 827 | |||
| 828 | impl<'d, T: Instance> embedded_hal_1::serial::blocking::Write for UarteTx<'d, T> { | ||
| 829 | fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { | ||
| 830 | self.blocking_write(buffer) | ||
| 831 | } | ||
| 832 | |||
| 833 | fn flush(&mut self) -> Result<(), Self::Error> { | ||
| 834 | Ok(()) | ||
| 835 | } | ||
| 836 | } | ||
| 837 | |||
| 838 | impl<'d, T: Instance> embedded_hal_async::serial::Write for UarteTx<'d, T> { | ||
| 839 | type WriteFuture<'a> | ||
| 840 | where | ||
| 841 | Self: 'a, | ||
| 842 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 843 | |||
| 844 | fn write<'a>(&'a mut self, buffer: &'a [u8]) -> Self::WriteFuture<'a> { | ||
| 845 | self.write(buffer) | ||
| 846 | } | ||
| 847 | |||
| 848 | type FlushFuture<'a> | ||
| 849 | where | ||
| 850 | Self: 'a, | ||
| 851 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 852 | |||
| 853 | fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> { | ||
| 854 | async move { Ok(()) } | ||
| 855 | } | ||
| 856 | } | ||
| 857 | |||
| 858 | // ===================== | ||
| 859 | |||
| 860 | impl<'d, T: Instance> embedded_hal_1::serial::ErrorType for UarteRx<'d, T> { | ||
| 861 | type Error = Error; | ||
| 862 | } | ||
| 863 | |||
| 864 | impl<'d, T: Instance> embedded_hal_async::serial::Read for UarteRx<'d, T> { | ||
| 865 | type ReadFuture<'a> | ||
| 866 | where | ||
| 867 | Self: 'a, | ||
| 868 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 869 | |||
| 870 | fn read<'a>(&'a mut self, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { | ||
| 871 | self.read(buffer) | ||
| 872 | } | ||
| 873 | } | ||
| 874 | |||
| 875 | // ===================== | ||
| 876 | |||
| 877 | impl<'d, U: Instance, T: TimerInstance> embedded_hal_1::serial::ErrorType | ||
| 878 | for UarteWithIdle<'d, U, T> | ||
| 879 | { | ||
| 880 | type Error = Error; | ||
| 881 | } | ||
| 882 | |||
| 883 | impl<'d, U: Instance, T: TimerInstance> embedded_hal_async::serial::Read | ||
| 884 | for UarteWithIdle<'d, U, T> | ||
| 885 | { | ||
| 886 | type ReadFuture<'a> | ||
| 887 | where | ||
| 888 | Self: 'a, | ||
| 889 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 890 | |||
| 891 | fn read<'a>(&'a mut self, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { | ||
| 892 | self.read(buffer) | ||
| 893 | } | ||
| 894 | } | ||
| 895 | |||
| 896 | impl<'d, U: Instance, T: TimerInstance> embedded_hal_async::serial::Write | ||
| 897 | for UarteWithIdle<'d, U, T> | ||
| 898 | { | ||
| 899 | type WriteFuture<'a> | ||
| 900 | where | ||
| 901 | Self: 'a, | ||
| 902 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 903 | |||
| 904 | fn write<'a>(&'a mut self, buffer: &'a [u8]) -> Self::WriteFuture<'a> { | ||
| 905 | self.write(buffer) | ||
| 906 | } | ||
| 907 | |||
| 908 | type FlushFuture<'a> | ||
| 909 | where | ||
| 910 | Self: 'a, | ||
| 911 | = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 912 | |||
| 913 | fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> { | ||
| 914 | async move { Ok(()) } | ||
| 915 | } | ||
| 916 | } | ||
| 917 | } | ||
diff --git a/embassy-nrf/src/util.rs b/embassy-nrf/src/util.rs index 2fd0bc5a8..76162b701 100644 --- a/embassy-nrf/src/util.rs +++ b/embassy-nrf/src/util.rs | |||
| @@ -1,16 +1,28 @@ | |||
| 1 | use core::mem; | ||
| 2 | |||
| 1 | const SRAM_LOWER: usize = 0x2000_0000; | 3 | const SRAM_LOWER: usize = 0x2000_0000; |
| 2 | const SRAM_UPPER: usize = 0x3000_0000; | 4 | const SRAM_UPPER: usize = 0x3000_0000; |
| 3 | 5 | ||
| 6 | // TODO: replace transmutes with core::ptr::metadata once it's stable | ||
| 7 | |||
| 8 | pub(crate) fn slice_ptr_parts<T>(slice: *const [T]) -> (usize, usize) { | ||
| 9 | unsafe { mem::transmute(slice) } | ||
| 10 | } | ||
| 11 | |||
| 12 | pub(crate) fn slice_ptr_parts_mut<T>(slice: *mut [T]) -> (usize, usize) { | ||
| 13 | unsafe { mem::transmute(slice) } | ||
| 14 | } | ||
| 15 | |||
| 4 | /// Does this slice reside entirely within RAM? | 16 | /// Does this slice reside entirely within RAM? |
| 5 | pub(crate) fn slice_in_ram<T>(slice: &[T]) -> bool { | 17 | pub(crate) fn slice_in_ram<T>(slice: *const [T]) -> bool { |
| 6 | let ptr = slice.as_ptr() as usize; | 18 | let (ptr, len) = slice_ptr_parts(slice); |
| 7 | ptr >= SRAM_LOWER && (ptr + slice.len() * core::mem::size_of::<T>()) < SRAM_UPPER | 19 | ptr >= SRAM_LOWER && (ptr + len * core::mem::size_of::<T>()) < SRAM_UPPER |
| 8 | } | 20 | } |
| 9 | 21 | ||
| 10 | /// Return an error if slice is not in RAM. | 22 | /// Return an error if slice is not in RAM. |
| 11 | #[cfg(not(feature = "nrf51"))] | 23 | #[cfg(not(feature = "nrf51"))] |
| 12 | pub(crate) fn slice_in_ram_or<T, E>(slice: &[T], err: E) -> Result<(), E> { | 24 | pub(crate) fn slice_in_ram_or<T, E>(slice: *const [T], err: E) -> Result<(), E> { |
| 13 | if slice.is_empty() || slice_in_ram(slice) { | 25 | if slice_in_ram(slice) { |
| 14 | Ok(()) | 26 | Ok(()) |
| 15 | } else { | 27 | } else { |
| 16 | Err(err) | 28 | Err(err) |
diff --git a/examples/nrf/Cargo.toml b/examples/nrf/Cargo.toml index ca013f8b7..fa7286923 100644 --- a/examples/nrf/Cargo.toml +++ b/examples/nrf/Cargo.toml | |||
| @@ -15,7 +15,6 @@ defmt-rtt = "0.3" | |||
| 15 | 15 | ||
| 16 | cortex-m = "0.7.3" | 16 | cortex-m = "0.7.3" |
| 17 | cortex-m-rt = "0.7.0" | 17 | cortex-m-rt = "0.7.0" |
| 18 | embedded-hal = "0.2.6" | ||
| 19 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 18 | panic-probe = { version = "0.3", features = ["print-defmt"] } |
| 20 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | 19 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } |
| 21 | rand = { version = "0.8.4", default-features = false } | 20 | rand = { version = "0.8.4", default-features = false } |
diff --git a/examples/nrf/src/bin/gpiote_port.rs b/examples/nrf/src/bin/gpiote_port.rs index 76c861d95..3ea9a6e67 100644 --- a/examples/nrf/src/bin/gpiote_port.rs +++ b/examples/nrf/src/bin/gpiote_port.rs | |||
| @@ -6,7 +6,6 @@ | |||
| 6 | mod example_common; | 6 | mod example_common; |
| 7 | 7 | ||
| 8 | use embassy::executor::Spawner; | 8 | use embassy::executor::Spawner; |
| 9 | use embassy::traits::gpio::{WaitForHigh, WaitForLow}; | ||
| 10 | use embassy_nrf::gpio::{AnyPin, Input, Pin as _, Pull}; | 9 | use embassy_nrf::gpio::{AnyPin, Input, Pin as _, Pull}; |
| 11 | use embassy_nrf::Peripherals; | 10 | use embassy_nrf::Peripherals; |
| 12 | use example_common::*; | 11 | use example_common::*; |
diff --git a/examples/nrf/src/bin/qspi.rs b/examples/nrf/src/bin/qspi.rs index c7f9503bb..b2e6bfc15 100644 --- a/examples/nrf/src/bin/qspi.rs +++ b/examples/nrf/src/bin/qspi.rs | |||
| @@ -7,7 +7,6 @@ mod example_common; | |||
| 7 | 7 | ||
| 8 | use defmt::assert_eq; | 8 | use defmt::assert_eq; |
| 9 | use embassy::executor::Spawner; | 9 | use embassy::executor::Spawner; |
| 10 | use embassy::traits::flash::Flash; | ||
| 11 | use embassy_nrf::Peripherals; | 10 | use embassy_nrf::Peripherals; |
| 12 | use embassy_nrf::{interrupt, qspi}; | 11 | use embassy_nrf::{interrupt, qspi}; |
| 13 | use example_common::*; | 12 | use example_common::*; |
diff --git a/examples/nrf/src/bin/qspi_lowpower.rs b/examples/nrf/src/bin/qspi_lowpower.rs index e9e1bac42..4e264ef2f 100644 --- a/examples/nrf/src/bin/qspi_lowpower.rs +++ b/examples/nrf/src/bin/qspi_lowpower.rs | |||
| @@ -8,7 +8,6 @@ mod example_common; | |||
| 8 | use core::mem; | 8 | use core::mem; |
| 9 | use embassy::executor::Spawner; | 9 | use embassy::executor::Spawner; |
| 10 | use embassy::time::{Duration, Timer}; | 10 | use embassy::time::{Duration, Timer}; |
| 11 | use embassy::traits::flash::Flash; | ||
| 12 | use embassy_nrf::Peripherals; | 11 | use embassy_nrf::Peripherals; |
| 13 | use embassy_nrf::{interrupt, qspi}; | 12 | use embassy_nrf::{interrupt, qspi}; |
| 14 | use example_common::*; | 13 | use example_common::*; |
diff --git a/examples/nrf/src/bin/rng.rs b/examples/nrf/src/bin/rng.rs index 2f1a26993..a35a9fa85 100644 --- a/examples/nrf/src/bin/rng.rs +++ b/examples/nrf/src/bin/rng.rs | |||
| @@ -5,9 +5,7 @@ | |||
| 5 | #[path = "../example_common.rs"] | 5 | #[path = "../example_common.rs"] |
| 6 | mod example_common; | 6 | mod example_common; |
| 7 | 7 | ||
| 8 | use defmt::unwrap; | ||
| 9 | use embassy::executor::Spawner; | 8 | use embassy::executor::Spawner; |
| 10 | use embassy::traits::rng::Rng as _; | ||
| 11 | use embassy_nrf::interrupt; | 9 | use embassy_nrf::interrupt; |
| 12 | use embassy_nrf::rng::Rng; | 10 | use embassy_nrf::rng::Rng; |
| 13 | use embassy_nrf::Peripherals; | 11 | use embassy_nrf::Peripherals; |
| @@ -19,14 +17,14 @@ async fn main(_spawner: Spawner, p: Peripherals) { | |||
| 19 | 17 | ||
| 20 | // Async API | 18 | // Async API |
| 21 | let mut bytes = [0; 4]; | 19 | let mut bytes = [0; 4]; |
| 22 | unwrap!(rng.fill_bytes(&mut bytes).await); // nRF RNG is infallible | 20 | rng.fill_bytes(&mut bytes).await; |
| 23 | defmt::info!("Some random bytes: {:?}", bytes); | 21 | defmt::info!("Some random bytes: {:?}", bytes); |
| 24 | 22 | ||
| 25 | // Sync API with `rand` | 23 | // Sync API with `rand` |
| 26 | defmt::info!("A random number from 1 to 10: {:?}", rng.gen_range(1..=10)); | 24 | defmt::info!("A random number from 1 to 10: {:?}", rng.gen_range(1..=10)); |
| 27 | 25 | ||
| 28 | let mut bytes = [0; 1024]; | 26 | let mut bytes = [0; 1024]; |
| 29 | unwrap!(rng.fill_bytes(&mut bytes).await); | 27 | rng.fill_bytes(&mut bytes).await; |
| 30 | let zero_count: u32 = bytes.iter().fold(0, |acc, val| acc + val.count_zeros()); | 28 | let zero_count: u32 = bytes.iter().fold(0, |acc, val| acc + val.count_zeros()); |
| 31 | let one_count: u32 = bytes.iter().fold(0, |acc, val| acc + val.count_ones()); | 29 | let one_count: u32 = bytes.iter().fold(0, |acc, val| acc + val.count_ones()); |
| 32 | defmt::info!( | 30 | defmt::info!( |
diff --git a/examples/nrf/src/bin/spim.rs b/examples/nrf/src/bin/spim.rs index fc31d140a..cda3baa26 100644 --- a/examples/nrf/src/bin/spim.rs +++ b/examples/nrf/src/bin/spim.rs | |||
| @@ -9,7 +9,6 @@ use embassy::executor::Spawner; | |||
| 9 | use embassy_nrf::gpio::{Level, Output, OutputDrive}; | 9 | use embassy_nrf::gpio::{Level, Output, OutputDrive}; |
| 10 | use embassy_nrf::Peripherals; | 10 | use embassy_nrf::Peripherals; |
| 11 | use embassy_nrf::{interrupt, spim}; | 11 | use embassy_nrf::{interrupt, spim}; |
| 12 | use embassy_traits::spi::FullDuplex; | ||
| 13 | use example_common::*; | 12 | use example_common::*; |
| 14 | 13 | ||
| 15 | #[embassy::main] | 14 | #[embassy::main] |
| @@ -31,7 +30,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { | |||
| 31 | ncs.set_low(); | 30 | ncs.set_low(); |
| 32 | cortex_m::asm::delay(5); | 31 | cortex_m::asm::delay(5); |
| 33 | let tx = [0xFF]; | 32 | let tx = [0xFF]; |
| 34 | unwrap!(spim.read_write(&mut [], &tx).await); | 33 | unwrap!(spim.transfer(&mut [], &tx).await); |
| 35 | cortex_m::asm::delay(10); | 34 | cortex_m::asm::delay(10); |
| 36 | ncs.set_high(); | 35 | ncs.set_high(); |
| 37 | 36 | ||
| @@ -44,7 +43,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { | |||
| 44 | ncs.set_low(); | 43 | ncs.set_low(); |
| 45 | cortex_m::asm::delay(5000); | 44 | cortex_m::asm::delay(5000); |
| 46 | let tx = [0b000_11101, 0]; | 45 | let tx = [0b000_11101, 0]; |
| 47 | unwrap!(spim.read_write(&mut rx, &tx).await); | 46 | unwrap!(spim.transfer(&mut rx, &tx).await); |
| 48 | cortex_m::asm::delay(5000); | 47 | cortex_m::asm::delay(5000); |
| 49 | ncs.set_high(); | 48 | ncs.set_high(); |
| 50 | info!("estat: {=[?]}", rx); | 49 | info!("estat: {=[?]}", rx); |
| @@ -54,7 +53,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { | |||
| 54 | ncs.set_low(); | 53 | ncs.set_low(); |
| 55 | cortex_m::asm::delay(5); | 54 | cortex_m::asm::delay(5); |
| 56 | let tx = [0b100_11111, 0b11]; | 55 | let tx = [0b100_11111, 0b11]; |
| 57 | unwrap!(spim.read_write(&mut rx, &tx).await); | 56 | unwrap!(spim.transfer(&mut rx, &tx).await); |
| 58 | cortex_m::asm::delay(10); | 57 | cortex_m::asm::delay(10); |
| 59 | ncs.set_high(); | 58 | ncs.set_high(); |
| 60 | 59 | ||
| @@ -63,7 +62,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { | |||
| 63 | ncs.set_low(); | 62 | ncs.set_low(); |
| 64 | cortex_m::asm::delay(5); | 63 | cortex_m::asm::delay(5); |
| 65 | let tx = [0b000_10010, 0]; | 64 | let tx = [0b000_10010, 0]; |
| 66 | unwrap!(spim.read_write(&mut rx, &tx).await); | 65 | unwrap!(spim.transfer(&mut rx, &tx).await); |
| 67 | cortex_m::asm::delay(10); | 66 | cortex_m::asm::delay(10); |
| 68 | ncs.set_high(); | 67 | ncs.set_high(); |
| 69 | 68 | ||
diff --git a/examples/nrf/src/bin/twim.rs b/examples/nrf/src/bin/twim.rs index 4c2f2bf2e..1ac3a3945 100644 --- a/examples/nrf/src/bin/twim.rs +++ b/examples/nrf/src/bin/twim.rs | |||
| @@ -26,7 +26,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { | |||
| 26 | info!("Reading..."); | 26 | info!("Reading..."); |
| 27 | 27 | ||
| 28 | let mut buf = [0u8; 16]; | 28 | let mut buf = [0u8; 16]; |
| 29 | unwrap!(twi.write_then_read(ADDRESS, &mut [0x00], &mut buf)); | 29 | unwrap!(twi.blocking_write_read(ADDRESS, &mut [0x00], &mut buf)); |
| 30 | 30 | ||
| 31 | info!("Read: {=[u8]:x}", buf); | 31 | info!("Read: {=[u8]:x}", buf); |
| 32 | } | 32 | } |
diff --git a/examples/nrf/src/bin/twim_lowpower.rs b/examples/nrf/src/bin/twim_lowpower.rs index 62a5f0c94..4a0596437 100644 --- a/examples/nrf/src/bin/twim_lowpower.rs +++ b/examples/nrf/src/bin/twim_lowpower.rs | |||
| @@ -36,7 +36,7 @@ async fn main(_spawner: Spawner, mut p: Peripherals) { | |||
| 36 | info!("Reading..."); | 36 | info!("Reading..."); |
| 37 | 37 | ||
| 38 | let mut buf = [0u8; 16]; | 38 | let mut buf = [0u8; 16]; |
| 39 | unwrap!(twi.write_then_read(ADDRESS, &mut [0x00], &mut buf)); | 39 | unwrap!(twi.blocking_write_read(ADDRESS, &mut [0x00], &mut buf)); |
| 40 | 40 | ||
| 41 | info!("Read: {=[u8]:x}", buf); | 41 | info!("Read: {=[u8]:x}", buf); |
| 42 | 42 | ||
diff --git a/examples/nrf/src/bin/uart.rs b/examples/nrf/src/bin/uart.rs index 208961c8b..68ee3978a 100644 --- a/examples/nrf/src/bin/uart.rs +++ b/examples/nrf/src/bin/uart.rs | |||
| @@ -7,7 +7,6 @@ mod example_common; | |||
| 7 | use example_common::*; | 7 | use example_common::*; |
| 8 | 8 | ||
| 9 | use embassy::executor::Spawner; | 9 | use embassy::executor::Spawner; |
| 10 | use embassy::traits::uart::{Read, Write}; | ||
| 11 | use embassy_nrf::gpio::NoPin; | 10 | use embassy_nrf::gpio::NoPin; |
| 12 | use embassy_nrf::{interrupt, uarte, Peripherals}; | 11 | use embassy_nrf::{interrupt, uarte, Peripherals}; |
| 13 | 12 | ||
diff --git a/examples/nrf/src/bin/uart_idle.rs b/examples/nrf/src/bin/uart_idle.rs index ec9a36026..76449c0e3 100644 --- a/examples/nrf/src/bin/uart_idle.rs +++ b/examples/nrf/src/bin/uart_idle.rs | |||
| @@ -4,11 +4,9 @@ | |||
| 4 | 4 | ||
| 5 | #[path = "../example_common.rs"] | 5 | #[path = "../example_common.rs"] |
| 6 | mod example_common; | 6 | mod example_common; |
| 7 | use embassy_traits::uart::ReadUntilIdle; | ||
| 8 | use example_common::*; | 7 | use example_common::*; |
| 9 | 8 | ||
| 10 | use embassy::executor::Spawner; | 9 | use embassy::executor::Spawner; |
| 11 | use embassy::traits::uart::Write; | ||
| 12 | use embassy_nrf::gpio::NoPin; | 10 | use embassy_nrf::gpio::NoPin; |
| 13 | use embassy_nrf::{interrupt, uarte, Peripherals}; | 11 | use embassy_nrf::{interrupt, uarte, Peripherals}; |
| 14 | 12 | ||
| @@ -19,11 +17,9 @@ async fn main(_spawner: Spawner, p: Peripherals) { | |||
| 19 | config.baudrate = uarte::Baudrate::BAUD115200; | 17 | config.baudrate = uarte::Baudrate::BAUD115200; |
| 20 | 18 | ||
| 21 | let irq = interrupt::take!(UARTE0_UART0); | 19 | let irq = interrupt::take!(UARTE0_UART0); |
| 22 | let mut uart = unsafe { | 20 | let mut uart = uarte::UarteWithIdle::new( |
| 23 | uarte::UarteWithIdle::new( | 21 | p.UARTE0, p.TIMER0, p.PPI_CH0, p.PPI_CH1, irq, p.P0_08, p.P0_06, NoPin, NoPin, config, |
| 24 | p.UARTE0, p.TIMER0, p.PPI_CH0, p.PPI_CH1, irq, p.P0_08, p.P0_06, NoPin, NoPin, config, | 22 | ); |
| 25 | ) | ||
| 26 | }; | ||
| 27 | 23 | ||
| 28 | info!("uarte initialized!"); | 24 | info!("uarte initialized!"); |
| 29 | 25 | ||
diff --git a/examples/nrf/src/bin/uart_split.rs b/examples/nrf/src/bin/uart_split.rs index 4b5dbb21f..a9c02e796 100644 --- a/examples/nrf/src/bin/uart_split.rs +++ b/examples/nrf/src/bin/uart_split.rs | |||
| @@ -4,16 +4,15 @@ | |||
| 4 | 4 | ||
| 5 | #[path = "../example_common.rs"] | 5 | #[path = "../example_common.rs"] |
| 6 | mod example_common; | 6 | mod example_common; |
| 7 | use example_common::*; | ||
| 8 | |||
| 7 | use embassy::blocking_mutex::kind::Noop; | 9 | use embassy::blocking_mutex::kind::Noop; |
| 8 | use embassy::channel::mpsc::{self, Channel, Sender}; | 10 | use embassy::channel::mpsc::{self, Channel, Sender}; |
| 11 | use embassy::executor::Spawner; | ||
| 9 | use embassy::util::Forever; | 12 | use embassy::util::Forever; |
| 13 | use embassy_nrf::gpio::NoPin; | ||
| 10 | use embassy_nrf::peripherals::UARTE0; | 14 | use embassy_nrf::peripherals::UARTE0; |
| 11 | use embassy_nrf::uarte::UarteRx; | 15 | use embassy_nrf::uarte::UarteRx; |
| 12 | use example_common::*; | ||
| 13 | |||
| 14 | use embassy::executor::Spawner; | ||
| 15 | use embassy::traits::uart::{Read, Write}; | ||
| 16 | use embassy_nrf::gpio::NoPin; | ||
| 17 | use embassy_nrf::{interrupt, uarte, Peripherals}; | 16 | use embassy_nrf::{interrupt, uarte, Peripherals}; |
| 18 | 17 | ||
| 19 | static CHANNEL: Forever<Channel<Noop, [u8; 8], 1>> = Forever::new(); | 18 | static CHANNEL: Forever<Channel<Noop, [u8; 8], 1>> = Forever::new(); |
diff --git a/examples/nrf/src/bin/wdt.rs b/examples/nrf/src/bin/wdt.rs index 78c2205d9..cc199be9d 100644 --- a/examples/nrf/src/bin/wdt.rs +++ b/examples/nrf/src/bin/wdt.rs | |||
| @@ -10,7 +10,6 @@ use embassy::executor::Spawner; | |||
| 10 | use embassy_nrf::gpio::{Input, Pull}; | 10 | use embassy_nrf::gpio::{Input, Pull}; |
| 11 | use embassy_nrf::wdt::{Config, Watchdog}; | 11 | use embassy_nrf::wdt::{Config, Watchdog}; |
| 12 | use embassy_nrf::Peripherals; | 12 | use embassy_nrf::Peripherals; |
| 13 | use embassy_traits::gpio::{WaitForHigh, WaitForLow}; | ||
| 14 | 13 | ||
| 15 | #[embassy::main] | 14 | #[embassy::main] |
| 16 | async fn main(_spawner: Spawner, p: Peripherals) { | 15 | async fn main(_spawner: Spawner, p: Peripherals) { |
