aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/timer/mod.rs
diff options
context:
space:
mode:
authorMatous Hybl <[email protected]>2021-12-08 17:36:40 +0100
committerMatous Hybl <[email protected]>2022-01-13 16:05:54 +0100
commita1f7a94c6924a5344ed29b60e11be673ca04bfcb (patch)
tree3c94336975c5a3be585997b136a080cca6e0d522 /embassy-stm32/src/timer/mod.rs
parent0d67ceb066f7b6d3b0163eaa3688b0499439a21c (diff)
Add low level timer API.
Diffstat (limited to 'embassy-stm32/src/timer/mod.rs')
-rw-r--r--embassy-stm32/src/timer/mod.rs224
1 files changed, 224 insertions, 0 deletions
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
new file mode 100644
index 000000000..ed2cb2d97
--- /dev/null
+++ b/embassy-stm32/src/timer/mod.rs
@@ -0,0 +1,224 @@
1use embassy::interrupt::Interrupt;
2
3use crate::rcc::{sealed::RccPeripheral as __RccPeri, RccPeripheral};
4use crate::time::Hertz;
5use stm32_metapac::timer::vals;
6
7#[cfg(feature = "unstable-pac")]
8pub mod low_level {
9 pub use super::sealed::*;
10}
11
12pub(crate) mod sealed {
13 use super::*;
14 pub trait Basic16bitInstance: RccPeripheral {
15 type Interrupt: Interrupt;
16
17 fn regs(&self) -> crate::pac::timer::TimBasic;
18
19 fn start(&mut self);
20
21 fn stop(&mut self);
22
23 fn reset(&mut self);
24
25 fn set_frequency<F: Into<Hertz>>(&mut self, frequency: F);
26
27 fn clear_update_interrupt(&mut self) -> bool;
28
29 fn enable_update_interrupt(&mut self, enable: bool);
30 }
31
32 pub trait GeneralPurpose16bitInstance: Basic16bitInstance {
33 fn regs_gp16(&self) -> crate::pac::timer::TimGp16;
34 }
35
36 pub trait GeneralPurpose32bitInstance: GeneralPurpose16bitInstance {
37 fn regs_gp32(&self) -> crate::pac::timer::TimGp32;
38
39 fn set_frequency<F: Into<Hertz>>(&mut self, frequency: F);
40 }
41
42 pub trait AdvancedControlInstance: GeneralPurpose16bitInstance {
43 fn regs_advanced(&self) -> crate::pac::timer::TimAdv;
44 }
45}
46
47pub trait GeneralPurpose16bitInstance: sealed::GeneralPurpose16bitInstance + 'static {}
48
49pub trait GeneralPurpose32bitInstance: sealed::GeneralPurpose32bitInstance + 'static {}
50
51pub trait AdvancedControlInstance: sealed::AdvancedControlInstance + 'static {}
52
53pub trait Basic16bitInstance: sealed::Basic16bitInstance + 'static {}
54
55#[allow(unused)]
56macro_rules! impl_basic_16bit_timer {
57 ($inst:ident, $irq:ident) => {
58 impl sealed::Basic16bitInstance for crate::peripherals::$inst {
59 type Interrupt = crate::interrupt::$irq;
60
61 fn regs(&self) -> crate::pac::timer::TimBasic {
62 crate::pac::timer::TimBasic(crate::pac::$inst.0)
63 }
64
65 fn start(&mut self) {
66 unsafe {
67 self.regs().cr1().modify(|r| r.set_cen(true));
68 }
69 }
70
71 fn stop(&mut self) {
72 let regs = self.regs();
73 unsafe {
74 regs.cr1().modify(|r| r.set_cen(false));
75 }
76 }
77
78 fn reset(&mut self) {
79 unsafe {
80 self.regs().cnt().write(|r| r.set_cnt(0));
81 }
82 }
83
84 fn set_frequency<F: Into<Hertz>>(&mut self, frequency: F) {
85 use core::convert::TryInto;
86 let f = frequency.into().0;
87 let timer_f = Self::frequency().0;
88 let pclk_ticks_per_timer_period = timer_f / f;
89 let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 16)).try_into());
90 let arr: u16 =
91 unwrap!((pclk_ticks_per_timer_period / (u32::from(psc) + 1)).try_into());
92
93 let regs = self.regs();
94 unsafe {
95 regs.psc().write(|r| r.set_psc(psc));
96 regs.arr().write(|r| r.set_arr(arr));
97
98 regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY));
99 regs.egr().write(|r| r.set_ug(true));
100 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT));
101 }
102 }
103
104 fn clear_update_interrupt(&mut self) -> bool {
105 unsafe {
106 let sr = self.regs().sr().read();
107 if sr.uif() {
108 self.regs().sr().modify(|r| {
109 r.set_uif(false);
110 });
111 true
112 } else {
113 false
114 }
115 }
116 }
117
118 fn enable_update_interrupt(&mut self, enable: bool) {
119 unsafe {
120 self.regs().dier().write(|r| r.set_uie(enable));
121 }
122 }
123 }
124 };
125}
126
127#[allow(unused)]
128macro_rules! impl_32bit_timer {
129 ($inst:ident) => {
130 impl sealed::GeneralPurpose32bitInstance for crate::peripherals::$inst {
131 fn regs_gp32(&self) -> crate::pac::timer::TimGp32 {
132 crate::pac::$inst
133 }
134
135 fn set_frequency<F: Into<Hertz>>(&mut self, frequency: F) {
136 use core::convert::TryInto;
137 let f = frequency.into().0;
138 let timer_f = Self::frequency().0;
139 let pclk_ticks_per_timer_period = (timer_f / f) as u64;
140 let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 32)).try_into());
141 let arr: u32 =
142 unwrap!(((pclk_ticks_per_timer_period / (psc as u64 + 1)).try_into()));
143
144 let regs = self.regs_gp32();
145 unsafe {
146 regs.psc().write(|r| r.set_psc(psc));
147 regs.arr().write(|r| r.set_arr(arr));
148
149 regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY));
150 regs.egr().write(|r| r.set_ug(true));
151 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT));
152 }
153 }
154 }
155 };
156}
157
158crate::pac::interrupts! {
159 ($inst:ident, timer, TIM_BASIC, UP, $irq:ident) => {
160 impl_basic_16bit_timer!($inst, $irq);
161
162 impl Basic16bitInstance for crate::peripherals::$inst {
163 }
164 };
165 ($inst:ident, timer, TIM_GP16, UP, $irq:ident) => {
166 impl_basic_16bit_timer!($inst, $irq);
167
168 impl Basic16bitInstance for crate::peripherals::$inst {
169 }
170
171 impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst {
172 fn regs_gp16(&self) -> crate::pac::timer::TimGp16 {
173 crate::pac::$inst
174 }
175 }
176
177 impl GeneralPurpose16bitInstance for crate::peripherals::$inst {
178 }
179 };
180
181 ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => {
182 impl_basic_16bit_timer!($inst, $irq);
183
184 impl Basic16bitInstance for crate::peripherals::$inst {
185 }
186
187 impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst {
188 fn regs_gp16(&self) -> crate::pac::timer::TimGp16 {
189 crate::pac::timer::TimGp16(crate::pac::$inst.0)
190 }
191 }
192
193 impl GeneralPurpose16bitInstance for crate::peripherals::$inst {
194 }
195
196 impl_32bit_timer!($inst);
197
198 impl GeneralPurpose32bitInstance for crate::peripherals::$inst {
199 }
200 };
201
202 ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => {
203 impl_basic_16bit_timer!($inst, $irq);
204
205 impl Basic16bitInstance for crate::peripherals::$inst {
206 }
207
208 impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst {
209 fn regs_gp16(&self) -> crate::pac::timer::TimGp16 {
210 crate::pac::timer::TimGp16(crate::pac::$inst.0)
211 }
212 }
213
214 impl GeneralPurpose16bitInstance for crate::peripherals::$inst {
215 }
216 impl sealed::AdvancedControlInstance for crate::peripherals::$inst {
217 fn regs_advanced(&self) -> crate::pac::timer::TimAdv {
218 crate::pac::$inst
219 }
220 }
221 impl AdvancedControlInstance for crate::peripherals::$inst {
222 }
223 };
224}