《RTC — RTC相關操作以及如何同步系統時間》


1.查看系統時間

date

 

 

2.查看RTC時間

  由於不同的RTC驅動讀取時間的方法不一樣。我這邊使用的是hi_rtc。是使用海思中自動的測試程序。

./tim  -g  time

 

3.系統時間同步成RTC時間

hwclock –r         顯示硬件時鍾與日期

hwclock –s         將系統時鍾調整為與目前的硬件時鍾一致。

hwclock –w        將硬件時鍾調整為與目前的系統時鍾一致。

  但是我使用相關命令會出現:

 

   提示找不到相對應的設備節點。

  因為我的設備節點是加載在/dev/hi_rtc中,所以通用的這個是不行了。(海思的RTC不能使用通過的系統時間同步命令)

 

  利用mktime和settimeofday的直接在讀取RTC時間時,將RTC時間再通過這兩個函數再寫入到系統時間中。

 

mktime函數:

  C 庫函數 time_t mktime(struct tm *timeptr) 把 timeptr 所指向的結構轉換為一個依據本地時區的 time_t 值。

#include <time.h>

time_t mktime(struct tm *timeptr)

參數:
struct tm {
   int tm_sec;         /* 秒,范圍從 0 到 59                */
   int tm_min;         /* 分,范圍從 0 到 59                */
   int tm_hour;        /* 小時,范圍從 0 到 23                */
   int tm_mday;        /* 一月中的第幾天,范圍從 1 到 31                    */
   int tm_mon;         /* 月份,范圍從 0 到 11                */
   int tm_year;        /* 自 1900 起的年數                */
   int tm_wday;        /* 一周中的第幾天,范圍從 0 到 6                */
   int tm_yday;        /* 一年中的第幾天,范圍從 0 到 365                    */
   int tm_isdst;       /* 夏令時                        */    
};

返回值:
該函數返回一個 time_t 值,該值對應於以參數傳遞的日歷時間。如果發生錯誤,則返回 -1 值。

  作用是,將時間轉換為自1900年1月1日以來持續時間的秒數,發生錯誤時返回-1。(注意這邊是自1900的1月份)

 

settimeofday函數:

#include<sys/time.h>
#include<unistd.h>

int settimeofday ( const struct timeval *tv,const struct timezone *tz);

參數:
struct  timeval{
       long  tv_sec;/**/
       long  tv_usec;/*微妙*/
};

struct  timezone{
        int tz_minuteswest;/*和greenwich 時間差了多少分鍾*/
        int tz_dsttime;/*type of DST correction*/

}

返回值:函數執行成功后返回0,失敗后返回-1,錯誤代碼存於errno中。

 

4.實例

 

/*
 * RTC sample&test code.
 */

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>

#include "hi_rtc.h"

void usage(void)
{
    printf(
            "\n"
            "Usage: ./test [options] [parameter1] ...\n"
            "Options: \n"
            "    -s(set)            Set time/alarm,     e.g '-s time 2012/7/15/13/37/59'\n"
            "    -g(get)            Get time/alarm,     e.g '-g alarm'\n"
            "    -w(write)        Write RTC register, e.g '-w <reg> <val>'\n"
            "    -r(ead)            Read RTC register,  e.g '-r <reg>'\n"
            "    -a(alarm)        Alarm ON/OFF',      e.g '-a ON'\n"
            "    -reset            RTC reset\n"
            "    -b(battery monitor) battery ON/OFF,     e.g '-b ON'\n"
            "    -f(requency)        frequency precise adjustment, e.g '-f <val>'\n"
            "\n");
    exit(1);
}


static int _atoul(const char *str, unsigned char *pvalue)
{
    unsigned int result=0;

    while (*str)
    {
        if (isdigit((int)*str))
        {
            if ((result<429496729) || ((result==429496729) && (*str<'6')))
            {
                result = result*10 + (*str)-48;
            }
            else
            {
                *pvalue = result;
                return -1;
            }
        }
        else
        {
            *pvalue=result;
            return -1;
        }
        str++;
    }
    *pvalue=result;
    return 0;
}


#define ASC2NUM(ch) (ch - '0')
#define HEXASC2NUM(ch) (ch - 'A' + 10)

static int  _atoulx(const char *str, unsigned char *pvalue)
{
    unsigned int   result=0;
    unsigned char  ch;

    while (*str)
    {
        ch=toupper(*str);
        if (isdigit(ch) || ((ch >= 'A') && (ch <= 'F' )))
        {
            if (result < 0x10000000)
            {
                result = (result << 4) + ((ch<='9')?(ASC2NUM(ch)):(HEXASC2NUM(ch)));
            }
            else
            {
                *pvalue=result;
                return -1;
            }
        }
        else
        {
            *pvalue=result;
            return -1;
        }
        str++;
    }

    *pvalue=result;
    return 0;
}

/*used for convert hex value from string to int*/
static int str_to_num(const char *str, unsigned char *pvalue)
{
    if ( *str == '0' && (*(str+1) == 'x' || *(str+1) == 'X') ){
        if (*(str+2) == '\0'){
            return -1;
        }
        else{
            return _atoulx(str+2, pvalue);
        }
    }
    else {
        return _atoul(str,pvalue);
    }
}

