【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 09:34:48
作者: SY
簡介
RTC
時鐘在電腦主板上,開發板上隨處可見,在主機斷電後,如果沒有後備電池供電,那麼系統時間將會丟失,因此一般的主板上都會配置一個 cr1220
的鈕釦電池。
這是開發板的 RTC
供電設計,如果開發板上電,後備電池不會輸出電流,因爲沒有壓降。當開發板斷電,後備電池供電,維持 RTC
中的時間。
移植
設備樹
&rtc {
status = "okay";
};
驅動文件
打開 driver/rtc/rtc-s3c.c
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,
否則在執行
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);
}
報錯。
menuconfig
Device Drivers --->
[*] Real Time Clock --->
<*> Samsung S3C series SoC RTC
燒錄
[ 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)
查看設備節點
[root@TINY4412:~]# ls /dev/rtc0
/dev/rtc0
APP
/*
* rtc driver for tiny4412
*
* Copyright (c) 2017
* Author: SY <[email protected]>
*
* 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;
}
測試
[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
時鐘:
[root@TINY4412:~]# date -s "2017-09-09 13:03:01"
Sat Sep 9 13:03:01 UTC 2017
設置硬件時鐘:
[root@TINY4412:~]# hwclock -w
[root@TINY4412:~]# hwclock
Sat Sep 9 13:03:11 2017 0.000000 seconds
[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
年左右,應該會有電。以後再來解決這個問題。