• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2025 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 use crate::scheduler;
15 use core::sync::atomic;
16 use cortex_m::peripheral::*;
17 use pw_log::info;
18 
19 const TICKS_PER_SEC: u32 = 10000000; // 10Mhz
20 const TICK_HZ: u32 = 100;
21 
22 // Store the total number of 100hz ticks we've accumulated to service
23 // current_time below.
24 static TICKS: atomic::AtomicU32 = atomic::AtomicU32::new(0);
25 
26 #[allow(dead_code)]
systick_dump()27 pub fn systick_dump() {
28     info!(
29         "counter {} reload {}",
30         SYST::get_current(),
31         SYST::get_reload()
32     );
33 }
34 
systick_early_init(syst: &mut SYST)35 pub fn systick_early_init(syst: &mut SYST) {
36     info!("starting monotonic systick\n");
37 
38     syst.disable_counter();
39     syst.disable_interrupt();
40     syst.clear_current();
41 
42     // set a 100Hz timer
43     syst.set_reload(TICKS_PER_SEC / TICK_HZ);
44     syst.enable_counter();
45 
46     syst.enable_interrupt();
47 }
48 
systick_init()49 pub fn systick_init() {}
50 
51 #[no_mangle]
52 #[allow(non_snake_case)]
SysTick()53 pub unsafe extern "C" fn SysTick() {
54     TICKS.fetch_add(1, atomic::Ordering::SeqCst);
55 
56     //info!("SysTick {}", current_time_ms());
57 
58     scheduler::tick(ticks_to_ms());
59 }
60 
ticks_to_ms() -> u3261 fn ticks_to_ms() -> u32 {
62     // TODO: handle unsafe wrapping multiplies
63     TICKS.load(atomic::Ordering::Relaxed) * 1000000 / TICK_HZ
64 }
65 
ticks_elapsed() -> u3266 fn ticks_elapsed() -> u32 {
67     // TODO: handle unsafe wrapping multiplies
68     (TICKS_PER_SEC / TICK_HZ) - SYST::get_current()
69 }
70 
71 #[allow(dead_code)]
current_time_ms() -> u3272 pub fn current_time_ms() -> u32 {
73     let time = ticks_to_ms() + (ticks_elapsed() * 1000000 / TICKS_PER_SEC);
74 
75     time
76 }
77