00001 /* 00002 * TOPPERS/ASP Kernel 00003 * Toyohashi Open Platform for Embedded Real-Time Systems/ 00004 * Advanced Standard Profile Kernel 00005 * 00006 * Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory 00007 * Toyohashi Univ. of Technology, JAPAN 00008 * Copyright (C) 2004-2008 by Embedded and Real-Time Systems Laboratory 00009 * Graduate School of Information Science, Nagoya Univ., JAPAN 00010 * 00011 * 上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ 00012 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改 00013 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する. 00014 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作 00015 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー 00016 * スコード中に含まれていること. 00017 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使 00018 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用 00019 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記 00020 * の無保証規定を掲載すること. 00021 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使 00022 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ 00023 * と. 00024 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著 00025 * 作権表示,この利用条件および下記の無保証規定を掲載すること. 00026 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに 00027 * 報告すること. 00028 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損 00029 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること. 00030 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理 00031 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを 00032 * 免責すること. 00033 * 00034 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お 00035 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的 00036 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ 00037 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ 00038 * の責任を負わない. 00039 * 00040 * @(#) $Id: sample1.c 927 2008-04-14 07:28:38Z ertl-hiro $ 00041 */ 00042 00043 /* 00044 * サンプルプログラム(1)の本体 00045 * 00046 * ASPカーネルの基本的な動作を確認するためのサンプルプログラム. 00047 * 00048 * プログラムの概要: 00049 * 00050 * ユーザインタフェースを受け持つメインタスク(タスクID: MAIN_TASK,優 00051 * 先度: MAIN_PRIORITY)と,3つの並列実行されるタスク(タスクID: 00052 * TASK1〜TASK3,初期優先度: MID_PRIORITY)で構成される.また,起動周 00053 * 期が2秒の周期ハンドラ(周期ハンドラID: CYCHDR1)を用いる. 00054 * 00055 * 並列実行されるタスクは,task_loop回空ループを実行する度に,タスクが 00056 * 実行中であることをあらわすメッセージを表示する. 00057 * 00058 * 周期ハンドラは,三つの優先度(HIGH_PRIORITY,MID_PRIORITY, 00059 * LOW_PRIORITY)のレディキューを回転させる.プログラムの起動直後は, 00060 * 周期ハンドラは停止状態になっている. 00061 * 00062 * メインタスクは,シリアルI/Oポートからの文字入力を行い(文字入力を 00063 * 待っている間は,並列実行されるタスクが実行されている),入力された 00064 * 文字に対応した処理を実行する.入力された文字と処理の関係は次の通り. 00065 * Control-Cまたは'Q'が入力されると,プログラムを終了する. 00066 * 00067 * '1' : 対象タスクをTASK1に切り換える(初期設定). 00068 * '2' : 対象タスクをTASK2に切り換える. 00069 * '3' : 対象タスクをTASK3に切り換える. 00070 * 'a' : 対象タスクをact_tskにより起動する. 00071 * 'A' : 対象タスクに対する起動要求をcan_actによりキャンセルする. 00072 * 'e' : 対象タスクにext_tskを呼び出させ,終了させる. 00073 * 't' : 対象タスクをter_tskにより強制終了する. 00074 * '>' : 対象タスクの優先度をHIGH_PRIORITYにする. 00075 * '=' : 対象タスクの優先度をMID_PRIORITYにする. 00076 * '<' : 対象タスクの優先度をLOW_PRIORITYにする. 00077 * 'G' : 対象タスクの優先度をget_priで読み出す. 00078 * 's' : 対象タスクにslp_tskを呼び出させ,起床待ちにさせる. 00079 * 'S' : 対象タスクにtslp_tsk(10秒)を呼び出させ,起床待ちにさせる. 00080 * 'w' : 対象タスクをwup_tskにより起床する. 00081 * 'W' : 対象タスクに対する起床要求をcan_wupによりキャンセルする. 00082 * 'l' : 対象タスクをrel_waiにより強制的に待ち解除にする. 00083 * 'u' : 対象タスクをsus_tskにより強制待ち状態にする. 00084 * 'm' : 対象タスクの強制待ち状態をrsm_tskにより解除する. 00085 * 'd' : 対象タスクにdly_tsk(10秒)を呼び出させ,時間経過待ちにさせる. 00086 * 'x' : 対象タスクに例外パターン0x0001の例外処理を要求する. 00087 * 'X' : 対象タスクに例外パターン0x0002の例外処理を要求する. 00088 * 'y' : 対象タスクにdis_texを呼び出させ,タスク例外を禁止する. 00089 * 'Y' : 対象タスクにena_texを呼び出させ,タスク例外を許可する. 00090 * 'r' : 3つの優先度(HIGH_PRIORITY,MID_PRIORITY,LOW_PRIORITY)のレ 00091 * ディキューを回転させる. 00092 * 'c' : 周期ハンドラを動作開始させる. 00093 * 'C' : 周期ハンドラを動作停止させる. 00094 * 'b' : アラームハンドラを5秒後に起動するよう動作開始させる. 00095 * 'B' : アラームハンドラを動作停止させる. 00096 * 'z' : 対象タスクにCPU例外を発生させる(タスクを終了させる). 00097 * 'Z' : 対象タスクにCPUロック状態でCPU例外を発生させる(プログラムを 00098 * 終了する). 00099 * 'V' : get_utmで性能評価用システム時刻を2回読む. 00100 * 'v' : 発行したシステムコールを表示する(デフォルト). 00101 * 'q' : 発行したシステムコールを表示しない. 00102 */ 00103 00104 #include <kernel.h> 00105 #include <t_syslog.h> 00106 #include <t_stdlib.h> 00107 #include "syssvc/serial.h" 00108 #include "syssvc/syslog.h" 00109 #include "kernel_cfg.h" 00110 #include "sample1.h" 00111 00112 /* 00113 * サービスコールのエラーのログ出力 00114 */ 00115 Inline void 00116 svc_perror(const char *file, int_t line, const char *expr, ER ercd) 00117 { 00118 if (ercd < 0) { 00119 t_perror(LOG_ERROR, file, line, expr, ercd); 00120 } 00121 } 00122 00123 #define SVC_PERROR(expr) svc_perror(__FILE__, __LINE__, #expr, (expr)) 00124 00125 /* 00126 * 並行実行されるタスクへのメッセージ領域 00127 */ 00128 char_t message[3]; 00129 00130 /* 00131 * ループ回数 00132 */ 00133 ulong_t task_loop; /* タスク内でのループ回数 */ 00134 ulong_t tex_loop; /* 例外処理ルーチン内でのループ回数 */ 00135 00136 /* 00137 * 並行実行されるタスク 00138 */ 00139 void task(intptr_t exinf) 00140 { 00141 volatile ulong_t i; 00142 int_t n = 0; 00143 int_t tskno = (int_t) exinf; 00144 const char *graph[] = { "|", " +", " *" }; 00145 char_t c; 00146 00147 SVC_PERROR(ena_tex()); 00148 while (1) { 00149 syslog(LOG_NOTICE, "task%d is running (%03d). %s", 00150 tskno, ++n, graph[tskno-1]); 00151 for (i = 0; i < task_loop; i++); 00152 c = message[tskno-1]; 00153 message[tskno-1] = 0; 00154 switch (c) { 00155 case 'e': 00156 syslog(LOG_INFO, "#%d#ext_tsk()", tskno); 00157 SVC_PERROR(ext_tsk()); 00158 assert(0); 00159 case 's': 00160 syslog(LOG_INFO, "#%d#slp_tsk()", tskno); 00161 SVC_PERROR(slp_tsk()); 00162 break; 00163 case 'S': 00164 syslog(LOG_INFO, "#%d#tslp_tsk(10000)", tskno); 00165 SVC_PERROR(tslp_tsk(10000)); 00166 break; 00167 case 'd': 00168 syslog(LOG_INFO, "#%d#dly_tsk(10000)", tskno); 00169 SVC_PERROR(dly_tsk(10000)); 00170 break; 00171 case 'y': 00172 syslog(LOG_INFO, "#%d#dis_tex()", tskno); 00173 SVC_PERROR(dis_tex()); 00174 break; 00175 case 'Y': 00176 syslog(LOG_INFO, "#%d#ena_tex()", tskno); 00177 SVC_PERROR(ena_tex()); 00178 break; 00179 #ifdef CPUEXC1 00180 case 'z': 00181 syslog(LOG_NOTICE, "#%d#raise CPU exception", tskno); 00182 RAISE_CPU_EXCEPTION; 00183 break; 00184 case 'Z': 00185 SVC_PERROR(loc_cpu()); 00186 syslog(LOG_NOTICE, "#%d#raise CPU exception", tskno); 00187 RAISE_CPU_EXCEPTION; 00188 SVC_PERROR(unl_cpu()); 00189 break; 00190 #endif /* CPUEXC1 */ 00191 default: 00192 break; 00193 } 00194 } 00195 } 00196 00197 /* 00198 * 並行して実行されるタスク用のタスク例外処理ルーチン 00199 */ 00200 void tex_routine(TEXPTN texptn, intptr_t exinf) 00201 { 00202 volatile ulong_t i; 00203 int_t tskno = (int_t) exinf; 00204 00205 syslog(LOG_NOTICE, "task%d receives exception 0x%04x.", tskno, texptn); 00206 for (i = 0; i < tex_loop; i++); 00207 00208 if ((texptn & 0x8000U) != 0U) { 00209 syslog(LOG_INFO, "#%d#ext_tsk()", tskno); 00210 SVC_PERROR(ext_tsk()); 00211 assert(0); 00212 } 00213 } 00214 00215 /* 00216 * CPU例外ハンドラ 00217 */ 00218 #ifdef CPUEXC1 00219 00220 void 00221 cpuexc_handler(void *p_excinf) 00222 { 00223 ID tskid; 00224 00225 syslog(LOG_NOTICE, "CPU exception handler (p_excinf = %08p).", p_excinf); 00226 if (sns_ctx() != true) { 00227 syslog(LOG_WARNING, 00228 "sns_ctx() is not true in CPU exception handler."); 00229 } 00230 if (sns_dpn() != true) { 00231 syslog(LOG_WARNING, 00232 "sns_dpn() is not true in CPU exception handler."); 00233 } 00234 syslog(LOG_INFO, "sns_loc = %d sns_dsp = %d sns_tex = %d", 00235 sns_loc(), sns_dsp(), sns_tex()); 00236 syslog(LOG_INFO, "xsns_dpn = %d xsns_xpn = %d", 00237 xsns_dpn(p_excinf), xsns_xpn(p_excinf)); 00238 00239 if (xsns_xpn(p_excinf)) { 00240 syslog(LOG_NOTICE, "Sample program ends with exception."); 00241 SVC_PERROR(ext_ker()); 00242 assert(0); 00243 } 00244 00245 SVC_PERROR(iget_tid(&tskid)); 00246 SVC_PERROR(iras_tex(tskid, 0x8000U)); 00247 } 00248 00249 #endif /* CPUEXC1 */ 00250 00251 /* 00252 * 周期ハンドラ 00253 * 00254 * HIGH_PRIORITY,MID_PRIORITY,LOW_PRIORITY の各優先度のレディキュー 00255 * を回転させる. 00256 */ 00257 void cyclic_handler(intptr_t exinf) 00258 { 00259 SVC_PERROR(irot_rdq(HIGH_PRIORITY)); 00260 SVC_PERROR(irot_rdq(MID_PRIORITY)); 00261 SVC_PERROR(irot_rdq(LOW_PRIORITY)); 00262 } 00263 00264 /* 00265 * アラームハンドラ 00266 * 00267 * HIGH_PRIORITY,MID_PRIORITY,LOW_PRIORITY の各優先度のレディキュー 00268 * を回転させる. 00269 */ 00270 void alarm_handler(intptr_t exinf) 00271 { 00272 SVC_PERROR(irot_rdq(HIGH_PRIORITY)); 00273 SVC_PERROR(irot_rdq(MID_PRIORITY)); 00274 SVC_PERROR(irot_rdq(LOW_PRIORITY)); 00275 } 00276 00277 /* 00278 * メインタスク 00279 */ 00280 void main_task(intptr_t exinf) 00281 { 00282 char_t c; 00283 ID tskid = TASK1; 00284 volatile ulong_t i; 00285 int_t tskno = 1; 00286 ER_UINT ercd; 00287 PRI tskpri; 00288 SYSTIM stime1, stime2; 00289 #ifdef TOPPERS_SUPPORT_GET_UTM 00290 SYSUTM utime1, utime2; 00291 #endif /* TOPPERS_SUPPORT_GET_UTM */ 00292 00293 SVC_PERROR(syslog_msk_log(LOG_UPTO(LOG_INFO), LOG_UPTO(LOG_EMERG))); 00294 syslog(LOG_NOTICE, "Sample program starts (exinf = %d).", (int_t) exinf); 00295 00296 /* 00297 * シリアルポートの初期化 00298 * 00299 * システムログタスクと同じシリアルポートを使う場合など,シリアル 00300 * ポートがオープン済みの場合にはここでE_OBJエラーになるが,支障は 00301 * ない. 00302 */ 00303 ercd = serial_opn_por(TASK_PORTID); 00304 if (ercd < 0 && MERCD(ercd) != E_OBJ) { 00305 syslog(LOG_ERROR, "%s (%d) reported by `serial_opn_por'.", 00306 itron_strerror(ercd), SERCD(ercd)); 00307 } 00308 SVC_PERROR(serial_ctl_por(TASK_PORTID, 00309 (IOCTL_CRLF | IOCTL_FCSND | IOCTL_FCRCV))); 00310 00311 /* 00312 * ループ回数の設定 00313 * 00314 * TASK_LOOPがマクロ定義されている場合,測定せずに,TASK_LOOPに定 00315 * 義された値を,タスク内でのループ回数とする. 00316 * 00317 * MEASURE_TWICEがマクロ定義されている場合,1回目の測定結果を捨て 00318 * て,2回目の測定結果を使う.1回目の測定は長めの時間が出るため. 00319 */ 00320 #ifdef TASK_LOOP 00321 task_loop = TASK_LOOP; 00322 #else /* TASK_LOOP */ 00323 00324 #ifdef MEASURE_TWICE 00325 task_loop = LOOP_REF; 00326 SVC_PERROR(get_tim(&stime1)); 00327 for (i = 0; i < task_loop; i++); 00328 SVC_PERROR(get_tim(&stime2)); 00329 #endif /* MEASURE_TWICE */ 00330 00331 task_loop = LOOP_REF; 00332 SVC_PERROR(get_tim(&stime1)); 00333 for (i = 0; i < task_loop; i++); 00334 SVC_PERROR(get_tim(&stime2)); 00335 task_loop = LOOP_REF * 400UL / (stime2 - stime1); 00336 00337 #endif /* TASK_LOOP */ 00338 tex_loop = task_loop / 5; 00339 00340 /* 00341 * タスクの起動 00342 */ 00343 SVC_PERROR(act_tsk(TASK1)); 00344 SVC_PERROR(act_tsk(TASK2)); 00345 SVC_PERROR(act_tsk(TASK3)); 00346 00347 /* 00348 * メインループ 00349 */ 00350 do { 00351 SVC_PERROR(serial_rea_dat(TASK_PORTID, &c, 1)); 00352 switch (c) { 00353 case 'e': 00354 case 's': 00355 case 'S': 00356 case 'd': 00357 case 'y': 00358 case 'Y': 00359 case 'z': 00360 case 'Z': 00361 message[tskno-1] = c; 00362 break; 00363 case '1': 00364 tskno = 1; 00365 tskid = TASK1; 00366 break; 00367 case '2': 00368 tskno = 2; 00369 tskid = TASK2; 00370 break; 00371 case '3': 00372 tskno = 3; 00373 tskid = TASK3; 00374 break; 00375 case 'a': 00376 syslog(LOG_INFO, "#act_tsk(%d)", tskno); 00377 SVC_PERROR(act_tsk(tskid)); 00378 break; 00379 case 'A': 00380 syslog(LOG_INFO, "#can_act(%d)", tskno); 00381 SVC_PERROR(ercd = can_act(tskid)); 00382 if (ercd >= 0) { 00383 syslog(LOG_NOTICE, "can_act(%d) returns %d", tskno, ercd); 00384 } 00385 break; 00386 case 't': 00387 syslog(LOG_INFO, "#ter_tsk(%d)", tskno); 00388 SVC_PERROR(ter_tsk(tskid)); 00389 break; 00390 case '>': 00391 syslog(LOG_INFO, "#chg_pri(%d, HIGH_PRIORITY)", tskno); 00392 SVC_PERROR(chg_pri(tskid, HIGH_PRIORITY)); 00393 break; 00394 case '=': 00395 syslog(LOG_INFO, "#chg_pri(%d, MID_PRIORITY)", tskno); 00396 SVC_PERROR(chg_pri(tskid, MID_PRIORITY)); 00397 break; 00398 case '<': 00399 syslog(LOG_INFO, "#chg_pri(%d, LOW_PRIORITY)", tskno); 00400 SVC_PERROR(chg_pri(tskid, LOW_PRIORITY)); 00401 break; 00402 case 'G': 00403 syslog(LOG_INFO, "#get_pri(%d, &tskpri)", tskno); 00404 SVC_PERROR(ercd = get_pri(tskid, &tskpri)); 00405 if (ercd >= 0) { 00406 syslog(LOG_NOTICE, "priority of task %d is %d", tskno, tskpri); 00407 } 00408 break; 00409 case 'w': 00410 syslog(LOG_INFO, "#wup_tsk(%d)", tskno); 00411 SVC_PERROR(wup_tsk(tskid)); 00412 break; 00413 case 'W': 00414 syslog(LOG_INFO, "#can_wup(%d)", tskno); 00415 SVC_PERROR(ercd = can_wup(tskid)); 00416 if (ercd >= 0) { 00417 syslog(LOG_NOTICE, "can_wup(%d) returns %d", tskno, ercd); 00418 } 00419 break; 00420 case 'l': 00421 syslog(LOG_INFO, "#rel_wai(%d)", tskno); 00422 SVC_PERROR(rel_wai(tskid)); 00423 break; 00424 case 'u': 00425 syslog(LOG_INFO, "#sus_tsk(%d)", tskno); 00426 SVC_PERROR(sus_tsk(tskid)); 00427 break; 00428 case 'm': 00429 syslog(LOG_INFO, "#rsm_tsk(%d)", tskno); 00430 SVC_PERROR(rsm_tsk(tskid)); 00431 break; 00432 case 'x': 00433 syslog(LOG_INFO, "#ras_tex(%d, 0x0001U)", tskno); 00434 SVC_PERROR(ras_tex(tskid, 0x0001U)); 00435 break; 00436 case 'X': 00437 syslog(LOG_INFO, "#ras_tex(%d, 0x0002U)", tskno); 00438 SVC_PERROR(ras_tex(tskid, 0x0002U)); 00439 break; 00440 case 'r': 00441 syslog(LOG_INFO, "#rot_rdq(three priorities)"); 00442 SVC_PERROR(rot_rdq(HIGH_PRIORITY)); 00443 SVC_PERROR(rot_rdq(MID_PRIORITY)); 00444 SVC_PERROR(rot_rdq(LOW_PRIORITY)); 00445 break; 00446 case 'c': 00447 syslog(LOG_INFO, "#sta_cyc(1)"); 00448 SVC_PERROR(sta_cyc(CYCHDR1)); 00449 break; 00450 case 'C': 00451 syslog(LOG_INFO, "#stp_cyc(1)"); 00452 SVC_PERROR(stp_cyc(CYCHDR1)); 00453 break; 00454 case 'b': 00455 syslog(LOG_INFO, "#sta_alm(1, 5000)"); 00456 SVC_PERROR(sta_alm(ALMHDR1, 5000)); 00457 break; 00458 case 'B': 00459 syslog(LOG_INFO, "#stp_alm(1)"); 00460 SVC_PERROR(stp_alm(ALMHDR1)); 00461 break; 00462 case 'V': 00463 #ifdef TOPPERS_SUPPORT_GET_UTM 00464 SVC_PERROR(get_utm(&utime1)); 00465 SVC_PERROR(get_utm(&utime2)); 00466 syslog(LOG_NOTICE, "utime1 = %ld, utime2 = %ld", 00467 (ulong_t) utime1, (ulong_t) utime2); 00468 #else /* TOPPERS_SUPPORT_GET_UTM */ 00469 syslog(LOG_NOTICE, "get_utm is not supported."); 00470 #endif /* TOPPERS_SUPPORT_GET_UTM */ 00471 break; 00472 case 'v': 00473 SVC_PERROR(syslog_msk_log(LOG_UPTO(LOG_INFO), 00474 LOG_UPTO(LOG_EMERG))); 00475 break; 00476 case 'q': 00477 SVC_PERROR(syslog_msk_log(LOG_UPTO(LOG_NOTICE), 00478 LOG_UPTO(LOG_EMERG))); 00479 break; 00480 #ifdef BIT_KERNEL 00481 case ' ': 00482 SVC_PERROR(loc_cpu()); 00483 { 00484 extern ER bit_kernel(void); 00485 00486 SVC_PERROR(ercd = bit_kernel()); 00487 if (ercd >= 0) { 00488 syslog(LOG_NOTICE, "bit_kernel passed."); 00489 } 00490 } 00491 SVC_PERROR(unl_cpu()); 00492 break; 00493 #endif /* BIT_KERNEL */ 00494 default: 00495 break; 00496 } 00497 } while (c != '\003' && c != 'Q'); 00498 00499 syslog(LOG_NOTICE, "Sample program ends."); 00500 SVC_PERROR(ext_ker()); 00501 assert(0); 00502 }
Copyright © 2008 by Kijineko Inc.