1、rtc_device 结构体是RTC设备在内核中的具体实现
snvs_rtc: snvs-rtc-lp {
compatible = "fsl,sec-v4.0-mon-rtc-lp";
regmap = <&snvs>;
offset = <0x34>;
interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
};
根据compatible找到驱动文件:rtc_snvs.c,驱动文件里面就是初始化rtc_device并注册。
rtc_device结构体里面重点是rtc_class_ops操作集。
2、应用程序可以通过 ioctl 函 数来设置/读取时间、设置/读取闹钟的操作,那么对应的 rtc_dev_ioctl 函数就会执行,通过cmd来决定具体操作,比如RTC_RD_TIME:rtc_read_time 会调用__rtc_read_time 函数,__rtc_read_time 函数会通过调用 rtc_class_ops 中的read_time 来从 RTC 设备中获取当前时间。
Linux 内核将
RTC
设备抽象为
rtc_device
结构体,因此
RTC
设备驱动就是申请并初始化
rtc_device
,最后将
rtc_device
注册到
Linux
内核里面。
struct
rtc_device
{
const struct
rtc_class_ops
*
ops
;
/* RTC
设备底层操作函数
*/
};
rtc_class_ops 为 RTC
设备的最底层操作函数集合,包括从
RTC
设备中读取时间、向
RTC
设备写入新的时间值等。
71
struct
rtc_class_ops
{
int
(*
open
)(
struct
device
*);
void
(*
release
)(
struct
device
*);
int
(*
ioctl
)(
struct
device
*,
unsigned int
,
unsigned long
);
int
(*
read_time
)(
struct
device
*,
struct
rtc_time
*);
int
(*
set_time
)(
struct
device
*,
struct
rtc_time
*);
int
(*
read_alarm
)(
struct
device
*,
struct
rtc_wkalrm
*);
int
(*
set_alarm
)(
struct
device
*,
struct
rtc_wkalrm
*);
int
(*
proc
)(
struct
device
*,
struct
seq_file
*);
int
(*
set_mmss64
)(
struct
device
*,
time64_t secs
);
int
(*
set_mmss
)(
struct
device
*,
unsigned long
secs
);
int
(*
read_callback
)(
struct
device
*,
int
data
);
int
(*
alarm_irq_enable
)(
struct
device
*,
unsigned int
enabled
);
};
RTC
是个字符设备,那么肯定有字符设备的
file_operations
函数操 作集,Linux
内核提供了一个
RTC
通用字符设备驱动文件,文件名为
drivers/rtc/rtc-dev.c
,
rtc-dev.c 文件提供了所有
RTC
设备共用的
file_operations
函数操作集,如下所示:
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
,
};
3、查看时间:date
设置rtc时间:date -s "2019-08-31 18:13:00"
设置完时间以后下次重启开发板时间会丢失,使hwclock -w //将当前系统时间写入到 RTC 里面