Skip to content

Commit b73e7eb

Browse files
committed
Improve timer modules
1 parent b3409e7 commit b73e7eb

File tree

20 files changed

+1216
-1179
lines changed

20 files changed

+1216
-1179
lines changed

src/common/timer.rs

Lines changed: 0 additions & 29 deletions
This file was deleted.

src/common/timer/counter.rs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
use super::*;
2+
use fugit::{HertzU32 as Hertz, MicrosDurationU32};
3+
4+
/// Hardware timers
5+
pub struct CounterHz<TIM> {
6+
pub(crate) tim: TIM,
7+
pub(crate) clk: Hertz,
8+
}
9+
10+
impl<TIM: GeneralTimer> CounterHz<TIM> {
11+
pub fn start(&mut self, timeout: Hertz) -> Result<(), Error> {
12+
// pause
13+
self.tim.disable_counter();
14+
15+
self.tim.clear_interrupt_flag(Event::Update);
16+
17+
// reset counter
18+
self.tim.reset_counter();
19+
20+
let clk = self.clk;
21+
self.tim.config_freq(clk, clk, timeout);
22+
23+
// start counter
24+
self.tim.enable_counter();
25+
26+
Ok(())
27+
}
28+
29+
pub fn wait(&mut self) -> nb::Result<(), Error> {
30+
if self.tim.get_interrupt_flag().contains(Event::Update) {
31+
self.tim.clear_interrupt_flag(Event::Update);
32+
Ok(())
33+
} else {
34+
Err(nb::Error::WouldBlock)
35+
}
36+
}
37+
38+
pub fn cancel(&mut self) -> Result<(), Error> {
39+
if !self.tim.is_counter_enabled() {
40+
return Err(Error::Disabled);
41+
}
42+
43+
// disable counter
44+
self.tim.disable_counter();
45+
Ok(())
46+
}
47+
48+
/// Restarts the timer in count down mode with user-defined prescaler and auto-reload register
49+
pub fn start_raw(&mut self, psc: u16, arr: u16) {
50+
// pause
51+
self.tim.disable_counter();
52+
53+
self.tim.set_prescaler(psc);
54+
55+
self.tim.set_auto_reload(arr as u32).unwrap();
56+
57+
// Trigger an update event to load the prescaler value to the clock
58+
self.tim.trigger_update();
59+
60+
// start counter
61+
self.tim.enable_counter();
62+
}
63+
64+
/// Retrieves the content of the prescaler register. The real prescaler is this value + 1.
65+
pub fn psc(&self) -> u16 {
66+
self.tim.read_prescaler()
67+
}
68+
69+
/// Retrieves the value of the auto-reload register.
70+
pub fn arr(&self) -> u16 {
71+
self.tim.read_auto_reload() as u16
72+
}
73+
74+
/// Resets the counter
75+
pub fn reset(&mut self) {
76+
// Sets the URS bit to prevent an interrupt from being triggered by
77+
// the UG bit
78+
self.tim.trigger_update();
79+
}
80+
81+
/// Returns the number of microseconds since the last update event.
82+
/// *NOTE:* This method is not a very good candidate to keep track of time, because
83+
/// it is very easy to lose an update event.
84+
pub fn now(&self) -> MicrosDurationU32 {
85+
let psc = self.tim.read_prescaler() as u32;
86+
87+
// freq_divider is always bigger than 0, since (psc + 1) is always less than
88+
// timer_clock
89+
let freq_divider = (self.clk.raw() / (psc + 1)) as u64;
90+
let cnt: u32 = self.tim.read_count().into();
91+
let cnt = cnt as u64;
92+
93+
// It is safe to make this cast, because the maximum timer period in this HAL is
94+
// 1s (1Hz), then 1 second < (2^32 - 1) microseconds
95+
MicrosDurationU32::from_ticks(u32::try_from(1_000_000 * cnt / freq_divider).unwrap())
96+
}
97+
}

