1#![macro_use]
4
5use core::marker::PhantomData;
6
7use embassy_hal_internal::interrupt::InterruptExt;
8use embassy_hal_internal::{Peri, PeripheralType};
9
10use crate::interrupt::typelevel::Interrupt as _;
11use crate::{interrupt, pac};
12
13#[derive(Debug, PartialEq, Eq)]
15#[cfg_attr(feature = "defmt", derive(defmt::Format))]
16pub struct PrescalerOutOfRangeError(u32);
17
18#[derive(Debug, PartialEq, Eq)]
20#[cfg_attr(feature = "defmt", derive(defmt::Format))]
21pub struct CompareOutOfRangeError(u32);
22
23#[derive(Debug, Copy, Clone, PartialEq, Eq)]
25#[cfg_attr(feature = "defmt", derive(defmt::Format))]
26pub enum Interrupt {
27 Tick,
29 Overflow,
31 Compare0,
33 Compare1,
35 Compare2,
37 Compare3,
39}
40
41#[derive(Debug, Copy, Clone)]
43#[cfg_attr(feature = "defmt", derive(defmt::Format))]
44pub enum CompareChannel {
45 _0,
47 _1,
49 _2,
51 _3,
53}
54
55pub(crate) trait SealedInstance {
56 fn regs() -> pac::rtc::Rtc;
57}
58
59#[allow(private_bounds)]
61pub trait Instance: SealedInstance + PeripheralType + 'static + Send {
62 type Interrupt: crate::interrupt::typelevel::Interrupt;
64
65 unsafe fn steal() -> Peri<'static, Self>;
72}
73
74macro_rules! impl_rtc {
75 ($type:ident, $pac_type:ident, $irq:ident) => {
76 impl crate::rtc::SealedInstance for peripherals::$type {
77 #[inline]
78 fn regs() -> pac::rtc::Rtc {
79 unsafe { pac::rtc::Rtc::from_ptr(pac::$pac_type.as_ptr()) }
80 }
81 }
82
83 impl crate::rtc::Instance for peripherals::$type {
84 type Interrupt = crate::interrupt::typelevel::$irq;
85
86 unsafe fn steal() -> embassy_hal_internal::Peri<'static, Self> {
87 unsafe { peripherals::$type::steal() }
88 }
89 }
90 };
91}
92
93pub struct Rtc<'d> {
95 r: pac::rtc::Rtc,
96 irq: interrupt::Interrupt,
97 _phantom: PhantomData<&'d ()>,
98}
99
100impl<'d> Rtc<'d> {
101 pub fn new<T: Instance>(_rtc: Peri<'d, T>, prescaler: u32) -> Result<Self, PrescalerOutOfRangeError> {
105 if prescaler >= (1 << 12) {
106 return Err(PrescalerOutOfRangeError(prescaler));
107 }
108
109 T::regs().prescaler().write(|w| w.set_prescaler(prescaler as u16));
110 Ok(Self {
111 r: T::regs(),
112 irq: T::Interrupt::IRQ,
113 _phantom: PhantomData,
114 })
115 }
116
117 pub fn new_for_freq<T: Instance>(rtc: Peri<'d, T>, freq_hz: u32) -> Result<Self, PrescalerOutOfRangeError> {
119 let prescaler = (32_768 / freq_hz).saturating_sub(1);
120 Self::new(rtc, prescaler)
121 }
122
123 pub unsafe fn steal<T: Instance>() -> Self {
130 Self {
131 r: T::regs(),
132 irq: T::Interrupt::IRQ,
133 _phantom: PhantomData,
134 }
135 }
136
137 #[cfg(feature = "unstable-pac")]
139 #[inline]
140 pub fn regs(&mut self) -> pac::rtc::Rtc {
141 self.r
142 }
143
144 #[inline]
146 pub fn enable(&mut self) {
147 self.r.tasks_start().write_value(1);
148 }
149
150 #[inline]
152 pub fn disable(&mut self) {
153 self.r.tasks_stop().write_value(1);
154 }
155
156 pub fn enable_interrupt(&mut self, int: Interrupt, enable_in_nvic: bool) {
160 let regs = self.r;
161 match int {
162 Interrupt::Tick => regs.intenset().write(|w| w.set_tick(true)),
163 Interrupt::Overflow => regs.intenset().write(|w| w.set_ovrflw(true)),
164 Interrupt::Compare0 => regs.intenset().write(|w| w.set_compare(0, true)),
165 Interrupt::Compare1 => regs.intenset().write(|w| w.set_compare(1, true)),
166 Interrupt::Compare2 => regs.intenset().write(|w| w.set_compare(2, true)),
167 Interrupt::Compare3 => regs.intenset().write(|w| w.set_compare(3, true)),
168 }
169 if enable_in_nvic {
170 unsafe { self.irq.enable() };
171 }
172 }
173
174 pub fn disable_interrupt(&mut self, int: Interrupt, disable_in_nvic: bool) {
178 let regs = self.r;
179 match int {
180 Interrupt::Tick => regs.intenclr().write(|w| w.set_tick(true)),
181 Interrupt::Overflow => regs.intenclr().write(|w| w.set_ovrflw(true)),
182 Interrupt::Compare0 => regs.intenclr().write(|w| w.set_compare(0, true)),
183 Interrupt::Compare1 => regs.intenclr().write(|w| w.set_compare(1, true)),
184 Interrupt::Compare2 => regs.intenclr().write(|w| w.set_compare(2, true)),
185 Interrupt::Compare3 => regs.intenclr().write(|w| w.set_compare(3, true)),
186 }
187 if disable_in_nvic {
188 self.irq.disable();
189 }
190 }
191
192 pub fn enable_event(&mut self, evt: Interrupt) {
194 let regs = self.r;
195 match evt {
196 Interrupt::Tick => regs.evtenset().write(|w| w.set_tick(true)),
197 Interrupt::Overflow => regs.evtenset().write(|w| w.set_ovrflw(true)),
198 Interrupt::Compare0 => regs.evtenset().write(|w| w.set_compare(0, true)),
199 Interrupt::Compare1 => regs.evtenset().write(|w| w.set_compare(1, true)),
200 Interrupt::Compare2 => regs.evtenset().write(|w| w.set_compare(2, true)),
201 Interrupt::Compare3 => regs.evtenset().write(|w| w.set_compare(3, true)),
202 }
203 }
204
205 pub fn disable_event(&mut self, evt: Interrupt) {
207 let regs = self.r;
208 match evt {
209 Interrupt::Tick => regs.evtenclr().write(|w| w.set_tick(true)),
210 Interrupt::Overflow => regs.evtenclr().write(|w| w.set_ovrflw(true)),
211 Interrupt::Compare0 => regs.evtenclr().write(|w| w.set_compare(0, true)),
212 Interrupt::Compare1 => regs.evtenclr().write(|w| w.set_compare(1, true)),
213 Interrupt::Compare2 => regs.evtenclr().write(|w| w.set_compare(2, true)),
214 Interrupt::Compare3 => regs.evtenclr().write(|w| w.set_compare(3, true)),
215 }
216 }
217
218 pub fn reset_event(&mut self, evt: Interrupt) {
220 let regs = self.r;
221 match evt {
222 Interrupt::Tick => regs.events_tick().write_value(0),
223 Interrupt::Overflow => regs.events_ovrflw().write_value(0),
224 Interrupt::Compare0 => regs.events_compare(0).write_value(0),
225 Interrupt::Compare1 => regs.events_compare(1).write_value(0),
226 Interrupt::Compare2 => regs.events_compare(2).write_value(0),
227 Interrupt::Compare3 => regs.events_compare(3).write_value(0),
228 }
229 }
230
231 pub fn is_event_triggered(&self, evt: Interrupt) -> bool {
233 let regs = self.r;
234 let val = match evt {
235 Interrupt::Tick => regs.events_tick().read(),
236 Interrupt::Overflow => regs.events_ovrflw().read(),
237 Interrupt::Compare0 => regs.events_compare(0).read(),
238 Interrupt::Compare1 => regs.events_compare(1).read(),
239 Interrupt::Compare2 => regs.events_compare(2).read(),
240 Interrupt::Compare3 => regs.events_compare(3).read(),
241 };
242 val == 1
243 }
244
245 pub fn set_compare(&mut self, reg: CompareChannel, val: u32) -> Result<(), CompareOutOfRangeError> {
248 if val >= (1 << 24) {
249 return Err(CompareOutOfRangeError(val));
250 }
251
252 let reg = match reg {
253 CompareChannel::_0 => 0,
254 CompareChannel::_1 => 1,
255 CompareChannel::_2 => 2,
256 CompareChannel::_3 => 3,
257 };
258
259 self.r.cc(reg).write(|w| w.set_compare(val));
260 Ok(())
261 }
262
263 #[inline]
265 pub fn clear(&self) {
266 self.r.tasks_clear().write_value(1);
267 }
268
269 #[inline]
271 pub fn read(&self) -> u32 {
272 self.r.counter().read().counter()
273 }
274}