1. 在Linux2.6.29内核中,RTC是以平台设备的方式注册进内核的。

① RTC驱动定义于文件:drivers/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,
},
};

② RTC平台资源定义于:arch/arm/plat-s3c24xx/devs.c

static struct resource s3c_rtc_resource[] = {
[] = {
.start = S3C24XX_PA_RTC,
.end = S3C24XX_PA_RTC + 0xff,
.flags = IORESOURCE_MEM,
},
[] = {
.start = IRQ_RTC,
.end = IRQ_RTC,
.flags = IORESOURCE_IRQ,
},
[] = {
.start = IRQ_TICK,
.end = IRQ_TICK,
.flags = IORESOURCE_IRQ
}
}; struct platform_device s3c_device_rtc = {
.name = "s3c2410-rtc",
.id = -,
.num_resources = ARRAY_SIZE(s3c_rtc_resource),
.resource = s3c_rtc_resource,
};

③ 当RTC设备驱动匹配到名字为“s3c2410-rtc”的设备时,会调用probe函数s3c_rtc_probe()

static int __devinit s3c_rtc_probe(struct platform_device *pdev)
{
struct rtc_device *rtc;
struct resource *res;
int ret;/* find the IRQs */
s3c_rtc_tickno = platform_get_irq(pdev, );
s3c_rtc_alarmno = platform_get_irq(pdev, );
/* get the memory region */
s3c_rtc_mem = request_mem_region(res->start,
res->end-res->start+,
pdev->name); s3c_rtc_base = ioremap(res->start, res->end - res->start + );/* check to see if everything is setup correctly */

s3c_rtc_enable(pdev, );
s3c_rtc_setfreq(&pdev->dev, );
device_init_wakeup(&pdev->dev, ); /* register RTC and exit */
rtc = rtc_device_register("s3c", &pdev->dev, &s3c_rtcops,
THIS_MODULE); rtc->max_user_freq = ; platform_set_drvdata(pdev, rtc);
return ;

(1) s3c_rtc_probe()函数分析1: 获取平台资源(中断号和IO内存),然后记录中断号,进行IO内存映射。

(2) s3c_rtc_probe()函数分析2: 调用rtc_device_register()函数,分配RTC的设备描述结构rtc_device,并填充其成员,然后进行设备注册(注册字符设备,注册进proc系统,注册进sys系统)

(3) s3c_rtc_probe()函数分析3: 保存RTC设备描述结构到平台设备驱动的dev域。

注: RTC的设备描述结构rtc_device是device结构的扩展,描述一个具体的RTC设备。

⑤ rtc_device_register()函数分析:

struct rtc_device *rtc_device_register(const char *name, struct device *dev,
const struct rtc_class_ops *ops,
struct module *owner)
{
struct rtc_device *rtc;
int id, err; if (idr_pre_get(&rtc_idr, GFP_KERNEL) == ) {
err = -ENOMEM;
goto exit;
} mutex_lock(&idr_lock);
err = idr_get_new(&rtc_idr, NULL, &id);
mutex_unlock(&idr_lock); if (err < )
goto exit; id = id & MAX_ID_MASK; rtc = kzalloc(sizeof(struct rtc_device), GFP_KERNEL);
if (rtc == NULL) {
err = -ENOMEM;
goto exit_idr;
} rtc->id = id;
rtc->ops = ops;
rtc->owner = owner;
rtc->max_user_freq = ;
rtc->dev.parent = dev;
rtc->dev.class = rtc_class;
rtc->dev.release = rtc_device_release; mutex_init(&rtc->ops_lock);
spin_lock_init(&rtc->irq_lock);
spin_lock_init(&rtc->irq_task_lock);
init_waitqueue_head(&rtc->irq_queue); strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE);
dev_set_name(&rtc->dev, "rtc%d", id); rtc_dev_prepare(rtc); err = device_register(&rtc->dev);
if (err)
goto exit_kfree; rtc_dev_add_device(rtc);
rtc_sysfs_add_device(rtc);
rtc_proc_add_device(rtc); dev_info(dev, "rtc core: registered %s as %s\n",
rtc->name, dev_name(&rtc->dev)); return rtc; }

(1) 为RTC设备描述结构(rtc_device)分配空间,并填充相关成员。

(2) 通过rtc_dev_prepare()函数填充RTC字符设备的主设备号和操作函数集rtc_dev_fops

void rtc_dev_prepare(struct rtc_device *rtc)
{
rtc->dev.devt = MKDEV(MAJOR(rtc_devt), rtc->id); cdev_init(&rtc->char_dev, &rtc_dev_fops);
rtc->char_dev.owner = rtc->owner;
}

