|
1 | | -use crate::stm32; |
2 | | - |
3 | | -use super::timer; |
4 | | - |
5 | | -#[cfg(feature = "stm32g4")] |
6 | | -use crate::hal::dma::PeripheralToMemory; |
7 | | -#[cfg(feature = "stm32g4")] |
8 | | -use crate::mcu::DmaMuxResources; |
9 | | - |
| 1 | +use super::timer::{self, Ch1, Ch2, ChExt, InstanceX}; |
| 2 | +use crate::ext::{Cptcr, MasterExt, TimExt}; |
10 | 3 | use core::marker::PhantomData; |
11 | | -#[cfg(feature = "hrtim_v2")] |
12 | | -use stm32::HRTIM_TIMF; |
13 | | -use stm32::{HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME}; |
14 | | - |
15 | | -pub struct Ch1; |
16 | | -pub struct Ch2; |
17 | 4 |
|
18 | 5 | pub struct Dma; |
19 | 6 | pub struct NoDma; |
@@ -168,121 +155,101 @@ pub fn dma_value_to_signed(x: u32, #[allow(unused_variables)] period: u16) -> i3 |
168 | 155 | } |
169 | 156 | } |
170 | 157 |
|
171 | | -macro_rules! impl_capture { |
172 | | - ($($TIMX:ident),+) => {$( |
173 | | - impl_capture!($TIMX: Ch1, cpt1r, cpt1cr, cpt1, cpt1ie, cpt1de, cpt1c); |
174 | | - impl_capture!($TIMX: Ch2, cpt2r, cpt2cr, cpt2, cpt2ie, cpt2de, cpt2c); |
175 | | - )+}; |
176 | | - |
177 | | - ($TIMX:ident: $CH:ident, $cptXr:ident, $cptXcr:ident, $cptX:ident, $cptXie:ident, $cptXde:ident, $cptXc:ident) => { |
178 | | - impl<PSCL> HrCapt<$TIMX, PSCL, $CH, NoDma> { |
179 | | - /// Add event to capture |
180 | | - /// |
181 | | - /// If multiple events are added, they will be ORed together meaning |
182 | | - /// that a capture will be trigger if any one of the events triggers |
183 | | - pub fn add_event<E: CaptureEvent<$TIMX, PSCL>>(&mut self, _event: &E) { |
184 | | - let tim = unsafe { &*$TIMX::ptr() }; |
185 | | - |
186 | | - // SAFETY: We are the only one with access to cptXYcr |
187 | | - unsafe { |
188 | | - tim.$cptXcr().modify(|r, w| w.bits(r.bits() | E::BITS)); |
189 | | - } |
190 | | - } |
191 | | - |
192 | | - /// Remove event to capture |
193 | | - pub fn remove_event<E: CaptureEvent<$TIMX, PSCL>>(&mut self, _event: &E) { |
194 | | - let tim = unsafe { &*$TIMX::ptr() }; |
195 | | - |
196 | | - // SAFETY: We are the only one with access to cptXYcr |
197 | | - unsafe { |
198 | | - tim.$cptXcr().modify(|r, w| w.bits(r.bits() & !E::BITS)); |
199 | | - } |
200 | | - } |
201 | | - |
202 | | - /// Force capture trigger now |
203 | | - pub fn trigger_now(&mut self) { |
204 | | - // SAFETY: We are the only one with access to cptXYcr |
205 | | - let tim = unsafe { &*$TIMX::ptr() }; |
206 | | - |
207 | | - tim.$cptXcr().modify(|_, w| w.swcpt().set_bit()); |
208 | | - } |
209 | | - |
210 | | - // TODO: It would be sufficient to instead of hr_control only require exclusive access to the owning timer |
211 | | - // however that would be hard to do since typically the capture device is a field of that same timer. |
212 | | - // Would it make more sense to have this method direcly on HrTim instead? |
213 | | - pub fn enable_interrupt(&mut self, enable: bool, _hr_control: &mut super::HrPwmControl) { |
214 | | - let tim = unsafe { &*$TIMX::ptr() }; |
215 | | - |
216 | | - tim.dier().modify(|_r, w| w.$cptXie().bit(enable)); |
217 | | - } |
218 | | - |
219 | | - pub fn enable_dma(self, _ch: timer::DmaChannel<$TIMX>) -> HrCapt<$TIMX, PSCL, $CH, Dma> { |
220 | | - // SAFETY: We own the only insance of this timers dma channel, no one else can do this |
221 | | - let tim = unsafe { &*$TIMX::ptr() }; |
222 | | - tim.dier().modify(|_r, w| w.$cptXde().set_bit()); |
223 | | - HrCapt { |
224 | | - _x: PhantomData |
225 | | - } |
226 | | - } |
| 158 | +impl<TIM: InstanceX, CH: ChExt, PSCL> HrCapt<TIM, PSCL, CH, NoDma> { |
| 159 | + /// Add event to capture |
| 160 | + /// |
| 161 | + /// If multiple events are added, they will be ORed together meaning |
| 162 | + /// that a capture will be trigger if any one of the events triggers |
| 163 | + pub fn add_event<E: CaptureEvent<TIM, PSCL>>(&mut self, _event: &E) { |
| 164 | + let tim = unsafe { &*TIM::ptr() }; |
| 165 | + |
| 166 | + // SAFETY: We are the only one with access to cptXYcr |
| 167 | + unsafe { |
| 168 | + tim.cptcr(CH::CH).modify(|r, w| w.bits(r.bits() | E::BITS)); |
| 169 | + } |
| 170 | + } |
| 171 | + |
| 172 | + /// Remove event to capture |
| 173 | + pub fn remove_event<E: CaptureEvent<TIM, PSCL>>(&mut self, _event: &E) { |
| 174 | + let tim = unsafe { &*TIM::ptr() }; |
| 175 | + |
| 176 | + // SAFETY: We are the only one with access to cptXYcr |
| 177 | + unsafe { |
| 178 | + tim.cptcr(CH::CH).modify(|r, w| w.bits(r.bits() & !E::BITS)); |
227 | 179 | } |
| 180 | + } |
| 181 | + |
| 182 | + /// Force capture trigger now |
| 183 | + pub fn trigger_now(&mut self) { |
| 184 | + // SAFETY: We are the only one with access to cptXYcr |
| 185 | + let tim = unsafe { &*TIM::ptr() }; |
| 186 | + |
| 187 | + tim.cptcr(CH::CH) |
| 188 | + .modify(|_, w| <TIM::RB as TimExt>::CPT1CRrs::set_swcpt(w)); |
| 189 | + } |
228 | 190 |
|
229 | | - impl<PSCL, DMA> HrCapture for HrCapt<$TIMX, PSCL, $CH, DMA> { |
230 | | - fn get_last(&self) -> (u16, CountingDirection) { |
231 | | - let tim = unsafe { &*$TIMX::ptr() }; |
232 | | - let data = tim.$cptXr().read(); |
| 191 | + // TODO: It would be sufficient to instead of hr_control only require exclusive access to the owning timer |
| 192 | + // however that would be hard to do since typically the capture device is a field of that same timer. |
| 193 | + // Would it make more sense to have this method direcly on HrTim instead? |
| 194 | + pub fn enable_interrupt(&mut self, enable: bool, _hr_control: &mut super::HrPwmControl) { |
| 195 | + let tim = unsafe { &*TIM::ptr() }; |
233 | 196 |
|
234 | | - #[cfg(feature = "hrtim_v2")] |
235 | | - let dir = match data.dir().bit() { |
236 | | - true => CountingDirection::Down, |
237 | | - false => CountingDirection::Up, |
238 | | - }; |
239 | | - #[cfg(any(feature = "hrtim_v1", feature = "hrtim_v1_1"))] |
240 | | - let dir = CountingDirection::Up; |
| 197 | + tim.dier().modify(|_r, w| w.cptie(CH::CH as _).bit(enable)); |
| 198 | + } |
241 | 199 |
|
242 | | - let value = data.cpt().bits(); |
| 200 | + pub fn enable_dma(self, _ch: timer::DmaChannel<TIM>) -> HrCapt<TIM, PSCL, CH, Dma> { |
| 201 | + // SAFETY: We own the only insance of this timers dma channel, no one else can do this |
| 202 | + let tim = unsafe { &*TIM::ptr() }; |
| 203 | + tim.dier().modify(|_r, w| w.cptde(CH::CH as _).set_bit()); |
| 204 | + HrCapt { _x: PhantomData } |
| 205 | + } |
| 206 | +} |
243 | 207 |
|
244 | | - (value, dir) |
245 | | - } |
| 208 | +impl<TIM: InstanceX, CH: ChExt, PSCL, DMA> HrCapture for HrCapt<TIM, PSCL, CH, DMA> { |
| 209 | + fn get_last(&self) -> (u16, CountingDirection) { |
| 210 | + let tim = unsafe { &*TIM::ptr() }; |
| 211 | + let data = tim.cptr(CH::CH).read(); |
246 | 212 |
|
247 | | - fn clear_interrupt(&mut self) { |
248 | | - let tim = unsafe { &*$TIMX::ptr() }; |
| 213 | + #[cfg(feature = "hrtim_v2")] |
| 214 | + let dir = match data.dir().bit() { |
| 215 | + true => CountingDirection::Down, |
| 216 | + false => CountingDirection::Up, |
| 217 | + }; |
| 218 | + #[cfg(any(feature = "hrtim_v1", feature = "hrtim_v1_1"))] |
| 219 | + let dir = CountingDirection::Up; |
249 | 220 |
|
250 | | - // No need for exclusive access since this is a write only register |
251 | | - tim.icr().write(|w| w.$cptXc().clear()); |
252 | | - } |
| 221 | + let value = data.cpt().bits(); |
253 | 222 |
|
254 | | - fn is_pending(&self) -> bool { |
255 | | - let tim = unsafe { &*$TIMX::ptr() }; |
| 223 | + (value, dir) |
| 224 | + } |
256 | 225 |
|
257 | | - // No need for exclusive access since this is a read only register |
258 | | - tim.isr().read().$cptX().bit() |
259 | | - } |
260 | | - } |
| 226 | + fn clear_interrupt(&mut self) { |
| 227 | + let tim = unsafe { &*TIM::ptr() }; |
261 | 228 |
|
262 | | - #[cfg(feature = "stm32g4")] |
263 | | - unsafe impl<PSCL> crate::hal::dma::traits::TargetAddress<PeripheralToMemory> for HrCapt<$TIMX, PSCL, $CH, Dma> { |
264 | | - #[inline(always)] |
265 | | - fn address(&self) -> u32 { |
266 | | - let tim = unsafe { &*$TIMX::ptr() }; |
267 | | - &tim.$cptXr() as *const _ as u32 |
268 | | - } |
| 229 | + // No need for exclusive access since this is a write only register |
| 230 | + tim.icr().write(|w| w.cptc(CH::CH as _).clear()); |
| 231 | + } |
269 | 232 |
|
270 | | - type MemSize = u32; |
| 233 | + fn is_pending(&self) -> bool { |
| 234 | + let tim = unsafe { &*TIM::ptr() }; |
271 | 235 |
|
272 | | - const REQUEST_LINE: Option<u8> = Some(DmaMuxResources::$TIMX as u8); |
273 | | - } |
274 | | - }; |
| 236 | + // No need for exclusive access since this is a read only register |
| 237 | + tim.isr().read().cpt(CH::CH as _).bit() |
| 238 | + } |
275 | 239 | } |
276 | 240 |
|
277 | | -impl_capture! { |
278 | | - HRTIM_TIMA, |
279 | | - HRTIM_TIMB, |
280 | | - HRTIM_TIMC, |
281 | | - HRTIM_TIMD, |
282 | | - HRTIM_TIME |
283 | | -} |
| 241 | +#[cfg(feature = "stm32g4")] |
| 242 | +unsafe impl<TIM: InstanceX, CH: ChExt, PSCL> |
| 243 | + crate::hal::dma::traits::TargetAddress<crate::hal::dma::PeripheralToMemory> |
| 244 | + for HrCapt<TIM, PSCL, CH, Dma> |
| 245 | +{ |
| 246 | + #[inline(always)] |
| 247 | + fn address(&self) -> u32 { |
| 248 | + let tim = unsafe { &*TIM::ptr() }; |
| 249 | + &tim.cptr(CH::CH) as *const _ as u32 |
| 250 | + } |
| 251 | + |
| 252 | + type MemSize = u32; |
284 | 253 |
|
285 | | -#[cfg(feature = "hrtim_v2")] |
286 | | -impl_capture! { |
287 | | - HRTIM_TIMF |
| 254 | + const REQUEST_LINE: Option<u8> = Some(TIM::DMA_MUX as u8); |
288 | 255 | } |
0 commit comments