1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
//! [`Monotonic`](rtic_time::Monotonic) implementations using the Real Time
//! Clock (RTC).
//!
//! Enabling the `rtic` feature is required to use this module.
//!
//! For RTIC v1, the old [`rtic_monotonic::Monotonic`] trait is implemented for
//! [`Rtc`](crate::rtc::Rtc) in [`Count32Mode`](crate::rtc::Count32Mode) in the
//! [`v1`] module. A monotonic for RTIC v2 is provided here.
//!
//! # RTC clock selection
//!
//! Prior to starting the monotonic, the RTC clock source must be configured
//! using [`clocks`](crate::clock). On SAMD11/21 platforms, the RTC clock must
//! be setup as a [generic clock](crate::clock::GenericClockController).
//! On SAMx5x platforms the RTC clock must be selected from either the 1.1024
//! kHz clock or the 32.768 kHz clock, either of which can be internal or
//! external.
//!
//! **NOTE: Eventually, starting the monotonic will require proof that the RTC
//! clock has been configured. However, this requires v2 of the clock API for
//! SAMx5x chips, which is not yet fully supported in the rest of the HAL.**
//!
//! # RTC modes
//!
//! The RTC on all chip variants has two counter modes: mode 0 features a 32-bit
//! hardware counter, and mode 1 features a a 16-bit hardware counter but some
//! additional features. Part of the [`Monotonic`](rtic_time::Monotonic)
//! contract is that the monotonic should always count up and never roll over
//! back to time zero. However, even the 32-bit hardware counter will overflow
//! after about 36 hours using the faster clock rate, which is not acceptable.
//!
//! A technique known as [half-period counting
//! (HPC)](rtic_time::half_period_counter) is used to effectively increase the
//! montononic counter to be 64 bits wide in either mode. The result is a
//! monotonic that effectively counts up forever without rolling over. This
//! technique requires two compare registers, one for waking RTIC tasks and one
//! for HPC. The number of compare registers available on ATSAMD chips is as
//! follows:
//!
//! | | SAMD11/21 | SAMx5x |
//! | -----------| --------- | ------ |
//! | **Mode 0** | 1 | 2 |
//! | **Mode 1** | 2 | 4 |
//!
//! As a result, HPC can be done in mode 0 for SAMx5x chips but requires mode 1
//! for SAMD11/21 variants. The monotonic provided for each variant uses the
//! appropriate RTC mode.
//!
//! The monotonics have the following specifications:
//!
//! | | 1 kHz clock | 32 kHz clock |
//! | ------------------------------------ | ------------------ | ------------------- |
//! | **Rollover period** | ~571 million years | ~17.8 million years |
//! | **HPC interrupt period (SAMD11/21)** | 32 seconds | 1 second |
//! | **HPC interrupt period (SAMx5x)** | ~24 days | ~18 hours |
//! | **Time resolution** | ~977 μs | ~31 μs |
//!
//! # Usage
//!
//! The monotonic should be created using the
//! [macro](crate::rtc_monotonic). The first macro argument is the name of
//! the global structure that will implement
//! [`Monotonic`](rtic_time::Monotonic). The RTC clock rate must be
//! known at compile time, and so the appropriate type from [`rtc_clock`] must
//! be passed to the macro as the second argument.
//!
//! Sometime during initialization, the monotonic also must be started by
//! calling the `start` method on the created monotonic. The
//! [`Rtc`](crate::pac::Rtc) peripheral struct must be passed to `start` to
//! ensure that the monotonic has complete control of the RTC.
//!
//! Note that the macro creates the RTC interrupt handler, and starting the
//! monotonic enables RTC interrupts in the NVIC, so that this does not need to
//! be done manually.
//!
//! # Example
//!
//! ```
//! use atsamd_hal::prelude::*;
//! use atsamd_hal::rtc::rtic::rtc_clock;
//!
//! // Create the monotonic struct named `Mono`
//! rtc_monotonic!(Mono, rtc_clock::Clock32k);
//!
//! // Uncomment if not using the RTIC RTOS:
//! // #[unsafe(no_mangle)]
//! // static RTIC_ASYNC_MAX_LOGICAL_PRIO: u8 = 1;
//! //
//! // This tells the monotonic driver the maximum interrupt
//! // priority it's allowed to use. RTIC sets it automatically,
//! // but you need to set it manually if you're writing
//! // a RTIC-less app.
//!
//! fn init() {
//! # // This is normally provided by the selected PAC
//! # let rtc = unsafe { core::mem::transmute(()) };
//! # let mut mclk = unsafe { core::mem::transmute(()) };
//! # let mut osc32kctrl = unsafe { core::mem::transmute(()) };
//! // Here the RTC clock source should be configured using the clocks API
//!
//! // Start the monotonic
//! Mono::start(rtc);
//! }
//!
//! async fn usage() {
//! loop {
//! // Use the monotonic
//! let timestamp = Mono::now();
//!
//! Mono::delay_until(timestamp + 2u32.secs()).await;
//! Mono::delay(100u32.millis()).await;
//! }
//! }
//! ```
//!
//! # Other notes
//!
//! The number returned by
//! [`Monotonic::now().ticks()`](rtic_monotonic::Monotonic::now) will always
//! increase (barring monotonic rollover). However, due to the register
//! [synchronization delay](https://onlinedocs.microchip.com/oxy/GUID-F5813793-E016-46F5-A9E2-718D8BCED496-en-US-14/GUID-0C52DB00-4BF6-4F41-85B5-B76529875364.html),
//! the number returned may not always increment by one every time it changes.
//! In fact, testing shows that it typically increments by four every time it
//! changes. This is true regardless of the clock rate used, as the
//! synchronization delay scales along with the clock period.
/// Items for RTIC v1.
///
/// This mainly implements [`rtic_monotonic::Monotonic`] for
/// [`Rtc<Count32Mode>`](crate::rtc::Rtc).
///
/// This will be removed in a future release, users should migrate to RTIC v2.
use ;
use ;
use crate;
use hal_cfg;
/// Types used to specify the RTC clock rate at compile time when creating the
/// monotonics.
///
/// These types utilize [type-level programming](crate::typelevel)
/// techniques and are passed to the [monotonic creation
/// macro](crate::rtc_monotonic).
/// The RTC clock rate must be specified at compile time so that the `Instant`
/// and `Duration` types in
/// [`TimerQueueBasedMonotonic`](rtic_time::monotonic::TimerQueueBasedMonotonic)
/// can be specified.
pub use RtcBackend;
,
>;
type Duration = $crateDuration <$clock_rate>RATE_HZ },
>;
}
$crateimpl_embedded_hal_delay_fugit!;
$crateimpl_embedded_hal_async_delay_fugit!;
};
}
/// Create an RTIC v2 monotonic that uses the RTC.
///
/// See the [`rtic`](crate::rtc::rtic) module for details.
/// This function was modified from the private function in `rtic-monotonics`,
/// part of the [`rtic`](https://github.com/rtic-rs/rtic) project.
///
/// Note that this depends on the static variable `RTIC_ASYNC_MAX_LOGICAL_PRIO`
/// defined as part of RTIC. Refer to the example in the [`rtic`
/// module](crate::rtc::rtic) documentation for more details.
///
/// See LICENSE-MIT and LICENSE-APACHE for the licenses.
unsafe