第1章用户空间访问
     
      
       RTC
      
     
    
     
     
     
      
       1.1
      
     
     概述
    
     
      RTC
     
     是“
     
      RealTimeClock”
     
     的简称。
     
      RTC
     
     时钟一般由板载电池供电,系统掉电后仍可以照常运行,系统启动的时候从
     
      RTC
     
     读取时间作为系统时间的初始值,系统启动以后内核会根据系统中断不停的更新系统时间,并每过
     
      11
     
     分钟将内核维护的系统时间写入
     
      RTC
     
     一次。系统掉电之后,
     
      RTC
     
     的时间不会丢失,而且会根据输入的震荡时钟信号不停的更新自己的时间。
    
     
     
     除了内核,用户空间也可以通过设备节点访问
     
      RTC
     
     。用户空间可以读取或者设置
     
      RTC
     
     的时间值,也可以在
     
      RTC
     
     的设备节点上睡眠,并设置
     
      RTC
     
     何时将自己唤醒,这对于需要定时或者周期性的唤醒的用户进程特别有用。
    
     
     
     本章介绍用户空间通过设备节点使用
     
      RTC
     
     的方法,不涉及内核空间使用
     
      RTC
     
     的知识。用户需要注意的是,虽然
     
      RTC
     
     设备节点的接口是固定的(所有的
     
      IOCTL
     
     命令在所有
     
      Linux
     
     系统上也都是一致的),用户自己系统(或开发板)上的
     
      RTC
     
     设备节点也许并不支持某些功能,这依赖于实际使用的
     
      RTC
     
     芯片和
     
      RTC
     
     设备驱动。因此这里介绍的某些功能,用户或许无法在自己的系统(或开发板)上使用。
    
     
     
     
      
       1.2
      
     
     重要的数据结构
    
     
      
       1.
       
        
         rtc_time
        
       
      
     
    
     
     
     对
     
      RTC
     
     的设备节点使用
     
      ioctl()
     
     接口的时候需要用到
     
      rtc_time
     
     结构体,它的定义如程序清单
     
      1 .1
     
     所示。
    
     
      
       
        
         structrtc_time {
         
        
       
      
     
    
     
      
       
        
         inttm_sec; /*
        
       
      
      
       
        秒,
       
      
      
       
        
         0
        
       
      
      
       
        ~
       
      
      
       
        
         60
        
       
      
      
       
        (
       
      
      
       
        
         60
        
       
      
      
       
        是闰秒的需要)
       
      
      
       
        
         */
        
       
      
     
    
     
      
       
        
         inttm_min; /*
        
       
      
      
       
        分钟,
       
      
      
       
        
         0~59*/
        
       
      
     
    
     
      
       
        
         inttm_hour; /*
        
       
      
      
       
        小时,
       
      
      
       
        
         0~23 */
        
       
      
     
    
     
      
       
        
         inttm_mday; /*
        
       
      
      
       
        本月中的第几天,
       
      
      
       
        
         1~31 */
        
       
      
     
    
     
      
       
        
         inttm_mon; /*
        
       
      
      
       
        自一月以来的第几个月,
       
      
      
       
        
         0~11*/
        
       
      
     
    
     
      
       
        
         inttm_year; /*
        
       
      
      
       
        自
       
      
      
       
        
         1900
        
       
      
      
       
        年以来的年数
       
      
      
       
        
         */
        
       
      
     
    
     
      
       
        
         inttm_wday; /*
        
       
      
      
       
        本周的第几天,
       
      
      
       
        
         0~6
        
       
      
      
       
        ,星期天是
       
      
      
       
        
         0 */
        
       
      
     
    
     
      
       
        
         inttm_yday; /*
        
       
      
      
       
        一年当中的第几天,
       
      
      
       
        
         0~365*/
        
       
      
     
    
     
      
       
        
         inttm_isdst; /*
        
       
      
      
       
        夏令时标志
       
      
      
       
        
         */
        
       
      
     
    
     
      
       
        
         };
        
       
      
     
    
     
      
       
        对于最后一个成员变量
       
      
      
       
        
         tm_isdst
        
       
      
      
       
        ,当它为正数的时候意味着正处在夏令时中,当是
       
      
      
       
        
         0
        
       
      
      
       
        的时候表示夏令时已经结束,负数表示不使用夏令时。
       
      
      
       
        
         1992
        
       
      
      
       
        年后中国大陆地区不再使用夏令时,因此这个成员应该总是负数。夏令时的意思是“
       
      
      
       
        
         DaylightSaving Time”
        
       
      
      
       
        ,是在太阳升起较早的季节(通常是夏季)人为将时钟拨快一小时,让人们充分利用日光以节约能源。
       
      
     
    
     
      
       2.
       
        
         rtc_wkalrm
        
       
      
     
    
     
     
     使用
     
      ioctl()
     
     设置
     
      wakeupalarm
     
     中断的时候需要用到
     
      rtc_wkalrm
     
     结构体做参数,它的定义如程序清单
     
      1 .2
     
     所示。
    
     
      
       
        
         structrtc_wkalrm {
         
        
       
      
     
    
     
      
       
        
         unsignedchar enabled; /* 0 =
        
       
      
      
       
        禁止
       
      
      
       
        
         alarm,1 =
        
       
      
      
       
        使能
       
      
      
       
        
         alarm */
        
       
      
     
    
     
      
       
        
         unsignedchar pending; /* 0 = alarm
        
       
      
      
       
        未挂起
       
      
      
       
        
         ,1 = alarm
        
       
      
      
       
        挂起(已发生)
       
      
      
       
        
         */
        
       
      
     
    
     
      
       
        
         structrtc_time time; /*
        
       
      
      
       
        设置的
       
      
      
       
        
         alarm
        
       
      
      
       
        中断发生的时刻
       
      
      
       
        
         */
        
       
      
     
    
     
      
       
        
         };
        
       
      
     
    
     
      
      
     
     当设置
     
      
       alarm
      
     
     中断的时间的时候,第一个成员变量
     
      
       enabled
      
     
     影响设置完时间之后是否使能
     
      
       alarm
      
     
     中断。如果
     
      enabled
     
     为
     
      0
     
     ,
     
      alarm
     
     中断的时间正常设置,但是中断功能将被禁止
     
      (
     
     即使设置之前是开启的
     
      )
     
     ;而如果
     
      enabled
     
     为
     
      1
     
     的话,
     
      RTC
     
     的
     
      alarm
     
     功能将被开启。设置时间的时候第二个成员
     
      pending
     
     无效。
    
     
     
     当使用
     
      ioctl
     
     读取
     
      alarm
     
     时间的时候,第一个成员
     
      enabled
     
     的值反应当前
     
      alarm
     
     中断的开启与否,第二个成员
     
      pending
     
     反应当前是否已有
     
      alarm
     
     中断挂起(发生)。
    
     
     
     第三个成员是上面已经介绍过的
     
      structrtc_time
     
     结构体,用来传递要设置或者已设置的
     
      alarm
     
     中断时间。
    
     
     
     对于
     
      alarm
     
     和
     
      wakeupalarm
     
     中断,将不会使用中文译名,因为无论定时中断、闹钟中断还是报警中断都不太合适。这两个中断在内核中其实是一回事,仅有的差别就是
     
      alarm
     
     中断只能设定为
     
      24
     
     小时内的某个时刻发生,而
     
      wakeupalarm
     
     中断可是设置为将来任意时刻发生。后面讲解的时候将会把它们两个做为一类中断来讲解。
    
     
      
       3.读取的数据格式
      
     
    
     
     
     在
     
      RTC
     
     设备节点上使用
     
      read()
     
     函数将会使进程进入睡眠,直到有一个中断发生。中断发生后从
     
      RTC
     
     设备节点只能读取一个
     
      unsignedlong
     
     类型的变量,无论发生了几次中断,一次只能读取一个
     
      unsignedlong
     
     。读取到的这个
     
      unsignedlong
     
     变量的最低一字节反应已经发生的中断类型,其余的字节反应自上次读取以来发生中断的次数。注意,如果自上次读取以来已发生了多钟类型的中断,并且每种类型的中断都发生了多次,根本没有办法判断每种中断类型各发生了几次。
    
     
      RTC
     
     共支持三种类型的中断:更新中断、周期中断和
     
      alarm/wakeupalarm
     
     中断。更新中断是在
     
      RTC
     
     的时间变化的时候发生的中断,由于
     
      RTC
     
     的最小单位是秒,所以更新中断的频率是
     
      1HZ
     
     ;周期中断是频率高于
     
      1HZ
     
     的中断(必须高于
     
      1HZ
     
     ),中断频率必须是
     
      2^N
     
     (
     
      N>=1
     
     ,整数)
     
      HZ
     
     ,并且只有
     
      Root
     
     用户能使用
     
      64HZ
     
     以上的频率;
     
      alarm/wakeupalarm
     
     中断是在未来某个时刻发生的中断,它只能发生一次,发生过后需要重新设置才能再次发生,其中
     
      alarm
     
     中断只能将中断发生时刻设定在
     
      24
     
     小时之内,
     
      wakeupalarm
     
     中断可以设定为未来的任意时刻。
    
     
     
     从
     
      RTC
     
     设备节点读出的最低字节使用掩码表示发生的中断类型。掩码的定义如程序清单
     
      1 .3
     
     所示。
    
     
      
       
        
         #defineRTC_IRQF 0x80 /*
        
       
      
      
       
        任意中断发生它都会置位
       
      
      
       
        
         */
        
       
      
     
    
     
      
       
        
         #defineRTC_PF 0x40 /*
        
       
      
      
       
        周期中断发生后该位置位
       
      
      
       
        
         */
        
       
      
     
    
     
      
       
        
         #defineRTC_AF 0x20 /* alarm/wakeup alarm
        
       
      
      
       
        中断
       
      
      
       
        
         */
        
       
      
     
    
     
      
       
        
         #defineRTC_UF 0x10 /*
        
       
      
      
       
        更新中断
       
      
      
       
        
         */
        
       
      
     
    
     
      
      
     
     当有多种类型的中断发生后而用户空间有没来得及读取的时候,会有多个位被置
     
      
       1
      
     
     。高字节中的中断次数是所有中断次数之和。
    
     
      
      
     
     现在需要澄清一下
     
      
       RTC
      
     
     中断的含义。这里的中断是说在
     
      
       RTC
      
     
     设备节点上使用
     
      
       read
      
     
     或
     
      
       select
      
     
     休眠的进程被唤醒,每次中断都发生一次唤醒操作。即使没有进程在设备节点上休眠,中断状态也不会丢失,而是在下一次读取的时候被读出。这里中断的概念和内核中的中断不是一回事。
    
     
     
     
      
       1.3
      
     
     用户和
     
      
       RTC
      
     
     的接口
    
     
      
       1.
       
        
         /dev
        
       
       接口
      
     
    
     
      
      
     
     如果系统中有
     
      
       udev
      
     
     模块的话,系统启动以后会在
     
      
       /dev
      
     
     下生成
     
      
       RTC
      
     
     的设备节点。一般
     
      
       RTC
      
     
     设备节点分为两类:
     
      
       /dev/rtc
      
     
     和
     
      
       /dev/rtcN
      
     
     (
     
      
       N>=0
      
     
     )。其中
     
      
       /dev/rtc
      
     
     是
     
      
       PC
      
     
     机上使用的接口,因为最早的时候系统中只有一个
     
      
       RTC
      
     
     设备,设备节点的名字就是
     
      
       rtc
      
     
     ,现在为了兼容以前的程序,仍然会建立这个设备节点,但是现在的
     
      
       /dev/rtc
      
     
     往往是一个指向其它设备节点的链接。随着嵌入式平台的兴起,
     
      
       Linux
      
     
     开始支持多个
     
      
       RTC
      
     
     设备了,因此必须用新的命名规则对不同的设备进行区分,所以产生了
     
      
       /dev/rtcN
      
     
     (
     
      
       N>=0
      
     
     )设备节点,
     
      
       /dev/rtc
      
     
     往往就是指向它们中某一个的链接。
    
     
      
      
     
     上面说
     
      
       Linux
      
     
     已经支持多个
     
      
       RTC
      
     
     了,那么系统启动的时候从哪个
     
      
       RTC
      
     
     读取时间呢?答案取决于编译内核之前配置内核的选项。
    
     
      
      
     
     假设现在某个开发板上有两个
     
      
       RTC
      
     
     设备,那么在
     
      
       /dev
      
     
     下的设备节点如下:
    
     
      
       
        
         [root@zlg/]# ls /dev/rtc*
        
       
      
     
    
     
      
       
        
         /dev/rtc /dev/rtc0 /dev/rtc1
        
       
      
     
    
     
      
       
        
         [root@zlg/]# ls -l /dev/rtc*
        
       
      
     
    
     
      
       
        
         lrwxrwxrwx 1 root root 4 Nov 25 17:32 /dev/
         
          rtc -> rtc0
         
        
       
      
     
    
     
      
       
        
         crw-r–r– 1 root root 254, 0 Nov 25 17:32 /dev/rtc0
        
       
      
     
    
     
      
       
        
         crw-rw—- 1 root root 254, 1 Nov 25 17:32 /dev/rtc1
        
       
      
     
    
     
      
       
        
         [root@zlg/]#
        
       
      
     
    
     
      
      
     
     可以看到,
     
      
       rtc
      
     
     是指向
     
      
       rtc0
      
     
     的一个链接。据此可以推断系统使用
     
      
       rtc0
      
     
     来读取系统时间。
    
     
      
      
     
     在这三个节点上可以使用
     
      
       open
      
     
     、
     
      
       close
      
     
     、
     
      
       read
      
     
     、
     
      
       ioctl
      
     
     和
     
      
       select
      
     
     等函数。有关这些函数的使用将会在后面介绍。
    
     
      
       2.
       
        
         
          proc
         
         
          fs
         
        
       
       接口
      
     
    
     
      
      
     
     如果系统中使用了
     
      
       procfs
      
     
     ,那么第一个
     
      
       RTC
      
     
     设备(
     
      
       rtc0
      
     
     )可以在
     
      
       /proc/driver/rtc
      
     
     中暴露自己的信息。
    
     
      
      
     
     读取这个文件会得到类似下面的信息:
    
     
      
       
        
         [root@zlg/]# cat /proc/driver/rtc
        
       
      
     
    
     
      
       
        
         rtc_time : 18:45:50
        
       
      
     
    
     
      
       
        
         rtc_date : 2011-01-03
        
       
      
     
    
     
      
       
        
         24hr : yes
        
       
      
     
    
     
      
       3.
       
        
         sysfs
        
       
       接口
      
     
    
     
      
       
        在
       
      
      
       
        
         
          /sys/class/
         
        
       
      
      
       
        下会生成一个名为
       
      
      
       
        
         
          rtc
         
        
       
      
      
       
        的目录,这个目录中会为每一个注册的
       
      
      
       
        
         
          rtc
         
        
       
      
      
       
        设备生成一个子目录,名为
       
      
      
       
        
         
          rtcN
         
        
       
      
      
       
        (
       
      
      
       
        
         
          N>=0
         
        
       
      
      
       
        ),每个子目录下的内容都是一致的,如下:
       
      
     
    
     
      
       
        
         [root@zlg/]# ls /sys/class/rtc/
        
       
      
     
    
     
      
       
        
         rtc0 rtc1
        
       
      
     
    
     
      
       
        
         [root@zlg/]# ls /sys/class/rtc/rtc0
        
       
      
     
    
     
      
       
        
         date device name since_epoch time
        
       
      
     
    
     
      
       
        
         dev max_user_freq power subsystem uevent
        
       
      
     
    
     
      
       
        
         [root@zlg/]# ls /sys/class/rtc/rtc1
        
       
      
     
    
     
      
       
        
         date device name since_epoch time
        
       
      
     
    
     
      
       
        
         dev max_user_freq power subsystem uevent
        
       
      
     
    
     
      
       
        
         [root@zlg/]#
        
       
      
     
    
     
      
       
        现在以
       
      
      
       
        
         
          rtc0
         
        
       
      
      
       
        为例访问用户比较关心的几个节点,它们的含义如下:
       
      
     
    
     
      
       
        
         [root@zlg/]# cat /sys/class/rtc/rtc0/date /*
        
       
      
      
       
        日期
       
      
      
       
        
         */
        
       
      
     
    
     
      
       
        
         2040-01-03
        
       
      
     
    
     
      
       
        
         [root@zlg/]# cat /sys/class/rtc/rtc0/name /*
        
       
      
      
       
        设备名
       
      
      
       
        
         */
        
       
      
     
    
     
      
       
        
         rtc-pcf8563
        
       
      
     
    
     
      
       
        
         [root@zlg/]# cat /sys/class/rtc/rtc0/since_epoch /*
        
       
      
      
       
        自
       
      
      
       
        
         1970
        
       
      
      
       
        年
       
      
      
       
        
         1
        
       
      
      
       
        月
       
      
      
       
        
         1
        
       
      
      
       
        日
       
      
      
       
        
         00:00:00
        
       
      
      
       
        以来的秒数
       
      
      
       
        
         */
        
       
      
     
    
     
      
       
        
         2209231116
        
       
      
     
    
     
      
       
        
         [root@zlg/]# cat /sys/class/rtc/rtc0/time /*
        
       
      
      
       
        时间
       
      
      
       
        
         */
        
       
      
     
    
     
      
       
        
         19:18:50
        
       
      
     
    
     
      
       
        
         [root@zlg/]# cat /sys/class/rtc/rtc0/dev /*
        
       
      
      
       
        设备节点号
       
      
      
       
        
         */
        
       
      
     
    
     
      
       
        
         254:0
        
       
      
     
    
     
      
       
        
         [root@zlg/]# cat /sys/class/rtc/rtc0/max_user_freq /*
        
       
      
      
       
        非
       
      
      
       
        
         Root
        
       
      
      
       
        用户可使用的最大周期中断频率
       
      
      
       
        
         */
        
       
      
     
    
     
      
       
        
         64
        
       
      
     
    
     
      
       
        
         [root@zlg/]#
        
       
      
     
    
     
     
     
      
       1.4IOCTL
      
     
     命令
    
     
      
      
     
     对于
     
      
       RTC
      
     
     设备在
     
      
       /dev
      
     
     下的设备节点可以使用
     
      
       ioctl()
      
     
     函数进行访问。这一小节介绍一下需要用到的
     
      
       IOCTL
      
     
     命令。
    
     
      
       1.
       
        
         alarm/wakeupalarm
        
       
       中断操作
      
     
    
