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()