Linux的RTC驱动相对还是比较简单的,可以将它作为一个普通的字符型设备,或者一个misc设备,也可以是一个平台设备,这都没有关系,主要还是对rtc_ops这个文件操作结构体中的成员填充,这里主要涉及到两个方面比较重要:

1. 在Linux中有硬件时钟与系统时钟等两种时钟。硬件时钟是指主机板上的时钟设备,也就是通常可在BIOS画面设定的时钟。系统时钟则是指kernel中的时钟。当Linux启动时,系统时钟会去读取硬件时钟的设定,之后系统时钟即独立运作。所有Linux相关指令与函数都是读取系统时钟的设定。

系统时钟的设定就是我们常用的date命令,而我们写的RTC驱动就是为硬件时钟服务的,它有属于自己的命令hwclock,因此使用date命令是不可能调用到我们的驱动的(在这点上开始把我郁闷到了,写完驱动之后,傻傻的用date指令来测试,当然结果是什么都没有),我们可以通过hwclock的一些指令来实现更新rtc时钟——也就是系统时钟和硬件时钟的交互。

hwclock –r显示硬件时钟与日期

hwclock –s将系统时钟调整为与目前的硬件时钟一致。

hwclock –w将硬件时钟调整为与目前的系统时钟一致。

用户输入 hwclck -s // 这个命令是 把硬件的时钟更新到系统中去

这个命令会调用busybox源码中的hwclock.c,在目录util-linux/hwclock.c 中的 ->int hwclock_main(int argc UNUSED_PARAM, char **argv)

后面的参数会以argv形式接收

opt = getopt32(argv, "lurswtf:", &rtcname);

会把argv的参数进行转换 l -> 0x01

u -> 0x02

r -> 0x04

s -> 0x08

w -> 0x10

t -> 0x20

f -> 0x40

: -> 0x80

#define HWCLOCK_OPT_LOCALTIME 0x01

#define HWCLOCK_OPT_UTC 0x02

#define HWCLOCK_OPT_SHOW 0x04 // 等价 hwclock –r 显示硬件的时间

#define HWCLOCK_OPT_HCTOSYS 0x08 // 等价 hwclock –s 硬件时间更新到系统时间

#define HWCLOCK_OPT_SYSTOHC 0x10 // 等价 hwclock –w 系统时间更新到硬件时间

#define HWCLOCK_OPT_SYSTZ 0x20

#define HWCLOCK_OPT_RTCFILE 0x40

if (opt & (HWCLOCK_OPT_UTC | HWCLOCK_OPT_LOCALTIME)) // 判断是是否是 hwclock –l -u

utc = (opt & HWCLOCK_OPT_UTC);

if (opt & HWCLOCK_OPT_HCTOSYS) // 判断是是否是 hwclock –s

to_sys_clock(&rtcname, utc);

else if (opt & HWCLOCK_OPT_SYSTOHC) // 判断是是否是 hwclock –w

from_sys_clock(&rtcname, utc);

else

/* default HWCLOCK_OPT_SHOW */ // 默认是 hwclock –r

show_clock(&rtcname, utc);

hwclock –s ->to_sys_clock-> read_rtc(pp_rtcname, NULL, utc); // 读rtc的时间

-> fd = rtc_xopen(pp_rtcname, O_RDONLY)

*default_rtc = "/dev/rtc";

rtc = open(*default_rtc, flags);

*default_rtc = "/dev/rtc0";

rtc = open(*default_rtc, flags);

*default_rtc = "/dev/misc/rtc";

// 会打开这几个默认的文件

-> rtc_read_tm(&tm_time, fd);

-> xioctl(fd, RTC_RD_TIME, ptm);

// 读系统的时间

-> settimeofday(&tv, &tz)) // 设置系统的时间

hwclock –w ->from_sys_clock(&rtcname, utc); -> rtc = rtc_xopen(pp_rtcname, O_WRONLY);

*default_rtc = "/dev/rtc";

rtc = open(*default_rtc, flags);

*default_rtc = "/dev/rtc0";

rtc = open(*default_rtc, flags);

*default_rtc = "/dev/misc/rtc";

// 会打开这几个默认的文件

-> gettimeofday(&tv, NULL); // 获得系统时间

-> xioctl(rtc, RTC_SET_TIME, &tm_time); // 设置系统时间

-> close(rtc) //

hwclock –r -> show_clock(const char **pp_rtcname, int utc)

-> time_t t = read_rtc(pp_rtcname, &sys_tv, utc);

->*default_rtc = "/dev/rtc";