- 
 
 
 
 RTC_ALM_SET
 
 
 
 
 
 
 设置
 
 
 
 
 
 
 alarm
 
 
 
 
 
 
 中断的触发时刻,使用的方式如下:
 
 
 
     
      
       
        
         ioctl(fd,RTC_ALM_SET, &rtc_tm);
        
       
      
     
    
- 
 
 
 其中第三个参数是一个
 
 
 
 
 
 
 structrtc_time
 
 
 
 
 
 
 结构体,这个结构体的成员请参考程序清单
 
 1 .1
 
 。注意,
 
 
 
 
 
 
 alarm
 
 
 
 
 
 
 中断的触发时间只能是
 
 
 
 
 
 
 24
 
 
 
 
 
 
 小时内的一个时刻,所以只有时、分、秒的部分是有效的,
 
 
 
 
 
 structrtc_time
 
 
 
 
 
 的年、月、日部分会被忽略。为了保证正确性,
 
 
 
 
 
 structrtc_time
 
 
 
 
 
 的
 
 
 
 
 
 tm_isdst
 
 
 
 
 
 成员应该设为
 
 
 
 
 
 -1
 
 
 
 
 
 。
 
 
 
 
 
 如当前时间是
 
 
 
 
 
 13:00:00
 
 
 
 
 
 ,而传入的时刻是
 
 
 
 
 
 14:00:00
 
 
 
 
 
 ,则意味着
 
 
 
 
 
 
 alarm
 
 
 
 
 
 
 中断
 
 将在一小时后发生。而如果传入的是
 
 
 
 
 
 
 
 12:00:00
 
 
 
 
 
 
 
 ,则意味着明天中午发生中断。总之,
 
 
 
 
 
 
 
 alarm
 
 
 
 
 
 
 
 中断不能超过
 
 
 
 
 
 
 
 24
 
 
 
 
 
 
 
 小时。
 
 
 
 
