UserProg


ユーザプログラム


 本装置は標準でいくつかのプロセス(システムプロセス)を搭載しており、接続形態によってはそのまま利用することができます。(例えば、ソケットサーバプロセス+RS−232Cプロセス -> 標準ソケットサーバ)

 一方、ユーザ固有の機能を実現するにはシステムプロセスの機能だけだは不十分なケースが多く、そのような場合にユーザ固有なユーザプログラムの作成が必要になります。
 ユーザプログラムからシステムプロセスおよびBIOSファンクションを利用することで、単純および効果的にユーザ固有の処理を記述することが可能です。

ユーザプログラムの構造
ユーザプログラムの作成
ユーザプログラムの本装置への組込み
ユーザプログラムの実行
ユーザプログラムの制御
本装置のメモリマップ
ユーザプログラム作成上の制約

【ユーザプログラムの構造】

 ユーザプログラムには次のヘッダを先頭に付加し、倫理アドレス0x0c060000以降にマッピングします。

+0
+1
+2
--
0C060000
0C060004
0C060008
プログラム
名称
0C06000C
0
(予約)
バージョン(上位)
バージョン(下位)
0C060010
プログラムサイズ
0C060014
エントリアドレス
0C060018
:
:
プログラムコード
データ
変数エリア

  プログラム名称
     ユーザプログラムの名称を指定します。
     英数字と_(アンダーバー)のみ指定可能。大文字と小文字は区別されます。

  バージョン
     ユーザプログラムのバージョンを2桁で指定します。

  プログラムサイズ
     上記ヘッダを含むプログラム全体のバイト数を65536の倍数で指定します。
     65536の倍数以外を指定した場合切り上げになります。

  エントリアドレス
     制御を渡す関数の論理アドレスを指定します。
     ユーザプログラムが起動されると、システムはユーザプログラムにプロセスIDを割り当て、
     これを引数としてエントリ関数に渡して制御を移します。

 上記ヘッダをC言語表現すると、以下のようになります。
     void main(int aPid);  /* エントリルーチンのプロトタイプ */
     const struct {
       char  Name[13];
       char  dmy;
       char  Ver;
       char  Rev;
       int   size;
       void  (*func)(int);
     } PrgHead = {"Sample", 0, 1, 0, 65536, main};
     プログラム名 = Sample 、バージョン = 1.00 、サイズ = 65536 、エントリ = main

【ユーザプログラムの作成】

 ユーザプログラムは、日立超LSIシステムズ社製の「SuperH Series C comliler Simulator Package」を使用してコンパイル・リンクし、最終ファイルとして本装置にダウンロードできるファイル形式である「モトローラSファイル」を生成します。
 本装置のユーザプログラムは「ビッグエンディアン」で作成します。コンパイラの標準ライブラリは、「SH3用」「非ポジションインディペンデント」「ビッグエンディアン」のもを選択してリンクします。

 以下に統合環境(Hitachi Embedded Workshop)での設定例を示します。

 @オブジェクトファイルの追加

  ※PrgHead 構造体の宣言してあるソースファイルから生成されるオブジェクトファイルを先頭にもっていきます。

 Aセクションの設定

  ※開始番地を60000番地に設定して下さい。
  ※セクションの順番は「CPDB」として下さい。

 B標準ライブラリ関数設定


  ※標準ライブラリの設定を変更します。
  ※EC++のチェックは外します。

 CCPUの設定

  ※CPUは「SH3」で「ビッグエンディアン」を設定します。

