sample1.c

説明を見る。
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.

ホームページ制作