rtc = open(*default_rtc, flags);

*default_rtc = "/dev/rtc0";

rtc = open(*default_rtc, flags);

*default_rtc = "/dev/misc/rtc";

// 会打开这几个默认的文件

-> fd = rtc_xopen(pp_rtcname, O_RDONLY);

-> rtc_read_tm(&tm_time, fd);

-> xioctl(fd, RTC_RD_TIME, ptm);以上可以知道, 读时间使用ioctl进行的,使用两个命令

RTC_RD_TIME // 读时间

RTC_SET_TIME // 设置时间第二部分: rtc驱动架构分析

rtc的驱动架构是基于platform机制实现的,platform_device是由设备树生成

rtc的设备树如下:

rtc@10070000

{

compatible = "samsung,s3c6410-rtc";

reg = < 0x10070000 0x100>;

interrupts = < 0 44 0>, <0 45 0>;

clocks = < &clock 346>;

clock-names = "rtc";

status = "disabled";

};这个设备树会生成platform_device

驱动在driver /rtc/rtc-s3c.c 文件中定义

static struct platform_driver s3c_rtc_driver = {

.probe = s3c_rtc_probe,

.remove = s3c_rtc_remove,

.id_table = s3c_rtc_driver_ids,

.driver = {

.name = "s3c-rtc",

.owner = THIS_MODULE,

.pm = &s3c_rtc_pm_ops,

.of_match_table = of_match_ptr(s3c_rtc_dt_match),

},

};

module_platform_driver(s3c_rtc_driver);实现了platform_driver s3c_rtc_driver的注册

设备树中的compatible = "samsung,s3c6410-rtc";和驱动中的 .compatible = "samsung,s3c6410-rtc",名称一直时,会执行驱动的probe函数-> s3c_rtc_probe

在probe函数中注册一个字符设备驱动