src/common/timer/mod.rs

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
pub mod pwm;
2+
pub use pwm::*;
3+
pub mod counter;
4+
pub use counter::*;
5+
6+
use crate::time::Hertz;
7+
8+
pub trait PwmTimer {
9+
fn start(&mut self);
10+
fn stop(&mut self);
11+
fn config_freq(&mut self, count_freq: Hertz, update_freq: Hertz);
12+
fn get_max_duty(&self) -> u32;
13+
fn get_count_value(&self) -> u32;
14+
}
15+
16+
pub trait PwmChannel {
17+
fn config(&mut self, mode: PwmMode, polarity: PwmPolarity);
18+
fn set_enable(&mut self, en: bool);
19+
fn get_max_duty(&self) -> u32;
20+
/// Remember to use `get_max_duty()`
21+
fn set_duty(&mut self, duty: u32);
22+
}
23+
24+
// ----------------------------------------------------------------------------
25+
26+
pub trait GeneralTimer {
27+
fn reset_config(&mut self);
28+
fn enable_counter(&mut self);
29+
fn disable_counter(&mut self);
30+
fn is_counter_enabled(&self) -> bool;
31+
fn reset_counter(&mut self);
32+
fn max_auto_reload() -> u32;
33+
unsafe fn set_auto_reload_unchecked(&mut self, arr: u32);
34+
fn set_auto_reload(&mut self, arr: u32) -> Result<(), Error>;
35+
fn read_auto_reload(&self) -> u32;
36+
fn set_prescaler(&mut self, psc: u16);
37+
fn read_prescaler(&self) -> u16;
38+
fn read_count(&self) -> u32;
39+
fn trigger_update(&mut self);
40+
fn config_freq(&mut self, clock: Hertz, count_freq: Hertz, update_freq: Hertz);
41+
42+
fn clear_interrupt_flag(&mut self, event: Event);
43+
fn listen_interrupt(&mut self, event: Event, b: bool);
44+
fn get_interrupt_flag(&self) -> Event;
45+
fn start_one_pulse(&mut self);
46+
}
47+
48+
pub trait TimerDirection: GeneralTimer {
49+
fn set_count_direction(&mut self, dir: CountDirection);
50+
}
51+
52+
pub trait TimerWithPwm: GeneralTimer {
53+
fn start_pwm(&mut self);
54+
fn stop_pwm(&mut self);
55+
56+
fn preload_output_channel_in_mode(&mut self, channel: Channel, mode: PwmMode);
57+
fn set_polarity(&mut self, channel: Channel, polarity: PwmPolarity);
58+
}
59+
60+
pub trait TimerWithPwm1Ch: TimerWithPwm {
61+
fn enable_ch1(&mut self, en: bool);
62+
fn set_ch1_cc_value(&mut self, value: u32);
63+
fn get_ch1_cc_value(&self) -> u32;
64+
}
65+
66+
pub trait TimerWithPwm2Ch: TimerWithPwm1Ch {
67+
fn enable_ch2(&mut self, en: bool);
68+
fn set_ch2_cc_value(&mut self, value: u32);
69+
fn get_ch2_cc_value(&self) -> u32;
70+
}
71+
72+
pub trait TimerWithPwm4Ch: TimerWithPwm2Ch {
73+
fn enable_ch3(&mut self, en: bool);
74+
fn set_ch3_cc_value(&mut self, value: u32);
75+
fn get_ch3_cc_value(&self) -> u32;
76+
fn enable_ch4(&mut self, en: bool);
77+
fn set_ch4_cc_value(&mut self, value: u32);
78+
fn get_ch4_cc_value(&self) -> u32;
79+
}
80+
81+
// Enumerate ------------------------------------------------------------------
82+
83+
#[derive(Clone, Copy, PartialEq, Eq)]
84+
pub enum Channel {
85+
C1,
86+
C2,
87+
C3,
88+
C4,
89+
}
90+
91+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
92+
pub enum CountDirection {
93+
Up,
94+
Down,
95+
}
96+
97+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
98+
pub enum PwmMode {
99+
Mode1,
100+
Mode2,
101+
}
102+
103+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
104+
pub enum PwmPolarity {
105+
ActiveHigh,
106+
ActiveLow,
107+
}
108+
109+
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
110+
pub enum Error {
111+
/// Timer is disabled
112+
Disabled,
113+
WrongAutoReload,
114+
}
115+
116+
/// Interrupt events
117+
#[derive(Clone, Copy, PartialEq, Eq)]
118+
pub enum SysEvent {
119+
/// [Timer] timed out / count down ended
120+
Update,
121+
}
122+
123+
bitflags::bitflags! {
124+
pub struct Event: u32 {
125+
const Update = 1 << 0;
126+
const C1 = 1 << 1;
127+
const C2 = 1 << 2;
128+
const C3 = 1 << 3;
129+
const C4 = 1 << 4;
130+
}
131+
}