- 
 
 
 
 RTC_ALM_READ
 
 
 
 
 
 
 读取已经设置的
 
 
 
 
 
 alarm
 
 
 
 
 
 中断时刻,使用的方式如下:
 
 
 
     
      
       
        
         ioctl(fd,RTC_ALM_READ, &rtc_tm);
        
       
      
     
    
- 
 
 
 
 RTC_WKALM_SET
 
 
 
 
 
 
 设置
 
 
 
 
 
 wakeupalarm
 
 
 
 
 
 中断的触发时刻,它和
 
 
 
 
 
 alarm
 
 
 
 
 
 中断的唯一不同之处就是
 
 
 
 
 
 wakeupalarm
 
 
 
 
 
 中断的触发时刻可以在未来的任意时刻。它的使用方式如下:
 
 
 
     
      
       
        
         ioctl(fd,RTC_WKALM_SET, &alarm);
        
       
      
     
    
- 
 
 
 第三个参数是一个
 
 
 
 
 
 structrtc_wkalrm
 
 
 
 
 
 结构体,请参考程序清单
 
 1 .2
 
 。
 
 
 
 
 
 structrtc_wkalrm
 
 
 
 
 
 的第一个成员
 
 
 
 
 
 enabled
 
 
 
 
 
 为
 
 
 
 
 
 1
 
 
 
 
 
 的话可以使
 
 
 
 
 
 ioctl()
 
 
 
 
 
 返回的时候中断功能就已经开启了。如果这里里没有开启中断功能,可以使用
 
 
 
 
 
 RTC_AIE_ON
 
 
 
 
 
 命令来开启,这个命令的用法在下面。
 
 
 
 
 
 由于
 
 
 
 
 
 
 alarm
 
 
 
 
 
 
 和
 
 
 
 
 
 
 wakeupalarm
 
 
 
 
 
 
 在内核中表现为一种中断,因此同一时刻只有一个是有效的。也就是说不可以使用
 
 
 
 
 
 
 alarm
 
 
 
 
 
 
 中断的同时使用
 
 
 
 
 
 
 wakeupalarm
 
 
 
 
 
 
 中断。只有最后一次设置的
 
 
 
 
 
 
 alarm
 
 
 
 
 
 
 或
 
 
 
 
 
 
 wakeupalarm
 
 
 
 
 
 
 中断触发时刻是有效的。
 
 
 
