OSDN Git Service

マルチプロジェクト型にレポジトリを変更するために移動した
[toppersasp4lpc/asp.git] / asp / sample / sample1.c
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) 2004-2010 by Embedded and Real-Time Systems Laboratory
9  *              Graduate School of Information Science, Nagoya Univ., JAPAN
10  * 
11  *  上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
12  *  ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
13  *  変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
14  *  (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
15  *      権表示,この利用条件および下記の無保証規定が,そのままの形でソー
16  *      スコード中に含まれていること.
17  *  (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
18  *      用できる形で再配布する場合には,再配布に伴うドキュメント(利用
19  *      者マニュアルなど)に,上記の著作権表示,この利用条件および下記
20  *      の無保証規定を掲載すること.
21  *  (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
22  *      用できない形で再配布する場合には,次のいずれかの条件を満たすこ
23  *      と.
24  *    (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
25  *        作権表示,この利用条件および下記の無保証規定を掲載すること.
26  *    (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
27  *        報告すること.
28  *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
29  *      害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
30  *      また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
31  *      由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
32  *      免責すること.
33  * 
34  *  本ソフトウェアは,無保証で提供されているものである.上記著作権者お
35  *  よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
36  *  に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
37  *  アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
38  *  の責任を負わない.
39  * 
40  *  @(#) $Id: sample1.c 1797 2010-06-07 04:24:19Z ertl-hiro $
41  */
42
43 /* 
44  *  サンプルプログラム(1)の本体
45  *
46  *  ASPカーネルの基本的な動作を確認するためのサンプルプログラム.
47  *
48  *  プログラムの概要:
49  *
50  *  ユーザインタフェースを受け持つメインタスク(タスクID: MAIN_TASK,優
51  *  先度: MAIN_PRIORITY)と,3つの並列実行されるタスク(タスクID:
52  *  TASK1〜TASK3,初期優先度: MID_PRIORITY)で構成される.また,起動周
53  *  期が2秒の周期ハンドラ(周期ハンドラID: CYCHDR1)を用いる.
54  *
55  *  並列実行されるタスクは,task_loop回空ループを実行する度に,タスクが
56  *  実行中であることをあらわすメッセージを表示する.
57  *
58  *  周期ハンドラは,三つの優先度(HIGH_PRIORITY,MID_PRIORITY,
59  *  LOW_PRIORITY)のレディキューを回転させる.プログラムの起動直後は,
60  *  周期ハンドラは停止状態になっている.
61  *
62  *  メインタスクは,シリアルI/Oポートからの文字入力を行い(文字入力を
63  *  待っている間は,並列実行されるタスクが実行されている),入力された
64  *  文字に対応した処理を実行する.入力された文字と処理の関係は次の通り.
65  *  Control-Cまたは'Q'が入力されると,プログラムを終了する.
66  *
67  *  '1' : 対象タスクをTASK1に切り換える(初期設定).
68  *  '2' : 対象タスクをTASK2に切り換える.
69  *  '3' : 対象タスクをTASK3に切り換える.
70  *  'a' : 対象タスクをact_tskにより起動する.
71  *  'A' : 対象タスクに対する起動要求をcan_actによりキャンセルする.
72  *  'e' : 対象タスクにext_tskを呼び出させ,終了させる.
73  *  't' : 対象タスクをter_tskにより強制終了する.
74  *  '>' : 対象タスクの優先度をHIGH_PRIORITYにする.
75  *  '=' : 対象タスクの優先度をMID_PRIORITYにする.
76  *  '<' : 対象タスクの優先度をLOW_PRIORITYにする.
77  *  'G' : 対象タスクの優先度をget_priで読み出す.
78  *  's' : 対象タスクにslp_tskを呼び出させ,起床待ちにさせる.
79  *  'S' : 対象タスクにtslp_tsk(10秒)を呼び出させ,起床待ちにさせる.
80  *  'w' : 対象タスクをwup_tskにより起床する.
81  *  'W' : 対象タスクに対する起床要求をcan_wupによりキャンセルする.
82  *  'l' : 対象タスクをrel_waiにより強制的に待ち解除にする.
83  *  'u' : 対象タスクをsus_tskにより強制待ち状態にする.
84  *  'm' : 対象タスクの強制待ち状態をrsm_tskにより解除する.
85  *  'd' : 対象タスクにdly_tsk(10秒)を呼び出させ,時間経過待ちにさせる.
86  *  'x' : 対象タスクに例外パターン0x0001の例外処理を要求する.
87  *  'X' : 対象タスクに例外パターン0x0002の例外処理を要求する.
88  *  'y' : 対象タスクにdis_texを呼び出させ,タスク例外を禁止する.
89  *  'Y' : 対象タスクにena_texを呼び出させ,タスク例外を許可する.
90  *  'r' : 3つの優先度(HIGH_PRIORITY,MID_PRIORITY,LOW_PRIORITY)のレ
91  *        ディキューを回転させる.
92  *  'c' : 周期ハンドラを動作開始させる.
93  *  'C' : 周期ハンドラを動作停止させる.
94  *  'b' : アラームハンドラを5秒後に起動するよう動作開始させる.
95  *  'B' : アラームハンドラを動作停止させる.
96  *  'z' : 対象タスクにCPU例外を発生させる(タスクを終了させる).
97  *  'Z' : 対象タスクにCPUロック状態でCPU例外を発生させる(プログラムを
98  *        終了する).
99  *  'V' : get_utmで性能評価用システム時刻を2回読む.
100  *  'v' : 発行したシステムコールを表示する(デフォルト).
101  *  'q' : 発行したシステムコールを表示しない.
102  */
103
104 #include <kernel.h>
105 #include <t_syslog.h>
106 #include <t_stdlib.h>
107 #include "syssvc/serial.h"
108 #include "syssvc/syslog.h"
109 #include "kernel_cfg.h"
110 #include "sample1.h"
111
112 /*
113  *  サービスコールのエラーのログ出力
114  */
115 Inline void
116 svc_perror(const char *file, int_t line, const char *expr, ER ercd)
117 {
118         if (ercd < 0) {
119                 t_perror(LOG_ERROR, file, line, expr, ercd);
120         }
121 }
122
123 #define SVC_PERROR(expr)        svc_perror(__FILE__, __LINE__, #expr, (expr))
124
125 /*
126  *  並行実行されるタスクへのメッセージ領域
127  */
128 char_t  message[3];
129
130 /*
131  *  ループ回数
132  */
133 ulong_t task_loop;              /* タスク内でのループ回数 */
134 ulong_t tex_loop;               /* 例外処理ルーチン内でのループ回数 */
135
136 /*
137  *  並行実行されるタスク
138  */
139 void task(intptr_t exinf)
140 {
141         volatile ulong_t        i;
142         int_t           n = 0;
143         int_t           tskno = (int_t) exinf;
144         const char      *graph[] = { "|", "  +", "    *" };
145         char_t          c;
146
147         SVC_PERROR(ena_tex());
148         while (1) {
149                 syslog(LOG_NOTICE, "task%d is running (%03d).   %s",
150                                                                                 tskno, ++n, graph[tskno-1]);
151                 for (i = 0; i < task_loop; i++);
152                 c = message[tskno-1];
153                 message[tskno-1] = 0;
154                 switch (c) {
155                 case 'e':
156                         syslog(LOG_INFO, "#%d#ext_tsk()", tskno);
157                         SVC_PERROR(ext_tsk());
158                         assert(0);
159                 case 's':
160                         syslog(LOG_INFO, "#%d#slp_tsk()", tskno);
161                         SVC_PERROR(slp_tsk());
162                         break;
163                 case 'S':
164                         syslog(LOG_INFO, "#%d#tslp_tsk(10000)", tskno);
165                         SVC_PERROR(tslp_tsk(10000));
166                         break;
167                 case 'd':
168                         syslog(LOG_INFO, "#%d#dly_tsk(10000)", tskno);
169                         SVC_PERROR(dly_tsk(10000));
170                         break;
171                 case 'y':
172                         syslog(LOG_INFO, "#%d#dis_tex()", tskno);
173                         SVC_PERROR(dis_tex());
174                         break;
175                 case 'Y':
176                         syslog(LOG_INFO, "#%d#ena_tex()", tskno);
177                         SVC_PERROR(ena_tex());
178                         break;
179 #ifdef CPUEXC1
180                 case 'z':
181                         syslog(LOG_NOTICE, "#%d#raise CPU exception", tskno);
182                         RAISE_CPU_EXCEPTION;
183                         break;
184                 case 'Z':
185                         SVC_PERROR(loc_cpu());
186                         syslog(LOG_NOTICE, "#%d#raise CPU exception", tskno);
187                         RAISE_CPU_EXCEPTION;
188                         SVC_PERROR(unl_cpu());
189                         break;
190 #endif /* CPUEXC1 */
191                 default:
192                         break;
193                 }
194         }
195 }
196
197 /*
198  *  並行して実行されるタスク用のタスク例外処理ルーチン
199  */
200 void tex_routine(TEXPTN texptn, intptr_t exinf)
201 {
202         volatile ulong_t        i;
203         int_t   tskno = (int_t) exinf;
204
205         syslog(LOG_NOTICE, "task%d receives exception 0x%04x.", tskno, texptn);
206         for (i = 0; i < tex_loop; i++);
207
208         if ((texptn & 0x8000U) != 0U) {
209                 syslog(LOG_INFO, "#%d#ext_tsk()", tskno);
210                 SVC_PERROR(ext_tsk());
211                 assert(0);
212         }
213 }
214
215 /*
216  *  CPU例外ハンドラ
217  */
218 #ifdef CPUEXC1
219
220 void
221 cpuexc_handler(void *p_excinf)
222 {
223         ID              tskid;
224
225         syslog(LOG_NOTICE, "CPU exception handler (p_excinf = %08p).", p_excinf);
226         if (sns_ctx() != true) {
227                 syslog(LOG_WARNING,
228                                         "sns_ctx() is not true in CPU exception handler.");
229         }
230         if (sns_dpn() != true) {
231                 syslog(LOG_WARNING,
232                                         "sns_dpn() is not true in CPU exception handler.");
233         }
234         syslog(LOG_INFO, "sns_loc = %d sns_dsp = %d sns_tex = %d",
235                                                                         sns_loc(), sns_dsp(), sns_tex());
236         syslog(LOG_INFO, "xsns_dpn = %d xsns_xpn = %d",
237                                                                         xsns_dpn(p_excinf), xsns_xpn(p_excinf));
238
239         if (xsns_xpn(p_excinf)) {
240                 syslog(LOG_NOTICE, "Sample program ends with exception.");
241                 SVC_PERROR(ext_ker());
242                 assert(0);
243         }
244
245         SVC_PERROR(iget_tid(&tskid));
246         SVC_PERROR(iras_tex(tskid, 0x8000U));
247 }
248
249 #endif /* CPUEXC1 */
250
251 /*
252  *  周期ハンドラ
253  *
254  *  HIGH_PRIORITY,MID_PRIORITY,LOW_PRIORITY の各優先度のレディキュー
255  *  を回転させる.
256  */
257 void cyclic_handler(intptr_t exinf)
258 {
259         SVC_PERROR(irot_rdq(HIGH_PRIORITY));
260         SVC_PERROR(irot_rdq(MID_PRIORITY));
261         SVC_PERROR(irot_rdq(LOW_PRIORITY));
262 }
263
264 /*
265  *  アラームハンドラ
266  *
267  *  HIGH_PRIORITY,MID_PRIORITY,LOW_PRIORITY の各優先度のレディキュー
268  *  を回転させる.
269  */
270 void alarm_handler(intptr_t exinf)
271 {
272         SVC_PERROR(irot_rdq(HIGH_PRIORITY));
273         SVC_PERROR(irot_rdq(MID_PRIORITY));
274         SVC_PERROR(irot_rdq(LOW_PRIORITY));
275 }
276
277 /*
278  *  メインタスク
279  */
280 void main_task(intptr_t exinf)
281 {
282         char_t  c;
283         ID              tskid = TASK1;
284         int_t   tskno = 1;
285         ER_UINT ercd;
286         PRI             tskpri;
287 #ifndef TASK_LOOP
288         volatile ulong_t        i;
289         SYSTIM  stime1, stime2;
290 #endif /* TASK_LOOP */
291 #ifdef TOPPERS_SUPPORT_GET_UTM
292         SYSUTM  utime1, utime2;
293 #endif /* TOPPERS_SUPPORT_GET_UTM */
294
295         SVC_PERROR(syslog_msk_log(LOG_UPTO(LOG_INFO), LOG_UPTO(LOG_EMERG)));
296         syslog(LOG_NOTICE, "Sample program starts (exinf = %d).", (int_t) exinf);
297
298         /*
299          *  シリアルポートの初期化
300          *
301          *  システムログタスクと同じシリアルポートを使う場合など,シリアル
302          *  ポートがオープン済みの場合にはここでE_OBJエラーになるが,支障は
303          *  ない.
304          */
305         ercd = serial_opn_por(TASK_PORTID);
306         if (ercd < 0 && MERCD(ercd) != E_OBJ) {
307                 syslog(LOG_ERROR, "%s (%d) reported by `serial_opn_por'.",
308                                                                         itron_strerror(ercd), SERCD(ercd));
309         }
310         SVC_PERROR(serial_ctl_por(TASK_PORTID,
311                                                         (IOCTL_CRLF | IOCTL_FCSND | IOCTL_FCRCV)));
312
313         /*
314          *  ループ回数の設定
315          *
316          *  TASK_LOOPがマクロ定義されている場合,測定せずに,TASK_LOOPに定
317          *  義された値を,タスク内でのループ回数とする.
318          *
319          *  MEASURE_TWICEがマクロ定義されている場合,1回目の測定結果を捨て
320          *  て,2回目の測定結果を使う.1回目の測定は長めの時間が出るため.
321          */
322 #ifdef TASK_LOOP
323         task_loop = TASK_LOOP;
324 #else /* TASK_LOOP */
325
326 #ifdef MEASURE_TWICE
327         task_loop = LOOP_REF;
328         SVC_PERROR(get_tim(&stime1));
329         for (i = 0; i < task_loop; i++);
330         SVC_PERROR(get_tim(&stime2));
331 #endif /* MEASURE_TWICE */
332
333         task_loop = LOOP_REF;
334         SVC_PERROR(get_tim(&stime1));
335         for (i = 0; i < task_loop; i++);
336         SVC_PERROR(get_tim(&stime2));
337         task_loop = LOOP_REF * 400UL / (stime2 - stime1);
338
339 #endif /* TASK_LOOP */
340         tex_loop = task_loop / 5;
341
342         /*
343          *  タスクの起動
344          */
345         SVC_PERROR(act_tsk(TASK1));
346         SVC_PERROR(act_tsk(TASK2));
347         SVC_PERROR(act_tsk(TASK3));
348
349         /*
350          *  メインループ
351          */
352         do {
353                 SVC_PERROR(serial_rea_dat(TASK_PORTID, &c, 1));
354                 switch (c) {
355                 case 'e':
356                 case 's':
357                 case 'S':
358                 case 'd':
359                 case 'y':
360                 case 'Y':
361                 case 'z':
362                 case 'Z':
363                         message[tskno-1] = c;
364                         break;
365                 case '1':
366                         tskno = 1;
367                         tskid = TASK1;
368                         break;
369                 case '2':
370                         tskno = 2;
371                         tskid = TASK2;
372                         break;
373                 case '3':
374                         tskno = 3;
375                         tskid = TASK3;
376                         break;
377                 case 'a':
378                         syslog(LOG_INFO, "#act_tsk(%d)", tskno);
379                         SVC_PERROR(act_tsk(tskid));
380                         break;
381                 case 'A':
382                         syslog(LOG_INFO, "#can_act(%d)", tskno);
383                         SVC_PERROR(ercd = can_act(tskid));
384                         if (ercd >= 0) {
385                                 syslog(LOG_NOTICE, "can_act(%d) returns %d", tskno, ercd);
386                         }
387                         break;
388                 case 't':
389                         syslog(LOG_INFO, "#ter_tsk(%d)", tskno);
390                         SVC_PERROR(ter_tsk(tskid));
391                         break;
392                 case '>':
393                         syslog(LOG_INFO, "#chg_pri(%d, HIGH_PRIORITY)", tskno);
394                         SVC_PERROR(chg_pri(tskid, HIGH_PRIORITY));
395                         break;
396                 case '=':
397                         syslog(LOG_INFO, "#chg_pri(%d, MID_PRIORITY)", tskno);
398                         SVC_PERROR(chg_pri(tskid, MID_PRIORITY));
399                         break;
400                 case '<':
401                         syslog(LOG_INFO, "#chg_pri(%d, LOW_PRIORITY)", tskno);
402                         SVC_PERROR(chg_pri(tskid, LOW_PRIORITY));
403                         break;
404                 case 'G':
405                         syslog(LOG_INFO, "#get_pri(%d, &tskpri)", tskno);
406                         SVC_PERROR(ercd = get_pri(tskid, &tskpri));
407                         if (ercd >= 0) {
408                                 syslog(LOG_NOTICE, "priority of task %d is %d", tskno, tskpri);
409                         }
410                         break;
411                 case 'w':
412                         syslog(LOG_INFO, "#wup_tsk(%d)", tskno);
413                         SVC_PERROR(wup_tsk(tskid));
414                         break;
415                 case 'W':
416                         syslog(LOG_INFO, "#can_wup(%d)", tskno);
417                         SVC_PERROR(ercd = can_wup(tskid));
418                         if (ercd >= 0) {
419                                 syslog(LOG_NOTICE, "can_wup(%d) returns %d", tskno, ercd);
420                         }
421                         break;
422                 case 'l':
423                         syslog(LOG_INFO, "#rel_wai(%d)", tskno);
424                         SVC_PERROR(rel_wai(tskid));
425                         break;
426                 case 'u':
427                         syslog(LOG_INFO, "#sus_tsk(%d)", tskno);
428                         SVC_PERROR(sus_tsk(tskid));
429                         break;
430                 case 'm':
431                         syslog(LOG_INFO, "#rsm_tsk(%d)", tskno);
432                         SVC_PERROR(rsm_tsk(tskid));
433                         break;
434                 case 'x':
435                         syslog(LOG_INFO, "#ras_tex(%d, 0x0001U)", tskno);
436                         SVC_PERROR(ras_tex(tskid, 0x0001U));
437                         break;
438                 case 'X':
439                         syslog(LOG_INFO, "#ras_tex(%d, 0x0002U)", tskno);
440                         SVC_PERROR(ras_tex(tskid, 0x0002U));
441                         break;
442                 case 'r':
443                         syslog(LOG_INFO, "#rot_rdq(three priorities)");
444                         SVC_PERROR(rot_rdq(HIGH_PRIORITY));
445                         SVC_PERROR(rot_rdq(MID_PRIORITY));
446                         SVC_PERROR(rot_rdq(LOW_PRIORITY));
447                         break;
448                 case 'c':
449                         syslog(LOG_INFO, "#sta_cyc(1)");
450                         SVC_PERROR(sta_cyc(CYCHDR1));
451                         break;
452                 case 'C':
453                         syslog(LOG_INFO, "#stp_cyc(1)");
454                         SVC_PERROR(stp_cyc(CYCHDR1));
455                         break;
456                 case 'b':
457                         syslog(LOG_INFO, "#sta_alm(1, 5000)");
458                         SVC_PERROR(sta_alm(ALMHDR1, 5000));
459                         break;
460                 case 'B':
461                         syslog(LOG_INFO, "#stp_alm(1)");
462                         SVC_PERROR(stp_alm(ALMHDR1));
463                         break;
464
465                 case 'V':
466 #ifdef TOPPERS_SUPPORT_GET_UTM
467                         SVC_PERROR(get_utm(&utime1));
468                         SVC_PERROR(get_utm(&utime2));
469                         syslog(LOG_NOTICE, "utime1 = %ld, utime2 = %ld",
470                                                                                 (ulong_t) utime1, (ulong_t) utime2);
471 #else /* TOPPERS_SUPPORT_GET_UTM */
472                         syslog(LOG_NOTICE, "get_utm is not supported.");
473 #endif /* TOPPERS_SUPPORT_GET_UTM */
474                         break;
475
476                 case 'v':
477                         SVC_PERROR(syslog_msk_log(LOG_UPTO(LOG_INFO),
478                                                                                 LOG_UPTO(LOG_EMERG)));
479                         break;
480                 case 'q':
481                         SVC_PERROR(syslog_msk_log(LOG_UPTO(LOG_NOTICE),
482                                                                                 LOG_UPTO(LOG_EMERG)));
483                         break;
484
485 #ifdef BIT_KERNEL
486                 case ' ':
487                         SVC_PERROR(loc_cpu());
488                         {
489                                 extern ER       bit_kernel(void);
490
491                                 SVC_PERROR(ercd = bit_kernel());
492                                 if (ercd >= 0) {
493                                         syslog(LOG_NOTICE, "bit_kernel passed.");
494                                 }
495                         }
496                         SVC_PERROR(unl_cpu());
497                         break;
498 #endif /* BIT_KERNEL */
499
500                 default:
501                         break;
502                 }
503         } while (c != '\003' && c != 'Q');
504
505         syslog(LOG_NOTICE, "Sample program ends.");
506         SVC_PERROR(ext_ker());
507         assert(0);
508 }