GadgetSeed  0.9.6
datetime.c
[詳解]
1 /** @file
2  @brief 日付時刻
3 
4  GadgetSeed の時計はカーネルタイマよりカウントされます。
5  システム起動時に最初にRTCデバイスより同期を行います。
6  RTCはUTC時刻が設定されます。
7 
8  @date 2015.09.19
9  @date 2007.05.01
10  @author Takashi SHUDO
11 
12  @page date_time 日付時刻
13 
14  GadgetSeed は日付時刻を取得、設定する機能があります。\n
15  GadgetSeed の日付時刻はカーネルタイマと同期しています。\n
16  RTC(リアルタムクロック)を持つシステムはRTCより取得される日時と同期させるために時計の進行速度が調整されます。
17  これらの機能は datetime.h で定義されています。
18 
19 
20  ---
21  @section system_time_struct システム時間構造体
22 
23  GadgetSeedの日付時刻はシステム時間を元に日付、時刻に変換する機能があります。\n
24  システム時間は以下の構造体で定義されています。
25 
26  @ref st_systime @copybrief st_systime
27 
28  システム時間のフィールド sec は32ビット長のUNIX時間(1970/01/01 00:00:00 からの1秒カウンタ)です。\n
29  システム時間のフィールド usec は32ビット長のナノ秒カウンタです。(0 - 999999)\n
30  システム時間はロケーションに関わらず、UTC時刻を示します。
31 
32 
33  ---
34  @section datetime_struct 時刻構造体
35 
36  時刻情報は時刻を年、月、日、曜日、時、分、秒、ミリ秒で示すデータ構造です。\n
37  時刻情報は以下の構造体で定義されています。
38 
39  @ref st_datetime @copybrief st_datetime
40 
41 
42  ---
43  @section datetime_api 日付時刻API
44 
45  @subsection get_time_api 時間取得API
46 
47  include ファイル : datetime.h
48 
49  | API名 | 機能 |
50  |:--------------------------|:------------------------------|
51  | get_systime() | @copybrief get_systime |
52  | get_systime_sec() | @copybrief get_systime_sec |
53  | fattime() | @copybrief fattime |
54 
55  @subsection time_convert_api システム時間、時刻情報変換API
56 
57  include ファイル : datetime.h
58 
59  | API名 | 機能 |
60  |:--------------------------|:--------------------------------------|
61  | unixtime_to_datetime() | @copybrief unixtime_to_datetime |
62  | systime_to_datetime() | @copybrief systime_to_datetime |
63  | datetime_to_utc() | @copybrief datetime_to_utc |
64  | datetime_to_systime() | @copybrief datetime_to_systime |
65 
66  @subsection time_strings_api 時刻情報文字列変換API
67 
68  include ファイル : datetime.h
69 
70  | API名 | 機能 |
71  |:--------------------------|:------------------------------|
72  | date_to_str() | @copybrief date_to_str |
73  | time_to_str() | @copybrief time_to_str |
74  | mtime_to_str() | @copybrief mtime_to_str |
75  | datetime_to_str() | @copybrief datetime_to_str |
76  | datemtime_to_str() | @copybrief datemtime_to_str |
77 
78  @subsection set_system_time_api システム時間設定API
79 
80  include ファイル : datetime.h
81 
82  | API名 | 機能 |
83  |:--------------------------|:--------------------------------------|
84  | set_systime() | @copybrief set_systime |
85  | sync_systime_from_rtc() | @copybrief sync_systime_from_rtc |
86  | adjust_systime() | @copybrief adjust_systime |
87  | sync_rtc_from_systime() | @copybrief sync_rtc_from_systime |
88 
89  @subsection set_rtc_api RTC制御API
90 
91  include ファイル : datetime.h
92 
93  | API名 | 機能 |
94  |:--------------------------|:----------------------|
95  | set_rtc() | @copybrief set_rtc |
96 
97  @subsection generic_time_api 汎用時間関数
98 
99  include ファイル : datetime.h
100 
101  | API名 | 機能 |
102  |:--------------------------|:--------------------------------------|
103  | date_to_dayofweek() | @copybrief date_to_dayofweek |
104  | is_leap_year() | @copybrief is_leap_year |
105  | num_of_day_in_month() | @copybrief num_of_day_in_month |
106 
107  @subsection periodic_processing_api 周期処理
108 
109  include ファイル : datetime.h
110 
111  | API名 | 機能 |
112  |:--------------------------|:--------------------------------------|
113  | register_sec_timer_func() | @copybrief register_sec_timer_func |
114 */
115 
116 #include "sysconfig.h"
117 #include "datetime.h"
118 #include "timer.h"
119 #include "device.h"
120 #include "device/rtc_ioctl.h"
121 #include "tprintf.h"
122 #include "tkprintf.h"
123 
124 //#define DEBUGKBITS 0x03
125 #include "dkprintf.h"
126 
127 #define DEF_SYSTIME_INC_COUNT (1000 * GSC_KERNEL_TIMER_INTERVAL_MSEC) ///< システム時間カーネルタイマ間隔増加分
128 
129 struct st_systime system_time; /**< システム時間(UNIX時間、UTC)
130  * 1970/01/01 00:00:00 からの1秒カウン
131  * タ(2038年問題非対応)
132  */
133 struct st_systime l_system_time; // 秒更新確認のための前回カーネルタイマ割り込み時のシステム時間
134 
135 #ifdef GSC_DEV_ENABLE_RTC
136 static struct st_device *rtc_dev = 0; ///< RTCデバイス
137 #ifndef GSC_RTC_RESOLUTION_IS_NOT_SEC // $gsc RTCの解像度は秒より精細
138 static struct st_systime last_rtcsystime;
139 #endif
140 #endif
141 static int systime_inc_count = DEF_SYSTIME_INC_COUNT;
142 
143 enum tsync_status {
144  TSYNC_NONE,
145  TSYNC_SYNC,
146  TSYNC_ADJUST
147 }; ///< RTCから日時同期中フラグ
148 
149 static volatile enum tsync_status tsync_status;
150 
151 timer_func sec_timer_func = 0; ///< 1秒間隔処理関数
152 
153 #ifdef GSC_DEV_ENABLE_RTC // $gsc リアルタイムクロックを有効にする
154 /**
155  @brief リアルタイムクロックより時刻を取得する
156 
157  @param[in] time 実時間
158 
159  @return !=0:エラー
160 */
161 int read_rtc_time(struct st_datetime *time)
162 {
163  if(rtc_dev == 0) {
164  SYSERR_PRINT("NO RTC Device.\n");
165  return -1;
166  }
167 
168  if(ioctl_device(rtc_dev, IOCMD_RTC_GET, 0, (void *)time) != 0) {
169  SYSERR_PRINT("Cannot read time from RTC.\n");
170  return -1;
171  }
172 
173  return 0;
174 }
175 #endif
176 
177 #ifdef DEBUGKBITS
178 static void disp_systime(struct st_datetime *rtcdatetime)
179 {
180  char str[DATEMTIME_STR_LEN+1];
181  struct st_datetime sysdatetime;
182 
183  datemtime_to_str(str, rtcdatetime);
184  DKPRINTF(0x01, "RTC : %s\n", str);
185 
186  systime_to_datetime(&sysdatetime, &system_time);
187  datemtime_to_str(str, &sysdatetime);
188  DKPRINTF(0x01, "SYS : %s\n", str);
189 
190  DKPRINTF(0x01, "UTC_COUNT : %ld.%06d\n", system_time.sec, system_time.usec);
191  DKPRINTF(0x01, "Increment : %d\n", systime_inc_count);
192 }
193 #endif
194 
195 #ifdef GSC_DEV_ENABLE_RTC
196 #ifdef GSC_RTC_DATETIME_SYNC_CYCLE
197 #define SYSTIME_ADJUST_MARGIN (1000 * 100) // システム時間補正しない誤差(100ms)
198 
199 #define ABS(x) ((x) < 0 ? -(x) : (x))
200 
201 static void calc_systime_inc_count(struct st_systime *rtcsystime)
202 {
203  unsigned long long system_time_count;
204  unsigned long long rtc_time_count;
205  int rtc_sys_diff_count; // RTCとシステム時間の差分
206  int error_correction = 0;
207 
208  system_time_count = ((unsigned long long)(system_time.sec) * 1000000) + system_time.usec;
209  rtc_time_count = ((unsigned long long)(rtcsystime->sec) * 1000000) + rtcsystime->usec;
210 
211  rtc_sys_diff_count = (int)(rtc_time_count - system_time_count);
212 
213  DKPRINTF(0x01, "RTC_COUNT : %lld\n", rtc_time_count);
214  DKPRINTF(0x01, "SYS_COUNT : %lld\n", system_time_count);
215  DKPRINTF(0x01, "RTC DIFF : %d\n", rtc_sys_diff_count);
216 
217  error_correction = rtc_sys_diff_count / GSC_RTC_DATETIME_SYNC_CYCLE;
218  DKPRINTF(0x01, "Error correction : %d\n", error_correction);
219 
220  // 時間インクリメント値設定
221  if(ABS(rtc_sys_diff_count) <= SYSTIME_ADJUST_MARGIN) {
222  systime_inc_count = DEF_SYSTIME_INC_COUNT + (error_correction * GSC_KERNEL_TIMER_INTERVAL_MSEC);
223  } else {
224  // 誤差が大きい場合は補正を2倍
225  DKPRINTF(0x01, "difference > %d\n", SYSTIME_ADJUST_MARGIN);
226  systime_inc_count = DEF_SYSTIME_INC_COUNT + (error_correction * GSC_KERNEL_TIMER_INTERVAL_MSEC * 2);
227  }
228  DKPRINTF(0x01, "systime_inc_count : %d\n", systime_inc_count);
229 }
230 #endif
231 #endif
232 
233 /**
234  @brief システムタイマ定期処理タイマ関数
235 
236  @param[in] ktime カーネル時間
237 
238  @return !=0:エラー
239 */
240 static void time_count_proc(void *sp, unsigned long long ktime)
241 {
242 #ifdef GSC_DEV_ENABLE_RTC
243  int flg_just_sec = 0;
244 #endif
245 
246  UNUSED_VARIABLE(ktime);
247 
248  system_time.usec += systime_inc_count;
249  if(system_time.usec >= (1000 * 1000)) {
250  system_time.usec -= (1000 * 1000);
251  system_time.sec ++;
252 #ifdef GSC_DEV_ENABLE_RTC
253  flg_just_sec = 1;
254 #endif
255  }
256  //tkprintf("system_time = %12d.%06d\n", system_time.sec, system_time.usec);
257  DKPRINTF(2, "system_time = %12d.%06d\n", system_time.sec, system_time.usec);
258 
259 #ifdef GSC_DEV_ENABLE_RTC
260  switch(tsync_status) {
261  case TSYNC_NONE:
262  break;
263 
264  case TSYNC_SYNC:
265  if(rtc_dev == 0) {
266  DKPRINTF(0x01, "RTC device not found\n");
267  tsync_status = TSYNC_NONE;
268  } else {
269  /*
270  * 分解能が1秒のRTC(殆どがそう)の場合、秒カ
271  * ウンタが変化するまで時刻情報を取得し続ける
272  */
273  struct st_datetime rtcdatetime;
274  struct st_systime rtcsystime = { 0, 0 };
275  DKPRINTF(0x02, "kernel time = %d\n", (int)ktime);
276  if(read_rtc_time(&rtcdatetime) != 0) {
277  SYSERR_PRINT("RTC access fail\n");
278  tsync_status = TSYNC_NONE;
279  } else {
280 #ifdef DEBUGKBITS
281  char str[DATEMTIME_STR_LEN+1];
282  datemtime_to_str(str, &rtcdatetime);
283  DKPRINTF(0x02, "RTC time : %s\n", str);
284 #endif
285  datetime_to_systime(&rtcsystime, &rtcdatetime);
286 #ifdef GSC_RTC_RESOLUTION_IS_NOT_SEC //
287  set_systime(&rtcsystime);
288  tsync_status = TSYNC_NONE;
289 #else // GSC_RTC_RESOLUTION_IS_NOT_SEC
290  if(last_rtcsystime.sec == 0) {
291  // 最初の時刻取得
292  DKPRINTF(0x02, "RTC resolution is sec\n");
293  last_rtcsystime.sec = rtcsystime.sec;
294  last_rtcsystime.usec = rtcsystime.usec;
295  } else {
296  // 秒が変わるまで取得し続ける
297  if(last_rtcsystime.sec != rtcsystime.sec) {
298  set_systime(&rtcsystime);
299  tsync_status = TSYNC_NONE;
300  }
301  }
302 #endif // GSC_RTC_RESOLUTION_IS_NOT_SEC
303 #ifdef DEBUGKBITS
304  if(tsync_status == TSYNC_NONE) {
305  disp_systime(&rtcdatetime);
306  DKPRINTF(0x01, "Time sync done.\n");
307  }
308 #endif
309  }
310  }
311  break;
312 
313 #ifdef GSC_RTC_DATETIME_SYNC_CYCLE
314  case TSYNC_ADJUST:
315  if(rtc_dev == 0) {
316  DKPRINTF(0x01, "RTC device not found\n");
317  tsync_status = TSYNC_NONE;
318  } else {
319  /*
320  分解能が1秒のRTC(殆どがそう)の場合、秒カ
321  ウンタが変化するまで時刻情報を取得し続ける
322  */
323  struct st_datetime rtcdatetime;
324  struct st_systime rtcsystime = { 0, 0 };
325  DKPRINTF(0x02, "kernel time = %d\n", (int)ktime);
326  if(read_rtc_time(&rtcdatetime) != 0) {
327  SYSERR_PRINT("RTC access fail\n");
328  tsync_status = TSYNC_NONE;
329  } else {
330 #ifdef DEBUGKBITS
331  char str[DATEMTIME_STR_LEN+1];
332  datemtime_to_str(str, &rtcdatetime);
333  DKPRINTF(0x02, "RTC time : %s\n", str);
334 #endif
335  datetime_to_systime(&rtcsystime, &rtcdatetime);
336 #ifdef GSC_RTC_RESOLUTION_IS_NOT_SEC //
337  calc_systime_inc_count(&rtcsystime);
338  tsync_status = TSYNC_NONE;
339 #else // GSC_RTC_RESOLUTION_IS_NOT_SEC
340  if(last_rtcsystime.sec == 0) {
341  // 最初の時刻取得
342  DKPRINTF(0x02, "RTC resolution is sec\n");
343  last_rtcsystime.sec = rtcsystime.sec;
344  last_rtcsystime.usec = rtcsystime.usec;
345  } else {
346  // 秒が変わるまで取得し続ける
347  if(last_rtcsystime.sec != rtcsystime.sec) {
348  calc_systime_inc_count(&rtcsystime);
349  tsync_status = TSYNC_NONE;
350  }
351  }
352 #endif // GSC_RTC_RESOLUTION_IS_NOT_SEC
353 #ifdef DEBUGKBITS
354  if(tsync_status == TSYNC_NONE) {
355  disp_systime(&rtcdatetime);
356  DKPRINTF(0x01, "Time adjust done.\n");
357  }
358 #endif
359  }
360  }
361  break;
362 #endif
363 
364  default:
365  SYSERR_PRINT("Invalid status %d\n", tsync_status);
366  break;
367  }
368 #endif // GSC_RTC_DATETIME_SYNC_CYCLE
369 
370 #ifdef GSC_DEV_ENABLE_RTC
371  if(flg_just_sec != 0) {
372  if(sec_timer_func != 0) {
374  }
375  }
376 #endif
377 }
378 
379 static const char weekname[7][10] = {
380  "Sunday", "Monday", "Tuesday", "Wednesday",
381  "Thursday", "Friday", "Saturday"
382 }; ///< 曜日文字列
383 
384 /**
385  @brief 時間を日付文字列に変換する
386 
387  @param[out] str 日付文字列ポインタ
388  @param[in] time 時間
389 */
390 void date_to_str(char *str, struct st_datetime *time)
391 {
392  (void)tsnprintf(str, DATE_STR_LEN, "%4d/%02d/%02d %3s",
393  time->year,
394  time->month,
395  time->day,
396  weekname[(int)time->dayofweek]);
397 }
398 
399 /**
400  @brief 時間を時間文字列に変換する
401 
402  @param[out] str 時間文字列ポインタ
403  @param[in] time 時間
404 */
405 void time_to_str(char *str, struct st_datetime *time)
406 {
407  (void)tsnprintf(str, TIME_STR_LEN, "%02d:%02d:%02d",
408  time->hour,
409  time->min,
410  time->sec);
411 }
412 
413 /**
414  @brief 時間をミリ秒時間文字列に変換する
415 
416  @param[out] str 時間文字列ポインタ
417  @param[in] time 時間
418 */
419 void mtime_to_str(char *str, struct st_datetime *time)
420 {
421  time_to_str(str, time);
422  (void)tsnprintf(&str[TIME_STR_LEN-1], MSEC_STR_LEN, ".%03d", time->msec);
423 }
424 
425 /**
426  @brief 時間を日付時間文字列に変換する
427 
428  @param[out] str 日付時間文字列ポインタ
429  @param[in] time 時間
430 */
431 void datetime_to_str(char *str, struct st_datetime *time)
432 {
433  date_to_str(str, time);
434  str[DATE_STR_LEN-1] = ' ';
435  time_to_str(&str[DATE_STR_LEN], time);
436 }
437 
438 /**
439  @brief 時間を日付ミリ秒時間文字列に変換する
440 
441  @param[out] str 日付時間文字列ポインタ
442  @param[in] time 時間
443 */
444 void datemtime_to_str(char *str, struct st_datetime *time)
445 {
446  date_to_str(str, time);
447  str[DATE_STR_LEN-1] = ' ';
448  mtime_to_str(&str[DATE_STR_LEN], time);
449 }
450 
451 #ifdef GSC_DEV_ENABLE_RTC
452 /*
453  @brief 時計をRTCと同期させる
454 
455  @return !=0:エラー
456 */
457 static int sync_time(void)
458 {
459  DKPRINTF(0x01, "Time synchronization...\n");
460 
461  if(rtc_dev == 0) {
462  SYSERR_PRINT("NO RTC Device.\n");
463  return -1;
464  }
465 
466 #ifndef GSC_RTC_RESOLUTION_IS_NOT_SEC
467  last_rtcsystime.sec = 0;
468  last_rtcsystime.usec = 0;
469 #endif
470  tsync_status = TSYNC_SYNC;
471 
472  while(tsync_status != TSYNC_NONE) {
473 #ifdef GSC_TARGET_SYSTEM_EMU
474  usleep(1000);
475 #endif
476  }
477 
478  DKPRINTF(0x01, "Time sync done.\n");
479 
480  return 0;
481 }
482 
483 /**
484  @brief 時間をリアルタイムクロックに設定する
485 
486  @param[in] time 実時間
487 
488  @return !=0:エラー
489 */
490 int set_rtc(struct st_datetime *time)
491 {
492  if(rtc_dev == 0) {
493  SYSERR_PRINT("NO RTC Device\n");
494  return -1;
495  }
496 
497  if(ioctl_device(rtc_dev, IOCMD_RTC_SET, 0, (void *)time) != 0) {
498  SYSERR_PRINT("Cannot set time to RTC.\n");
499  return -1;
500  }
501 
502  return 0;
503 }
504 #endif
505 
506 /**
507  @brief 時計を初期する
508 
509  時間をリアルタイムクロックより読み出し設定する
510 
511  @param[in] devname RTCデバイス名
512 
513  リアルタイムクロックが無いシステムでは"0"を設定する
514 
515  @return !=0:エラー
516 */
517 int init_time(char *devname)
518 {
519  tsync_status = TSYNC_NONE;
520  l_system_time.sec = 0;
521  l_system_time.usec = 0;
522  system_time.sec = 0; // 1970/01/01 00:00:00
523  system_time.usec = 0;
524 
526  SYSERR_PRINT("Cannot register time func.\n");
527  goto err;
528  }
529 
530 #ifdef GSC_DEV_ENABLE_RTC
531  if(devname == 0) {
532  return -1;
533  }
534 
535  rtc_dev = open_device(devname);
536 
537  if(rtc_dev == 0) {
538  SYSERR_PRINT("Cannot open RTC device.\n");
539  goto err;
540  }
541 
542  if(sync_time()) {
543  goto err;
544  }
545 #endif
546 
547 // time.dayofweek = date_to_dayofweek(time.year, time.month, time.day);
548 
549  return 0;
550 
551  err:
552  return -1;
553 }
554 
555 /*
556  @brief ユリウス日より日時を取得する
557 
558  @param[in] jd ユリウス日時
559  @param[out] year 西暦年
560  @param[out] month 月
561  @param[out] day 日
562 */
563 static void jd2greg(int jd, short *year, char *month, char *day)
564 {
565  int century;
566  int y, m;
567 
568  jd += 32045;
569  century = (4 * jd - 1)/ 146097L;
570  jd -= 146097L * century / 4;
571  y = (4 * jd - 1) / 1461;
572  jd -= 1461L * y / 4;
573  y += 100 * century;
574  m = (5 * jd - 3) / 153 + 3;
575  jd -= (153 * m - 457) / 5;
576  if(m > 12) {
577  m -= 12;
578  y++;
579  }
580  *year = (y - 4800);
581  *month = m;
582  *day = jd;
583 }
584 
585 /**
586  @brief 西暦年、月、日より曜日を求める
587 
588  @param[out] year 西暦年
589  @param[out] month 月
590  @param[out] day 日
591 
592  @return 曜日(0:日曜日、6:土曜日)
593 */
594 char date_to_dayofweek(short year, char month, char day)
595 {
596 #if 0
597  return (year + year/4 - year/100 + year/400
598  + (13 * month + 8)/5 + day) % 7;
599 #else
600  static const int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
601  year -= month < 3;
602  return (year + year/4 - year/100 + year/400 + t[month-1] + day) % 7;
603 #endif
604 }
605 
606 /**
607  @brief うるう年か調べる
608 
609  @param[in] year 西暦年
610 
611  @return 0:うるう年ではない、1:うるう年
612 */
613 int is_leap_year(int year)
614 {
615  if(year < 4) {
616  return 0;
617  } else if(year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
618  return 1;
619  } else {
620  return 0;
621  }
622 }
623 
624 /**
625  @brief うるう月か調べる
626 
627  @param[in] year 西暦年
628  @param[in] month 月
629 
630  @return 日数
631 */
632 int num_of_day_in_month(int year, int month)
633 {
634  int rt = 0;
635 
636  const static int mofd[12] = {
637  31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
638  };
639 
640  if((month > 12) || (month < 1)) {
641  return 0;
642  }
643 
644  rt = mofd[month - 1];
645  if(is_leap_year(year) != 0) {
646  rt += 1;
647  }
648 
649  return rt;
650 }
651 
652 /**
653  @brief UNIX時間より時刻を求める
654 
655  @param[out] datetime 時刻
656  @param[in] unixtime UNIX時間
657 */
658 void unixtime_to_datetime(struct st_datetime *datetime, struct st_systime *unixtime)
659 {
660  t_time sec = unixtime->sec;
661  t_time jday = (sec/((int)24*60*60)) + 2440588; // ユリウス日へ
662 
663  DKPRINTF(0x02, "jday = %d\n", jday);
664 
665  jd2greg(jday, &(datetime->year), &(datetime->month),
666  &(datetime->day));
667 
668  datetime->dayofweek = date_to_dayofweek(datetime->year,
669  datetime->month,
670  datetime->day);
671 
672  datetime->hour = ((sec % (24L*60*60)) / (60*60));
673  datetime->min = ((sec % (60*60)) / 60);
674  datetime->sec = (sec % 60);
675  datetime->msec = unixtime->usec / 1000;
676 }
677 
678 /**
679  @brief システム時間よりローカル時刻を求める
680 
681  @param[out] datetime 時刻(ローカル)
682  @param[in] time システム時間
683 */
684 void systime_to_datetime(struct st_datetime *datetime, struct st_systime *stime)
685 {
686  struct st_systime localtime;
687 
688  localtime.sec = stime->sec + GSC_DIFF_FROM_LOCAL_TIME_SEC;
689  localtime.usec = stime->usec;
690 
691  unixtime_to_datetime(datetime, &localtime);
692 }
693 
694 /**
695  @brief ローカル西暦年月日、時間よりUTCを求める
696 
697  UTC 1970/01/01 00:00:00 が 0 になる
698  JST 1970/01/01 09:00:00 が 0 になる
699 
700  @param[in] datetime 西暦年月日、時間
701 
702  @return UTC時間
703 */
704 t_time datetime_to_utc(struct st_datetime *datetime)
705 {
706  int year = datetime->year;
707  int month = datetime->month;
708  t_time utc;
709 
710  if((month -= 2) < 1) {
711  year --;
712  month += 12;
713  }
714 
715  utc = (year/4 - year/100 + year/400
716  + 367L*month/12 + datetime->day) + year*365 - 719499L;
717 
718  DKPRINTF(0x02, "day = %d\n", utc);
719 
720  utc *= ((int)24*60*60);
721  utc += ((int)(datetime->hour)*(60*60) + datetime->min*60 + datetime->sec);
722 
724 
725  return utc;
726 }
727 
728 /**
729  @brief ローカル西暦年月日、時間よりシステム時間を求める
730 
731  1970/01/01 00:00:00 が 0 になる
732 
733  @param[out] systime システム時間
734  @param[in] datetime 西暦年月日、時間
735 */
736 void datetime_to_systime(struct st_systime *systime, struct st_datetime *datetime)
737 {
738  systime->sec = datetime_to_utc(datetime) + GSC_DIFF_FROM_LOCAL_TIME_SEC;
739  systime->usec = datetime->msec * 1000;
740 }
741 
742 /**
743  @brief UTC時刻からシステム時間を設定する
744 
745  @param[in] systime UTC時刻
746 */
747 void set_systime(struct st_systime *systime)
748 {
749  // [TODO] タイマ割り込みでも更新しているので排他的な処理が必要
750  system_time.sec = systime->sec;
751  system_time.usec = systime->usec;
752 
753 #ifdef GSC_DEV_ENABLE_RTC
754  sync_rtc_from_systime();
755 #endif
756 
757  (void)eprintf("Set RTC Time = %d.%03d\n", (int)systime->sec, (int)systime->usec/1000);
758 }
759 
760 /**
761  @brief システム時間(秒)を取得する
762 
763  @return 現在UTC時刻
764 */
765 t_time get_systime_sec(void)
766 {
767  return (volatile int)system_time.sec;
768 }
769 
770 /**
771  @brief FAT 現在実時間を取得する
772 
773  @return FAT 現在実時間
774 */
775 unsigned int fattime(void)
776 {
777  struct st_systime systime;
778  struct st_datetime time;
779 
780  get_systime(&systime);
781  systime_to_datetime(&time, &systime);
782 
783  if(time.year < 1980) {
784  time.year = 1980;
785  }
786 
787  return ((unsigned int)(time.year-1980) << 25) +
788  ((unsigned int)(time.month) << 21) +
789  ((unsigned int)(time.day) << 16) +
790  ((unsigned int)(time.hour) << 11) +
791  ((unsigned int)(time.min) << 5) +
792  ((unsigned int)(time.sec) / 2);
793 }
794 
795 /**
796  @brief システム時間を取得する
797 
798  @param[out] システム時間
799 
800  @return エラーコード
801 */
802 void get_systime(struct st_systime *systime)
803 {
804  int usec, usec2;
805 
806  systime->sec = system_time.sec;
807  usec = system_time.usec;
808  usec2 = system_time.usec;
809  if(usec2 < usec) {
810  systime->sec = system_time.sec;
811  }
812  systime->usec = system_time.usec;
813 }
814 
815 /**
816  @brief 時刻秒更新に同期した1秒周期処理を登録する
817 
818  @param[in] func 1秒周期処理関数
819 */
821 {
822  sec_timer_func = func;
823 }
824 
825 #ifdef GSC_DEV_ENABLE_RTC
826 /**
827  @brief RTC時刻からシステム時間を設定する
828 */
829 void sync_systime_from_rtc(void)
830 {
831  (void)sync_time();
832 }
833 
834 #ifdef GSC_RTC_DATETIME_SYNC_CYCLE
835 /**
836  @brief RTC時刻からシステム時間の増加値を調整する
837 */
838 void adjust_systime(void)
839 {
840 #ifndef GSC_RTC_RESOLUTION_IS_NOT_SEC
841  last_rtcsystime.sec = 0;
842  last_rtcsystime.usec = 0;
843 #endif
844  tsync_status = TSYNC_ADJUST;
845 }
846 #endif
847 
848 /**
849  @brief システム時間からRTC時刻を設定する
850 */
851 void sync_rtc_from_systime(void)
852 {
853  struct st_systime systime;
854  struct st_datetime datetime;
855 
856  get_systime(&systime);
857  unixtime_to_datetime(&datetime, &systime);
858  (void)set_rtc(&datetime);
859 }
860 #endif
int init_time(char *devname)
時計を初期する
Definition: datetime.c:517
時刻構造体
Definition: datetime.h:29
void datetime_to_str(char *str, struct st_datetime *time)
時間を日付時間文字列に変換する
Definition: datetime.c:431
RTCドライバ ioctl 用マクロ定義
short msec
ミリ秒
Definition: datetime.h:37
char hour
Definition: datetime.h:34
static void time_count_proc(void *sp, unsigned long long ktime)
システムタイマ定期処理タイマ関数
Definition: datetime.c:240
システム時間
Definition: datetime.h:40
int usec
マイクロ秒(0〜999999)
Definition: datetime.h:42
void register_sec_timer_func(timer_func func)
時刻秒更新に同期した1秒周期処理を登録する
Definition: datetime.c:820
struct st_device * open_device(char *name)
デバイスをオープンする
Definition: device.c:262
void datemtime_to_str(char *str, struct st_datetime *time)
時間を日付ミリ秒時間文字列に変換する
Definition: datetime.c:444
void datetime_to_systime(struct st_systime *systime, struct st_datetime *datetime)
ローカル西暦年月日、時間よりシステム時間を求める
Definition: datetime.c:736
char min
Definition: datetime.h:35
#define IOCMD_RTC_GET
時刻を取得する
Definition: rtc_ioctl.h:18
int is_leap_year(int year)
うるう年か調べる
Definition: datetime.c:613
char month
Definition: datetime.h:31
char date_to_dayofweek(short year, char month, char day)
西暦年、月、日より曜日を求める
Definition: datetime.c:594
int register_timer_func(timer_func func, unsigned long interval)
周期処理を追加する
Definition: timer.c:274
カーネルタイマ
char sec
Definition: datetime.h:36
日付時刻
void time_to_str(char *str, struct st_datetime *time)
時間を時間文字列に変換する
Definition: datetime.c:405
#define GSC_KERNEL_TIMER_INTERVAL_MSEC
$gsc カーネルタイマ割り込み間隔(ms)
Definition: timer.h:14
t_time sec
Definition: datetime.h:41
カーネル用機能限定printf
t_time get_systime_sec(void)
システム時間(秒)を取得する
Definition: datetime.c:765
void mtime_to_str(char *str, struct st_datetime *time)
時間をミリ秒時間文字列に変換する
Definition: datetime.c:419
void unixtime_to_datetime(struct st_datetime *datetime, struct st_systime *unixtime)
UNIX時間より時刻を求める
Definition: datetime.c:658
#define IOCMD_RTC_SET
時刻を設定する
Definition: rtc_ioctl.h:17
void date_to_str(char *str, struct st_datetime *time)
時間を日付文字列に変換する
Definition: datetime.c:390
unsigned long long kernel_time_count
カーネル時間(ms)
Definition: timer.c:70
unsigned int fattime(void)
FAT 現在実時間を取得する
Definition: datetime.c:775
char day
Definition: datetime.h:32
int eprintf(const char *fmt,...)
エラー出力用簡易printf
Definition: tprintf.c:104
void set_systime(struct st_systime *systime)
UTC時刻からシステム時間を設定する
Definition: datetime.c:747
void get_systime(struct st_systime *systime)
システム時間を取得する
Definition: datetime.c:802
static const char weekname[7][10]
曜日文字列
Definition: datetime.c:379
void systime_to_datetime(struct st_datetime *datetime, struct st_systime *stime)
システム時間よりローカル時刻を求める
Definition: datetime.c:684
char dayofweek
曜日 0:日曜日〜6:土曜日
Definition: datetime.h:33
#define GSC_DIFF_FROM_LOCAL_TIME_SEC
$gsc UTCと日本時間(+9時間)との時差(秒)
Definition: datetime.h:18
void(* timer_func)(void *sp, unsigned long long systime)
カーネルタイマ周期処理関数の型
Definition: timer.h:19
struct st_systime system_time
Definition: datetime.c:129
デバイスドライバAPI
デバイスドライバ構造体
Definition: device.h:25
t_time datetime_to_utc(struct st_datetime *datetime)
ローカル西暦年月日、時間よりUTCを求める
Definition: datetime.c:704
カーネル、ドライバ(非タスク)デバッグ用マクロ
int ioctl_device(struct st_device *dev, unsigned int com, unsigned int arg, void *param)
デバイスを制御する
Definition: device.c:525
timer_func sec_timer_func
1秒間隔処理関数
Definition: datetime.c:151
#define DEF_SYSTIME_INC_COUNT
システム時間カーネルタイマ間隔増加分
Definition: datetime.c:127
機能限定printf
short year
Definition: datetime.h:30
int tsnprintf(char *str, unsigned int size, const char *fmt,...)
簡易snprintf
Definition: tprintf.c:60
int num_of_day_in_month(int year, int month)
うるう月か調べる
Definition: datetime.c:632