- 
 
 
 
 RTC_WKALM_RD
 
 
 
 
 
 
 读取
 
 
 
 
 
 
 wakeupalarm
 
 
 
 
 
 
 中断的触发时刻。它的使用方式如下:
 
 
 
     
      
       
        
         ioctl(fd,RTC_WKALM_RD, &alarm);
        
       
      
     
    
- 
 
 
 
 RTC_AIE_ON
 
 
 
 
 
 
 开启
 
 
 
 
 
 
 alarm/wakeupalarm
 
 
 
 
 
 
 中断。使用上面的命令设置了中断的时刻还不能启用中断,必须使用这个命令来开启。
 
 
 
- 
 
 
 
 RTC_AIE_OFF
 
 
 
 
 
 
 关闭
 
 
 
 
 
 alarm/wakeupalarm
 
 
 
 
 
 中断。但是不会改变已经设置的中断触发时刻。
 
 
 
     
      
       2.更新中断(
       
        
         
          updateint
         
        
       
       )操作
      
     
    
- 
 
 
 
 
 
 
 RTC_UIE_ON
 
 
 
 
 
 
 
 开启
 
 
 
 
 
 
 RTC
 
 
 
 
 
 
 更新中断。更新中断每秒钟触发一次,因此频率为
 
 
 
 
 
 
 1HZ
 
 
 
 
 
 
 。有些
 
 
 
 
 
 
 RTC
 
 
 
 
 
 
 芯片或者
 
 
 
 
 
 
 RTC
 
 
 
 
 
 
 驱动不支持更新中断,可以使用软件来模拟,但前提是编译内核前配置内核时选择了软件模拟的功能,选项的路径如下:
 
 
 
     
      
       
        
         DeviceDriver->RealTime Clock->RTC UIE emulation on dev interface
        
       
      
     
    
