【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 的鈕釦電池。

這裏寫圖片描述

這是開發板的 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 <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 年左右,應該會有電。以後再來解決這個問題。

參考

設備樹學習之(六)RTC

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章