diff options
Diffstat (limited to 'embassy-nrf')
| -rw-r--r-- | embassy-nrf/CHANGELOG.md | 3 | ||||
| -rw-r--r-- | embassy-nrf/src/gpiote.rs | 68 |
2 files changed, 65 insertions, 6 deletions
diff --git a/embassy-nrf/CHANGELOG.md b/embassy-nrf/CHANGELOG.md index 72ecb116a..52a8a7a05 100644 --- a/embassy-nrf/CHANGELOG.md +++ b/embassy-nrf/CHANGELOG.md | |||
| @@ -23,6 +23,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 | |||
| 23 | - bugfix: Do not write to UICR from non-secure code on nrf53 | 23 | - bugfix: Do not write to UICR from non-secure code on nrf53 |
| 24 | - bugfix: Add delay to uart init anomaly fix | 24 | - bugfix: Add delay to uart init anomaly fix |
| 25 | - changed: `BufferedUarte::read_ready` now uses the same definition for 'empty' so following read calls will not block when true is returned | 25 | - changed: `BufferedUarte::read_ready` now uses the same definition for 'empty' so following read calls will not block when true is returned |
| 26 | - added: add `gpiote::InputChannel::wait_for_high()` and `wait_for_low()` to wait for specific signal level | ||
| 27 | - changed: `gpiote::InputChannel::wait()` now takes a mutable reference to `self` to avoid interference from concurrent calls | ||
| 28 | - changed: `gpiote::InputChannel::wait()` now ensures events are seen as soon as the function is called, even if the future is not polled | ||
| 26 | 29 | ||
| 27 | ## 0.8.0 - 2025-09-30 | 30 | ## 0.8.0 - 2025-09-30 |
| 28 | 31 | ||
diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs index 91944d8cd..d4f6668f3 100644 --- a/embassy-nrf/src/gpiote.rs +++ b/embassy-nrf/src/gpiote.rs | |||
| @@ -349,16 +349,73 @@ impl<'d> InputChannel<'d> { | |||
| 349 | } | 349 | } |
| 350 | 350 | ||
| 351 | /// Asynchronously wait for an event in this channel. | 351 | /// Asynchronously wait for an event in this channel. |
| 352 | pub async fn wait(&self) { | 352 | /// |
| 353 | let g = self.ch.regs(); | 353 | /// It is possible to call this function and await the returned future later. |
| 354 | let num = self.ch.number(); | 354 | /// If an even occurs in the mean time, the future will immediately report ready. |
| 355 | let waker = self.ch.waker(); | 355 | pub fn wait(&mut self) -> impl Future<Output = ()> { |
| 356 | // NOTE: This is `-> impl Future` and not an `async fn` on purpose. | ||
| 357 | // Otherwise, events will only be detected starting at the first poll of the returned future. | ||
| 358 | Self::wait_internal(&mut self.ch) | ||
| 359 | } | ||
| 360 | |||
| 361 | /// Asynchronously wait for the pin to become high. | ||
| 362 | /// | ||
| 363 | /// The channel must be configured with [`InputChannelPolarity::LoToHi`] or [`InputChannelPolarity::Toggle`]. | ||
| 364 | /// If the channel is not configured to detect rising edges, it is unspecified when the returned future completes. | ||
| 365 | /// | ||
| 366 | /// It is possible to call this function and await the returned future later. | ||
| 367 | /// If an even occurs in the mean time, the future will immediately report ready. | ||
| 368 | pub fn wait_for_high(&mut self) -> impl Future<Output = ()> { | ||
| 369 | // NOTE: This is `-> impl Future` and not an `async fn` on purpose. | ||
| 370 | // Otherwise, events will only be detected starting at the first poll of the returned future. | ||
| 371 | |||
| 372 | // Subscribe to the event before checking the pin level. | ||
| 373 | let wait = Self::wait_internal(&mut self.ch); | ||
| 374 | let pin = &self.pin; | ||
| 375 | async move { | ||
| 376 | if pin.is_high() { | ||
| 377 | return; | ||
| 378 | } | ||
| 379 | wait.await; | ||
| 380 | } | ||
| 381 | } | ||
| 382 | |||
| 383 | /// Asynchronously wait for the pin to become low. | ||
| 384 | /// | ||
| 385 | /// The channel must be configured with [`InputChannelPolarity::HiToLo`] or [`InputChannelPolarity::Toggle`]. | ||
| 386 | /// If the channel is not configured to detect falling edges, it is unspecified when the returned future completes. | ||
| 387 | /// | ||
| 388 | /// It is possible to call this function and await the returned future later. | ||
| 389 | /// If an even occurs in the mean time, the future will immediately report ready. | ||
| 390 | pub fn wait_for_low(&mut self) -> impl Future<Output = ()> { | ||
| 391 | // NOTE: This is `-> impl Future` and not an `async fn` on purpose. | ||
| 392 | // Otherwise, events will only be detected starting at the first poll of the returned future. | ||
| 393 | |||
| 394 | // Subscribe to the event before checking the pin level. | ||
| 395 | let wait = Self::wait_internal(&mut self.ch); | ||
| 396 | let pin = &self.pin; | ||
| 397 | async move { | ||
| 398 | if pin.is_low() { | ||
| 399 | return; | ||
| 400 | } | ||
| 401 | wait.await; | ||
| 402 | } | ||
| 403 | } | ||
| 404 | |||
| 405 | /// Internal implementation for `wait()` and friends. | ||
| 406 | fn wait_internal(channel: &mut Peri<'_, AnyChannel>) -> impl Future<Output = ()> { | ||
| 407 | // NOTE: This is `-> impl Future` and not an `async fn` on purpose. | ||
| 408 | // Otherwise, events will only be detected starting at the first poll of the returned future. | ||
| 409 | |||
| 410 | let g = channel.regs(); | ||
| 411 | let num = channel.number(); | ||
| 412 | let waker = channel.waker(); | ||
| 356 | 413 | ||
| 357 | // Enable interrupt | 414 | // Enable interrupt |
| 358 | g.events_in(num).write_value(0); | 415 | g.events_in(num).write_value(0); |
| 359 | g.intenset(INTNUM).write(|w| w.0 = 1 << num); | 416 | g.intenset(INTNUM).write(|w| w.0 = 1 << num); |
| 360 | 417 | ||
| 361 | poll_fn(|cx| { | 418 | poll_fn(move |cx| { |
| 362 | CHANNEL_WAKERS[waker].register(cx.waker()); | 419 | CHANNEL_WAKERS[waker].register(cx.waker()); |
| 363 | 420 | ||
| 364 | if g.events_in(num).read() != 0 { | 421 | if g.events_in(num).read() != 0 { |
| @@ -367,7 +424,6 @@ impl<'d> InputChannel<'d> { | |||
| 367 | Poll::Pending | 424 | Poll::Pending |
| 368 | } | 425 | } |
| 369 | }) | 426 | }) |
| 370 | .await; | ||
| 371 | } | 427 | } |
| 372 | 428 | ||
| 373 | /// Get the associated input pin. | 429 | /// Get the associated input pin. |
