@@ -14,6 +14,18 @@ use embassy_time_queue_utils::Queue;
1414use crate :: raw:: { k_timeout_t, k_timer, k_timer_init, k_timer_start} ;
1515use crate :: sys:: K_FOREVER ;
1616
17+ /// The time base configured into Zephyr.
18+ pub const ZEPHYR_TICK_HZ : u64 = crate :: time:: SYS_FREQUENCY as u64 ;
19+
20+ /// The configured Embassy time tick rate.
21+ pub const EMBASSY_TICK_HZ : u64 = embassy_time_driver:: TICK_HZ ;
22+
23+ /// When the zephyr and embassy rates differ, use this intermediate type. This can be selected by
24+ /// feature. At the worst case, with Embassy's tick at 1Mhz, and Zephyr's at 50k, it is a little
25+ /// over 11 years. Higher of either will reduce that further. But, 128-bit arithmetic is fairly
26+ /// inefficient.
27+ type InterTime = u128 ;
28+
1729embassy_time_driver:: time_driver_impl!( static DRIVER : ZephyrTimeDriver = ZephyrTimeDriver {
1830 queue: Mutex :: new( RefCell :: new( Queue :: new( ) ) ) ,
1931 timer: Mutex :: new( RefCell :: new( unsafe { mem:: zeroed( ) } ) ) ,
@@ -63,20 +75,54 @@ impl ZTimer {
6375 }
6476}
6577
78+ /// Convert from a zephyr tick count, to an embassy tick count.
79+ ///
80+ /// This is done using an intermediate type defined above.
81+ /// This conversion truncates.
82+ fn zephyr_to_embassy ( ticks : u64 ) -> u64 {
83+ if ZEPHYR_TICK_HZ == EMBASSY_TICK_HZ {
84+ // This should happen at compile time.
85+ return ticks;
86+ }
87+
88+ // Otherwise do the intermediate conversion.
89+ let prod = ( ticks as InterTime ) * ( EMBASSY_TICK_HZ as InterTime ) ;
90+ ( prod / ( ZEPHYR_TICK_HZ as InterTime ) ) as u64
91+ }
92+
93+ /// Convert from an embassy tick count to a zephyr.
94+ ///
95+ /// This conversion use ceil so that values are always large enough.
96+ fn embassy_to_zephyr ( ticks : u64 ) -> u64 {
97+ if ZEPHYR_TICK_HZ == EMBASSY_TICK_HZ {
98+ return ticks;
99+ }
100+
101+ let prod = ( ticks as InterTime ) * ( ZEPHYR_TICK_HZ as InterTime ) ;
102+ prod. div_ceil ( EMBASSY_TICK_HZ as InterTime ) as u64
103+ }
104+
105+ fn zephyr_now ( ) -> u64 {
106+ crate :: time:: now ( ) . ticks ( )
107+ }
108+
66109impl Driver for ZephyrTimeDriver {
67110 fn now ( & self ) -> u64 {
68- crate :: time :: now ( ) . ticks ( )
111+ zephyr_to_embassy ( zephyr_now ( ) )
69112 }
70113
71114 fn schedule_wake ( & self , at : u64 , waker : & core:: task:: Waker ) {
72115 critical_section:: with ( |cs| {
73116 let mut queue = self . queue . borrow ( cs) . borrow_mut ( ) ;
74117 let mut timer = self . timer . borrow ( cs) . borrow_mut ( ) ;
75118
119+ // All times below are in Zephyr units.
120+ let at = embassy_to_zephyr ( at) ;
121+
76122 if queue. schedule_wake ( at, waker) {
77- let mut next = queue. next_expiration ( self . now ( ) ) ;
78- while !timer. set_alarm ( next, self . now ( ) ) {
79- next = queue. next_expiration ( self . now ( ) ) ;
123+ let mut next = queue. next_expiration ( zephyr_now ( ) ) ;
124+ while !timer. set_alarm ( next, zephyr_now ( ) ) {
125+ next = queue. next_expiration ( zephyr_now ( ) ) ;
80126 }
81127 }
82128 } )
@@ -89,9 +135,9 @@ impl ZephyrTimeDriver {
89135 let mut queue = self . queue . borrow ( cs) . borrow_mut ( ) ;
90136 let mut timer = self . timer . borrow ( cs) . borrow_mut ( ) ;
91137
92- let mut next = queue. next_expiration ( self . now ( ) ) ;
93- while !timer. set_alarm ( next, self . now ( ) ) {
94- next = queue. next_expiration ( self . now ( ) ) ;
138+ let mut next = queue. next_expiration ( zephyr_now ( ) ) ;
139+ while !timer. set_alarm ( next, zephyr_now ( ) ) {
140+ next = queue. next_expiration ( zephyr_now ( ) ) ;
95141 }
96142 } )
97143 }
0 commit comments