(3)通过rtc_dev_add_device()将RTC以字符设备注册进内核

void rtc_dev_add_device(struct rtc_device *rtc)
{
if (cdev_add(&rtc->char_dev, rtc->dev.devt, ))
printk(KERN_WARNING "%s: failed to add char device %d:%d\n",
rtc->name, MAJOR(rtc_devt), rtc->id);
else
pr_debug("%s: dev (%d:%d)\n", rtc->name,
MAJOR(rtc_devt), rtc->id);
}

(4)RTC字符设备操作函数集rtc_dev_fops:用于实现访问RTC设备文件/dev/rtc0的操作方法,包括open、read、ioctl等方法。

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,
};

(5)RTC设备操作函数集s3c_rtcops:用于实现操作RTC设备的基本方法。也是rtc_device_register()函数中赋值给rtc(rtc_device结构)的ops成员的

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,
};

注:s3c_rtcops属于RTC的设备描述结构rtc_device的成员,用于实现操作RTC的基本方法;而rtc_dev_fops属于cdev结构的成员,用于实现访问RTC设备文件/dev/rtc0的基本方法。rtc_dev_fops中的成员需要调用s3c_rtcops中的成员来实现其具体功能。

2. Linux2.6.29内核中,RTC平台驱动已经注册进内核,但RTC平台资源并未注册。我们添加RTC仅需要把RTC的平台资源结构体添加到平台资源初始化列表中即可。

(1)向smdk2440_devices[]数组中添加s3c_device_rtc

static struct platform_device *smdk2440_devices[] __initdata = {
&s3c_device_usb,
&s3c_device_lcd,
&s3c_device_wdt,
&s3c_device_i2c0,
&s3c_device_iis,
&smdk2440_device_eth,
&s3c_device_rtc,
};

(2)重新配置内核,加入RTC的驱动:Device Drivers--->Real Time Clock-->Samsung S3C series Soc RTC

3. RTC测试

(1)操作设备文件/dev/rtc0

(2)通过proc查看:cat /proc/driver/rtc

(3)通过sys文件系统接口:cat /sys/class/trc/rtc0/date; cat /sys/class/trc/rtc0/time

#include <stdio.h>
#include <linux/rtc.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h> static const char default_rtc[] = "/dev/rtc0"; int main(int argc, char** argv)
{
int fd, retval;
struct rtc_time rtc_tm;
const char* rtc = default_rtc; switch(argc)
{
case :
rtc = argv[];
break;
case :
break;
default:
fprintf(stderr, "usage: TestRtc [RtcDev]");
return ;
} fd = open(rtc, O_RDONLY);
if(fd == -)
{
perror(rtc);
exit(errno);
} retval = ioctl(fd, RTC_RD_TIME, &rtc_tm);
if(retval == -)
{
perror("RTC_RD_TIME ioctl");
exit(errno);
} printf("Current RTC date/time is %d-%d-%d, %02d:%02d:%02d.\n",
rtc_tm.tm_year + , rtc_tm.tm_mon + , rtc_tm.tm_mday,
rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec); return ;
}

最新文章

  1. 108. Convert Sorted Array to Binary Search Tree
  2. yii使用MongoDB作为数据库服务软件[win7环境下](1)
  3. 数据库相关 sql 语句
  4. SQL模式匹配
  5. jquery 取值赋值
  6. shell复习笔记----命令与参数
  7. 深入了解overflow
  8. jquery easyUI 日期格式化,DateBox只显示年
  9. vps使用(centos)
  10. EFDB 基本规范&amp;知识
  11. Ansible批量修改root密码
  12. java程序可以跨平台运行的原因
  13. html限制文本框只能输入数字和一个小数点
  14. python基本语法汇总
  15. 【python014--字符串内置函数】
  16. BZOJ 1874 取石子游戏 - SG函数
  17. windows 下为Python安装redis
  18. Netcat使用方法
  19. Android之从Browser中打开本地的应用程序&amp;微信检测是否有对应app
  20. 利用Tensorflow进行自然语言处理(NLP)系列之一Word2Vec

热门文章

  1. nginx安装目录文件
  2. java排查故障
  3. 异步http接口调用库:httpx
  4. python+selenium实现百度关键词搜索自动化操作
  5. 面向对象案例 - 学生信息管理系统V1.0
  6. Java学习之路【第一篇】:前言
  7. [SD心灵鸡汤]000.每月一则 - 索引
  8. 【转】网页的title左边的小图片怎么添加
  9. MongoDB启动和关闭问题
  10. 如何管理win系列服务器,win10 pro如何 使用远程桌面