酔漢電子工作手帳

2007-03-29

1秒休止

| 23:54 | 1秒休止 - 酔漢電子工作手帳 を含むブックマーク はてなブックマーク - 1秒休止 - 酔漢電子工作手帳

昨日のプログラムは、1行印字して終了するだけでした。次に連続して何行も印字させるプログラムを作って見ましょう。

今回紹介するのは、終わりなく延々と印字するプログラムです。そのため、syslog()関数はwhile(1)ループの中にいれます。

syslog()関数では、現在何回目のループであるかも印字させることにします。C言語の標準ライブラリを使っている場合には、このような印字はprintf()で行います。TOPPERS/JSPsyslog()関数はprintf()関数と同じように使うこともできます。今回の例ではフォーマット文字列"%d"を使って10進数の印字を行います。

   syslog( "answer= %d", ans );

printfと異なるのは、勝手に改行される点です。したがって、一行にまとめたい出力は、syslog()関数一回で出力する様にしてください。

一行印字を連続して行うと、あっという間にものすごい数の行が出力されてしまいます。そこで、今回は出力後に1000mS休止させることにします。

    tslp_tsk( 1000 );

tslp_tsk()関数はuITRON4のAPIです。この関数関数を呼び出したタスクを休止状態にいれます。休止状態に入ったあと、引数で指定したミリ秒経過すると、タスクを実行可能状態に戻します。

これらを使って1秒ごとにメッセージを出力するプログラムにまとめたのが以下のコードです。ファイル名はsample1.c。

#include <t_services.h>
#include "kernel_id.h"
#include "sample1.h"

void main_task(VP_INT exinf)
{
    int i;
	
    i = 0;
    while(1){
        syslog(LOG_NOTICE, "Hello, ADuC7026! %d", i );
        i++;
        tslp_tsk( 1000 );
    }
}

sample1.hとsample1.cfgは昨日のものを使いまわします。

このタスクが印字する周期はおよそ1秒であることに気をつけてください。tslp_tsk()は引数で指示した時間休止することを保証しますが、それよりわずかに長くなるのが普通です。これは、TOPPERS/JSPの内部時間がティック・タイマーと言われるタイマーを元に計測されるためです。ティックタイマーの生成する割り込み(ティック)が時間計測の分解能になり、その分解能より高い精度は望めません。

また、仮に正確に1000mS休止して復帰しても、syslog()などの実行時間が余計にかかるため、やはり全体の周期はやや長くなります。

トラックバック - http://ecrafts.g.hatena.ne.jp/suikan/20070329

2007-03-28

最小プログラム

| 23:11 | 最小プログラム - 酔漢電子工作手帳 を含むブックマーク はてなブックマーク - 最小プログラム - 酔漢電子工作手帳

TOPPERS/JSPの最小プログラム*1です。起動するとタスクを一つだけアクティブにし、メッセージをシリアル・ポートに出力してタスクを終了します。メッセージの出力には、ロギング機能を使っています。

プログラムのビルドやダウンロードに関しては組込みプログラミングにEclipseを使う(2)を参照してください。

手順としては、

  1. sample1を構築
  2. それを改造

という流れになります。

プログラム本体

筋から言えばここはコンフィグレーション・ファイルから説明するべきかもしれません。しかしそれでは色気も何もないので、一番楽しそうなメイン・プログラムから。ファイルはsample1.cです。

#include <t_services.h>
#include "kernel_id.h"
#include "sample1.h"

void main_task(VP_INT exinf)
{
    syslog(LOG_NOTICE, "Hello, ADuC7026!" );
}

三つあるインクルード文はそれぞれ

  • TOPPERS/JSPの標準ヘッダ・ファイル
  • コンフィグレータが出力したヘッダ・ファイル
  • ユーザーが用意したヘッダファイル

を、読み込みます。一番基本的な構成です。

関数main_task()はその名の通りメイン・タスクとして実行されます。実行するとsyslog()関数を呼び出して終了します。

syslog()関数TOPPERS/JSPの持つロギング関数で、どのような媒体に出力するかは処理系依存です。しかし標準的な実装ではシリアルポートへログデータを記録します。PizzaFactory3.1 Expressに同梱されているADuC7026用のTOPPERS/JSPも、シリアルポートにしゅつりょくします。

9600bps,8bit,non-parityに設定した端末ソフトをつないでプログラムを実行すると、システム起動メッセージに続いて"Hello, ADuC7026!"と端末に表示されます。

