osal_rs/freertos/
timer.rs1use core::any::Any;
21use core::fmt::{Debug, Display};
22use core::ops::Deref;
23use core::ptr::null_mut;
24
25use alloc::boxed::Box;
26use alloc::string::{String, ToString};
27use alloc::sync::Arc;
28
29use crate::freertos::ffi::pdPASS;
30use crate::to_c_str;
31use crate::traits::{ToTick, TimerParam, TimerFn, TimerFnPtr};
32use crate::utils::{OsalRsBool, Result, Error};
33use super::ffi::{TimerHandle, pvTimerGetTimerID, xTimerCreate, osal_rs_timer_start, osal_rs_timer_change_period, osal_rs_timer_delete, osal_rs_timer_reset, osal_rs_timer_stop};
34use super::types::{TickType};
35
36#[derive(Clone)]
37pub struct Timer {
38 pub handle: TimerHandle,
39 name: String,
40 callback: Option<Arc<TimerFnPtr>>,
41 param: Option<TimerParam>,
42}
43
44unsafe impl Send for Timer {}
45unsafe impl Sync for Timer {}
46
47impl Timer {
48 #[inline]
49 pub fn new_with_to_tick<F>(name: &str, timer_period_in_ticks: impl ToTick, auto_reload: bool, param: Option<TimerParam>, callback: F) -> Result<Self>
50 where
51 F: Fn(Box<dyn TimerFn>, Option<TimerParam>) -> Result<TimerParam> + Send + Sync + Clone + 'static {
52 Self::new(name, timer_period_in_ticks.to_ticks(), auto_reload, param, callback)
53 }
54
55 #[inline]
56 pub fn start_with_to_tick(&self, ticks_to_wait: impl ToTick) -> OsalRsBool {
57 self.start(ticks_to_wait.to_ticks())
58 }
59
60 #[inline]
61 pub fn stop_with_to_tick(&self, ticks_to_wait: impl ToTick) -> OsalRsBool {
62 self.stop(ticks_to_wait.to_ticks())
63 }
64
65 #[inline]
66 pub fn reset_with_to_tick(&self, ticks_to_wait: impl ToTick) -> OsalRsBool {
67 self.reset(ticks_to_wait.to_ticks())
68 }
69
70 #[inline]
71 pub fn change_period_with_to_tick(&self, new_period_in_ticks: impl ToTick, new_period_ticks: impl ToTick) -> OsalRsBool {
72 self.change_period(new_period_in_ticks.to_ticks(), new_period_ticks.to_ticks())
73 }
74
75 #[inline]
76 pub fn delete_with_to_tick(&mut self, ticks_to_wait: impl ToTick) -> OsalRsBool {
77 self.delete(ticks_to_wait.to_ticks())
78 }
79}
80
81extern "C" fn callback_c_wrapper(handle: TimerHandle) {
82
83 if handle.is_null() {
84 return;
85 }
86
87 let param_ptr = unsafe {
88 pvTimerGetTimerID(handle)
89 };
90
91 let mut timer_instance: Box<Timer> = unsafe { Box::from_raw(param_ptr as *mut _) };
92
93 timer_instance.as_mut().handle = handle;
94
95 let param_arc: Option<Arc<dyn Any + Send + Sync>> = timer_instance
96 .param
97 .clone();
98
99 if let Some(callback) = &timer_instance.callback.clone() {
100 let _ = callback(timer_instance, param_arc);
101 }
102}
103
104impl TimerFn for Timer {
105 fn new<F>(name: &str, timer_period_in_ticks: TickType, auto_reload: bool, param: Option<TimerParam>, callback: F) -> Result<Self>
106 where
107 F: Fn(Box<dyn TimerFn>, Option<TimerParam>) -> Result<TimerParam> + Send + Sync + Clone + 'static {
108
109 let mut boxed_timer = Box::new(Self {
110 handle: core::ptr::null_mut(),
111 name: name.to_string(),
112 callback: Some(Arc::new(callback.clone())),
113 param: param.clone(),
114 });
115
116 let handle = unsafe {
117 xTimerCreate( to_c_str!(name),
118 timer_period_in_ticks,
119 if auto_reload { 1 } else { 0 },
120 Box::into_raw(boxed_timer.clone()) as *mut _,
121 Some(super::timer::callback_c_wrapper)
122 )
123 };
124
125 if handle.is_null() {
126 Err(Error::NullPtr)
127 } else {
128 boxed_timer.as_mut().handle = handle;
129 Ok(*boxed_timer)
130 }
131
132 }
133
134 fn start(&self, ticks_to_wait: TickType) -> OsalRsBool {
135 if unsafe {
136 osal_rs_timer_start(self.handle, ticks_to_wait)
137 } != pdPASS {
138 OsalRsBool::False
139 } else {
140 OsalRsBool::True
141 }
142 }
143
144 fn stop(&self, ticks_to_wait: TickType) -> OsalRsBool {
145 if unsafe {
146 osal_rs_timer_stop(self.handle, ticks_to_wait)
147 } != pdPASS {
148 OsalRsBool::False
149 } else {
150 OsalRsBool::True
151 }
152 }
153
154 fn reset(&self, ticks_to_wait: TickType) -> OsalRsBool {
155 if unsafe {
156 osal_rs_timer_reset(self.handle, ticks_to_wait)
157 } != pdPASS {
158 OsalRsBool::False
159 } else {
160 OsalRsBool::True
161 }
162 }
163
164 fn change_period(&self, new_period_in_ticks: TickType, new_period_ticks: TickType) -> OsalRsBool {
165 if unsafe {
166 osal_rs_timer_change_period(self.handle, new_period_in_ticks, new_period_ticks)
167 } != pdPASS {
168 OsalRsBool::False
169 } else {
170 OsalRsBool::True
171 }
172 }
173
174 fn delete(&mut self, ticks_to_wait: TickType) -> OsalRsBool {
175 if unsafe {
176 osal_rs_timer_delete(self.handle, ticks_to_wait)
177 } != pdPASS {
178 self.handle = null_mut();
179 OsalRsBool::False
180 } else {
181 self.handle = null_mut();
182 OsalRsBool::True
183 }
184 }
185}
186
187impl Drop for Timer {
188 fn drop(&mut self) {
189 self.delete(0);
190 }
191}
192
193impl Deref for Timer {
194 type Target = TimerHandle;
195
196 fn deref(&self) -> &Self::Target {
197 &self.handle
198 }
199}
200
201impl Debug for Timer {
202 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
203 f.debug_struct("Timer")
204 .field("handle", &self.handle)
205 .field("name", &self.name)
206 .finish()
207 }
208}
209
210impl Display for Timer {
211 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
212 write!(f, "Timer {{ name: {}, handle: {:?} }}", self.name, self.handle)
213 }
214}