A no_std CMOS–based Real‑Time Clock (RTC) driver for x86 / x86_64 PCs and QEMU guests.
It offers a safe, minimal wrapper around the legacy CMOS I/O ports (0x70/0x71) so you can read or set the wall‑clock time as a UNIX timestamp.
[dependencies]
x86_rtc = "0.1"MSRV ≥ 1.71 (matches latest stable channel).
Platform note — on non‑x86 targets the crate compiles to “stubs” (all zeros / no‑ops), so you can still share code across multi‑arch projects without
cfgexplosions.
| Function | Description |
|---|---|
Rtc::new() |
Create an instance; snapshots Status Register B to learn BCD vs. Binary and 12 h vs. 24 h formats. |
get_unix_timestamp() |
Spin‑locks around the update‑in‑progress flag, converts CMOS date + time into seconds since 1970‑01‑01 UTC. |
set_unix_timestamp(u64) |
Converts a UNIX timestamp back to calendar fields (handles leap‑years & BCD) and writes them to the RTC. |
use x86_rtc::Rtc;
fn main() {
// SAFETY: on real HW you should disable interrupts to avoid half‑updated reads.
// In a hobby OS this is typically done with `x86_64::instructions::interrupts::disable();`
let rtc = Rtc::new();
let now = rtc.get_unix_timestamp();
println!("UNIX time: {now}");
// … or push a timestamp back (e.g. after getting NTP time)
// rtc.set_unix_timestamp(1_725_888_000); // 2025‑07‑01 00:00:00 UTC
}| Feature | Default? | Effect |
|---|---|---|
| none | ✅ | Build for x86/x86_64 with CMOS I/O; other targets produce dummy stubs. |
std |
❌ | Enable std for use in userspace binaries/tests. |
- Select CMOS register via 0x70 (with NMI masked), then read/write via 0x71.
- Interpret Status Reg B bits to decide BCD ↔ Binary and 12 h ↔ 24 h handling.
- Guard against partial updates using the UIP flag in Status Reg A.
- Convert calendar <→ epoch seconds using an internal,
const fn/no_stdmktime clone.
- All port I/O is wrapped in
unsafeblocks but exposed through safe methods. - Spin‑waits use
core::hint::spin_loop()— no busy‑waits once data is stable. set_unix_timestampperforms bounds checking and BCD conversion before writing.