diff options
| -rw-r--r-- | embassy-stm32/src/time_driver.rs | 19 | ||||
| -rw-r--r-- | embassy-time/src/driver.rs | 4 |
2 files changed, 20 insertions, 3 deletions
diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs index ea9c22d87..9981800b2 100644 --- a/embassy-stm32/src/time_driver.rs +++ b/embassy-stm32/src/time_driver.rs | |||
| @@ -474,16 +474,29 @@ impl Driver for RtcDriver { | |||
| 474 | return false; | 474 | return false; |
| 475 | } | 475 | } |
| 476 | 476 | ||
| 477 | let safe_timestamp = timestamp.max(t + 3); | ||
| 478 | |||
| 479 | // Write the CCR value regardless of whether we're going to enable it now or not. | 477 | // Write the CCR value regardless of whether we're going to enable it now or not. |
| 480 | // This way, when we enable it later, the right value is already set. | 478 | // This way, when we enable it later, the right value is already set. |
| 481 | r.ccr(n + 1).write(|w| w.set_ccr(safe_timestamp as u16)); | 479 | r.ccr(n + 1).write(|w| w.set_ccr(timestamp as u16)); |
| 482 | 480 | ||
| 483 | // Enable it if it'll happen soon. Otherwise, `next_period` will enable it. | 481 | // Enable it if it'll happen soon. Otherwise, `next_period` will enable it. |
| 484 | let diff = timestamp - t; | 482 | let diff = timestamp - t; |
| 485 | r.dier().modify(|w| w.set_ccie(n + 1, diff < 0xc000)); | 483 | r.dier().modify(|w| w.set_ccie(n + 1, diff < 0xc000)); |
| 486 | 484 | ||
| 485 | // Reevaluate if the alarm timestamp is still in the future | ||
| 486 | let t = self.now(); | ||
| 487 | if timestamp <= t { | ||
| 488 | // If alarm timestamp has passed since we set it, we have a race condition and | ||
| 489 | // the alarm may or may not have fired. | ||
| 490 | // Disarm the alarm and return `false` to indicate that. | ||
| 491 | // It is the caller's responsibility to handle this ambiguity. | ||
| 492 | r.dier().modify(|w| w.set_ccie(n + 1, false)); | ||
| 493 | |||
| 494 | alarm.timestamp.set(u64::MAX); | ||
| 495 | |||
| 496 | return false; | ||
| 497 | } | ||
| 498 | |||
| 499 | // We're confident the alarm will ring in the future. | ||
| 487 | true | 500 | true |
| 488 | }) | 501 | }) |
| 489 | } | 502 | } |
diff --git a/embassy-time/src/driver.rs b/embassy-time/src/driver.rs index 5fe7becaf..81ee1b0f5 100644 --- a/embassy-time/src/driver.rs +++ b/embassy-time/src/driver.rs | |||
| @@ -108,6 +108,10 @@ pub trait Driver: Send + Sync + 'static { | |||
| 108 | /// The `Driver` implementation should guarantee that the alarm callback is never called synchronously from `set_alarm`. | 108 | /// The `Driver` implementation should guarantee that the alarm callback is never called synchronously from `set_alarm`. |
| 109 | /// Rather - if `timestamp` is already in the past - `false` should be returned and alarm should not be set, | 109 | /// Rather - if `timestamp` is already in the past - `false` should be returned and alarm should not be set, |
| 110 | /// or alternatively, the driver should return `true` and arrange to call the alarm callback as soon as possible, but not synchronously. | 110 | /// or alternatively, the driver should return `true` and arrange to call the alarm callback as soon as possible, but not synchronously. |
| 111 | /// There is a rare third possibility that the alarm was barely in the future, and by the time it was enabled, it had slipped into the | ||
| 112 | /// past. This is can be detected by double-checking that the alarm is still in the future after enabling it; if it isn't, `false` | ||
| 113 | /// should also be returned to indicate that the callback may have been called already by the alarm, but it is not guaranteed, so the | ||
| 114 | /// caller should also call the callback, just like in the more common `false` case. (Note: This requires idempotency of the callback.) | ||
| 111 | /// | 115 | /// |
| 112 | /// When callback is called, it is guaranteed that now() will return a value greater or equal than timestamp. | 116 | /// When callback is called, it is guaranteed that now() will return a value greater or equal than timestamp. |
| 113 | /// | 117 | /// |
