版权所有,转载必须说明转自 http://my.csdn.net/weiqing1981127

实时时钟的作用主要是为操作系统提供一个可靠的时间,并在断电下,RTC时钟也可以通过电池供电一直运行下去。实时时钟驱动也有一个子系统,叫做RTC子系统,其源代码目录是/driver/rtc/,在这个目录下有一个rtc核心代码区,主要是Rtc-dev.c、Rtc-sysfs.c和Rtc-proc.c三个文件,其中Rtc-dev.c主要是增加一个字符设备的作用,例如用户层的ioctl命令就是通过访问该文件;Rtc-sysfs.c主要是创建device_attribute机制;Rtc-proc.c文件主要创建/proc属性文件。另外对于RTC设备。内核中的说明文档在/Document/Rtc.txt中

我们这里讲的是基于mini2440的RTC驱动,其对应驱动是/driver/rtc/Rtc-s3c.c

RTC驱动源码路径在/driver/rtc/Rtc-s3c.c

查看/driver/rtc/Makefile

rtc-core-$(CONFIG_RTC_INTF_DEV)       += rtc-dev.o

rtc-core-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o

rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o

obj-$(CONFIG_RTC_DRV_S3C)  += rtc-s3c.o

查看/driver/rtc//Konfig

config RTC_INTF_DEV

boolean "/dev/rtcN (character devices)"

default RTC_CLASS

config RTC_INTF_PROC

boolean "/proc/driver/rtc (procfs for rtc0)"

depends on PROC_FS

config RTC_INTF_SYSFS

boolean "/sys/class/rtc/rtcN (sysfs)"

depends on SYSFS

default RTC_CLASS

config RTC_DRV_S3C

tristate "Samsung S3C series SoC RTC"

depends on ARCH_S3C2410

所以配置内核make menuconfig 时,需要选中这几项。

现在先来看如何移植,下面就看移植代码了,因为通过查看"s3c2410-rtc"名知道,在内核Devs.c文件中已经定义如下代码

struct platform_device s3c_device_rtc = {

.name               = "s3c2410-rtc",

.id             = -1,

.num_resources       = ARRAY_SIZE(s3c_rtc_resource),

.resource   = s3c_rtc_resource,

};

所以只要在mach-mini2440.c这个mini2440开发板的BSP中把这个s3c_device_rtc加入到mini2440_devices数组

static struct platform_device *mini2440_devices[] __initdata = {

……

& s3c_device_rtc, //添加

};

这样配置完后,进行make zImage生成zImage内核镜像。

下面大致说说/driver/rtc/Rtc-s3c.c

static struct platform_driver s3c2410_rtc_driver = {

.probe            = s3c_rtc_probe,

.remove          = __devexit_p(s3c_rtc_remove),

.suspend  = s3c_rtc_suspend,

.resume          = s3c_rtc_resume,

.driver            = {

.name      = "s3c2410-rtc",  //驱动名

.owner    = THIS_MODULE,

},

};

跟踪下探测函数probe

static int __devinit s3c_rtc_probe(struct platform_device *pdev)

{

struct rtc_device *rtc;

struct resource *res;

int ret;

pr_debug("%s: probe=%p\n", __func__, pdev);

s3c_rtc_tickno = platform_get_irq(pdev, 1);  //获取滴答中断号

if (s3c_rtc_tickno < 0) {

dev_err(&pdev->dev, "no irq for rtc tick\n");

return -ENOENT;

}

s3c_rtc_alarmno = platform_get_irq(pdev, 0);  //获取闹钟中断号

if (s3c_rtc_alarmno < 0) {

dev_err(&pdev->dev, "no irq for alarm\n");

return -ENOENT;

}

pr_debug("s3c2410_rtc: tick irq %d, alarm irq %d\n",

s3c_rtc_tickno, s3c_rtc_alarmno);

res = platform_get_resource(pdev, IORESOURCE_MEM, 0); //获取资源

if (res == NULL) {

dev_err(&pdev->dev, "failed to get memory region resource\n");

return -ENOENT;

}

s3c_rtc_mem = request_mem_region(res->start,

res->end-res->start+1,

pdev->name);  //申请资源

if (s3c_rtc_mem == NULL) {

dev_err(&pdev->dev, "failed to reserve memory region\n");

ret = -ENOENT;

goto err_nores;

}

s3c_rtc_base = ioremap(res->start, res->end - res->start + 1); //物理地址到虚拟地址的映射

if (s3c_rtc_base == NULL) {

dev_err(&pdev->dev, "failed ioremap()\n");

ret = -EINVAL;

goto err_nomap;

}

s3c_rtc_enable(pdev, 1);

pr_debug("s3c2410_rtc: RTCCON=%02x\n",

readb(s3c_rtc_base + S3C2410_RTCCON));

s3c_rtc_setfreq(&pdev->dev, 1);     //设置频率

device_init_wakeup(&pdev->dev, 1);

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

THIS_MODULE);  //注册rtc设备

