source: rtos_arduino/trunk/asp_1.9.2/kernel/time_event.c@ 136

Last change on this file since 136 was 136, checked in by ertl-honda, 8 years ago

ライブラリとOS及びベーシックなサンプルの追加.

File size: 11.6 KB
Line 
1/*
2 * TOPPERS/ASP Kernel
3 * Toyohashi Open Platform for Embedded Real-Time Systems/
4 * Advanced Standard Profile Kernel
5 *
6 * Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
7 * Toyohashi Univ. of Technology, JAPAN
8 * Copyright (C) 2005-2013 by Embedded and Real-Time Systems Laboratory
9 * Graduate School of Information Science, Nagoya Univ., JAPAN
10 *
11 * 上記著作権者
12は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
13 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
14 * 変・再é…
15å¸ƒï¼ˆä»¥ä¸‹ï¼Œåˆ©ç”¨ã¨å‘¼ã¶ï¼‰ã™ã‚‹ã“とを無償で許諾する.
16 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
17 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
18 * スコード中に含まれていること.
19 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
20 * 用できる形で再é…
21å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
22å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
23 * 者
24マニュアルなど)に,上記の著作権表示,この利用条件および下記
25 * の無保証規定を掲載すること.
26 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
27 * 用できない形で再é…
28å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®ã„ずれかの条件を満たすこ
29 * と.
30 * (a) 再é…
31å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
32マニュアルなど)に,上記の著
33 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
34 * (b) 再é…
35å¸ƒã®å½¢æ…
36‹ã‚’,別に定める方法によって,TOPPERSプロジェクトに
37 * 報告すること.
38 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
39 * 害からも,上記著作権者
40およびTOPPERSプロジェクトをå…
41è²¬ã™ã‚‹ã“と.
42 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
43 * 由に基づく請求からも,上記著作権者
44およびTOPPERSプロジェクトを
45 * å…
46è²¬ã™ã‚‹ã“と.
47 *
48 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者
49お
50 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
51 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
52 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
53 * の責任を負わない.
54 *
55 * $Id: time_event.c 2559 2013-10-19 06:53:19Z ertl-hiro $
56 */
57
58/*
59 * タイムイベント管理モジュール
60 */
61
62#include "kernel_impl.h"
63#include "time_event.h"
64
65/*
66 * タイムイベントヒープ操作マクロ
67 */
68#define PARENT(index) ((index) >> 1) /* 親ノードを求める */
69#define LCHILD(index) ((index) << 1) /* 左の子ノードを求める */
70#define TMEVT_NODE(index) (tmevt_heap[(index) - 1])
71
72/*
73 * イベント発生時刻比較マクロ
74 *
75 * イベント発生時刻は,min_timeからの相対値で比較する.すなわち,
76 * min_timeを最小値(最も近い時刻),mit_time-1が最大値(最も遠い時刻)
77 * とみなして比較する.
78 */
79#define EVTTIM_LT(t1, t2) (((t1) - min_time) < ((t2) - min_time))
80#define EVTTIM_LE(t1, t2) (((t1) - min_time) <= ((t2) - min_time))
81
82#ifdef TOPPERS_tmeini
83
84/*
85 * 現在のシステム時刻(単位: 1ミリ秒)
86 *
87 * 厳密には,前のタイムティックのシステム時刻.
88 */
89EVTTIM current_time;
90
91/*
92 * タイムイベントヒープ中で有効な最小のシステム時刻(単位: 1ミリ秒)
93 */
94EVTTIM min_time;
95
96/*
97 * 次のタイムティックのシステム時刻(単位: 1ミリ秒)
98 */
99EVTTIM next_time;
100
101/*
102 * システム時刻積算用変数(単位: 1/TIC_DENOミリ秒)
103 */
104#if TIC_DENO != 1U
105uint_t next_subtime;
106#endif /* TIC_DENO != 1U */
107
108/*
109 * タイムイベントヒープの最後の使用領域のインデックス
110 */
111uint_t last_index;
112
113/*
114 * タイマモジュールの初期化
115 */
116void
117initialize_tmevt(void)
118{
119 current_time = 0U;
120 min_time = 0U;
121 next_time = current_time + TIC_NUME / TIC_DENO;
122#if TIC_DENO != 1U
123 next_subtime = TIC_NUME % TIC_DENO;
124#endif /* TIC_DENO != 1U */
125 last_index = 0U;
126}
127
128#endif /* TOPPERS_tmeini */
129
130/*
131 * タイムイベントの挿å…
132¥ä½ç½®ã‚’上向きに探索
133 *
134 * 時刻timeに発生するタイムイベントを挿å…
135¥ã™ã‚‹ãƒŽãƒ¼ãƒ‰ã‚’空けるために,
136 * ヒープの上に向かって空ノードを移動させる.移動前の空ノードの位置を
137 * indexに渡すと,移動後の空ノードの位置(すなわち挿å…
138¥ä½ç½®ï¼‰ã‚’返す.
139 */
140#ifdef TOPPERS_tmeup
141
142uint_t
143tmevt_up(uint_t index, EVTTIM time)
144{
145 uint_t parent;
146
147 while (index > 1) {
148 /*
149 * 親ノードのイベント発生時刻の方が早い(または同じ)ならば,
150 * indexが挿å…
151¥ä½ç½®ãªã®ã§ãƒ«ãƒ¼ãƒ—を抜ける.
152 */
153 parent = PARENT(index);
154 if (EVTTIM_LE(TMEVT_NODE(parent).time, time)) {
155 break;
156 }
157
158 /*
159 * 親ノードをindexの位置に移動させる.
160 */
161 TMEVT_NODE(index) = TMEVT_NODE(parent);
162 TMEVT_NODE(index).p_tmevtb->index = index;
163
164 /*
165 * indexを親ノードの位置に更新.
166 */
167 index = parent;
168 }
169 return(index);
170}
171
172#endif /* TOPPERS_tmeup */
173
174/*
175 * タイムイベントの挿å…
176¥ä½ç½®ã‚’下向きに探索
177 *
178 * 時刻timeに発生するタイムイベントを挿å…
179¥ã™ã‚‹ãƒŽãƒ¼ãƒ‰ã‚’空けるために,
180 * ヒープの下に向かって空ノードを移動させる.移動前の空ノードの位置を
181 * indexに渡すと,移動後の空ノードの位置(すなわち挿å…
182¥ä½ç½®ï¼‰ã‚’返す.
183 */
184#ifdef TOPPERS_tmedown
185
186uint_t
187tmevt_down(uint_t index, EVTTIM time)
188{
189 uint_t child;
190
191 while ((child = LCHILD(index)) <= last_index) {
192 /*
193 * 左右の子ノードのイベント発生時刻を比較し,早い方の子ノード
194 * の位置をchildに設定する.以下の子ノードは,ここで選ばれた方
195 * の子ノードのこと.
196 */
197 if (child + 1 <= last_index
198 && EVTTIM_LT(TMEVT_NODE(child + 1).time,
199 TMEVT_NODE(child).time)) {
200 child = child + 1;
201 }
202
203 /*
204 * 子ノードのイベント発生時刻の方が遅
205い(または同じ)ならば,
206 * indexが挿å…
207¥ä½ç½®ãªã®ã§ãƒ«ãƒ¼ãƒ—を抜ける.
208 */
209 if (EVTTIM_LE(time, TMEVT_NODE(child).time)) {
210 break;
211 }
212
213 /*
214 * 子ノードをindexの位置に移動させる.
215 */
216 TMEVT_NODE(index) = TMEVT_NODE(child);
217 TMEVT_NODE(index).p_tmevtb->index = index;
218
219 /*
220 * indexを子ノードの位置に更新.
221 */
222 index = child;
223 }
224 return(index);
225}
226
227#endif /* TOPPERS_tmedown */
228
229/*
230 * タイムイベントヒープへの登録
231 *
232 * p_tmevtbで指定したタイムイベントブロックを,timeで指定した時間が経
233 * 過後にイベントが発生するように,タイムイベントヒープに登録する.
234 */
235#ifdef TOPPERS_tmeins
236
237void
238tmevtb_insert(TMEVTB *p_tmevtb, EVTTIM time)
239{
240 uint_t index;
241
242 /*
243 * last_indexをインクリメントし,そこから上に挿å…
244¥ä½ç½®ã‚’探す.
245 */
246 index = tmevt_up(++last_index, time);
247
248 /*
249 * タイムイベントをindexの位置に挿å…
250¥ã™ã‚‹ï¼Ž
251 */
252 TMEVT_NODE(index).time = time;
253 TMEVT_NODE(index).p_tmevtb = p_tmevtb;
254 p_tmevtb->index = index;
255}
256
257#endif /* TOPPERS_tmeins */
258
259/*
260 * タイムイベントヒープからの削除
261 */
262#ifdef TOPPERS_tmedel
263
264void
265tmevtb_delete(TMEVTB *p_tmevtb)
266{
267 uint_t index = p_tmevtb->index;
268 uint_t parent;
269 EVTTIM event_time = TMEVT_NODE(last_index).time;
270
271 /*
272 * 削除によりタイムイベントヒープが空になる場合は何もしない.
273 */
274 if (--last_index == 0) {
275 return;
276 }
277
278 /*
279 * 削除したノードの位置に最後のノード(last_index+1の位置のノード)
280 * を挿å…
281¥ã—,それを適切な位置へ移動させる.実際には,最後のノード
282 * を実際に挿å…
283¥ã™ã‚‹ã®ã§ã¯ãªãï¼Œå‰Šé™¤ã—たノードの位置が空ノードにな
284 * るので,最後のノードを挿å…
285¥ã™ã¹ãä½ç½®ã¸å‘けて空ノードを移動させ
286 * る.
287 * 最後のノードのイベント発生時刻が,削除したノードの親ノードのイ
288 * ベント発生時刻より前の場合には,上に向かって挿å…
289¥ä½ç½®ã‚’探す.そ
290 * うでない場合には,下に向かって探す.
291 */
292 if (index > 1 && EVTTIM_LT(event_time,
293 TMEVT_NODE(parent = PARENT(index)).time)) {
294 /*
295 * 親ノードをindexの位置に移動させる.
296 */
297 TMEVT_NODE(index) = TMEVT_NODE(parent);
298 TMEVT_NODE(index).p_tmevtb->index = index;
299
300 /*
301 * 削除したノードの親ノードから上に向かって挿å…
302¥ä½ç½®ã‚’探す.
303 */
304 index = tmevt_up(parent, event_time);
305 }
306 else {
307 /*
308 * 削除したノードから下に向かって挿å…
309¥ä½ç½®ã‚’探す.
310 */
311 index = tmevt_down(index, event_time);
312 }
313
314 /*
315 * 最後のノードをindexの位置に挿å…
316¥ã™ã‚‹ï¼Ž
317 */
318 TMEVT_NODE(index) = TMEVT_NODE(last_index + 1);
319 TMEVT_NODE(index).p_tmevtb->index = index;
320}
321
322#endif /* TOPPERS_tmedel */
323
324/*
325 * タイムイベントヒープのå…
326ˆé ­ã®ãƒŽãƒ¼ãƒ‰ã®å‰Šé™¤
327 */
328Inline void
329tmevtb_delete_top(void)
330{
331 uint_t index;
332 EVTTIM event_time = TMEVT_NODE(last_index).time;
333
334 /*
335 * 削除によりタイムイベントヒープが空になる場合は何もしない.
336 */
337 if (--last_index == 0) {
338 return;
339 }
340
341 /*
342 * ルートノードに最後のノード(last_index + 1 の位置のノード)を
343 * 挿å…
344¥ã—,それを適切な位置へ移動させる.実際には,最後のノードを
345 * 実際に挿å…
346¥ã™ã‚‹ã®ã§ã¯ãªãï¼Œãƒ«ãƒ¼ãƒˆãƒŽãƒ¼ãƒ‰ãŒç©ºãƒŽãƒ¼ãƒ‰ã«ãªã‚‹ã®ã§ï¼Œæœ€
347 * 後のノードを挿å…
348¥ã™ã¹ãä½ç½®ã¸å‘けて空ノードを移動させる.
349 */
350 index = tmevt_down(1, event_time);
351
352 /*
353 * 最後のノードをindexの位置に挿å…
354¥ã™ã‚‹ï¼Ž
355 */
356 TMEVT_NODE(index) = TMEVT_NODE(last_index + 1);
357 TMEVT_NODE(index).p_tmevtb->index = index;
358}
359
360/*
361 * タイムイベントまでの残り時間の計算
362 */
363#ifdef TOPPERS_tmeltim
364
365RELTIM
366tmevt_lefttim(TMEVTB *p_tmevtb)
367{
368 EVTTIM time;
369
370 time = TMEVT_NODE(p_tmevtb->index).time;
371 if (EVTTIM_LE(time, next_time)) {
372 /*
373 * 次のタイムティックで処理される場合には0を返す.
374 */
375 return(0U);
376 }
377 else {
378 return((RELTIM)(time - base_time));
379 }
380}
381
382#endif /* TOPPERS_tmeltim */
383
384/*
385 * タイムティックの供給
386 */
387#ifdef TOPPERS_sigtim
388
389void
390signal_time(void)
391{
392 TMEVTB *p_tmevtb;
393
394 assert(sense_context());
395 assert(!i_sense_lock());
396
397 i_lock_cpu();
398
399 /*
400 * current_timeを更新する.
401 */
402 current_time = next_time;
403
404 /*
405 * next_time,next_subtimeを更新する.
406 */
407#if TIC_DENO == 1U
408 next_time = current_time + TIC_NUME;
409#else /* TIC_DENO == 1U */
410 next_subtime += TIC_NUME % TIC_DENO;
411 next_time = current_time + TIC_NUME / TIC_DENO;
412 if (next_subtime >= TIC_DENO) {
413 next_subtime -= TIC_DENO;
414 next_time += 1U;
415 }
416#endif /* TIC_DENO == 1U */
417
418 /*
419 * current_timeよりイベント発生時刻の早い(または同じ)タイムイベ
420 * ントを,タイムイベントヒープから削除し,コールバック関数を呼び
421 * 出す.
422 */
423 while (last_index > 0 && EVTTIM_LE(TMEVT_NODE(1).time, current_time)) {
424 p_tmevtb = TMEVT_NODE(1).p_tmevtb;
425 tmevtb_delete_top();
426 (*(p_tmevtb->callback))(p_tmevtb->arg);
427 }
428
429 /*
430 * min_timeを更新する.
431 */
432 min_time = current_time;
433
434 i_unlock_cpu();
435}
436
437#endif /* TOPPERS_sigtim */
Note: See TracBrowser for help on using the repository browser.