- 
 
 
 开启和关闭更新中断都不需要传入参数。
 
 
 
- 
 
 
 
 RTC_UIE_OFF
 
 
 
 
 
 
 关闭
 
 
 
 
 
 RTC
 
 
 
 
 
 更新中断。
 
 
 
     
      
       3.周期中断(
       
        
         
          Periodicint
         
        
       
       )操作
      
     
    
- 
 
 
 
 RTC_IRQP_SET
 
 
 
 
 
 
 设置周期中断的频率。使用的方法如下:
 
 
 
     
      
       
        
         ioctl(fd,RTC_IRQP_SET, tmp);
        
       
      
     
    
- 
 
 
 
 
 tmp
 
 
 
 
 
 
 是一个
 
 
 
 
 
 
 unsignedlong
 
 
 
 
 
 
 类型的变量,它的值必须是
 
 
 
 
 
 
 2
 
 
 
 
 
 
 的幂,也就是
 
 
 
 
 
 
 2^N
 
 
 
 
 
 
 (
 
 
 
 
 
 
 N>=1
 
 
 
 
 
 
 )。非
 
 
 
 
 
 
 Root
 
 
 
 
 
 
 用户无法使用
 
 
 
 
 
 
 64HZ
 
 
 
 
 
 
 以上的周期中断。
 
 
 
