《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, ®v); 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, ®v); 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);