rtc = devm_rtc_device_register(&pdev->dev, "s3c", &s3c_rtcops,

-> rtc = rtc_device_register(name, dev, ops, owner);

-> of_id = of_alias_get_id(dev->of_node, "rtc"); // 注册一个rtc的类

-> rtc_dev_prepare(rtc);

-> cdev_init(&rtc->char_dev, &rtc_dev_fops);

-> rtc_dev_add_device(rtc);

-> if (cdev_add(&rtc->char_dev, rtc->dev.devt, 1))

-> rtc_sysfs_add_device(rtc); // 等价于 mknod /dev/rtc c 254 0

-> s3c_rtc_gettime(NULL, &rtc_tm); // 获得系统的时间以上是一个字符设备的创建。

注册了一个cdev结构体和file_operations结构体rtc_dev_fops

rtc_dev_fops实现如下:

static const struct file_operations rtc_dev_fops = {

.owner = THIS_MODULE,

.llseek = no_llseek,

.read = rtc_dev_read,

.poll = rtc_dev_poll,

.unlocked_ioctl = rtc_dev_ioctl,

.open = rtc_dev_open,

.release = rtc_dev_release,

.fasync = rtc_dev_fasync,

};由以上可知 : 应用程序调用ioctl 驱动也调用ioctl

hwclock –w -> xioctl(fd, RTC_RD_TIME, ptm); -> rtc_dev_ioctl(命令) (用户空间) (内核空间)

-> case RTC_RD_TIME:rtc_read_time(rtc, &tm);

if (copy_to_user(uarg, &tm, sizeof(tm)))由以上可知 : 应用程序调用ioctl 驱动也调用ioctl

hwclock –s -> xioctl(fd, RTC_SET_TIME, ptm); -> rtc_dev_ioctl(命令) (用户空间) (内核空间)

-> case RTC_SET_TIME:

if (copy_from_user(&tm, uarg, sizeof(tm)))

return rtc_set_time(rtc, &tm);

hwclock –r -> xioctl(fd, RTC_RD_TIME , ptm); -> rtc_dev_ioctl(命令) (用户空间) (内核空间)

-> case RTC_RD_TIME: rtc_read_time(rtc, &tm);

if (copy_to_user(uarg, &tm, sizeof(tm)))

嵌入式物联网需要学的东西真的非常多,千万不要学错了路线和内容,导致工资要不上去!

无偿分享大家一个资料包,差不多150多G。里面学习内容、面经、项目都比较新也比较全!某鱼上买估计至少要好几十。(点击找小助理领取)

linux下的rtc机制相关推荐

  1. 2017-2018-1 20155222 《信息安全系统设计基础》第10周 Linux下的IPC机制

    2017-2018-1 20155222 <信息安全系统设计基础>第10周 Linux下的IPC机制 IPC机制 在linux下的多个进程间的通信机制叫做IPC(Inter-Process ...

  2. linux下测试RTC驱动相关的命令date和hwclock常见用法简介

    之前对Linux下面时间相关的内容,一无所知,第一次见到hwclock,不知为何物,也没找到解释清楚的帖子.故此整理一下,简单介绍Linux下验证rtc驱动是否工作正常,相关的的命令:date和hwc ...

  3. linux下的rtc设备驱动,linux下测试RTC驱动相关的命令date和hwclock常见用法讲解

    之前对Linux下面时间相关的内容,一无所知,第一次见到hwclock,不知为何物,也没找到解释清楚的帖子.故此整理一下,简单介绍Linux下验证rtc驱动是否工作正常,相关的的命令:date和hwc ...

  4. Linux下的RTC子系统

    版权所有,转载必须说明转自 http://my.csdn.net/weiqing1981127 实时时钟的作用主要是为操作系统提供一个可靠的时间,并在断电下,RTC时钟也可以通过电池供电一直运行下去. ...

  5. linux下的缓存机制及清理buffer/cache/swap的方法梳理

    1)缓存机制介绍 在Linux系统中,为了提高文件系统性能,内核利用一部分物理内存分配出缓冲区,用于缓存系统操作和数据文件,当内核收到读写的请求时,内核先去缓存区找是否有请求的数据,有就直接返回,如果 ...

  6. linux从a自增10_C语言程序前后自增(++a、a++)在Linux下的实现机制

    看到一道"经典Linux C"面试题,关于左值和右值的. 华为笔试题 1.写出判断ABCD四个表达式的是否正确, 若正确, 写出经过表达式中 a的值(3分) int a = 4; ...

  7. Linux下的UDEV机制 / 守护进程

    一.Udev概念引入 udev是一个设备管理工具,udev以守护进程的形式运行,通过 侦听内核发出来的uevent来管 理 /dev目录下的设备文件. udev在 用户空间运行,而 不在内核空间 运行 ...

  8. 从一道面试题谈linux下fork的运行机制

    http://kb.cnblogs.com/page/76622/ 今天一位朋友去一个不错的外企面试linux开发职位,面试官出了一个如下的题目: 给出如下C程序,在linux下使用gcc编译: #i ...

  9. 机制 linux_从一道面试题谈linux下fork的运行机制

    今天一位朋友去一个不错的外企面试linux开发职位,面试官出了一个如下的题目: 给出如下C程序,在linux下使用gcc编译: #include "stdio.h" #includ ...

最新文章

  1. ENAS加载自己的数据集之路
  2. SNMP功能开发简介 二 net-snmp源码分析报文处理流程图
  3. 1.8 深入解析new运算符
  4. boost::set_difference相关的测试程序
  5. CSS中可继承的属性
  6. java xy,java – 某个z深度的xy位置
  7. 大号字代码php,如何用QQ发超大汉字_php
  8. linuc和python常用命令是一样的么_linuc和python常用命令是一样的么_python教程3--《linux常用命令》...
  9. python中argsort_浅述python中argsort()函数的实例用法
  10. 一、安装Windows 2012域控(For SQLServer 2014 AlwaysOn)
  11. Linux查看当前系统的版本信息
  12. Python笔记 之 矩阵元素选取
  13. 标定学习笔记(五)-- Halcon手眼标定例程:Hand-eye-Calibration with a moving cam
  14. 不断网情况下,如何关闭红蜘蛛多媒体网络教室
  15. “己欲立而立人,己欲达而达人。”
  16. [转]应对新劳动法:华为万名员工“自愿”辞职[http://news.qq.com/a/20071030/001675.htm]
  17. Python爬虫新手教程:微医挂号网医生数据抓取!
  18. 解决obsidian无法加载第三方插件(社区插件)的问题
  19. 基于Java(Jsp+servelet+Javabean)+MySQL实现图书管理系统【100010229】
  20. 小程序scroll-view实现左右联动

热门文章

  1. CFileDialog使用总结
  2. 编程入门篇之零基础入门(通用)
  3. 3.1 向量的模和单位向量
  4. TM遥感影像波段/通道bands
  5. 运放使用“虚短”和”虚断“的理解
  6. MacW资讯:苹果mac触摸板使用技巧
  7. Next.js性能优化之ISR渲染入门和原理探索
  8. 100!的尾数有多少个零?
  9. WSL无法访问网络的解决办法
  10. 虚拟化环境下,如何高效开展勒索病毒防护加固?