/*used for convert time frome string to struct rtc_time_t*/
static int parse_string(char *string, rtc_time_t *p_tm)
{
    char *comma, *head;
    int value[10];
    int i;

    if (!string || !p_tm)
        return -1;

    if (!strchr(string, '/'))
        return -1;

    head = string;
    i = 0;
    comma = NULL;

    for(;;) {    
        comma = strchr(head, '/');

        if (!comma){
            value[i++] = atoi(head);
            break;
        }

        *comma = '\0';
        value[i++] = atoi(head);
        head = comma+1;    
    }
    
    if (i < 5)
        return -1;

    p_tm->year   = value[0];
    p_tm->month  = value[1];
    p_tm->date   = value[2];
    p_tm->hour   = value[3];
    p_tm->minute = value[4];
    p_tm->second = value[5];
    p_tm->weekday = 0;

    return 0;
}

int main(int argc, const char *argv[])
{
    struct tm tm_time;
    struct timeval val_time;
    rtc_time_t tm;
    reg_data_t regv;
    int ret = -1;
    int fd = -1;
    
    const char *dev_name = "/dev/hi_rtc";
    char string[50] = {0};

    if (argc < 2){
        usage();
        return 0;
    }

    fd = open(dev_name, O_RDWR);
    if (fd < 0) {
        printf("open %s failed\n", dev_name);
        return -1;
    }

    if (!strcmp(argv[1],"-s")) {
        if (argc < 4) {
            usage();
            goto err1;    
        }

        if (!strcmp(argv[2], "time")) {

            strncpy(string, argv[3], sizeof(string)-1);

            ret = parse_string(string, &tm);
            if (ret < 0)
            {
                printf("parse time param failed\n");
                goto err1;
            }
            printf("set time\n");

            /* code */
            printf("year:%d\n", tm.year);
            printf("month:%d\n",tm.month);
            printf("date:%d\n", tm.date); 
            printf("hour:%d\n", tm.hour);
            printf("minute:%d\n", tm.minute);
            printf("second:%d\n", tm.second);

            ret = ioctl(fd, HI_RTC_SET_TIME, &tm);
            if (ret < 0) {
                printf("ioctl: HI_RTC_SET_TIME failed\n");
                goto err1;
            }    
        } 
        else if (!strcmp(argv[2], "alarm")) 
        {
            strncpy(string, argv[3], sizeof(string)-1);

            ret = parse_string(string, &tm);
            if (ret < 0) {
                printf("parse alarm param failed\n");
                goto err1;
            }
            printf("set alarm\n");
#if 1            
            printf("year:%d\n", tm.year);
            printf("month:%d\n",tm.month);
            printf("date:%d\n", tm.date); 
            printf("hour:%d\n", tm.hour);
            printf("minute:%d\n", tm.minute);
            printf("second:%d\n", tm.second);
#endif            
            ret = ioctl(fd, HI_RTC_ALM_SET, &tm);
            if (ret < 0) {
                printf("ioctl: HI_RTC_ALM_SET failed\n");
                goto err1;
            }    
         } else {
            printf("unknown options %s\n", argv[2]);
            goto err1;
        }
    } else if (!strcmp(argv[1],"-g")) {
        if (argc < 3) {
            usage();
            goto err1;    
        }

        //read RTC
        if (!strcmp(argv[2], "time")) {

            printf("[RTC_RD_TIME]\n");
            
            ret = ioctl(fd, HI_RTC_RD_TIME, &tm);
            if (ret < 0) {
                printf("ioctl: HI_RTC_RD_TIME failed\n");
                goto err1;
            }
            
            printf("Current time value: \n");
        } else if (!strcmp(argv[2], "alarm")) {
        
            printf("[RTC_RD_ALM]\n");

            ret = ioctl(fd, HI_RTC_ALM_READ, &tm);
            if (ret < 0) {
                printf("ioctl: HI_RTC_ALM_READ failed\n");
                goto err1;
            }
            
            printf("Current alarm value: \n");
        } else {
            printf("unknow options %s\n", argv[2]);
            goto err1;
        }

        printf("year %d\n", tm.year);
        printf("month %d\n", tm.month);
        printf("date %d\n", tm.date);
        printf("hour %d\n", tm.hour);
        printf("minute %d\n", tm.minute);
        printf("second %d\n", tm.second);
        printf("weekday %d\n", tm.weekday);

        tm_time.tm_year        = tm.year - 1900;
        tm_time.tm_mon        = tm.month -1;
        tm_time.tm_mday        = tm.date;
        tm_time.tm_hour        = tm.hour;
        tm_time.tm_min        = tm.minute;
        tm_time.tm_sec        = tm.second;
        tm_time.tm_wday        = tm.weekday;
        
        val_time.tv_sec   = mktime(&tm_time);
        val_time.tv_usec        = 0;
        settimeofday(&val_time,NULL);

        
    } else if (!strcmp(argv[1],"-w")) {

        if (argc < 4) {
            usage();
            goto err1;
        }

        ret = str_to_num(argv[2], &(regv.reg));
        if (ret != 0) {
            printf("reg 0x%08x invalid\n", regv.reg);
            goto err1;
        }

        ret = str_to_num(argv[3], &(regv.val));
        if (ret != 0) {
            printf("val 0x%08x invalid\n", regv.val);
            goto err1;
        }
        
        printf("\n");
        printf("[RTC_REG_SET] reg:%02x, val:%02x\n", regv.reg, regv.val);
        printf("\n");

        ret = ioctl(fd, HI_RTC_REG_SET, &regv);
        if (ret < 0) {
            printf("ioctl: HI_RTC_REG_SET failed\n");
            goto err1;
        }

    } else if (!strcmp(argv[1],"-r")) {

        if (argc < 3) {
            usage();
            goto err1;
        }
        
        ret = str_to_num(argv[2], &(regv.reg));
        if (ret != 0) {
            printf("reg 0x%08x invalid\n", regv.reg);
            goto err1;
        }

        regv.val = 0;

        ret = ioctl(fd, HI_RTC_REG_READ, &regv);
        if (ret < 0) {
            printf("ioctl: HI_RTC_REG_READ failed\n");
            goto err1;
        }

        printf("\n");
        printf("[RTC_REG_GET] reg:0x%02x, val:0x%02x\n", regv.reg, regv.val);
        printf("\n");
    } else if (!strcmp(argv[1],"-a")) {

        if (argc < 3) {
            usage();
            goto err1;
        }

        if (!strcmp(argv[2], "ON")) {
            ret = ioctl(fd, HI_RTC_AIE_ON);
        } else if (!strcmp(argv[2], "OFF")) {
            ret = ioctl(fd, HI_RTC_AIE_OFF);
        }

        if (ret < 0) {
            printf("ioctl: HI_RTC_AIE_ON/OFF failed\n");
            goto err1;
        }

    } else if (!strcmp(argv[1],"-reset")) {

        printf("[RTC_RESET]\n");

        ret = ioctl(fd, HI_RTC_RESET);
        if(ret){
            printf("reset err\n");
            goto err1;
        }
    } else if (!strcmp(argv[1], "-b")) {

        if (argc < 3) {
            usage();
            goto err1;
        }

        if (!strcmp(argv[2], "ON")) {
            //printf("RTC temperature compensation on!\n");
            ret = ioctl(fd, HI_RTC_BM_ON);
        } else if (!strcmp(argv[2], "OFF")) {
            //printf("RTC temperature compensation off!\n");
            ret = ioctl(fd, HI_RTC_BM_OFF);
        }

        if (ret < 0) {
            printf("ioctl: HI_RTC_BM_ON/OFF failed\n");
            goto err1;
        }
    } else if (!strcmp(argv[1], "-f")) {
        
        unsigned int freq;
        rtc_freq_t value;
        
        // print current frequency value
        if (argc  < 3)
        {
            ret = ioctl(fd, HI_RTC_GET_FREQ, &value);
            if (ret < 0)
            {
                printf("get current frequency failed\n");
                goto err1;
            }    
            
            freq = value.freq_l;
            printf("current frequency : %d\n", freq);    
        }    
        // set frequency 
        else if (argc == 3)
        {
            freq = atoi(argv[2]);
            
            if (freq > 3277600 || freq < 3276000)
            {
                printf("invalid freq %d\n", freq);
                goto err1;
            }
        
            value.freq_l = freq;
            
            ret = ioctl(fd, HI_RTC_SET_FREQ, &value);
            if (ret < 0)
            {
                printf("get current frequency failed\n");
                goto err1;
            }
        }

    } else {
        printf("unknown download mode.\n");
        goto err1;
    }

err1:
    close(fd);

    return 0;
}

 

  以上是基於海思SDK中的/drv/rtc中的rtc_test.c修改的,修改的部分如下。(上面代碼已經是修改完的了,下面的代碼是從上面代碼中截取出來的)

 

    struct tm tm_time;
    struct timeval val_time;

//讀取RTC時間,放在結構體變量tm中
        ret = ioctl(fd, HI_RTC_RD_TIME, &tm);

    printf("year %d\n", tm.year);
    printf("month %d\n", tm.month);
    printf("date %d\n", tm.date);
    printf("hour %d\n", tm.hour);
    printf("minute %d\n", tm.minute);
    printf("second %d\n", tm.second);
    printf("weekday %d\n", tm.weekday);

        tm_time.tm_year        = tm.year - 1900;
        tm_time.tm_mon        = tm.month -1;
        tm_time.tm_mday        = tm.date;
        tm_time.tm_hour        = tm.hour;
        tm_time.tm_min        = tm.minute;
        tm_time.tm_sec        = tm.second;
        tm_time.tm_wday        = tm.weekday;
        
        val_time.tv_sec   = mktime(&tm_time);
        val_time.tv_usec        = 0;
        settimeofday(&val_time,NULL);


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM