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

【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 的纽扣电池。

【TINY4412】LINUX移植笔记:(25)设备树RTC驱动_第1张图片

这是开发板的 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);
 }

报错。

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 
#include 
#include 
#include 
#include  
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 


#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 年左右,应该会有电。以后再来解决这个问题。

参考

设备树学习之(六)RTC

你可能感兴趣的:(TINY4412,LINUX)