【TINY4412】LINUX移植笔记:(25)设备树RTC驱动

环境

宿主机 : 虚拟机 Ubuntu 16.04 LTS / X64
目标板[底板]: Tiny4412SDK - 1506
目标板[核心板]: Tiny4412 - 1412
LINUX内核: 4.12.0
交叉编译器: arm-none-linux-gnueabi-gcc(gcc version 4.8.3 20140320)
日期: 2017-9-9 20:30:09
作者: SY

简介

RTC 时钟在电脑主板上,开发板上随处可见,在主机断电后,如果没有后备电池供电,那么系统时间将会丢失,因此一般的主板上都会配置一个 cr1220 的纽扣电池。

1

这是开发板的 RTC 供电设计,如果开发板上电,后备电池不会输出电流,因为没有压降。当开发板断电,后备电池供电,维持 RTC 中的时间。

移植

设备树

1
2
3
&rtc {
status = "okay";
};

驱动文件

打开 driver/rtc/rtc-s3c.c

1
2
3
4
5
6
7
8
9
10
11
static struct s3c_rtc_data const s3c6410_rtc_data = {
.max_user_freq = 32768,
.needs_src_clk = false,
.irq_handler = s3c6410_rtc_irq,
.set_freq = s3c6410_rtc_setfreq,
.enable_tick = s3c6410_rtc_enable_tick,
.save_tick_cnt = s3c6410_rtc_save_tick_cnt,
.restore_tick_cnt = s3c6410_rtc_restore_tick_cnt,
.enable = s3c24xx_rtc_enable,
.disable = s3c6410_rtc_disable,
};

.needs_src_clk = true, 改为 .needs_src_clk = false, 否则在执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if (info->data->needs_src_clk) {
info->rtc_src_clk = devm_clk_get(&pdev->dev, "rtc_src");
if (IS_ERR(info->rtc_src_clk)) {
ret = PTR_ERR(info->rtc_src_clk);
if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev,
"failed to find rtc source clock\n");
else
dev_dbg(&pdev->dev,
"probe deferred due to missing rtc src clk\n");
clk_disable_unprepare(info->rtc_clk);
return ret;
}
clk_prepare_enable(info->rtc_src_clk);
}

报错。

1
2
3
Device Drivers --->
[*] Real Time Clock --->
<*> Samsung S3C series SoC RTC

烧录

1
2
3
4
5
[ 3.932861] s3c-rtc 10070000.rtc: rtc disabled, re-enabling
[ 3.938078] s3c-rtc 10070000.rtc: warning: invalid RTC value so initializing it
[ 3.945378] rtc rtc0: invalid alarm value: 1900-1-2 0:0:0
[ 3.950841] s3c-rtc 10070000.rtc: rtc core: registered s3c as rtc0
[ 4.109938] s3c-rtc 10070000.rtc: setting system clock to 2000-01-01 00:00:38 UTC (946684838)

查看设备节点

1
2
[root@TINY4412:~]# ls /dev/rtc0
/dev/rtc0

APP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/*
* rtc driver for tiny4412
*
* Copyright (c) 2017
* Author: SY <1530454315@qq.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <stdbool.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/epoll.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#include <linux/rtc.h>
#if 1
static void help(void)
{
printf("Usage:\n");
printf(" read: ./rtc r\n");
printf(" write: ./rtc w [year] [month] [day] [hour] [minuter] [second]\n");
}
#endif
bool set_time(int fd, struct rtc_time *time)
{
int ret = ioctl(fd, RTC_SET_TIME, time);
if (ret < 0) {
perror("set rtc time error");
return false;
}
return true;
}
bool get_time(int fd, struct rtc_time *time)
{
int ret = ioctl(fd, RTC_RD_TIME, time);
if (ret < 0) {
perror("get rtc time error");
return false;
}
printf("> %04d-%02d-%02d %02d:%02d:%02d\n", 1900+time->tm_year, time->tm_mon, time->tm_mday,
time->tm_hour, time->tm_min, time->tm_sec);
return true;
}
int main(int argc, char **argv)
{
if (argc < 2) {
help();
exit(0);
}
char rw = argv[1][0];
if (rw == 'w') {
if (argc != 8) {
help();
exit(0);
}
}
int fd = open("/dev/rtc0", O_RDWR);
if(!fd) {
printf("open /dev/rtc0 return error\n");
exit(0);
}
struct rtc_time time = {0};
switch (rw) {
case 'r': {
get_time(fd, &time);
break;
}
case 'w': {
time.tm_year = atoi(argv[2]) - 1900;
time.tm_mon = atoi(argv[3]);
time.tm_mday = atoi(argv[4]);
time.tm_hour = atoi(argv[5]);
time.tm_min = atoi(argv[6]);
time.tm_sec = atoi(argv[7]);
set_time(fd, &time);
break;
}
default:
help();
break;
}
close(fd);
return 0;
}

测试

1
2
3
4
5
[root@TINY4412:~]# ./tmp/rtc r
> 2000-00-01 00:02:47
[root@TINY4412:~]# ./tmp/rtc w 2017 9 9 12 53 10
[root@TINY4412:~]# ./tmp/rtc r
> 2017-09-09 12:53:12

或者直接通过 Linux 命令设置时钟。

设置 Linux 时钟:

1
2
[root@TINY4412:~]# date -s "2017-09-09 13:03:01"
Sat Sep 9 13:03:01 UTC 2017

设置硬件时钟:

1
2
3
[root@TINY4412:~]# hwclock -w
[root@TINY4412:~]# hwclock
Sat Sep 9 13:03:11 2017 0.000000 seconds
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@TINY4412:~]# hwclock -h
hwclock: invalid option -- 'h'
BusyBox v1.27.0 (2017-08-05 19:36:54 CST) multi-call binary.
Usage: hwclock [-r|--show] [-s|--hctosys] [-w|--systohc] [-t|--systz] [-l|--localtime] [-u|--utc] [-f|--rtc FILE]
Query and set hardware clock (RTC)
-r Show hardware clock time
-s Set system time from hardware clock
-w Set hardware clock from system time
-t Set in-kernel timezone, correct system time
if hardware clock is in local time
-u Assume hardware clock is kept in UTC
-l Assume hardware clock is kept in local time
-f FILE Use specified device (e.g. /dev/rtc2)

现在遇到的问题是,只要不掉电,读写 RTC 时间都是正常的,但是关机等待 1min 后重启,时间就丢失了!电池放在这里 1 年左右,应该会有电。以后再来解决这个问题。

参考

设备树学习之(六)RTC

SY wechat
扫一扫,用手机访问本站