Skip to content

Commit 3a3d578

Browse files
authored
feat: refactor timer mechanism and bump to 0.4.0 (#15)
1 parent a4fc344 commit 3a3d578

17 files changed

Lines changed: 232 additions & 188 deletions

File tree

Cargo.lock

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,18 @@ members = [
99
]
1010

1111
[workspace.package]
12-
version = "0.3.2"
12+
version = "0.4.0"
1313
edition = "2021"
1414
description = "This crate provides the interface for multiple platforms."
1515
authors = ["yfblock@321353225@qq.com"]
1616
license = "MIT"
1717
repository = "https://github.com/Byte-OS/polyhal"
1818

1919
[workspace.dependencies]
20-
polyhal = { version = "0.3.2" }
21-
polyhal-boot = { version = "0.3.2" }
22-
polyhal-macro = { version = "0.3.2" }
23-
polyhal-trap = { version = "0.3.2" }
20+
polyhal = { version = "0.4.0" }
21+
polyhal-boot = { version = "0.4.0" }
22+
polyhal-macro = { version = "0.4.0" }
23+
polyhal-trap = { version = "0.4.0" }
2424

2525
bitflags = "2.9.0"
2626
cfg-if = "1.0.0"

example/src/main.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@
44
mod allocator;
55
mod frame;
66
mod pci;
7+
use core::hint::spin_loop;
78
use core::panic::PanicInfo;
9+
use core::time::Duration;
810

911
use frame::frame_alloc;
12+
use polyhal::irq::IRQ;
1013
use polyhal::mem::{get_fdt, get_mem_areas};
1114
use polyhal::percpu::get_local_thread_pointer;
15+
use polyhal::timer::{self, current_time};
1216
use polyhal::{
1317
common::PageAlloc,
1418
instruction::{ebreak, shutdown},
@@ -31,6 +35,9 @@ impl PageAlloc for PageAllocImpl {
3135
}
3236
}
3337

38+
#[percpu]
39+
static mut TIMER_TICKS: usize = 0;
40+
3441
/// kernel interrupt
3542
#[polyhal::arch_interrupt]
3643
fn kernel_interrupt(ctx: &mut TrapFrame, trap_type: TrapType) {
@@ -51,7 +58,10 @@ fn kernel_interrupt(ctx: &mut TrapFrame, trap_type: TrapType) {
5158
log::info!("illegal instruction");
5259
}
5360
Timer => {
54-
log::info!("Timer");
61+
TIMER_TICKS.with_mut(|ticks| *ticks += 1);
62+
let next = current_time() + Duration::from_millis(100);
63+
timer::set_next_timer(next);
64+
log::info!("Timer: {:#x?} next: {:#x?}", TIMER_TICKS.read(), next);
5565
}
5666
_ => {
5767
log::warn!("unsuspended trap type: {:?}", trap_type);
@@ -87,8 +97,18 @@ fn main(hartid: usize) {
8797

8898
// Test BreakPoint Interrupt
8999
ebreak();
90-
91100
crate::pci::init();
101+
102+
log::info!("Waiting for TIMER_TICKS greater than 5");
103+
IRQ::int_enable();
104+
let target = current_time() + Duration::from_millis(1);
105+
timer::set_next_timer(target);
106+
log::info!("current: {:#x?} target: {:#x?}", current_time(), target);
107+
108+
while *TIMER_TICKS <= 5 {
109+
spin_loop();
110+
}
111+
92112
log::info!("Run END. Shutdown successfully.");
93113
shutdown();
94114
}

polyhal-trap/src/trap/aarch64.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use tock_registers::interfaces::Readable;
55

66
use crate::trapframe::TrapFrame;
77
use polyhal::irq::{get_irq, TIMER_IRQ_NUM};
8-
use polyhal::timer::set_next_timer;
98

109
use super::{EscapeReason, TrapType};
1110

@@ -38,7 +37,6 @@ fn handle_exception(tf: &mut TrapFrame, kind: TrapKind, source: TrapSource) -> T
3837
let trap_type = match irq.irq_num() {
3938
TIMER_IRQ_NUM => {
4039
irq.ack();
41-
set_next_timer();
4240
TrapType::Timer
4341
}
4442
_ => TrapType::Irq(irq),

polyhal-trap/src/trap/riscv64.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ mod macros;
44
use super::{EscapeReason, TrapType};
55
use crate::trapframe::TrapFrame;
66
use core::arch::naked_asm;
7-
use polyhal::{consts::VIRT_ADDR_START, timer};
7+
use polyhal::consts::VIRT_ADDR_START;
88
use riscv::{
99
interrupt::{Exception, Interrupt},
1010
register::{
@@ -47,10 +47,7 @@ fn kernel_callback(context: &mut TrapFrame) -> TrapType {
4747
}
4848
Trap::Exception(Exception::UserEnvCall) => TrapType::SysCall,
4949
// 时钟中断
50-
Trap::Interrupt(Interrupt::SupervisorTimer) => {
51-
timer::set_next_timeout();
52-
TrapType::Timer
53-
}
50+
Trap::Interrupt(Interrupt::SupervisorTimer) => TrapType::Timer,
5451
Trap::Exception(Exception::StorePageFault) => TrapType::StorePageFault(stval),
5552
Trap::Exception(Exception::StoreFault) => TrapType::StorePageFault(stval),
5653
Trap::Exception(Exception::InstructionPageFault) => TrapType::InstructionPageFault(stval),

polyhal/src/arch/x86_64/apic.rs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,24 +26,6 @@ static mut LOCAL_APIC: Option<LocalApic> = None;
2626
static mut IS_X2APIC: bool = false;
2727
static IO_APIC: Once<MutexNoIrq<IoApic>> = Once::new();
2828

29-
/// Registers an IRQ handler for the given IRQ.
30-
///
31-
/// It also enables the IRQ if the registration succeeds. It returns `false` if
32-
/// the registration failed.
33-
// pub fn register_handler(vector: usize, handler: crate::irq::IrqHandler) -> bool {
34-
// crate::irq::register_handler_common(vector, handler)
35-
// }
36-
37-
/// Dispatches the IRQ.
38-
///
39-
/// This function is called by the common interrupt handler. It looks
40-
/// up in the IRQ handler table and calls the corresponding handler. If
41-
/// necessary, it also acknowledges the interrupt controller after handling.
42-
// pub fn dispatch_irq(vector: usize) {
43-
// crate::irq::dispatch_irq_common(vector);
44-
// unsafe { local_apic().end_of_interrupt() };
45-
// }
46-
4729
pub fn local_apic<'a>() -> &'a mut LocalApic {
4830
// It's safe as LAPIC is per-cpu.
4931
unsafe { LOCAL_APIC.as_mut().unwrap() }

polyhal/src/components/irq/aarch64.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use arm_gicv2::{translate_irq, InterruptType};
33
use arm_gicv2::{GicCpuInterface, GicDistributor};
44

55
use crate::components::irq::{IRQVector, IRQ};
6+
use crate::ctor::CtorType;
67
use crate::utils::MutexNoIrq;
78
use crate::PhysAddr;
89

@@ -87,3 +88,5 @@ impl IRQ {
8788
DAIF.read(DAIF::I) == 0
8889
}
8990
}
91+
92+
ph_ctor!(AARCH64_INIT_GIC, CtorType::Cpu, init);
Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,48 @@
1+
use core::time::Duration;
2+
13
use aarch64_cpu::registers::{CNTFRQ_EL0, CNTPCT_EL0, CNTP_CTL_EL0, CNTP_TVAL_EL0};
24
use tock_registers::interfaces::{Readable, Writeable};
35

4-
use crate::{
5-
components::irq::{IRQ, TIMER_IRQ_NUM},
6-
time::Time,
7-
};
6+
use crate::components::irq::{IRQ, TIMER_IRQ_NUM};
87

9-
impl Time {
10-
#[inline]
11-
pub fn get_freq() -> usize {
12-
CNTFRQ_EL0.get() as _
13-
}
8+
use super::current_time;
149

15-
/// Returns the current clock time in hardware ticks.
16-
#[inline]
17-
pub fn now() -> Self {
18-
Self(CNTPCT_EL0.get() as _)
19-
}
10+
/// Get ticks from system clock
11+
///
12+
/// # Return
13+
///
14+
/// - [u64] clock ticks
15+
#[inline]
16+
pub fn get_ticks() -> u64 {
17+
CNTPCT_EL0.get()
2018
}
2119

22-
pub fn set_next_timer() {
23-
CNTP_TVAL_EL0.set(CNTFRQ_EL0.get() / 1000);
20+
/// Get frequency of the system clock
21+
///
22+
/// # Return
23+
///
24+
/// - [u64] n ticks per second
25+
#[inline]
26+
pub fn get_freq() -> u64 {
27+
CNTFRQ_EL0.get()
28+
}
29+
30+
/// Set the next timer
31+
///
32+
/// # parameters
33+
///
34+
/// - next [Duration] next time from system boot
35+
#[inline]
36+
pub fn set_next_timer(next: Duration) {
37+
let curr = current_time();
38+
if next < curr {
39+
return;
40+
}
41+
let interval = next - curr;
42+
CNTP_TVAL_EL0.set(
43+
interval.as_secs() * get_freq()
44+
+ interval.subsec_nanos() as u64 * get_freq() / 1_000_000_000,
45+
);
2446
}
2547

2648
pub fn init() {
@@ -30,5 +52,5 @@ pub fn init() {
3052
CNTP_TVAL_EL0.set(0);
3153
// Enable the timer irq.
3254
IRQ::irq_enable(TIMER_IRQ_NUM);
33-
set_next_timer();
55+
set_next_timer(Duration::ZERO);
3456
}

polyhal/src/components/timer/loongarch64.rs

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,57 @@
1+
use core::time::Duration;
2+
13
use loongArch64::register::ecfg::{self, LineBasedInterrupt};
24
use loongArch64::register::tcfg;
35
/// Returns the current clock time in hardware ticks.
46
use loongArch64::time::{get_timer_freq, Time};
57
use spin::Lazy;
68

9+
use crate::timer::current_time;
10+
711
// static mut FREQ: usize = 0;
8-
static FREQ: Lazy<usize> = Lazy::new(|| get_timer_freq());
12+
static FREQ: Lazy<u64> = Lazy::new(|| get_timer_freq() as _);
913

10-
impl crate::time::Time {
11-
#[inline]
12-
pub fn get_freq() -> usize {
13-
*FREQ
14-
}
14+
/// Get ticks from system clock
15+
///
16+
/// # Return
17+
///
18+
/// - [u64] clock ticks
19+
#[inline]
20+
pub fn get_ticks() -> u64 {
21+
Time::read() as _
22+
}
23+
24+
/// Get frequency of the system clock
25+
///
26+
/// # Return
27+
///
28+
/// - [u64] n ticks per second
29+
#[inline]
30+
pub fn get_freq() -> u64 {
31+
*FREQ
32+
}
1533

16-
/// Returns the current clock time in hardware ticks.
17-
#[inline]
18-
pub fn now() -> Self {
19-
Self(Time::read())
34+
/// Set the next timer
35+
///
36+
/// # parameters
37+
///
38+
/// - next [Duration] next time from system boot#[inline]
39+
pub fn set_next_timer(next: Duration) {
40+
let curr = current_time();
41+
if next < curr {
42+
return;
2043
}
44+
let interval = next - curr;
45+
tcfg::set_init_val(
46+
(interval.as_secs() * get_freq()
47+
+ interval.subsec_nanos() as u64 * get_freq() / 1_000_000_000) as _,
48+
);
49+
tcfg::set_en(true);
2150
}
2251

2352
pub fn init() {
24-
let ticks = ((*FREQ / 1000) + 3) & !3;
25-
tcfg::set_periodic(true); // set timer to one-shot mode
26-
tcfg::set_init_val(ticks); // set timer initial value
53+
tcfg::set_periodic(false); // set timer to one-shot mode
54+
tcfg::set_init_val(0); // set timer initial value
2755
tcfg::set_en(true); // enable timer
2856

2957
let inter = LineBasedInterrupt::TIMER

polyhal/src/components/timer/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
55
use core::time::Duration;
66

7-
use crate::{ctor::CtorType, Time};
7+
use crate::ctor::CtorType;
88

99
super::define_arch_mods!();
1010

@@ -15,7 +15,9 @@ super::define_arch_mods!();
1515
/// Return [Duration] with current time
1616
#[inline]
1717
pub fn current_time() -> Duration {
18-
Duration::from_nanos(Time::now().raw() as _)
18+
let ticks = get_ticks();
19+
let freq = get_freq();
20+
Duration::new(ticks / freq, ((ticks % freq) * 1_000_000_000 / freq) as u32)
1921
}
2022

2123
ph_ctor!(ARCH_INIT_TIMER, CtorType::Platform, init);

0 commit comments

Comments
 (0)