mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-22 07:03:22 +00:00
实现了rtc的抽象,并且把x86的cmos rtc接入到设备驱动模型 (#674)
* 实现了rtc的抽象,并且把x86的cmos rtc接入到设备驱动模型。
This commit is contained in:
@ -16,6 +16,7 @@ pub mod timeconv;
|
||||
pub mod timekeep;
|
||||
pub mod timekeeping;
|
||||
pub mod timer;
|
||||
|
||||
/* Time structures. (Partitially taken from smoltcp)
|
||||
|
||||
The `time` module contains structures used to represent both
|
||||
@ -124,6 +125,61 @@ pub struct Instant {
|
||||
impl Instant {
|
||||
pub const ZERO: Instant = Instant::from_micros_const(0);
|
||||
|
||||
/// mktime64 - 将日期转换为秒。
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - year0: 要转换的年份
|
||||
/// - mon0: 要转换的月份
|
||||
/// - day: 要转换的天
|
||||
/// - hour: 要转换的小时
|
||||
/// - min: 要转换的分钟
|
||||
/// - sec: 要转换的秒
|
||||
///
|
||||
/// 将公历日期转换为1970-01-01 00:00:00以来的秒数。
|
||||
/// 假设输入为正常的日期格式,即1980-12-31 23:59:59 => 年份=1980, 月=12, 日=31, 时=23, 分=59, 秒=59。
|
||||
///
|
||||
/// [For the Julian calendar(俄罗斯在1917年之前使用,英国及其殖民地在大西洋1752年之前使用,
|
||||
/// 其他地方在1582年之前使用,某些社区仍然在使用)省略-year/100+year/400项,
|
||||
/// 并在结果上加10。]
|
||||
///
|
||||
/// 这个算法最初由高斯(我认为是)发表。
|
||||
///
|
||||
/// 要表示闰秒,可以通过将sec设为60(在ISO 8601允许)来调用此函数。
|
||||
/// 闰秒与随后的秒一样处理,因为它们在UNIX时间中不存在。
|
||||
///
|
||||
/// 支持将午夜作为当日末尾的24:00:00编码 - 即明天的午夜(在ISO 8601允许)。
|
||||
///
|
||||
/// ## 返回
|
||||
///
|
||||
/// 返回:给定输入日期自1970-01-01 00:00:00以来的秒数
|
||||
pub fn mktime64(year0: u32, mon0: u32, day: u32, hour: u32, min: u32, sec: u32) -> Self {
|
||||
let mut mon: i64 = mon0.into();
|
||||
let mut year: u64 = year0.into();
|
||||
let day: u64 = day.into();
|
||||
let hour: u64 = hour.into();
|
||||
let min: u64 = min.into();
|
||||
let sec: u64 = sec.into();
|
||||
|
||||
mon -= 2;
|
||||
/* 1..12 -> 11,12,1..10 */
|
||||
if mon <= 0 {
|
||||
/* Puts Feb last since it has leap day */
|
||||
mon += 12;
|
||||
year -= 1;
|
||||
}
|
||||
let mon = mon as u64;
|
||||
|
||||
let secs = ((((year / 4 - year / 100 + year / 400 + 367 * mon / 12 + day) + year * 365
|
||||
- 719499)
|
||||
* 24 + hour) /* now have hours - midnight tomorrow handled here */
|
||||
* 60 + min)/* now have minutes */
|
||||
* 60
|
||||
+ sec; /* finally seconds */
|
||||
|
||||
Self::from_secs(secs as i64)
|
||||
}
|
||||
|
||||
/// Create a new `Instant` from a number of microseconds.
|
||||
pub fn from_micros<T: Into<i64>>(micros: T) -> Instant {
|
||||
Instant {
|
||||
|
@ -1,6 +1,10 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
use crate::driver::timers::rtc::rtc::RtcTime;
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::driver::rtc::interface::rtc_read_time_default;
|
||||
|
||||
use super::TimeSpec;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type ktime_t = i64;
|
||||
@ -14,48 +18,16 @@ fn ktime_to_ns(kt: ktime_t) -> i64 {
|
||||
/// @brief 从RTC获取当前时间,然后计算时间戳。
|
||||
/// 时间戳为从UTC+0 1970-01-01 00:00到当前UTC+0时间,所经过的纳秒数。
|
||||
/// 注意,由于当前未引入时区,因此本函数默认时区为UTC+8来计算
|
||||
fn ktime_get_real() -> ktime_t {
|
||||
let mut rtc_time: RtcTime = RtcTime::default();
|
||||
|
||||
{
|
||||
let r = rtc_time.get();
|
||||
// 返回错误码
|
||||
if let Err(e) = r {
|
||||
return e as ktime_t;
|
||||
}
|
||||
}
|
||||
|
||||
let mut day_count: i32 = 0;
|
||||
for year in 1970..rtc_time.year {
|
||||
let leap: bool = (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0);
|
||||
if leap {
|
||||
day_count += 366;
|
||||
} else {
|
||||
day_count += 365;
|
||||
}
|
||||
}
|
||||
for month in 1..rtc_time.month {
|
||||
match month {
|
||||
1 | 3 | 5 | 7 | 8 | 10 | 12 => day_count += 31,
|
||||
2 => day_count += 28,
|
||||
4 | 6 | 9 | 11 => day_count += 30,
|
||||
_ => day_count += 0,
|
||||
}
|
||||
}
|
||||
|
||||
day_count += rtc_time.day - 1;
|
||||
//转换成纳秒
|
||||
let timestamp: ktime_t = day_count as i64 * 86_400_000_000_000i64
|
||||
+ (rtc_time.hour - 8) as i64 * 3_600_000_000_000i64
|
||||
+ rtc_time.minute as i64 * 60_000_000_000i64
|
||||
+ rtc_time.second as i64 * 1_000_000_000u64 as ktime_t;
|
||||
|
||||
return timestamp;
|
||||
fn ktime_get_real() -> Result<ktime_t, SystemError> {
|
||||
let rtc_time = rtc_read_time_default()?;
|
||||
let time_spec: TimeSpec = rtc_time.into();
|
||||
let r = time_spec.tv_sec * 1_000_000_000 + time_spec.tv_nsec;
|
||||
return Ok(r);
|
||||
}
|
||||
|
||||
/// @brief 暴露给外部使用的接口,返回一个时间戳
|
||||
#[inline]
|
||||
pub fn ktime_get_real_ns() -> i64 {
|
||||
let kt: ktime_t = ktime_get_real();
|
||||
let kt: ktime_t = ktime_get_real().unwrap_or(0);
|
||||
return ktime_to_ns(kt);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
use alloc::sync::Arc;
|
||||
use core::sync::atomic::{compiler_fence, AtomicBool, AtomicI64, Ordering};
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
arch::CurrentIrqArch,
|
||||
@ -207,6 +208,13 @@ pub fn do_gettimeofday() -> PosixTimeval {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn do_settimeofday64(time: TimeSpec) -> Result<(), SystemError> {
|
||||
timekeeper().0.write_irqsave().xtime = time;
|
||||
// todo: 模仿linux,实现时间误差校准。
|
||||
// https://code.dragonos.org.cn/xref/linux-6.6.21/kernel/time/timekeeping.c?fi=do_settimeofday64#1312
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/// # 初始化timekeeping模块
|
||||
#[inline(never)]
|
||||
pub fn timekeeping_init() {
|
||||
|
Reference in New Issue
Block a user