@@ -14,6 +14,18 @@ use embassy_time_queue_utils::Queue;
14
14
use crate :: raw:: { k_timeout_t, k_timer, k_timer_init, k_timer_start} ;
15
15
use crate :: sys:: K_FOREVER ;
16
16
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
+
17
29
embassy_time_driver:: time_driver_impl!( static DRIVER : ZephyrTimeDriver = ZephyrTimeDriver {
18
30
queue: Mutex :: new( RefCell :: new( Queue :: new( ) ) ) ,
19
31
timer: Mutex :: new( RefCell :: new( unsafe { mem:: zeroed( ) } ) ) ,
@@ -63,20 +75,54 @@ impl ZTimer {
63
75
}
64
76
}
65
77
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
+
66
109
impl Driver for ZephyrTimeDriver {
67
110
fn now ( & self ) -> u64 {
68
- crate :: time :: now ( ) . ticks ( )
111
+ zephyr_to_embassy ( zephyr_now ( ) )
69
112
}
70
113
71
114
fn schedule_wake ( & self , at : u64 , waker : & core:: task:: Waker ) {
72
115
critical_section:: with ( |cs| {
73
116
let mut queue = self . queue . borrow ( cs) . borrow_mut ( ) ;
74
117
let mut timer = self . timer . borrow ( cs) . borrow_mut ( ) ;
75
118
119
+ // All times below are in Zephyr units.
120
+ let at = embassy_to_zephyr ( at) ;
121
+
76
122
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 ( ) ) ;
80
126
}
81
127
}
82
128
} )
@@ -89,9 +135,9 @@ impl ZephyrTimeDriver {
89
135
let mut queue = self . queue . borrow ( cs) . borrow_mut ( ) ;
90
136
let mut timer = self . timer . borrow ( cs) . borrow_mut ( ) ;
91
137
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 ( ) ) ;
95
141
}
96
142
} )
97
143
}
0 commit comments