时间子系统10_hpet时钟初始化
// 时钟mult :mult/2^shift = ns/cyc // 参考:http://www.bluezd.info/archives/reg_clock_event_device_1
// x86平台初始化
// 注:arch/x86/kernel/x86_init.c
1.1 struct x86_init_ops x86_init __initdata = {...//时钟初始化.timers = {.setup_percpu_clockev = setup_boot_APIC_clock,.tsc_pre_init = x86_init_noop,.timer_init = hpet_time_init,},...
};// 时钟初始化
// 函数任务:
// 1.初始化hpet时钟源,时钟事件设备
// 2.初始化tsc时钟源
// 调用路径start_kernel->time_init
1.1 void __init time_init(void)
{//初始化hpet时钟源x86_init.timers.timer_init();tsc_init();
}// 初始化hpet
// 函数任务:
// 1.注册hpet clocksource,hpet clockevent
// 2.注册时钟中断处理程序
// 调用路径:time_init->hpet_time_init
2.1 void __init hpet_time_init(void)
{//注册hpet clocksource,hpet clockeventif (!hpet_enable())setup_pit_timer();//分配时钟中断setup_default_timer_irq();
}// 注册hpet时钟源
// 调用路径:hpet_time_init->hpet_enable->hpet_clocksource_register
// 函数任务:
// 1.初始化hpet clocksource硬件设备
// 2.检查hpet计数器是否正常工作
// 2.1 等待200000 tsc,判断hpet计数是否变化
// 3.计算hpet mult值
// 4.向系统注册hpet时钟源
2.2 static int hpet_clocksource_register(void)
{u64 start, now;cycle_t t1;//初始化hpet clocksource硬件设备hpet_restart_counter();//检测hpet计数器是否工作t1 = hpet_readl(HPET_COUNTER);rdtscll(start);//检测办法// 200000tsc之后,判断hpet计数器是否发生变化do {rep_nop();rdtscll(now);} while ((now - start) < 200000UL);if (t1 == hpet_readl(HPET_COUNTER)) {printk(KERN_WARNING"HPET counter not counting. HPET disabled\n");return -ENODEV;}//计算hpet clocksource的shift值clocksource_hpet.mult = div_sc(hpet_period, FSEC_PER_NSEC, HPET_SHIFT);//注册hpet时钟源clocksource_register(&clocksource_hpet);return 0;
}// hpet时钟源
2.3 static struct clocksource clocksource_hpet = {.name = "hpet",.rating = 250,//精度排名.read = read_hpet,.mask = HPET_MASK,.shift = HPET_SHIFT,.flags = CLOCK_SOURCE_IS_CONTINUOUS,//连续时钟源.resume = hpet_resume_counter,};// 注册hpet 时钟事件设备
// 调用路径:hpet_time_init->hpet_enable->hpet_legacy_clockevent_register
// 函数任务:
// 1.hpet clockevent硬件初始化
// 2.计算hpet mult
// 3.计算hpet cpu掩码
// 3.1 IO_APIC初始化完成后,设置hpet对所有cpu可用
// 4.计算hpet clockevent设备可重新编程的最大、最小时间间隔
// 5.设置hpet clockevent设备为全局事件设备
// 注:
// hpet clockevent存在可重新编程的上下时间间隔
3.1 static void hpet_legacy_clockevent_register(void)
{//hpet clockevent硬件初始化hpet_enable_legacy_int();//计算hpet clockevent的multhpet_clockevent.mult = div_sc((unsigned long) FSEC_PER_NSEC,hpet_period, hpet_clockevent.shift);//最大时间间隔hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF,&hpet_clockevent);//重新编程的最小时间间隔5ushpet_clockevent.min_delta_ns = 5000;//当io-apic初始化完成后,才会使hpet 服务于所有cpuhpet_clockevent.cpumask = cpumask_of(smp_processor_id());//注册hpet clockeventclockevents_register_device(&hpet_clockevent);//hpet作为全局时钟事件设备global_clock_event = &hpet_clockevent;
}// hpet clockevent设备
3.2 static struct clock_event_device hpet_clockevent = {.name = "hpet",.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,//支持周期和单触发模式.set_mode = hpet_legacy_set_mode,.set_next_event = hpet_legacy_next_event,//设置事件将要发生的时间.shift = 32,.irq = 0,//使用0号irq.rating = 50,
};// 时钟中断控制块
4.1 static struct irqaction irq0 = {.handler = timer_interrupt,.flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER,.name = "timer"
};// 设置时钟中断处理程序
// 调用路径:hpet_time_init->setup_default_timer_irq
4.2 void __init setup_default_timer_irq(void)
{setup_irq(0, &irq0);
}// 时钟中断处理程序
// 函数任务:
// 1.向中断控制器应答
// 2.通知全局时钟事件设备处理时间到期
4.3 static irqreturn_t timer_interrupt(int irq, void *dev_id)
{//向中断控制器应答时钟中断if (timer_ack) {raw_spin_lock(&i8259A_lock);outb(0x0c, PIC_MASTER_OCW3);/* Ack the IRQ; AEOI will end it automatically. */inb(PIC_MASTER_POLL);raw_spin_unlock(&i8259A_lock);}//全局时钟源设备的时间处理函数global_clock_event->event_handler(global_clock_event);if (MCA_bus)outb_p(inb_p(0x61)| 0x80, 0x61);return IRQ_HANDLED;
}
时间子系统10_hpet时钟初始化相关推荐
- Linux时间子系统之时钟源层(Clock Source)
所谓时钟源设备,Linux将其抽象为一个可以记录时间流逝的设备,其值随着时间的流逝递增.将前一次读取的值和当前的值做比较就知道过去了多长的时间.但是它不一定是记录当前具体时间的设备,它只记录过去了多少 ...
- Linux时间子系统之八:动态时钟框架(CONFIG_NO_HZ、tickless)【转】
转自:http://blog.csdn.net/droidphone/article/details/8112948 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 数据结构 ...
- linux 多核 系统时钟,Linux时间子系统之(十五):clocksource
Linux时间子系统之(十五):clocksource 作者:linuxer 发布于:2014-12-1 19:03 分类:时间子系统 一.前言 和洋葱一样,软件也是有层次的,内核往往需要对形形色色的 ...
- Linux时间子系统之三:时间的维护者:timekeeper
专题文档汇总目录 Notes: 原文地址:Linux时间子系统之三:时间的维护者:timekeeper 本系列文章的前两节讨论了用于计时的时钟源:clocksource,以及内核内部时间的一些表示方法 ...
- Linux时间子系统(二) 软件架构
一.前言 本文的主要内容是描述内核时间子系统的软件框架.首先介绍了从旧的时间子系统迁移到新的时间子系统的源由,介绍新的时间子系统的优势.第三章汇整了时间子系统的相关文件以及内核配置.最后描述各种内核配 ...
- Linux时间子系统之六:高精度定时器(HRTIMER)的原理和实现
转自:http://blog.csdn.net/droidphone/article/details/8074892 上一篇文章,我介绍了传统的低分辨率定时器的实现原理.而随着内核的不断演进,大牛们已 ...
- Linux时间子系统之(五):POSIX Clock
专题文档汇总目录 Notes: 本章主要介绍了若干种类的静态时钟,这些时钟都可以通过k_clock表示,注册到posix_clocks中.这些都是静态时钟,可以分为三大类:各种REALTIME时钟.带 ...
- Linux时间子系统之Tick层
所谓Tick设备,也称作滴答设备,就是系统中的一个周期中断设备,其周期间隔由内核编译选项定义. Tick设备在Linux时间子系统中用tick_device结构体表示(代码位于kernel/time/ ...
- 解BUG-xenomai内核与linux内核时间子系统之间存在漂移
版权声明:本文为本文为博主原创文章,转载请注明出处https://blog.csdn.net/qq_22654551.如有问题,欢迎指正. 一.问题起源 何为漂移?举个例子两颗32.768kHz晶振C ...
最新文章
- VMware HA实战攻略之五VMwareHA测试验收
- java 正则表达式语法_Java 正则表达式基础语法
- android入门学习-天气预报app(一)
- 模仿网易(163)首页Ajax功能中的鼠标延时触发
- axure菜单移动隐藏_如何使用隐藏的移动网络更快地完成工作
- SQL Server查询执行计划–基础
- PostFix邮件网关无法向公网投递邮件问题分析
- python安装详细步骤windows10_Windows10系统安装Python教程
- 改写自SqlHelper的SqliteHelper
- 太牛了!阿里p8全面透彻剖析《Netty权威指南》,程序员必看!
- linux串口编程(termios结构体说明)
- 20多年来,我国网络文学行业发生了天翻地覆的变化
- Word不计算封面、目录页数将正文页码修改为第几页共几页的格式
- 波士顿房价预测python决策树_波士顿房价预测 - 最简单入门机器学习 - Jupyter
- PS软件学习知识盘点
- G.652光纤各个子类的主要区别及应用
- 【个人C++学习日记】
- Java实现split字符串分割方法
- 【逗老师带你学IT】PRTG获取HUAWEI FusionServer iBMC传感器状态
- 实训|第十天从底层解释一下U盘内存为什么变小的原因附数据恢复的基本原理...
热门文章
- 申请著作权的流程有哪些
- python安装math模块_python math模块
- 网上书城项目的需求分析、数据库表设计及前端界面的编写(项目进度一)
- 数据结构(C语言版)之栈及递归
- GitHub下载 无法分配请求的地址_Hexo+Github--搭建个人博客(一)准备工作amp;amp;环境搭建
- java ee字体_[分享] 23种漂亮的字体代码,
- 腾讯数据科学家详解用户选择行为分析核心模型
- mysql如何进行数据透视_使用MySQL的数据透视表
- PostgreSQL之如何敲开PG的大门?
- 使用Rust开发编译系统(C以及Rust编译的过程)