GadgetSeed  0.9.6
timer.c
[詳解]
1 /** @file
2  @brief カーネルタイマ
3 
4  GadgetSeed のカーネルタイマは KERNEL_TIMER_INTERVAL_MSEC(ms) 周期
5  処理タイマデバイスを使用します。
6 
7  @date 2007.03.18
8  @author Takashi SHUDO
9 
10  @page kernel_timer カーネルタイマ
11 
12  GadgetSeedのカーネルタイマはシステム起動からの経過時間をミリ秒単位で示す64ビット長カウンタです。
13 
14  カーネルタイマに同期した周期処理関数を登録または登録解除することが出来ます。\n
15  周期処理関数は非タスクコンテキストで実行されます。
16 
17 
18  ---
19  @section kernel_timer_api カーネルタイマAPI
20 
21  カーネルタイマに関する以下のAPIがあります。\n
22  これらは timer.h で定義されています。
23 
24  include ファイル : timer.h
25 
26  | API名 | 機能 |
27  |:--------------------------|:--------------------------------------|
28  | get_kernel_time() | @copybrief get_kernel_time |
29  | register_timer_func() | @copybrief register_timer_func |
30  | unregister_timer_func() | @copybrief unregister_timer_func |
31 
32 
33  ---
34  @section system_time システムタイム
35 
36  GadgetSeedは @ref kernel_timer とは別にシステムタイム値を取得する機能があります。
37 
38  システムタイムはus(マイクロ秒)の精度を持つ64ビット長のカウンタです。\n
39  システムタイムはカーネルタイマデバイスより取得します。\n
40  そのためシステムタイム値はカーネルタイマデバイスが持つ必要があります。
41 
42  システムタイム取得のためのデバイスドライバAPIは[TBD]参照。
43 
44  @subsection system_time_api システムタイムAPI
45 
46  include ファイル : timer.h
47 
48  | API名 | 機能 |
49  |:--------------------------|:------------------------------|
50  | get_system_utime() | @copybrief get_system_utime |
51 
52  システムタイムはカーネルタイマより分解能が高いカウンタです。\n
53  但し取得するためのAPI(@ref get_system_utime)はカーネルタイマデバイスにアクセスするために取得の処理時間は長くなります。\n
54  分解能が必要でない場合、@ref get_kernel_time を使うことを推奨します。
55 */
56 
57 #include "sysconfig.h"
58 #include "timer.h"
59 #include "device/timer_ioctl.h"
60 #include "datetime.h"
61 #include "tkprintf.h"
62 
63 //#define DEBUGKBITS 0x01
64 #include "dkprintf.h"
65 
66 #ifndef GSC_KERNEL_MAX_KERNEL_TIMER_FUNC
67 #define GSC_KERNEL_MAX_KERNEL_TIMER_FUNC 8 ///< $gsc カーネルタイマに登録できる最大定期処理関数数
68 #endif
69 
70 unsigned long long kernel_time_count; ///< カーネル時間(ms)
71 
72 static struct st_device *timer_dev; ///< カーネルタイマデバイス
73 static unsigned char flg_exec_func; ///< タイマ関数実行フラグ
74 static timer_func timer_func_list[GSC_KERNEL_MAX_KERNEL_TIMER_FUNC]; ///< タイマ関数リスト
75 static unsigned long func_interval[GSC_KERNEL_MAX_KERNEL_TIMER_FUNC]; ///< タイマ関数実行間隔
76 static unsigned long func_timecnt[GSC_KERNEL_MAX_KERNEL_TIMER_FUNC]; ///< タイマ関数タイマ
77 static timer_func kernel_timer_func = 0;
78 
79 /**
80  @brief タイマ関数の周期実行を開始する
81 
82  @return !=0:エラー
83 */
84 void start_timer_func(void)
85 {
86  flg_exec_func = 1;
87 }
88 
89 /**
90  @brief タイマ関数の周期実行を停止する
91 
92  @return !=0:エラー
93 */
94 void stop_timer_func(void)
95 {
96  flg_exec_func = 0;
97 }
98 
99 /*
100  @brief カーネルタイマ定期処理
101 
102  @param[in] sp 割り込み時スタックポインタ
103 */
104 static volatile int flg_timer_count = 1;
105 
106 static void kernel_timer(void *sp)
107 {
108  int i;
109 
110  if(flg_timer_count != 0) {
111  flg_timer_count = 0;
112  }
113 
115 
116  if(flg_exec_func == 0) {
117  return;
118  }
119 
120  for(i=0; i<GSC_KERNEL_MAX_KERNEL_TIMER_FUNC; i++) {
121  if(timer_func_list[i]) {
123  if(func_timecnt[i] >= func_interval[i]) {
124  //func_timecnt[i] = 0;
125  func_timecnt[i] -= func_interval[i];
127  }
128  }
129  }
130 
131  if(kernel_timer_func != 0) {
132  kernel_timer_func(sp, kernel_time_count);
133  }
134 }
135 
136 /**
137  @brief カーネルタイマを初期化する
138 
139  @param[in] devname カーネルタイマデバイス名
140 */
141 
142 static int int_count = 0;
143 
144 void init_timer(char *devname)
145 {
146  int i;
147  kernel_time_count = 0;
148 
149  stop_timer_func();
150 
151  for(i=0; i<GSC_KERNEL_MAX_KERNEL_TIMER_FUNC; i++) {
152  timer_func_list[i] = 0;
153  }
154  kernel_timer_func = 0;
155 
156  timer_dev = open_device(devname);
157 
158  if(timer_dev == 0) {
159  SYSERR_PRINT("Cannot open timer device.\n");
160  goto err;
161  }
162 
163  if(ioctl_device(timer_dev, IOCMD_TIMER_SETFUNC, 0, (void *)kernel_timer)) {
164  SYSERR_PRINT("Cannot register timer function.\n");
165  goto err;
166  }
167 
168  if(ioctl_device(timer_dev, IOCMD_TIMER_START, 0, 0)) {
169  SYSERR_PRINT("Cannot start system timer.\n");
170  goto err;
171  }
172 
173 #ifndef GSC_TARGET_SYSTEM_EMU
174  while(flg_timer_count) {
175  int_count ++;
176  }
177 #else
178  int_count = 1000000; // [TODO] 適当な値
179 #endif
180 
181  DKPRINTF(0x01, "%d ms count = %d\n", GSC_KERNEL_TIMER_INTERVAL_MSEC, int_count);
182 
183 err:
184  return;
185 }
186 
187 /**
188  @brief カーネル時間を取得する
189 
190  @return カーネル時間(msec)
191 */
192 unsigned long long get_kernel_time(void)
193 {
194  return kernel_time_count + ioctl_device(timer_dev, IOCMD_TIMER_GETTIME, 0, 0);
195 }
196 
197 /**
198  @brief システム時間を取得する
199 
200  @return システム時間(usec)
201 */
202 unsigned long long get_system_utime(void)
203 {
204  unsigned long long utime;
205 
206  ioctl_device(timer_dev, IOCMD_TIMER_GETSYSTIME, 0, (void *)&utime);
207 
208  return utime;
209 }
210 
211 /**
212  @brief 指定時間待つ
213 
214  @param[in] time 待ち時間(msec)
215 */
216 void wait_time(unsigned int time)
217 {
218  volatile unsigned long long t, nt;
219 
220  if(time == 0) {
221  // 0なら即終了
222  return;
223  } else {
224  // 最低 time 分はカウントするため +1
225  nt = get_kernel_time() + time + 1;
226  }
227 
228  while(1) {
229  t = get_kernel_time();
230  if(t < nt) {
231  DKPRINTF(0x02, "kernel_time = %d\n", get_kernel_time());
232  } else {
233  break;
234  }
235  }
236 }
237 
238 /**
239  @brief 指定時間待つ
240 
241  @param[in] time 待ち時間(usec)
242 */
243 void wait_utime(unsigned int time)
244 {
245  volatile unsigned int i, count;
246 
247  count = (time * int_count) / GSC_KERNEL_TIMER_INTERVAL_MSEC / 1000;
248 
249  DKFPRINTF(0x01, "timr = %d, count = %d\n", count);
250 
251  for(i=0; i<count; i++) {
252  ;
253  }
254 }
255 
256 /**
257  @brief カーネル周期処理を追加する
258 
259  @param[in] func 周期処理関数
260 */
262 {
263  kernel_timer_func = func;
264 }
265 
266 /**
267  @brief 周期処理を追加する
268 
269  @param[in] func 周期処理関数
270  @param[in] interval 周期処理実行周期(msec)
271 
272  @return !=0:エラー
273 */
274 int register_timer_func(timer_func func, unsigned long interval)
275 {
276  int i;
277 
278  for(i=0; i<GSC_KERNEL_MAX_KERNEL_TIMER_FUNC; i++) {
279  if(timer_func_list[i] == 0) {
280  timer_func_list[i] = func;
281  func_interval[i] = interval;
282  func_timecnt[i] = 0;
284  return 0;
285  }
286  }
287 
288  SYSERR_PRINT("Cannot register timer func (over GSC_KERNEL_MAX_KERNEL_TIMER_FUNC).\n");
289 
290  return -1;
291 }
292 
293 /**
294  @brief 周期処理を削除する
295 
296  @param[in] func 周期処理関数
297 
298  @return !=0:エラー
299 */
301 {
302  int i;
303 
304  for(i=0; i<GSC_KERNEL_MAX_KERNEL_TIMER_FUNC; i++) {
305  if(timer_func_list[i] == func) {
306  timer_func_list[i] = 0;
307  return 0;
308  }
309  }
310 
311  SYSERR_PRINT("Cannot unregister timer func.\n");
312 
313  return -1;
314 }
315 
316 /**
317  @brief タイマを開始する
318 
319  @return !=0:エラー
320 */
321 int start_timer(void)
322 {
323  int rt;
324 
325  rt = ioctl_device(timer_dev, IOCMD_TIMER_START, 0, 0);
326 
327  if(rt != 0) {
328  return rt;
329  }
330 
331 #ifdef DEV_ENABLE_RTC
332  rt = sync_time();
333 #endif
334  return rt;
335 }
336 
337 /**
338  @brief タイマを停止する
339 
340  @return !=0:エラー
341 */
342 int stop_timer(void)
343 {
344  return ioctl_device(timer_dev, IOCMD_TIMER_STOP, 0, 0);
345 }
unsigned long long get_system_utime(void)
システム時間を取得する
Definition: timer.c:202
#define IOCMD_TIMER_GETSYSTIME
タイマの値を取得する(usec)
Definition: timer_ioctl.h:21
int start_timer(void)
タイマを開始する
Definition: timer.c:321
static unsigned long func_interval[GSC_KERNEL_MAX_KERNEL_TIMER_FUNC]
タイマ関数実行間隔
Definition: timer.c:75
struct st_device * open_device(char *name)
デバイスをオープンする
Definition: device.c:262
static unsigned long func_timecnt[GSC_KERNEL_MAX_KERNEL_TIMER_FUNC]
タイマ関数タイマ
Definition: timer.c:76
#define IOCMD_TIMER_SETFUNC
タイマの割り込みハンドラ処理を登録する
Definition: timer_ioctl.h:18
#define IOCMD_TIMER_STOP
タイマのカウントを停止する
Definition: timer_ioctl.h:20
カーネルタイマ
日付時刻
static int int_count
カーネルタイマを初期化する
Definition: timer.c:142
#define GSC_KERNEL_TIMER_INTERVAL_MSEC
$gsc カーネルタイマ割り込み間隔(ms)
Definition: timer.h:14
void wait_time(unsigned int time)
指定時間待つ
Definition: timer.c:216
static struct st_device * timer_dev
カーネルタイマデバイス
Definition: timer.c:72
カーネル用機能限定printf
int register_timer_func(timer_func func, unsigned long interval)
周期処理を追加する
Definition: timer.c:274
unsigned long long kernel_time_count
カーネル時間(ms)
Definition: timer.c:70
void register_kernel_timer_func(timer_func func)
カーネル周期処理を追加する
Definition: timer.c:261
int unregister_timer_func(timer_func func)
周期処理を削除する
Definition: timer.c:300
void wait_utime(unsigned int time)
指定時間待つ
Definition: timer.c:243
#define IOCMD_TIMER_GETTIME
タイマの値を取得する(msec)
Definition: timer_ioctl.h:17
unsigned long long get_kernel_time(void)
カーネル時間を取得する
Definition: timer.c:192
void(* timer_func)(void *sp, unsigned long long systime)
カーネルタイマ周期処理関数の型
Definition: timer.h:19
#define IOCMD_TIMER_START
タイマのカウントを開始する
Definition: timer_ioctl.h:19
int stop_timer(void)
タイマを停止する
Definition: timer.c:342
#define GSC_KERNEL_MAX_KERNEL_TIMER_FUNC
$gsc カーネルタイマに登録できる最大定期処理関数数
Definition: timer.c:67
デバイスドライバ構造体
Definition: device.h:25
static timer_func timer_func_list[GSC_KERNEL_MAX_KERNEL_TIMER_FUNC]
タイマ関数リスト
Definition: timer.c:74
カーネル、ドライバ(非タスク)デバッグ用マクロ
void stop_timer_func(void)
タイマ関数の周期実行を停止する
Definition: timer.c:94
int ioctl_device(struct st_device *dev, unsigned int com, unsigned int arg, void *param)
デバイスを制御する
Definition: device.c:525
void start_timer_func(void)
タイマ関数の周期実行を開始する
Definition: timer.c:84
static unsigned char flg_exec_func
タイマ関数実行フラグ
Definition: timer.c:73
タイマドライバ ioctl 用マクロ定義