source: rubycfg_asp/trunk/csp/sample1n/sample1.c@ 315

Last change on this file since 315 was 315, checked in by coas-nagasima, 7 years ago

SVNプロパティを設定

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc; charset=UTF-8
File size: 18.5 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) 2004-2012 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 315 2017-07-23 05:29:40Z coas-nagasima $
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 * され,プログラムの動作が確認しずらくなるためである.また,低速なシ
59 * リアルポートを用いてメッセージを出力する場合に,すべてのメッセージ
60 * が出力できるように,メッセージの量を制限するという理由もある.
61 *
62 * 周期ハンドラは,三つの優先度(HIGH_PRIORITY,MID_PRIORITY,
63 * LOW_PRIORITY)のレディキューを回転させる.プログラムの起動直後は,
64 * 周期ハンドラは停止状態になっている.
65 *
66 * メインタスクは,シリアルI/Oポートからの文字入力を行い(文字入力を
67 * 待っている間は,並行実行されるタスクが実行されている),入力された
68 * 文字に対応した処理を実行する.入力された文字と処理の関係は次の通り.
69 * Control-Cまたは'Q'が入力されると,プログラムを終了する.
70 *
71 * '1' : 対象タスクをTASK1に切り換える(初期設定).
72 * '2' : 対象タスクをTASK2に切り換える.
73 * '3' : 対象タスクをTASK3に切り換える.
74 * 'a' : 対象タスクをact_tskにより起動する.
75 * 'A' : 対象タスクに対する起動要求をcan_actによりキャンセルする.
76 * 'e' : 対象タスクにext_tskを呼び出させ,終了させる.
77 * 't' : 対象タスクをter_tskにより強制終了する.
78 * '>' : 対象タスクの優先度をHIGH_PRIORITYにする.
79 * '=' : 対象タスクの優先度をMID_PRIORITYにする.
80 * '<' : 対象タスクの優先度をLOW_PRIORITYにする.
81 * 'G' : 対象タスクの優先度をget_priで読み出す.
82 * 's' : 対象タスクにslp_tskを呼び出させ,起床待ちにさせる.
83 * 'S' : 対象タスクにtslp_tsk(10秒)を呼び出させ,起床待ちにさせる.
84 * 'w' : 対象タスクをwup_tskにより起床する.
85 * 'W' : 対象タスクに対する起床要求をcan_wupによりキャンセルする.
86 * 'l' : 対象タスクをrel_waiにより強制的に待ち解除にする.
87 * 'u' : 対象タスクをsus_tskにより強制待ち状態にする.
88 * 'm' : 対象タスクの強制待ち状態をrsm_tskにより解除する.
89 * 'd' : 対象タスクにdly_tsk(10秒)を呼び出させ,時間経過待ちにさせる.
90 * 'x' : 対象タスクに例外パターン0x0001の例外処理を要求する.
91 * 'X' : 対象タスクに例外パターン0x0002の例外処理を要求する.
92 * 'y' : 対象タスクにdis_texを呼び出させ,タスク例外を禁止する.
93 * 'Y' : 対象タスクにena_texを呼び出させ,タスク例外を許可する.
94 * 'r' : 3つの優先度(HIGH_PRIORITY,MID_PRIORITY,LOW_PRIORITY)のレ
95 * ディキューを回転させる.
96 * 'c' : 周期ハンドラを動作開始させる.
97 * 'C' : 周期ハンドラを動作停止させる.
98 * 'b' : アラームハンドラを5秒後に起動するよう動作開始させる.
99 * 'B' : アラームハンドラを動作停止させる.
100 * 'z' : 対象タスクにCPU例外を発生させる(タスクを終了させる).
101 * 'Z' : 対象タスクにCPUロック状態でCPU例外を発生させる(プログラムを
102 * 終了する).
103 * '@' : タスク3をacre_tskにより生成し,def_texによりタスク例外処理
104 * ルーチンを設定する.
105 * '!' : 対象タスクをdel_tskにより削除する.
106 * 'V' : get_utmで性能評価用システム時刻を2回読む.
107 * 'v' : 発行したシステムコールを表示する(デフォルト).
108 * 'q' : 発行したシステムコールを表示しない.
109 */
110
111#include <kernel.h>
112#include <t_syslog.h>
113#include <t_stdlib.h>
114#include "syssvc/serial.h"
115#include "syssvc/syslog.h"
116#include "kernel_cfg.h"
117#include "sample1n.h"
118#include "sample1.h"
119
120/*
121 * サービスコールのエラーのログ出力
122 */
123Inline void
124svc_perror(const char *file, int_t line, const char *expr, ER ercd)
125{
126 if (ercd < 0) {
127 t_perror(LOG_ERROR, file, line, expr, ercd);
128 }
129}
130
131#define SVC_PERROR(expr) svc_perror(__FILE__, __LINE__, #expr, (expr))
132
133/*
134 * 並行実行されるタスクへのメッセージ領域
135 */
136char message[3];
137
138/*
139 * ループ回数
140 */
141ulong_t task_loop; /* タスク内でのループ回数 */
142ulong_t tex_loop; /* 例外処理ルーチン内でのループ回数 */
143
144/*
145 * 並行実行されるタスク
146 */
147void task(intptr_t exinf)
148{
149 volatile ulong_t i;
150 int_t n = 0;
151 int_t tskno = (int_t) exinf;
152 const char *graph[] = { "|", " +", " *" };
153 char c;
154
155 SVC_PERROR(ena_tex());
156 while (true) {
157 syslog(LOG_NOTICE, "task%d is running (%03d). %s",
158 tskno, ++n, graph[tskno-1]);
159 for (i = 0; i < task_loop; i++);
160 c = message[tskno-1];
161 message[tskno-1] = 0;
162 switch (c) {
163 case 'e':
164 syslog(LOG_INFO, "#%d#ext_tsk()", tskno);
165 SVC_PERROR(ext_tsk());
166 assert(0);
167 case 's':
168 syslog(LOG_INFO, "#%d#slp_tsk()", tskno);
169 SVC_PERROR(slp_tsk());
170 break;
171 case 'S':
172 syslog(LOG_INFO, "#%d#tslp_tsk(10000)", tskno);
173 SVC_PERROR(tslp_tsk(10000));
174 break;
175 case 'd':
176 syslog(LOG_INFO, "#%d#dly_tsk(10000)", tskno);
177 SVC_PERROR(dly_tsk(10000));
178 break;
179 case 'y':
180 syslog(LOG_INFO, "#%d#dis_tex()", tskno);
181 SVC_PERROR(dis_tex());
182 break;
183 case 'Y':
184 syslog(LOG_INFO, "#%d#ena_tex()", tskno);
185 SVC_PERROR(ena_tex());
186 break;
187#ifdef CPUEXC1
188 case 'z':
189 syslog(LOG_NOTICE, "#%d#raise CPU exception", tskno);
190 RAISE_CPU_EXCEPTION;
191 break;
192 case 'Z':
193 SVC_PERROR(loc_cpu());
194 syslog(LOG_NOTICE, "#%d#raise CPU exception", tskno);
195 RAISE_CPU_EXCEPTION;
196 SVC_PERROR(unl_cpu());
197 break;
198#endif /* CPUEXC1 */
199 default:
200 break;
201 }
202 }
203}
204
205/*
206 * 並行して実行されるタスク用のタスク例外処理ルーチン
207 */
208void tex_routine(TEXPTN texptn, intptr_t exinf)
209{
210 volatile ulong_t i;
211 int_t tskno = (int_t) exinf;
212
213 syslog(LOG_NOTICE, "task%d receives exception 0x%04x.", tskno, texptn);
214 for (i = 0; i < tex_loop; i++);
215
216 if ((texptn & 0x8000U) != 0U) {
217 syslog(LOG_INFO, "#%d#ext_tsk()", tskno);
218 SVC_PERROR(ext_tsk());
219 assert(0);
220 }
221}
222
223/*
224 * CPU例外ハンドラ
225 */
226#ifdef CPUEXC1
227
228void
229cpuexc_handler(void *p_excinf)
230{
231 ID tskid;
232
233 syslog(LOG_NOTICE, "CPU exception handler (p_excinf = %08p).", p_excinf);
234 if (sns_ctx() != true) {
235 syslog(LOG_WARNING,
236 "sns_ctx() is not true in CPU exception handler.");
237 }
238 if (sns_dpn() != true) {
239 syslog(LOG_WARNING,
240 "sns_dpn() is not true in CPU exception handler.");
241 }
242 syslog(LOG_INFO, "sns_loc = %d sns_dsp = %d sns_tex = %d",
243 sns_loc(), sns_dsp(), sns_tex());
244 syslog(LOG_INFO, "xsns_dpn = %d xsns_xpn = %d",
245 xsns_dpn(p_excinf), xsns_xpn(p_excinf));
246
247 if (xsns_xpn(p_excinf)) {
248 syslog(LOG_NOTICE, "Sample program ends with exception.");
249 SVC_PERROR(ext_ker());
250 assert(0);
251 }
252
253 SVC_PERROR(iget_tid(&tskid));
254 SVC_PERROR(iras_tex(tskid, 0x8000U));
255}
256
257#endif /* CPUEXC1 */
258
259/*
260 * 周期ハンドラ
261 *
262 * HIGH_PRIORITY,MID_PRIORITY,LOW_PRIORITY の各優先度のレディキュー
263 * を回転させる.
264 */
265void cyclic_handler(intptr_t exinf)
266{
267 SVC_PERROR(irot_rdq(HIGH_PRIORITY));
268 SVC_PERROR(irot_rdq(MID_PRIORITY));
269 SVC_PERROR(irot_rdq(LOW_PRIORITY));
270}
271
272/*
273 * アラームハンドラ
274 *
275 * HIGH_PRIORITY,MID_PRIORITY,LOW_PRIORITY の各優先度のレディキュー
276 * を回転させる.
277 */
278void alarm_handler(intptr_t exinf)
279{
280 SVC_PERROR(irot_rdq(HIGH_PRIORITY));
281 SVC_PERROR(irot_rdq(MID_PRIORITY));
282 SVC_PERROR(irot_rdq(LOW_PRIORITY));
283}
284
285/*
286 * メインタスク
287 */
288void main_task(intptr_t exinf)
289{
290 char c;
291 ID tskid = TASK1;
292 int_t tskno = 1;
293 ER_UINT ercd;
294 PRI tskpri;
295#ifndef TASK_LOOP
296 volatile ulong_t i;
297 SYSTIM stime1, stime2;
298#endif /* TASK_LOOP */
299#ifdef TOPPERS_SUPPORT_GET_UTM
300 SYSUTM utime1, utime2;
301#endif /* TOPPERS_SUPPORT_GET_UTM */
302 T_CTSK ctsk;
303 T_DTEX dtex;
304 ID TASK3 = -1;
305
306 SVC_PERROR(syslog_msk_log(LOG_UPTO(LOG_INFO), LOG_UPTO(LOG_EMERG)));
307 syslog(LOG_NOTICE, "Sample program starts (exinf = %d).", (int_t) exinf);
308
309 /*
310 * シリアルポートの初期化
311 *
312 * システムログタスクと同じシリアルポートを使う場合など,シリアル
313 * ポートがオープン済みの場合にはここでE_OBJエラーになるが,支障は
314 * ない.
315 */
316 ercd = serial_opn_por(TASK_PORTID);
317 if (ercd < 0 && MERCD(ercd) != E_OBJ) {
318 syslog(LOG_ERROR, "%s (%d) reported by `serial_opn_por'.",
319 itron_strerror(ercd), SERCD(ercd));
320 }
321 SVC_PERROR(serial_ctl_por(TASK_PORTID,
322 (IOCTL_CRLF | IOCTL_FCSND | IOCTL_FCRCV)));
323
324 /*
325 * ループ回数の設定
326 *
327 * 並行実行されるタスク内での空ループの回数(task_loop)は,空ルー
328 * プの実行時間が約0.4秒になるように設定する.この設定のために,
329 * LOOP_REF回の空ループの実行時間を,その前後でget_timを呼ぶことで
330 * 測定し,その測定結果から空ループの実行時間が0.4秒になるループ回
331 * 数を求め,task_loopに設定する.
332 *
333 * LOOP_REFは,デフォルトでは1,000,000に設定しているが,想定したよ
334 * り遅いプロセッサでは,サンプルプログラムの実行開始に時間がかか
335 * りすぎるという問題を生じる.逆に想定したより速いプロセッサでは,
336 * LOOP_REF回の空ループの実行時間が短くなり,task_loopに設定する値
337 * の誤差が大きくなるという問題がある.
338 *
339 * そこで,そのようなターゲットでは,target_test.hで,LOOP_REFを適
340 * 切な値に定義するのが望ましい.
341 *
342 * また,task_loopの値を固定したい場合には,その値をTASK_LOOPにマ
343 * クロ定義する.TASK_LOOPがマクロ定義されている場合,上記の測定を
344 * 行わずに,TASK_LOOPに定義された値を空ループの回数とする.
345 *
346 * ターゲットによっては,空ループの実行時間の1回目の測定で,本来よ
347 * りも長めになるものがある.このようなターゲットでは,MEASURE_TWICE
348 * をマクロ定義することで,1回目の測定結果を捨てて,2回目の測定結果
349 * を使う.
350 *
351 * タスク例外処理ルーチン内での空ループの回数(tex_loop)は,
352 * task_loopの4分の1の値(空ループの実行時間が0.1秒になるループ回
353 * 数)に設定する.
354 */
355#ifdef TASK_LOOP
356 task_loop = TASK_LOOP;
357#else /* TASK_LOOP */
358
359#ifdef MEASURE_TWICE
360 task_loop = LOOP_REF;
361 SVC_PERROR(get_tim(&stime1));
362 for (i = 0; i < task_loop; i++);
363 SVC_PERROR(get_tim(&stime2));
364#endif /* MEASURE_TWICE */
365
366 task_loop = LOOP_REF;
367 SVC_PERROR(get_tim(&stime1));
368 for (i = 0; i < task_loop; i++);
369 SVC_PERROR(get_tim(&stime2));
370 task_loop = LOOP_REF * 400UL / (stime2 - stime1);
371
372#endif /* TASK_LOOP */
373 tex_loop = task_loop / 4;
374
375 /*
376 * タスクの起動
377 */
378 SVC_PERROR(act_tsk(TASK1));
379 SVC_PERROR(act_tsk(TASK2));
380
381 /*
382 * メインループ
383 */
384 do {
385 SVC_PERROR(serial_rea_dat(TASK_PORTID, &c, 1));
386 switch (c) {
387 case 'e':
388 case 's':
389 case 'S':
390 case 'd':
391 case 'y':
392 case 'Y':
393 case 'z':
394 case 'Z':
395 message[tskno-1] = c;
396 break;
397 case '1':
398 tskno = 1;
399 tskid = TASK1;
400 break;
401 case '2':
402 tskno = 2;
403 tskid = TASK2;
404 break;
405 case '3':
406 tskno = 3;
407 tskid = TASK3;
408 break;
409 case 'a':
410 syslog(LOG_INFO, "#act_tsk(%d)", tskno);
411 SVC_PERROR(act_tsk(tskid));
412 break;
413 case 'A':
414 syslog(LOG_INFO, "#can_act(%d)", tskno);
415 SVC_PERROR(ercd = can_act(tskid));
416 if (ercd >= 0) {
417 syslog(LOG_NOTICE, "can_act(%d) returns %d", tskno, ercd);
418 }
419 break;
420 case 't':
421 syslog(LOG_INFO, "#ter_tsk(%d)", tskno);
422 SVC_PERROR(ter_tsk(tskid));
423 break;
424 case '>':
425 syslog(LOG_INFO, "#chg_pri(%d, HIGH_PRIORITY)", tskno);
426 SVC_PERROR(chg_pri(tskid, HIGH_PRIORITY));
427 break;
428 case '=':
429 syslog(LOG_INFO, "#chg_pri(%d, MID_PRIORITY)", tskno);
430 SVC_PERROR(chg_pri(tskid, MID_PRIORITY));
431 break;
432 case '<':
433 syslog(LOG_INFO, "#chg_pri(%d, LOW_PRIORITY)", tskno);
434 SVC_PERROR(chg_pri(tskid, LOW_PRIORITY));
435 break;
436 case 'G':
437 syslog(LOG_INFO, "#get_pri(%d, &tskpri)", tskno);
438 SVC_PERROR(ercd = get_pri(tskid, &tskpri));
439 if (ercd >= 0) {
440 syslog(LOG_NOTICE, "priority of task %d is %d", tskno, tskpri);
441 }
442 break;
443 case 'w':
444 syslog(LOG_INFO, "#wup_tsk(%d)", tskno);
445 SVC_PERROR(wup_tsk(tskid));
446 break;
447 case 'W':
448 syslog(LOG_INFO, "#can_wup(%d)", tskno);
449 SVC_PERROR(ercd = can_wup(tskid));
450 if (ercd >= 0) {
451 syslog(LOG_NOTICE, "can_wup(%d) returns %d", tskno, ercd);
452 }
453 break;
454 case 'l':
455 syslog(LOG_INFO, "#rel_wai(%d)", tskno);
456 SVC_PERROR(rel_wai(tskid));
457 break;
458 case 'u':
459 syslog(LOG_INFO, "#sus_tsk(%d)", tskno);
460 SVC_PERROR(sus_tsk(tskid));
461 break;
462 case 'm':
463 syslog(LOG_INFO, "#rsm_tsk(%d)", tskno);
464 SVC_PERROR(rsm_tsk(tskid));
465 break;
466 case 'x':
467 syslog(LOG_INFO, "#ras_tex(%d, 0x0001U)", tskno);
468 SVC_PERROR(ras_tex(tskid, 0x0001U));
469 break;
470 case 'X':
471 syslog(LOG_INFO, "#ras_tex(%d, 0x0002U)", tskno);
472 SVC_PERROR(ras_tex(tskid, 0x0002U));
473 break;
474 case 'r':
475 syslog(LOG_INFO, "#rot_rdq(three priorities)");
476 SVC_PERROR(rot_rdq(HIGH_PRIORITY));
477 SVC_PERROR(rot_rdq(MID_PRIORITY));
478 SVC_PERROR(rot_rdq(LOW_PRIORITY));
479 break;
480 case 'c':
481 syslog(LOG_INFO, "#sta_cyc(1)");
482 SVC_PERROR(sta_cyc(CYCHDR1));
483 break;
484 case 'C':
485 syslog(LOG_INFO, "#stp_cyc(1)");
486 SVC_PERROR(stp_cyc(CYCHDR1));
487 break;
488 case 'b':
489 syslog(LOG_INFO, "#sta_alm(1, 5000)");
490 SVC_PERROR(sta_alm(ALMHDR1, 5000));
491 break;
492 case 'B':
493 syslog(LOG_INFO, "#stp_alm(1)");
494 SVC_PERROR(stp_alm(ALMHDR1));
495 break;
496 case '@':
497 ctsk.tskatr = TA_NULL;
498 ctsk.exinf = 3;
499 ctsk.task = task;
500 ctsk.itskpri = MID_PRIORITY;
501 ctsk.stksz = STACK_SIZE;
502 ctsk.stk = NULL;
503 SVC_PERROR(TASK3 = acre_tsk(&ctsk));
504
505 dtex.texatr = TA_NULL;
506 dtex.texrtn = tex_routine;
507 SVC_PERROR(def_tex(TASK3, &dtex));
508
509 syslog(LOG_NOTICE, "task3 is created with tskid = %d.",
510 (int_t) TASK3);
511 break;
512 case '!':
513 syslog(LOG_INFO, "#del_tsk(%d)", tskno);
514 SVC_PERROR(del_tsk(tskid));
515 break;
516
517 case 'V':
518#ifdef TOPPERS_SUPPORT_GET_UTM
519 SVC_PERROR(get_utm(&utime1));
520 SVC_PERROR(get_utm(&utime2));
521 syslog(LOG_NOTICE, "utime1 = %ld, utime2 = %ld",
522 (ulong_t) utime1, (ulong_t) utime2);
523#else /* TOPPERS_SUPPORT_GET_UTM */
524 syslog(LOG_NOTICE, "get_utm is not supported.");
525#endif /* TOPPERS_SUPPORT_GET_UTM */
526 break;
527
528 case 'v':
529 SVC_PERROR(syslog_msk_log(LOG_UPTO(LOG_INFO),
530 LOG_UPTO(LOG_EMERG)));
531 break;
532 case 'q':
533 SVC_PERROR(syslog_msk_log(LOG_UPTO(LOG_NOTICE),
534 LOG_UPTO(LOG_EMERG)));
535 break;
536
537#ifdef BIT_KERNEL
538 case ' ':
539 SVC_PERROR(loc_cpu());
540 {
541 extern ER bit_kernel(void);
542
543 SVC_PERROR(ercd = bit_kernel());
544 if (ercd >= 0) {
545 syslog(LOG_NOTICE, "bit_kernel passed.");
546 }
547 }
548 SVC_PERROR(unl_cpu());
549 break;
550#endif /* BIT_KERNEL */
551
552 default:
553 break;
554 }
555 } while (c != '\003' && c != 'Q');
556
557 syslog(LOG_NOTICE, "Sample program ends.");
558 SVC_PERROR(ext_ker());
559 assert(0);
560}
Note: See TracBrowser for help on using the repository browser.