src/common/timer/pwm.rs

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
use super::*;
2+
use crate::timer::Channel;
3+
4+
// Implement Traits -----------------------------------------------------------
5+
6+
pub struct PwmChannel1<TIM> {
7+
tim: TIM,
8+
}
9+
impl<TIM> PwmChannel1<TIM> {
10+
pub fn new(tim: TIM) -> Self {
11+
Self { tim }
12+
}
13+
}
14+
impl<TIM: TimerWithPwm1Ch> PwmChannel for PwmChannel1<TIM> {
15+
#[inline(always)]
16+
fn config(&mut self, mode: PwmMode, polarity: PwmPolarity) {
17+
self.tim
18+
.preload_output_channel_in_mode(Channel::C1, mode.into());
19+
self.tim.set_polarity(Channel::C1, polarity);
20+
}
21+
22+
#[inline(always)]
23+
fn set_enable(&mut self, en: bool) {
24+
self.tim.enable_ch1(en);
25+
}
26+
27+
#[inline(always)]
28+
fn get_max_duty(&self) -> u32 {
29+
(self.tim.read_auto_reload() as u32).wrapping_add(1)
30+
}
31+
32+
#[inline(always)]
33+
fn set_duty(&mut self, duty: u32) {
34+
self.tim.set_ch1_cc_value(duty);
35+
}
36+
}
37+
38+
pub struct PwmChannel2<TIM> {
39+
pub(super) tim: TIM,
40+
}
41+
impl<TIM> PwmChannel2<TIM> {
42+
pub fn new(tim: TIM) -> Self {
43+
Self { tim }
44+
}
45+
}
46+
impl<TIM: TimerWithPwm2Ch> PwmChannel for PwmChannel2<TIM> {
47+
#[inline(always)]
48+
fn config(&mut self, mode: PwmMode, polarity: PwmPolarity) {
49+
self.tim
50+
.preload_output_channel_in_mode(Channel::C2, mode.into());
51+
self.tim.set_polarity(Channel::C2, polarity);
52+
}
53+
54+
#[inline(always)]
55+
fn set_enable(&mut self, en: bool) {
56+
self.tim.enable_ch2(en);
57+
}
58+
59+
#[inline(always)]
60+
fn get_max_duty(&self) -> u32 {
61+
(self.tim.read_auto_reload() as u32).wrapping_add(1)
62+
}
63+
64+
#[inline(always)]
65+
fn set_duty(&mut self, duty: u32) {
66+
self.tim.set_ch2_cc_value(duty);
67+
}
68+
}
69+
70+
pub struct PwmChannel3<TIM> {
71+
pub(super) tim: TIM,
72+
}
73+
impl<TIM> PwmChannel3<TIM> {
74+
pub fn new(tim: TIM) -> Self {
75+
Self { tim }
76+
}
77+
}
78+
impl<TIM: TimerWithPwm4Ch> PwmChannel for PwmChannel3<TIM> {
79+
#[inline(always)]
80+
fn config(&mut self, mode: PwmMode, polarity: PwmPolarity) {
81+
self.tim
82+
.preload_output_channel_in_mode(Channel::C3, mode.into());
83+
self.tim.set_polarity(Channel::C3, polarity);
84+
}
85+
86+
#[inline(always)]
87+
fn set_enable(&mut self, en: bool) {
88+
self.tim.enable_ch3(en);
89+
}
90+
91+
#[inline(always)]
92+
fn get_max_duty(&self) -> u32 {
93+
(self.tim.read_auto_reload() as u32).wrapping_add(1)
94+
}
95+
96+
#[inline(always)]
97+
fn set_duty(&mut self, duty: u32) {
98+
self.tim.set_ch3_cc_value(duty);
99+
}
100+
}
101+
102+
pub struct PwmChannel4<TIM> {
103+
pub(super) tim: TIM,
104+
}
105+
impl<TIM> PwmChannel4<TIM> {
106+
pub fn new(tim: TIM) -> Self {
107+
Self { tim }
108+
}
109+
}
110+
impl<TIM: TimerWithPwm4Ch> PwmChannel for PwmChannel4<TIM> {
111+
#[inline(always)]
112+
fn config(&mut self, mode: PwmMode, polarity: PwmPolarity) {
113+
self.tim
114+
.preload_output_channel_in_mode(Channel::C4, mode.into());
115+
self.tim.set_polarity(Channel::C4, polarity);
116+
}
117+
118+
#[inline(always)]
119+
fn set_enable(&mut self, en: bool) {
120+
self.tim.enable_ch4(en);
121+
}
122+
123+
#[inline(always)]
124+
fn get_max_duty(&self) -> u32 {
125+
(self.tim.read_auto_reload() as u32).wrapping_add(1)
126+
}
127+
128+
#[inline(always)]
129+
fn set_duty(&mut self, duty: u32) {
130+
self.tim.set_ch4_cc_value(duty);
131+
}
132+
}

0 commit comments

Comments
 (0)