if (IS_ERR(rtc)) {

dev_err(&pdev->dev, "cannot attach rtc\n");

ret = PTR_ERR(rtc);

goto err_nortc;

}

rtc->max_user_freq = 128;

platform_set_drvdata(pdev, rtc);

return 0;

err_nortc:

s3c_rtc_enable(pdev, 0);

iounmap(s3c_rtc_base);

err_nomap:

release_resource(s3c_rtc_mem);

err_nores:

return ret;

}

我们主要关注注册rtc设备的时传入参数s3c_rtcops

static const struct rtc_class_ops s3c_rtcops = {

.open             = s3c_rtc_open,  //打开

.release    = s3c_rtc_release,  //关闭

.read_time      = s3c_rtc_gettime,  //获取当前时间

.set_time = s3c_rtc_settime,  //设置当前时间

.read_alarm     = s3c_rtc_getalarm,  //获取闹钟时间

.set_alarm       = s3c_rtc_setalarm,  //设置闹钟时间

.irq_set_freq   = s3c_rtc_setfreq,  //设置频率

.irq_set_state  = s3c_rtc_setpie,

.proc               = s3c_rtc_proc,

};

对于struct rtc_class_ops结构体中的成员,其每个函数的具体实现,都是跟自己使用的设备相关的,比如我们这样使用的是S3C2410,那么在struct rtc_class_ops里定义的函数使用的就是三星平台下的资源。如果要在其他平台下使用,那么就是修改这里的struct rtc_class_ops操作函数。

在rtc_device_register中,会调用rtc_dev_prepare函数,而rtc_dev_prepare函数会把rtc_dev_fops注册进内核,而rtc_dev_fops就是我们在增加字符设备的文件Rtc-dev.c中定义的file_operations操作函数,这样注册rtc设备其实就表示用户可以访问通过访问file_operations函数来达到访问rtc设备的目的。

在我们的/driver/rtc/Class.c中的模块加载函数中调用rtc_sysfs_init来完成注册sys文件系统,而rtc_sysfs_init就是我们在Rtc-sysyfs.c中定义的,跟踪下rtc_sysfs_ini

void __init rtc_sysfs_init(struct class *rtc_class)

{

rtc_class->dev_attrs = rtc_attrs;

}

然后看看rtc_attrs属性

static struct device_attribute rtc_attrs[] = {

__ATTR(name, S_IRUGO, rtc_sysfs_show_name, NULL),

__ATTR(date, S_IRUGO, rtc_sysfs_show_date, NULL),

__ATTR(time, S_IRUGO, rtc_sysfs_show_time, NULL),

__ATTR(since_epoch, S_IRUGO, rtc_sysfs_show_since_epoch, NULL),

__ATTR(max_user_freq, S_IRUGO | S_IWUSR, rtc_sysfs_show_max_user_freq,

rtc_sysfs_set_max_user_freq),

__ATTR(hctosys, S_IRUGO, rtc_sysfs_show_hctosys, NULL),

{ },

};

好了,这就是给用户的第二个操作接口,我们来看看这些属性的show和store属性是不是真的能调用在Rtc-s3c.c中的RTC操作函数s3c_rtcops。我们把注意力放在time的show属性函数rtc_sysfs_show_time上

static ssize_t rtc_sysfs_show_time(struct device *dev, struct device_attribute *attr,

char *buf)

{

ssize_t retval;

struct rtc_time tm;

retval = rtc_read_time(to_rtc_device(dev), &tm);  //调用封装的读时间函数

if (retval == 0) {

retval = sprintf(buf, "%02d:%02d:%02d\n",

tm.tm_hour, tm.tm_min, tm.tm_sec);

}

return retval;

}

跟踪rtc_read_time函数

int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm)

{

int err;

err = mutex_lock_interruptible(&rtc->ops_lock);

if (err)

return err;

if (!rtc->ops)

err = -ENODEV;

else if (!rtc->ops->read_time)

err = -EINVAL;

else {

memset(tm, 0, sizeof(struct rtc_time));

err = rtc->ops->read_time(rtc->dev.parent, tm);  //调用s3c_rtcops操作中读时间函数

}

mutex_unlock(&rtc->ops_lock);

return err;

}

好了,我已经跟踪到我们需要找的信息了,这样我们就能证实在Rtc-sysyfs.c中定义的设备的show和store属性是真的能调用在Rtc-s3c.c中的RTC操作函数s3c_rtcops的。