- 
 
 
 
 
 
 
 RTC_IRQP_READ
 
 
 
 
 
 
 
 读取周期中断的频率。使用方式如下:
 
 
 
     
      
       
        
         ioctl(fd,RTC_IRQP_READ, &tmp);
        
       
      
     
    
- 
 
 
 
 
 tmp
 
 
 
 
 
 
 是一个
 
 
 
 
 
 
 unsignedlong
 
 
 
 
 
 
 类型的变量,它保存返回的周期中断频率。
 
 
 
- 
 
 
 
 RTC_PIE_ON
 
 
 
 
 
 
 开启周期中断功能。周期中断的频率设置好之后还不能立即使用,必须使用此命令来开启。
 
 
 
- 
 
 
 
 RTC_PIE_OFF
 
 
 
 
 
 
 关闭周期中断功能。之前设置的周期中断频率依然有效。
 
 
 
     
      
       4.
       
        
         RTC
        
       
       时间操作
      
     
    
- 
 
 
 
 
 
 RTC_SET_TIME
 
 
 
 
 
 
 设置
 
 
 
 
 
 
 RTC
 
 
 
 
 
 
 的时间。这个命令和中断无关,用于更新
 
 
 
 
 
 
 RTC
 
 
 
 
 
 
 芯片的当前时间。使用的方式如下:
 
 
 
     
      
       
        
         ioctl(fd,RTC_SET_TIME, &rtc_tm)
        
       
      
     
    
