1use crate::prelude::v1::*;
2use crate::base::*;
3use crate::task::*;
4use crate::shim::*;
5use crate::mutex::*;
6use crate::queue::*;
7use crate::units::*;
8
9unsafe impl Send for Timer {}
10unsafe impl Sync for Timer {}
11
12pub struct Timer {
18 handle: FreeRtosTimerHandle,
19 detached: bool
20}
21
22pub struct TimerBuilder<D: DurationTicks> {
24 name: String,
25 period: D,
26 auto_reload: bool
27}
28
29impl<D: DurationTicks> TimerBuilder<D> {
30 pub fn set_name(&mut self, name: &str) -> &mut Self {
32 self.name = name.into();
33 self
34 }
35
36 pub fn set_period(&mut self, period: D) -> &mut Self {
38 self.period = period;
39 self
40 }
41
42 pub fn set_auto_reload(&mut self, auto_reload: bool) -> &mut Self {
44 self.auto_reload = auto_reload;
45 self
46 }
47
48 pub fn create<F>(&self, callback: F) -> Result<Timer, FreeRtosError>
52 where F: Fn(Timer) -> (),
53 F: Send + 'static
54 {
55 Timer::spawn(self.name.as_str(), self.period.to_ticks(), self.auto_reload, callback)
56 }
57}
58
59
60
61impl Timer {
62 pub fn new<D: DurationTicks>(period: D) -> TimerBuilder<D> {
64 TimerBuilder {
65 name: "timer".into(),
66 period: period,
67 auto_reload: true
68 }
69 }
70
71 unsafe fn spawn_inner<'a>(name: &str,
72 period_ticks: FreeRtosTickType,
73 auto_reload: bool,
74 callback: Box<Fn(Timer) + Send + 'a>,)
75 -> Result<Timer, FreeRtosError> {
76 let f = Box::new(callback);
77 let param_ptr = &*f as *const _ as *mut _;
78
79 let (success, timer_handle) = {
80 let name = name.as_bytes();
81 let name_len = name.len();
82 let mut _timer_handle = mem::zeroed::<CVoid>();
83
84 let ret = freertos_rs_timer_create(name.as_ptr(),
85 name_len as u8,
86 period_ticks,
87 if auto_reload { 1 } else { 0 },
88 param_ptr,
89 timer_callback);
90
91 ((ret as usize) != 0, ret)
92 };
93
94 if success {
95 mem::forget(f);
96 } else {
97 return Err(FreeRtosError::OutOfMemory);
98 }
99
100 extern "C" fn timer_callback(handle: FreeRtosTimerHandle) -> () {
101 unsafe {
102 {
103 let timer = Timer {
104 handle: handle,
105 detached: true
106 };
107 if let Ok(callback_ptr) = timer.get_id() {
108 let b = Box::from_raw(callback_ptr as *mut Box<Fn(Timer)>);
109 b(timer);
110 Box::into_raw(b);
111 }
112 }
113 }
114 }
115
116 Ok(Timer {
117 handle: timer_handle as *const _,
118 detached: false
119 })
120 }
121
122
123 fn spawn<F>(name: &str,
124 period_tick: FreeRtosTickType,
125 auto_reload: bool,
126 callback: F)
127 -> Result<Timer, FreeRtosError>
128 where F: Fn(Timer) -> (),
129 F: Send + 'static
130 {
131 unsafe {
132 Timer::spawn_inner(name, period_tick, auto_reload, Box::new(callback))
133 }
134 }
135
136 pub fn start<D: DurationTicks>(&self, block_time: D) -> Result<(), FreeRtosError> {
138 unsafe {
139 if freertos_rs_timer_start(self.handle, block_time.to_ticks()) == 0 {
140 Ok(())
141 } else {
142 Err(FreeRtosError::Timeout)
143 }
144 }
145 }
146
147 pub fn stop<D: DurationTicks>(&self, block_time: D) -> Result<(), FreeRtosError> {
149 unsafe {
150 if freertos_rs_timer_stop(self.handle, block_time.to_ticks()) == 0 {
151 Ok(())
152 } else {
153 Err(FreeRtosError::Timeout)
154 }
155 }
156 }
157
158 pub fn change_period<D: DurationTicks>(&self, block_time: D, new_period: D) -> Result<(), FreeRtosError> {
160 unsafe {
161 if freertos_rs_timer_change_period(self.handle, block_time.to_ticks(), new_period.to_ticks()) == 0 {
162 Ok(())
163 } else {
164 Err(FreeRtosError::Timeout)
165 }
166 }
167 }
168
169 pub unsafe fn detach(mut self) {
174 self.detached = true;
175 }
176
177 fn get_id(&self) -> Result<FreeRtosVoidPtr, FreeRtosError> {
178 unsafe {
179 Ok(freertos_rs_timer_get_id(self.handle))
180 }
181 }
182}
183
184impl Drop for Timer {
185 fn drop(&mut self) {
186 if self.detached == true { return; }
187
188 unsafe {
189 if let Ok(callback_ptr) = self.get_id() {
190 Box::from_raw(callback_ptr as *mut Box<Fn(Timer)>);
192 }
193
194 freertos_rs_timer_delete(self.handle, Duration::ms(1000).to_ticks());
196 }
197 }
198}