RTC驱动测试

Linux 中更改时间的方法一般使用date 命令,为了把S3C2440 内部带的时钟与linux 系统时钟同步,

一般使用hwclock 命令,下面是它们的使用方法:

(1) date -s 042916352007 #设置时间为 2007-04-29 16:34

(2) hwclock -w #把刚刚设置的时间存入S3C2440 内部的RTC

(3).开机时使用hwclock -s 命令可以恢复 linux 系统时钟为RTC, 一般把该语句放入

/etc/init.d/rcS 文件自动执行。

另外需要注意的是:有时候你会发现自己的实时时钟会在走时一段时间后不准,这注意是设计时钟电路时匹配电容的取值不对,电容公式是C1*C2/(C1+C2)+C3,其中C1和C2是两个并联电容,C3是寄生电容,C3一般取3-5PF。

Linux下的RTC子系统相关推荐

  1. linux i2c子系统看不懂啊,Linux 下的I2C子系统

    Linux 下的I2C子系统 2013.7.16 本文分为两部分,一.设备模型 二.平台相关 . ================================================ 第一 ...

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

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

  3. linux input子系统 pdf,Linux下的Input子系统.pdf

    计 算 机 系 统 应 用 ||ww.c·S-a.org.cn 2013年 第 22卷 第 l2期 Linux下的Input子系统① 朱银瑞,吴庆洪,吴华玲 (辽宁科技大学 电子与信息工程学院,鞍山) ...

  4. linux input子系统 pdf,Linux下的Input子系统①.PDF

    Linux下的Input子系统①.PDF 计 算 机 系 统 应 用 2013 年 第 22 卷 第 12 期 Linux 下的Input 子系统① 朱银瑞, 吴庆洪, 吴华玲 (辽宁科技大学 电子与 ...

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

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

  6. Linux下的Keyboard子系统

    版权所有,转载请说明转自 http://my.csdn.net/weiqing1981127 最简单的按键驱动就是一个中断处理函数,当用户有按键,通过read函数向应用层上报按键信息.而我们这里讲的k ...

  7. Linux下的Backlight子系统

    版权所有,转载必须说明转自 http://my.csdn.net/weiqing1981127 原创作者:南京邮电大学  通信与信息系统专业 研二 魏清 一.Backlight背光子系统概述 我们的L ...

  8. Linux下的LED子系统

    最简单的led驱动就是从端口输出0或1来关闭或点亮灯.而我们这里讲的led子系统,主要是对led事件进行了分装和优化,这里我们主要讲的是可以实现跨平台的led驱动.不管你是使用三星的平台,还是Atme ...

  9. linux下的rtc机制

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

最新文章

  1. Lecture 2: Preliminary Review--Mind Map
  2. 做创业公司长期价值的共建者,高榕资本完成5亿美元新基金募资
  3. axure元件库 文件上传_一库:便捷的前后台元件库
  4. 计算机设计大赛校赛攻略(郑州轻工业大学)
  5. storm32云台说明书_STorM32 BGC三轴云台控制板电机驱动电路设计(驱动芯片DRV8313)
  6. python 抓取微博评论破亿_利用python实现爬取微博评论的方法
  7. Linux复制文件到当前目录
  8. 高频交易巨头GETCO的发达史
  9. 抖音高贵气质的签名_抖音签名大全2020最新版-抖音个性签名男生女生-抖音个性签名霸气-腾牛个性网...
  10. 复杂网络盘传播搜索关键字
  11. 解决phpstudy的Apache启动失败
  12. FindMeChat(盲盒社交)-匿名聊天-好玩有趣的社交平台
  13. 回调函数,监听函数 关系 个人学习理解
  14. ssh免密码登录3种解决方法
  15. 【react】This synthetic event is reused for performance reasons.
  16. stack unwinding
  17. ubuntu20.04下载安装有道词典
  18. RaspBerry Pi 系统安装——Raspbian(精简版)
  19. 准大三学生暑期社会实践真实感悟
  20. 一年前, 打了一份关于谷歌英雄迟暮的草稿, 终究和它一起迟暮了

热门文章

  1. Boost.Math 和 Boost.Multiprecision 以提供 许多十进制数字精度的测试程序
  2. boost::make_maximal_planar用法的测试程序
  3. boost::dijkstra_shortest_paths_no_color_map用法的测试程序
  4. boost::fusion::move用法的测试程序
  5. VTK:相互作用之SelectAnActor
  6. QtObject QML类型
  7. QDoc包括外部代码includingexternalcode
  8. Qt Creator在外部应用程序上运行Valgrind工具
  9. C语言Huffman Encode霍夫曼编码的算法(附完整源码)
  10. C语言实现Trie字典树 (附完整源码)