ヘッダ・ファイル

ファイルはsample1.hです。このファイルは通常はアプリケーション自身で使うほか、コンフィグレーション・ファイルからも読み込まれます。今回のアプリケーションは規模が小さいため、コンフィグレータが使う資源のみを宣言しています。

コンフィグレータは関数プロトタイプを理解できません。コンフィグレータは_MACRO_ONLYマクロを事前に宣言しますので、プロトタイプは_MACRO_ONLYマクロが宣言されていないときにのみ有効とすることで、問題を回避しています。

タスク優先度とスタックサイズはいずれもコンフィグレーションの中で使います。この二つはプログラム中で使うことはないと思われますので、コンフィグレーション・ファイルに直接値を書きこんでもかまいません。しかし、タスクの構成に関するパラメータは、関数宣言などとともにヘッダ・ファイルにまとめたほうが、全体の見通しはすっきりするでしょう。

#include <t_services.h>

/* メインタスクのパラメタ */
#define MAIN_PRIORITY     5    /* 優先度 */
#define MAIN_STACK_SIZE 512    /* スタックサイズ */

#ifndef _MACRO_ONLY
extern void main_task(VP_INT exinf);

#endif /* _MACRO_ONLY */

コンフィグレーション・ファイル

ファイル名はsample1.cfgです。

コンフィグレーション・ファイルはコンフィグレータに対して静的にセマフォタスクといった資源を作り出すよう指示するためのファイルです。コンフィグレータが作り出した資源は、実行中にアプリケーションプログラムから利用することができます。

TOPPERS/JSPタスクセマフォアプリケーションの実行中に作り出す手段を持っていないため、コンフィグレーション・ファイルがこれらを作り出す唯一の手段になります。

コンフィグレーションファイルには二つのインクルード文が存在します。

#includeは、コンフィグレータの実行中にファイルを読み込み、コンフィグレータに利用させるためのものです。INCLUDEはコンフィグレータの出力ファイル、つまりkernel_id.hとkernel_cfg.hの中に#include文を埋め込むためのものです。両者は実際にファイルが読み込まれる時期が異なりますので注意してください。

CRE_TSKは、タスクを静的に作るためのAPIです。詳しくはuITRON4の仕様書を参照してください。今回の例ではMAIN_TASKという識別子がコンフィグレータによって生成されます。この識別子は、アプリケーション・プルグラム中で「この」タスクを示すIDとしていつでも利用できます。

コンフィグレーション・ファイルの最後にある3つのインクルード文は、ティック・タイマーとロギング機能を実装するためのタスクセマフォ割り込みハンドラを宣言するためのものです。

ティック・タイマOSの必須機能ですから、必ず宣言しなければなりません。

ロギング機能は便利ですので、特に理由がない限り使うほうがいいでしょう。

インクルード文のパスはシステムによって異なります。PizzaFactory3 Expressを使った場合にはプラグイン内部へのパスがここに現れます。したがって、以下のコンフィグレーション・ファイルをそのままPizzaFactoryで使おうとしてもうまく行きません。PizzaFactoryがsample1用に生成したパスをそのまま使ってください。

#define _MACRO_ONLY
#include "sample1.h"

INCLUDE("\"sample1.h\"");
CRE_TSK(
    MAIN_TASK, { 
        TA_HLNG|TA_ACT,     /* 高級言語記述、最初からアクティブ */
        0,                  /* extinfに渡す値 */
        main_task,          /* タスクとして使う関数 */
        MAIN_PRIORITY,      /* タスク実行順位 */
        MAIN_STACK_SIZE,    /* タスク・スタックの大きさ[Byte] */
        NULL                /* スタックのアドレス。NULLなら自動割付 */
    });

#include "/your/path/systask/timer.cfg"
#include "/your/path/systask/serial.cfg"
#include "/your/path/systask/logtask.cfg"

実行結果

ADuC7026TOPPERS/JSPアプリケーションを動かすには、プログラムを内蔵フラッシュROMに書き込みます。そしてターゲットのシリアルポートに9600bps,8bit,non-parityのターミナルを接続し、ターゲットをリセットします。

正しくビルド、書き込みができていれば以下のような出力がターミナル上に現れます。

f:id:suikan:20070328235712p:image

*1:の、ちょっと先

トラックバック - http://ecrafts.g.hatena.ne.jp/suikan/20070328