Files
ViperOS/VKernel/Kernel/platform/pch/timer.vp
T
TermiNexus dcb7c5c2c0 chore(ViperOS): 落库内核侧进行中的改动(26 文件,+1573/-1805)
内容由用户产出,本次仅代为提交、未做任何语义修改;含 static 修饰符前置迁移等(新增 static 前缀 16 行)。提交消息为中性描述——如需更精确的说明请 amend。
2026-09-28 15:24:52 +08:00

130 lines
4.3 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import platform.pch.pic as pic
import platform.pch.pit as pit
import sched.sched as sched
import drivers.core.cpu.apic as apic
import drivers.serial.uart.serial as serial
import viperlib
import asm
define TIMER_FREQUENCY = 1000
define TICKS_PER_SECOND = TIMER_FREQUENCY
define MILLISECONDS_PER_TICK = (1000 / TIMER_FREQUENCY)
static ticks: volatile uint64 = 0
static seconds: volatile uint32 = 0
static milliseconds: volatile uint32 = 0
static timer_running: volatile bool = False
_dbg_once: int = 0
def timer_init():
global ticks, seconds, milliseconds, timer_running
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
ticks = 0
seconds = 0
milliseconds = 0
timer_running = True
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
pit.pit_init(TIMER_FREQUENCY)
# [DBG] 读 PIT 计数器验证是否在走(用后移除)
asm.outb(0x43, 0x00) # latch channel 0
_lo: uint8 = asm.inb(0x40)
_hi: uint8 = asm.inb(0x40)
_cnt: int = int(_lo) | (int(_hi) << 8)
_cb: [40]char
viperlib.snprintf(&_cb, 40, "[PIT] cnt=%d\n", _cnt)
serial.puts(&_cb)
def timer_handler():
global ticks, seconds, milliseconds, timer_running, _dbg_once
# [DBG] 一次性打印:'H' 出现说明定时 ISR 被调用(用后移除)
if _dbg_once == 0:
_dbg_once = 1
serial.puts("H")
if not timer_running:
pic.eoi(0)
apic.eoi()
return
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
ticks = ticks + 1
milliseconds = milliseconds + MILLISECONDS_PER_TICK
if milliseconds >= 1000:
seconds = seconds + 1
milliseconds = milliseconds - 1000
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
sched.Scheduler.sched_tick()
pic.eoi(0)
# LAPIC EOI:APIC 启用后中断经 LINT0(EXTINT) 送达会置 LAPIC ISR,
# 只发 PIC EOI 不清 LAPIC ISR → 首个定时中断后后续中断被屏蔽 →
# ticks 不推进 → msleep 永久挂起(QEMU/OVMF 下 APIC 必启用)。
apic.eoi()
def timer_start():
global timer_running
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
timer_running = True
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
def timer_stop():
global timer_running
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
timer_running = False
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
def timer_reset():
global ticks, seconds, milliseconds
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
ticks = 0
seconds = 0
milliseconds = 0
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
def timer_get_ticks() -> uint64:
current_ticks: uint64
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
current_ticks = ticks
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
return current_ticks
def timer_get_seconds() -> uint32:
current_seconds: uint32
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
current_seconds = seconds
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
return current_seconds
def timer_get_milliseconds() -> uint32:
current_milliseconds: uint32
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
current_milliseconds = milliseconds
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
return current_milliseconds
def timer_get_time(out_seconds: uint32*, out_milliseconds: uint32*):
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
if out_seconds:
*out_seconds = seconds
if out_milliseconds:
*out_milliseconds = milliseconds
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
def timer_msleep(ms: uint32):
target: uint64 = ticks + (ms + MILLISECONDS_PER_TICK - 1) / MILLISECONDS_PER_TICK
_spin: uint64 = 0
while ticks < target:
# [DBG] 自旋计数:每 1M 次迭代打印 s——hlt 能唤醒说明中断触发
# (用后移除)
_spin += 1
if (_spin & 0xFFFFF) == 0:
serial.puts("s")
asm.sti()
asm.hlt()
sched.Scheduler._yield()
def timer_sleep(sec: uint32):
target: uint64 = ticks + sec * TICKS_PER_SECOND
while ticks < target:
asm.sti()
asm.hlt()
sched.Scheduler._yield()