Skip to content

Commit

Permalink
Merge pull request tock#4266 from GabrielPavaloiu/mutable-frequency-s…
Browse files Browse the repository at this point in the history
…ystick

systick: made frequency mutable
  • Loading branch information
alevy authored Jan 2, 2025
2 parents 6ce6199 + df053e3 commit 47319ba
Showing 1 changed file with 26 additions and 7 deletions.
33 changes: 26 additions & 7 deletions arch/cortex-m/src/systick.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@

//! ARM Cortex-M SysTick peripheral.
use core::cell::Cell;
use kernel::utilities::registers::interfaces::{Readable, Writeable};
use kernel::utilities::registers::{register_bitfields, FieldValue, ReadOnly, ReadWrite};
use kernel::utilities::StaticRef;

use core::num::NonZeroU32;

/// The `SysTickFrequencyCapability` allows the holder to change the Cortex M
/// SysTick `hertz` field.
pub unsafe trait SysTickFrequencyCapability {}

#[repr(C)]
struct SystickRegisters {
syst_csr: ReadWrite<u32, ControlAndStatus::Register>,
Expand Down Expand Up @@ -59,7 +64,7 @@ register_bitfields![u32,
///
/// Documented in the Cortex-MX Devices Generic User Guide, Chapter 4.4
pub struct SysTick {
hertz: u32,
hertz: Cell<u32>,
external_clock: bool,
}

Expand All @@ -73,7 +78,7 @@ impl SysTick {
/// value in hardware.
pub unsafe fn new() -> SysTick {
SysTick {
hertz: 0,
hertz: Cell::new(0),
external_clock: false,
}
}
Expand All @@ -86,8 +91,8 @@ impl SysTick {
/// * `clock_speed` - the frequency of SysTick tics in Hertz. For example,
/// if the SysTick is driven by the CPU clock, it is simply the CPU speed.
pub unsafe fn new_with_calibration(clock_speed: u32) -> SysTick {
let mut res = SysTick::new();
res.hertz = clock_speed;
let res = SysTick::new();
res.hertz.set(clock_speed);
res
}

Expand All @@ -101,7 +106,7 @@ impl SysTick {
/// if the SysTick is driven by the CPU clock, it is simply the CPU speed.
pub unsafe fn new_with_calibration_and_external_clock(clock_speed: u32) -> SysTick {
let mut res = SysTick::new();
res.hertz = clock_speed;
res.hertz.set(clock_speed);
res.external_clock = true;
res
}
Expand All @@ -111,15 +116,29 @@ impl SysTick {
// Otherwise, compute the frequncy using the calibration value that is set
// in hardware.
fn hertz(&self) -> u32 {
if self.hertz != 0 {
self.hertz
let hz = self.hertz.get();
if hz != 0 {
hz
} else {
// The `tenms` register is the reload value for 10ms, so
// Hertz = number of tics in 1 second = tenms * 100
let tenms = SYSTICK_BASE.syst_calib.read(CalibrationValue::TENMS);
tenms * 100
}
}

/// Modifies the locally stored frequncy
///
/// # Important
///
/// This function does not change the actual systick frequency.
/// This function must be called only while the clock is not armed.
/// When changing the hardware systick frequency, the reload value register
/// should be updated and the current value register should be reset, in
/// order for the tick count to match the current frequency.
pub fn set_hertz(&self, clock_speed: u32, _capability: &dyn SysTickFrequencyCapability) {
self.hertz.set(clock_speed);
}
}

impl kernel::platform::scheduler_timer::SchedulerTimer for SysTick {
Expand Down

0 comments on commit 47319ba

Please sign in to comment.