- 
 
 
 第三个参数以一个
 
 
 
 
 
 
 structrtc_time
 
 
 
 
 
 
 变量,各个成员的含义请参考程序清单
 
 1 .1
 
 。
 
 
 
- 
 
 
 
 RTC_RD_TIME
 
 
 
 
 
 
 
 
 
 
 
 
 读取
 
 
 
 
 
 RTC
 
 
 
 
 
 硬件中的当前时刻。使用的方式如下:
 
 
 
     
      
       
        
         ioctl(fd,RTC_RD_TIME, &rtc_tm);
        
       
      
     
    
     
     
     
      
       1.5
      
     
     用户空间使用访问
     
      
       RTC
      
     
     的例程
    
     
      
       
        用户空间使用
       
      
      
       
        
         RTC
        
       
      
      
       
        设备的方法就是设置好中断的参数然后使用
       
      
      
       
        
         read
        
       
      
      
       
        或者
       
      
      
       
        
         select
        
       
      
      
       
        在设备节点上睡眠,等待中断将自己唤醒后读取设备节点的数据来判断中断类型和次数。
       
      
     
    
     
      
       
        本文撰写的依据是
       
      
      
       
        
         
          2.6.27.8
         
        
       
      
      
       
        版本的内核。在内核的
       
      
      
       
        
         
          /driver/documentation/rtc.txt
         
        
       
      
      
       
        中有一个用户空间访问
       
      
      
       
        
         
          RTC
         
        
       
      
      
       
        设备节点的例程
       
      
     
    
     
      
       
        1.6  3250
       
      
      开发板不支持的
      
       
        RTC
       
      
      功能
     
    
     
      
      
     
    
     
      
       3250
      
     
     开发板上有两个
     
      
       RTC
      
     
     设备,一个片外的
     
      
       pcf8563
      
     
     和一个片内的
     
      
       RTC
      
     
     。其中片
     
      
       pcf8563
      
     
     仅仅支持读取和设置时间,不支持硬件的更新中断和
     
      
       alarm/wakeupalarm
      
     
     中断。片内的
     
      
       RTC
      
     
     不支持更新中断,但是支持
     
      
       alarm/wakeupalarm
      
     
     中断。在
     
      
       sys/class/rtc
      
     
     和
     
      
       /dev
      
     
     下,
     
      
       pcf8563
      
     
     对应
     
      
       rtc0
      
     
     ,片内
     
      
       RTC
      
     
     对应
     
      
       rtc1
      
     
     。内核的系统时间是从
     
      
       rtc0
      
     
     读取的,并不使用
     
      
       rtc1
      
     
     。
    
     
      
      
     
     虽然
     
      
       3250
      
     
     开发板的两个
     
      
       RTC
      
     
     硬件上并不支持更新中断,但是可以开启软件模拟更新中断的功能,开启的方法是在编译内核前使用“
     
      
       makemenuconfig”
      
     
     命令来配置内核,使内核支持软件模拟更新中断的功能。选择这个功能的路径如下:
    
     
      
       
        
         DeviceDriver->Real Time Clock->RTC UIE emulation on dev interface
        
       
      
     
    
     
      
      
     
     选择之后重新编译内核并下载到开发板就可以支持软件模拟的更新中断了,但是对用户空间来说,和硬件更新中断是没有区别的。
    
    ============================================
    
    作者:yuanlulu
    
    http://blog.csdn.net/yuanlulu
    版权没有,但是转载请保留此段声明
    
    ============================================
   
 