【ユーザプログラムの本装置への組込み】

 「モトローラSファイル」形式で生成されたユーザプログラムのオブジェクトファイルは、本装置を設定モード(ロータリスイッチ「7」にした状態)にし、RS−232CインタフェースまたはFTPクライアントにより本装置のユーザプログラム格納エリアへダウンロードします。
  なお、BIOSファンクションの「WriteProgram」(プログラム書込み)を使用することにより、ユーザプログラム実行中に、別のユーザプログラムを本装置のユーザプログラム格納エリアへダウンロードすることもできます。

 本装置は、64キロバイトを一単位としたユーザプログラム格納エリアを10個管理しています。各ユーザプログラムが64キロバイト以内であれば、最大10本のユーザプログラムを本装置上で同時に実行させることができます。また、1本のユーザプログラムで最大640キロバイトのプログラムとして動作させることできます。

 ユーザプログラムは、格納エリアの上位の空きエリアから格納されます。このとき、プログラムヘッダの中のプログラム名称がキーとなり、同じプログラム名称のユーザプログラムをダウンロードすると、すでに格納されているプログラムを上書きします。プログラムサイズが64キロバイトを超える場合、格納に必要な連続エリアに格納されます。

 下図の例では
     @ 64キロバイトのプログラム(Prg1)が1本格納されているときに、
           192キロバイトのプログラム(Prg2)をダウンロードした場合です。
     A さらにPrg1を変更(Prg1' サイズが192キロバイト)してダウンロードした場合です。

00040000
       1
Prg1
     1
Prg1
     1
空き
       2      2      2
       3      3
Prg2
     3
Prg2
       4      4      4
       5
@   5
A   5
       6
空き
⇒   6
⇒   6
Prg1'
       7      7      7
       8      8
空き
     8
       9      9      9
空き
      10     10     10

 従いまして、プログラム格納エリアが虫食い状態で使用されていた場合、64キロバイト以上の連続エリアが確保できなくて大きなユーザプログラムのダウンロードができない場合があります。その場合、一旦全てのユーザプログラムを削除して、再度ダウンロードして下さい。

【ユーザプログラムの実行】

 本装置に格納したユーザプログラムを実行させるには、本装置の動作パラメータ設定において、起動時に実行するプログラムの名称を「起動プログラム」の項目に設定します。またユーザプログラムの中から「Exec」(プログラム実行)ファンクションをコールすることでも起動可能です。
 ユーザプログラムを実行する場合、ユーザプログラムは実行時に格納エリアから、0x0C060000 番地から始まるRAMエリアに転送されます。
 プログラムサイズに 65536 を指定した場合の実行時のメモリ配置は、プログラム先頭は 0x0C060000 番地にスタックポインタは 0x0C070000 の初期化されます。

 ユーザプログラムの実行エリアは論理アドレスです。複数のユーザプログラムが動作する場合も、各プログラムは 0x0C060000 番地から配置されますが、対応する物理アドレスは互いに重ならないように配置されます。
 131072バイトの大きさのプログラム(Prg1)と196608バイトの大きさのプログラム(Prg2)が同時に動作する場合、下図のような配置になります。()内は物理アドレスを表します。

0C060000
Prg1
0C060000
Prg2
(0C060000)
Prg1の定数
(0C080000)
Prg2の定数
Prg1のコード
Prg2のコード
 
Prg1の変数
Prg1のスタック
0C07FFFF
Prg2の変数
(0C07FFFF)
Prg2のスタック
 
 
0C08FFFF
 
(0C0AFFFF)

【ユーザプログラムの制御】

 本装置が起動されるとシステムは、動作パラメータで指定されている「起動プログラム」名称をもとに、該当するユーザプログラムをユーザプログラム格納エリアより実行メモリにロードし、プロセスIDを付与と共に、制御をユーザプログラムのエントリに移します。

 ユーザプログラムを複数実行させる場合は、本装置起動後最初に実行するユーザプログラム内において「Exec」(プログラム実行)ファンクションを利用して、他のユーザプログラムを実行します。
 「Exec」ファンクションが呼び出されると、システムは該当プログラムをユーザプログラム格納エリアからプログラム実行メモリにロードし、新たなプロセスIDの付与と共に、制御をそのユーザプログラムのエントリアドレスに移し、呼び出し元のプログラムは一時停止状態となります。
 「Exec」ファンクションは、ユーザプログラムの起動の他、システムの持つシステムプロセス(FTPサーバプロセス・ソケットクライアントプロセス・ソケットサーバプロセス・TELNETサーバプロセス・UDPスループロセス・RS−232Cスループロセス)をユーザプログラムから利用する場合にも使用します。なおシステムプロセスについてはプロセスリファレンスを参照して下さい。

 呼び出し元プログラムが一時停止状態となるBIOSファンクションには、「Exec」ファンクションのほか、「PutMsg」( メッセージ追加 )ファンクション・「GetMsg」( メッセージ取得 )ファンクション・「TimeWait」( 指定時間ウェイト )ファンクションがあります。

 以下に制御の移り変わりの例を示します。

[UserPrg1]
@
[UserPrg2]
Exec "UserPrg2" →→→→→→→→ A
  ↓
  B  ←←←←←←←←←←←←← PutMsg
  ↓
Exec "UserPrg3" →→→→→→→→ C
  ↓
[UserPrg3]
GetMsg →→→→→→→→→→ D
  ↓
 E  ←←←←←←←←←←←←←←←←←←←←←←←←←←←←←← PutMsg
  ↓
GetMsg →→→→→→→→→→ F
  ↓
PutMsg →→→→→→→→→→ G
  ↓
 H  ←←←←←←←←←←←←←←←←←←←←←←←←←←←←←← PutMsg
  ↓

 @〜Hは処理の順番を示します。また→→→は制御の移り変わりを示します。

【本装置のメモリマップ】

ROMマップ
RAMマップ
+000000
Boot格納領域
+000000
システム予約領域
+060000
ユーザプログラム
+030000
動作パラメータ格納領域
動作領域
+040000
+100000
ユーザプログラム
ヒープ領域
格納領域
+0E0000
ユーザPM格納領域
+200000
+100000
システム使用領域
Kernel格納領域
+140000
+500000
未使用領域
未使用領域
+1FFFFF
+7FFFFF

 未使用領域について

 RAMマップ上の 500000H〜7FFFFFH は未使用領域となります。ユーザプログラムより直接未使用領域のアドレスにアクセスすることで、ワークメモリとして使用することが可能です。
 ただし、システム起動時による初期化やメモリ管理は行なわないため、メモリ破壊等を起こさないように注意して下さい。

【ユーザプログラム作成上の制約】

 本装置上では、ユーザプログラム以外に少なくとも「リモートセットアップ」プロセス、「HTTPD」プロセスが動作しています。
   ・リモートセットアップ リモートPCより設定の取得・変更を行う機能
   ・HTTPD 設定用のWEBサーバ
 また、ユーザプログラムが複数動作する場合、ユーザプログラムがシステムプロセスを起動している場合等他の「プロセス」が存在します。

 従いまして、ユーザプログラムが「制御を離さない作り」をした場合、他の「プロセス」が動作できなくなります。

 「制御を離さない作り」とは「PutMsg」( メッセージ追加 )ファンクション・「GetMsg」( メッセージ取得 )ファンクション・「TimeWait」( 指定時間ウェイト )を定期的に呼び出さないプログラムのことで、完全に自プロセス以外が動作しない状態になります。
 この方法でも単独プログラムとして動作はしますが、リモートから設定参照・設定変更ができなため、本装置のロータリスイッチ、リセットスイッチを操作しなければなりません。また、他の「プロセス」の動作が必要な場合は、この作りは避けて下さい。

 推奨するユーザプログラムの作り(メインルーチン)は以下になります。

<ユーザプログラム例> (プロセス起動、メッセージ送信をしない場合)
 void main(aPid)    /* メインルーチン(エントリアドレス) */
 {
   TMsg     Rmsg;
     /* @ ユーザプログラム 初期化処理 */
   while(1) {
     /* A ユーザプログラム メイン処理 */
     if(TimeWait(10) != 0 ) { /* 制御を一旦戻す */
       /* 自プロセス宛のメッセージが無ければ TimeWait の戻り値は0 */
       GetMsg(&Rmsg);
       switch(Rmsg.cmd) {
         case MSG_SYSMSG:
           /* B ユーザプログラム シリアル処理 */
           /* C ユーザプログラム ソケット処理 */
           break;
        /* エラーメッセージ処理 */
         default:
           if(Rmsg.prmlen > 4) Free(Rmsg.prm);
           Rmsg.dest = Rmsg.src;
           Rmsg.src = (short)aPid;
           Rmsg.rqrs = MSG_ERROR;
           Rmsg.prmlen = (Word)4;
           Rmsg.prm = (char **)(int)Rmsg.cmd;
           Rmsg.cmd = ERR_MSGCMD;
           PutMsg(&Rmsg);
           break;
       }
     }
   }
 }

 上記@〜Cへ「ユーザプログラム処理」を記述して下さい。