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);