11use crate :: * ;
22use core:: { cell:: UnsafeCell , marker:: PhantomData } ;
3- use os_trait:: {
4- FakeRawMutex , KilohertzU32 , MicrosDurationU32 , TickInstant , TickTimeoutNs , TickTimeoutState ,
5- prelude:: * ,
6- } ;
3+ use os_trait:: { FakeRawMutex , MicrosDurationU32 , prelude:: * } ;
74
85/// `OsInterface` implementation, the N can be choose between [`SemaphoreNotifier`]
96pub struct FreeRTOS < N > {
2017 type RawMutex = FakeRawMutex ;
2118 type Notifier = N :: Notifier ;
2219 type NotifyWaiter = N :: Waiter ;
23- type Timeout = TickTimeoutNs < FreeRtosTickInstant > ;
24- type TimeoutState = TickTimeoutState < FreeRtosTickInstant > ;
20+ type Timeout = FreeRtosTimeoutNs ;
21+ type TimeoutState = FreeRtosTimeoutState ;
2522 type Delay = FreeRtosTickDelayNs ;
2623
2724 const O : Self = Self { _n : PhantomData } ;
3330
3431 #[ inline]
3532 fn timeout ( ) -> Self :: Timeout {
36- TickTimeoutNs :: < FreeRtosTickInstant > :: new ( )
33+ FreeRtosTimeoutNs :: new ( )
3734 }
3835
3936 #[ inline]
@@ -207,13 +204,13 @@ impl FreeRtosTickDelayNs {
207204impl DelayNs for FreeRtosTickDelayNs {
208205 #[ inline]
209206 fn delay_ns ( & mut self , ns : u32 ) {
210- let mut t = TickTimeoutNs :: < FreeRtosTickInstant > :: new ( ) . start_ns ( ns) ;
207+ let mut t = FreeRtosTimeoutNs :: new ( ) . start_ns ( ns) ;
211208 while !t. timeout ( ) { }
212209 }
213210
214211 #[ inline]
215212 fn delay_us ( & mut self , us : u32 ) {
216- let mut t = TickTimeoutNs :: < FreeRtosTickInstant > :: new ( ) . start_us ( us) ;
213+ let mut t = FreeRtosTimeoutNs :: new ( ) . start_us ( us) ;
217214 while !t. timeout ( ) {
218215 CurrentTask :: yield_now ( ) ;
219216 }
@@ -225,65 +222,171 @@ impl DelayNs for FreeRtosTickDelayNs {
225222 }
226223}
227224
228- #[ derive( Clone , Copy ) ]
229- pub struct FreeRtosTickInstant {
230- sys_tick : u32 ,
231- tick_count : u32 ,
225+ #[ derive( Default ) ]
226+ pub struct FreeRtosTimeoutNs { }
227+
228+ impl FreeRtosTimeoutNs {
229+ pub const fn new ( ) -> Self {
230+ Self { }
231+ }
232232}
233233
234- #[ cfg( cortex_m) ]
235- impl TickInstant for FreeRtosTickInstant {
234+ impl TimeoutNs for FreeRtosTimeoutNs {
235+ type TimeoutState = FreeRtosTimeoutState ;
236+
236237 #[ inline]
237- fn frequency ( ) -> KilohertzU32 {
238- use os_trait:: fugit:: HertzU32 ;
239- HertzU32 :: from_raw ( utils:: cpu_clock_hz ( ) ) . convert ( )
238+ fn start_ns ( & self , timeout : u32 ) -> Self :: TimeoutState {
239+ Self :: TimeoutState :: new_ns ( timeout)
240240 }
241241
242- fn now ( ) -> Self {
243- use core:: sync:: atomic:: { Ordering , compiler_fence} ;
244- use cortex_m:: peripheral:: SYST ;
242+ #[ inline]
243+ fn start_us ( & self , timeout : u32 ) -> Self :: TimeoutState {
244+ Self :: TimeoutState :: new_us ( timeout)
245+ }
245246
246- let tick_count = FreeRtosUtils :: get_tick_count ( ) ;
247- let sys_tick = SYST :: get_current ( ) ;
248- compiler_fence ( Ordering :: Acquire ) ;
249- let tick_count2 = FreeRtosUtils :: get_tick_count ( ) ;
250- let sys_tick2 = SYST :: get_current ( ) ;
247+ # [ inline ]
248+ fn start_ms ( & self , timeout : u32 ) -> Self :: TimeoutState {
249+ Self :: TimeoutState :: new_ms ( timeout )
250+ }
251+ }
251252
252- if tick_count != tick_count2 {
253- Self {
254- sys_tick : sys_tick2,
255- tick_count : tick_count2,
256- }
257- } else {
253+ #[ cfg( cortex_m) ]
254+ pub use sys_tick_timeout:: * ;
255+ #[ cfg( cortex_m) ]
256+ mod sys_tick_timeout {
257+ use super :: * ;
258+ use core:: sync:: atomic:: { Ordering , compiler_fence} ;
259+ use cortex_m:: peripheral:: SYST ;
260+
261+ #[ derive( Clone , Copy ) ]
262+ pub struct FreeRtosTimeoutState {
263+ sys_tick : u32 ,
264+ count : u32 ,
265+ timeout_tick : u64 ,
266+ }
267+
268+ impl FreeRtosTimeoutState {
269+ pub fn new_ns ( timeout : u32 ) -> Self {
270+ let ns = timeout as u64 ;
271+ let timeout_tick = ( ns * Self :: frequency ( ) ) . div_ceil ( 1_000_000 ) ;
272+ Self :: new ( timeout_tick)
273+ }
274+
275+ pub fn new_us ( timeout : u32 ) -> Self {
276+ let us = timeout as u64 ;
277+ let timeout_tick = ( us * Self :: frequency ( ) ) . div_ceil ( 1_000 ) ;
278+ Self :: new ( timeout_tick)
279+ }
280+
281+ pub fn new_ms ( timeout : u32 ) -> Self {
282+ let ms = timeout as u64 ;
283+ let timeout_tick = ms * Self :: frequency ( ) ;
284+ Self :: new ( timeout_tick)
285+ }
286+
287+ #[ inline]
288+ fn frequency ( ) -> u64 {
289+ // to kHz
290+ ( utils:: cpu_clock_hz ( ) / 1000 ) as u64
291+ }
292+
293+ fn new ( timeout_tick : u64 ) -> Self {
294+ let ( sys_tick, count) = Self :: now ( ) ;
295+ let ( sys_tick, count) = Self :: add ( sys_tick, count, timeout_tick) ;
258296 Self {
259297 sys_tick,
260- tick_count,
298+ count,
299+ timeout_tick,
300+ }
301+ }
302+
303+ fn now ( ) -> ( u32 , u32 ) {
304+ let count = FreeRtosUtils :: get_tick_count ( ) ;
305+ let sys_tick = SYST :: get_current ( ) ;
306+ compiler_fence ( Ordering :: Acquire ) ;
307+ let count2 = FreeRtosUtils :: get_tick_count ( ) ;
308+ let sys_tick2 = SYST :: get_current ( ) ;
309+
310+ if count != count2 {
311+ ( sys_tick2, count2)
312+ } else {
313+ ( sys_tick, count)
261314 }
262315 }
316+
317+ fn add ( sys_tick : u32 , count : u32 , tick : u64 ) -> ( u32 , u32 ) {
318+ let reload = ( SYST :: get_reload ( ) + 1 ) as u64 ;
319+ let mut diff_count = tick / reload;
320+ let diff_sys_tick = ( tick - diff_count * reload) as u32 ;
321+ let new_sys_tick = if diff_sys_tick > sys_tick {
322+ diff_count += 1 ;
323+ sys_tick + reload as u32 - diff_sys_tick
324+ } else {
325+ sys_tick - diff_sys_tick
326+ } ;
327+ ( new_sys_tick, count. wrapping_add ( diff_count as u32 ) )
328+ }
263329 }
264330
265- fn tick_since ( self , earlier : Self ) -> u32 {
266- use cortex_m:: peripheral:: SYST ;
267- let reload = SYST :: get_reload ( ) + 1 ;
268- ( self . tick_count - earlier. tick_count ) * reload + earlier. sys_tick - self . sys_tick
331+ impl TimeoutState for FreeRtosTimeoutState {
332+ /// Can be reused without calling `restart()`.
333+ fn timeout ( & mut self ) -> bool {
334+ let ( sys_tick, count) = Self :: now ( ) ;
335+ if count > self . count || ( count == self . count && sys_tick < self . sys_tick ) {
336+ ( self . sys_tick , self . count ) =
337+ Self :: add ( self . sys_tick , self . count , self . timeout_tick ) ;
338+ true
339+ } else {
340+ false
341+ }
342+ }
343+
344+ fn restart ( & mut self ) {
345+ let ( sys_tick, count) = Self :: now ( ) ;
346+ ( self . sys_tick , self . count ) = Self :: add ( sys_tick, count, self . timeout_tick ) ;
347+ }
269348 }
270349}
271350
272351#[ cfg( not( cortex_m) ) ]
273- impl TickInstant for FreeRtosTickInstant {
274- #[ inline]
275- fn frequency ( ) -> KilohertzU32 {
276- todo ! ( )
352+ pub use other_timeout:: * ;
353+ #[ cfg( not( cortex_m) ) ]
354+ mod other_timeout {
355+ use super :: * ;
356+
357+ #[ derive( Clone , Copy ) ]
358+ pub struct FreeRtosTimeoutState {
359+ timeout : u32 ,
277360 }
278361
279- fn now ( ) -> Self {
280- Self {
281- sys_tick : 0 ,
282- tick_count : 0 ,
362+ impl FreeRtosTimeoutState {
363+ pub fn new_ns ( timeout : u32 ) -> Self {
364+ Self :: new ( timeout)
365+ }
366+
367+ pub fn new_us ( timeout : u32 ) -> Self {
368+ Self :: new ( timeout)
369+ }
370+
371+ pub fn new_ms ( timeout : u32 ) -> Self {
372+ Self :: new ( timeout)
373+ }
374+
375+ fn new ( timeout : u32 ) -> Self {
376+ Self { timeout }
283377 }
284378 }
285379
286- fn tick_since ( self , _earlier : Self ) -> u32 {
287- self . tick_count + self . sys_tick
380+ impl TimeoutState for FreeRtosTimeoutState {
381+ /// Can be reused without calling `restart()`.
382+ #[ inline]
383+ fn timeout ( & mut self ) -> bool {
384+ true
385+ }
386+
387+ #[ inline]
388+ fn restart ( & mut self ) {
389+ self . timeout = 0 ;
390+ }
288391 }
289392}
0 commit comments