2015年(109)
分类: LINUX
2015-01-23 16:37:51
原文地址:SEP4020的RTC驱动设计注意点 作者:myleeming
Linux的RTC驱动相对还是比较简单的,可以将它作为一个普通的字符型设备,或者一个misc设备,也可以是一个平台设备,这都没有关系,主要还是对rtc_ops这个文件操作结构体中的成员填充,这里主要涉及到两个方面比较重要:
1. 在Linux中有硬件时钟与系统时钟等两种时钟。硬件时钟是指主机板上的时钟设备,也就是通常可在BIOS画面设定的时钟。系统时钟则是指kernel中的时钟。当Linux启动时,系统时钟会去读取硬件时钟的设定,之后系统时钟即独立运作。所有Linux相关指令与函数都是读取系统时钟的设定。
系统时钟的设定就是我们常用的date命令,而我们写的RTC驱动就是为硬件时钟服务的,它有属于自己的命令hwclock,因此使用date命令是不可能调用到我们的驱动的(在这点上开始把我郁闷到了,写完驱动之后,傻傻的用date指令来测试,当然结果是什么都没有),我们可以通过hwclock的一些指令来实现更新rtc时钟——也就是系统时钟和硬件时钟的交互。
hwclock –r 显示硬件时钟与日期
hwclock –s 将系统时钟调整为与目前的硬件时钟一致。
hwclock –w 将硬件时钟调整为与目前的系统时钟一致。
2. 第二点就是内核空间和用户空间的交互,在系统启动结束,我们实际是处在用户态,因此我们使用指令输入的内容也是在用户态,而我们的驱动是在内核态的,内核态和用户态是互相不可见的,因此我们需要特殊的函数来实现这两种形态的交互,这就是以下两个函数:
copy_from_user(从用户态到内核态)
copy_to_user (从内核态到用户态)
当然这两个函数需要我们在内核驱动中实现。
RTC最基本的两个命令就是设置时间,读取时间。
设置时间——设置时间会调用系统默认的RTC_SET_TIME,很显然就是处在用户态的用户将自己所要设置的时间信息传递给内核态,
case RTC_SET_TIME:
{
struct rtc_time rtc_tm;
if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time)))
return -EFAULT;
sep4020_rtc_settime(&rtc_tm);//把用户态得到的信息传递给设置时间这个函数
return 0;
}
读取时间——设置时间会调用系统默认的RTC_RD_TIME,很显然就是需要通过内核态的驱动将芯片时钟取出,并传递给用户态
case RTC_RD_TIME: /* Read the time/date from RTC */
{
sep4020_rtc_gettime(&septime);//通过驱动的读函数读取芯片时钟
copy_to_user((void *)arg, &septime, sizeof septime);//传递给用户态
}