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()27pub 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)35pub 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()49pub fn systick_init() {} 50 51 #[no_mangle] 52 #[allow(non_snake_case)] SysTick()53pub 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() -> u3261fn ticks_to_ms() -> u32 { 62 // TODO: handle unsafe wrapping multiplies 63 TICKS.load(atomic::Ordering::Relaxed) * 1000000 / TICK_HZ 64 } 65 ticks_elapsed() -> u3266fn 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() -> u3272pub fn current_time_ms() -> u32 { 73 let time = ticks_to_ms() + (ticks_elapsed() * 1000000 / TICKS_PER_SEC); 74 75 time 76 } 77