Files
Deshab-OS/CODE/sdk/include/deshab/tsc.h
T

90 lines
2.8 KiB
C
Raw Normal View History

2026-08-09 22:14:01 +08:00
/* deshab/tsc.h - TSC 时钟校准与延时
*
* 整合 dkm_shared.h 的 dkm_tsc_calibrate/delay_ms/delay_us/serial_wait_tx
* 与 net_stack.h 的 ns_tsc_calibrate/rdtsc,统一前缀为 dsb_。
*
* 用法:
* dsb_tsc_calibrate() - 在模块入口开头调用,PIT ch0 ~10ms 校准 TSC
* dsb_rdtsc() - 读取 TSC 时间戳
* dsb_delay_ms/us() - 基于 TSC 的忙等延时
* dsb_deadline_reached()- 截止时间判定
* dsb_serial_wait_tx() - 串口发送就绪等待(100us 超时)
*
* 每个 .elf/.drv 包含本头后获得独立 file-local dsb_tsc_per_ms 副本。
*/
#ifndef DESHAB_TSC_H
#define DESHAB_TSC_H
#include "types.h"
#include "portio.h"
static u64 dsb_tsc_per_ms = 0;
static inline u64 dsb_rdtsc(void) {
u32 lo, hi;
__asm__ volatile("rdtsc" : "=a"(lo), "=d"(hi));
return ((u64)hi << 32) | lo;
}
/* PIT ch0 + TSC 校准 ~10ms 区间,推算每毫秒 TSC 周期数。 */
static inline void dsb_tsc_calibrate(void) {
if (dsb_tsc_per_ms) return;
dsb_outb(0x43, 0x30); /* ch0, lo+hi, mode 0, binary */
dsb_outb(0x40, 0x7C); /* 11932 low = ~10ms */
dsb_outb(0x40, 0x2E); /* 11932 high */
u64 tsc_start = dsb_rdtsc();
u16 prev = 0;
u64 loops = 0;
for (;;) {
dsb_outb(0x43, 0x00);
u16 cur = (u16)dsb_inb(0x40) | ((u16)dsb_inb(0x40) << 8);
if (cur > prev && loops > 10) break;
prev = cur;
loops++;
}
dsb_tsc_per_ms = (dsb_rdtsc() - tsc_start) / 10;
if (!dsb_tsc_per_ms) dsb_tsc_per_ms = 3000; /* 兜底 ~3GHz */
}
static inline int dsb_deadline_reached(u64 deadline) {
return (i64)(dsb_rdtsc() - deadline) >= 0;
}
static inline void dsb_delay_ms(u32 ms) {
if (!dsb_tsc_per_ms) {
for (volatile u32 i = 0; i < 100000 * ms; i++) __asm__ volatile("pause");
return;
}
u64 target = dsb_tsc_per_ms * ms;
u64 start = dsb_rdtsc();
while (dsb_rdtsc() - start < target) __asm__ volatile("pause");
}
static inline void dsb_delay_us(u32 us) {
if (!dsb_tsc_per_ms) {
for (volatile u32 i = 0; i < 100 * us; i++) __asm__ volatile("pause");
return;
}
u64 target = dsb_tsc_per_ms * us / 1000;
u64 start = dsb_rdtsc();
while (dsb_rdtsc() - start < target) __asm__ volatile("pause");
}
/* 串口发送就绪等待(100us 超时)。com_port = 0x3F8 (COM1)。 */
static inline void dsb_serial_wait_tx(u16 com_port) {
if (!dsb_tsc_per_ms) {
for (volatile u32 i = 0; i < 100000; i++) {
if (dsb_inb((u16)(com_port + 5)) & 0x20) break;
__asm__ volatile("pause");
}
return;
}
u64 deadline = dsb_rdtsc() + dsb_tsc_per_ms / 10;
while (dsb_rdtsc() < deadline) {
if (dsb_inb((u16)(com_port + 5)) & 0x20) break;
__asm__ volatile("pause");
}
}
#endif /* DESHAB_TSC_H */