[HOME] [AKI-H8のページ]

RTOS を移植する

ここにかかれている内容は既に古くなっています。
HOSそのものは http://sourceforge.jp/projects/hos/で開発が続けられています。

履歴

1999年1月20日 - 公開
1999年1月21日 - 誤記を修正
1999年2月11日 - 不具合対策追記

フリーの H8 用リアルタイムOS、HOS-H8 を GNU H8クロス開発環境でコンパイ ルできるように移植します。このソフトウェアは Windows 環境上で動作するイ エローソフト社のコンパイ ラ用に作られているので、これを gcc / gas 用に 変更する必要があります。 C の部分については特に手をいれる必要がありませんが、アセンブラの部分は、 「Cとアセンブラのリンケージの方法の違い」や、「アセンブラ表記の違い」が 存在するので、これらを修正する必要があります。

HOS-H8 GNU 移植ソースパッケージ

下記の対応を行った GNU 対応ソースを公開します。 これを (hos-h8-v0.02-gnu.tar.gz[58879bytes])ダウンロードください。 移植部分の解説はあまり丁寧ではないので、 ソースと以下の内容をあわせてお読みください。

GNU版バグ対応

hos-h8-v0.02-gnu.tar.gz には次の不具合があることが分かりました。

HOS-H8 について

doc/manual.txt から引用します。
HOS-H8 はμITRON3.0仕様に準拠した 日立 H8/300H シリーズ用のリアルタイ ムOSです。 主に個人レベルでのホビーを目的とした物でROM化するシステムにリンクす るだけで簡単に組み込むことが出来ます。
Ryuz Laboratoryにて公開さ れています。詳細やオリジナルファイルの入手に関してはこちらを御覧ください。

なお、以下の内容は Ver 0.02 のソースを元に記述してあります。

まずはじめに SJIS DOSファイルからの変換

HOS-H8 のソースは漢字コードが SJIS、また、行末コードが CRLF で EOF も存 在します。これを EUC、行末コード LF に変換します。
% sh
$ for i in *.c; do
$ ack -ezuA $i
$ rm $i.bak
$ done

Cソースの対応

アセンブラソースの対応

アセンブラソースはCソース程簡単ではありません。 アセンブラ表記が違うからです。これを1行1行手で変換するのは大 変なので、sed を使って可能な限り一括して変換してしまいます。

もちろん C とアセンブラとのリンケージなどどうしても自動では対応できない 物があります。これらはそれぞれ手で対応していきます。

イエローソフトのアセンブラ表記と、gas のアセンブラ表記の違いは代表的な物 では次のようになります。

項目 イエローソフト表記 gas 表記
16進数表現 H'1234 0x1234
2進数表現 B'0101 0b0101
定数定義 シンボル equ 式 .equ シンボル 式
外部ラベル宣言 public ラベル名 .global ラベル名
外部ラベル参照 .extern ラベル名 記述不要
segment 定義 segment セグメント名 .section セクション名
データ領域 ds.b/ds.w/ds.l .space 1/.space 2/.space 4

その他、gas ではレジスタ名は小文字である必要があります。 そして、H8/300H 用である宣言 .h8300h をファイルの先頭に加えます。

例えば H' -> 0x の変換を行う sed script は

です。また equ の変換を行う sed script は です(\tは実際には TAB コードです)。
こうして gas でエラーが出ないように変換するスクリプトは、 このように(asmconv.sed.gz[410bytes]) なりました。 これを のように実行すれば変換できます。

Cとアセンブラのリンケージの対応

gcc H8/300 コンパイラでは、引数の引渡しに、最初の3つまでが R0(ER0) か ら R2(ER2) を使い、残りはスタックを使います。 また、関数コールにおいて、R3(ER3)からR6(ER6)のレジスタが破壊されてはいけ ません。
一方イエローソフトのコンパイラでは、引数の引渡しは全てスタックを使用しま す。また R6(ER6)以外はレジスタ破壊は許されます。
オリジナルソースではイエローソフトのルールに合わせて書かれているので、こ れを gcc 用に書き換えます。

例として task_dsp.asm の swc_dsp() の書き換えを以下に示します。(diff -c の出力結果です。先頭が - はオリジナルから削る部分、+ は追加する部分です。)

 ; -----------------------------------------------
 ;  タスク切り替え
 ;  H   __swc_dsp(T_TCB *tcb);
 ; -----------------------------------------------
+;;     er0 : T_TCB *tcb
+;;
                .section .text
                .global ___swc_dsp
 ___swc_dsp:    
+       push.l  er3
+       push.l  er4
+       push.l  er5
                push.l  er6
-               mov.l   @(8, er7), er0  ; 引数取得
+                                       ; 引数取得
                subs    #2, er7         ; リターンパラメータ用領域作成
                mov.l   @_curtcb,er1
                mov.l   er7,@er1        ; スタックポインタ保存
                mov.l   @er0, er7       ; スタックポインタ復帰
                mov.l   er0,@_curtcb    ; 新tcb登録
                pop.w   r0              ; リターンパラメーター取得
                pop.l   er6
+       pop.l   er5
+       pop.l   er4
+       pop.l   er3
                rts

コンフィグレータの対応

コンフィグレーションファイルの解析部分はそのまま流用でき、変更する部分は 基本的にアセンブラの記述方法を gas に合わせます。変更部分は全て
 #ifdef __GNUC__
 〜
 #else
 〜
 #endif
でくくってあります。

スタートアップルーチンの対応

リンカが決定するアドレスを参照して、DATAセグメントのコピー、BSSセグメン トのクリアを行っている部分を対応します。
本来なら GNU 側がデフォルトで使用しているラベルを使うように、スタートアッ プルーチンを書き換えるのででしょうが、 今回はオリジナルソースが使用しているラベルが使えるように、リンカスクリプ ト側を書き換えます。

データセグメントの初期化は DATA_rom から書かれているデータを DATA_start から DATA_size バイトコピーすることで行います。 つまり DATA_start から実際に参照するデータを DATA_rom のアドレスに出力す るように書けば良いわけです。リンカスクリプトの DATAセグメント部分は次の ようになります。

.data : AT (ADDR(.text) + SIZEOF(.text)){
        DATA_rom = ADDR(.text) + SIZEOF(.text);
        DATA_start = .;
        *(.data)
        DATA_end = .;
        }  > ram
        DATA_size_low = SIZEOF(.data);
AT() を使います。これで解決アドレスと格納アドレスを別々にできます。 そして、スタートアップルーチンで使用するシンボルにアドレスをそれぞれ代入 します。

BSS セグメントは解決アドレスと格納アドレスは同じですので、シンボルへの代 入だけです。

.bss : {
        BSS_start = .;
        *(.bss)
        *(COMMON)
        BSS_end = .;
        }  >ram
        BSS_size_low = SIZEOF(.bss);

更にスタートアップアドレス hos_start を ENTRY() で定義します。

ENTRY("hos_start");

その他

時間管理を行う構造体 SYSTIME が 48ビットデータを上位16ビットの utime と 下位32ビットの ltime のメンバに分けられています。デフォルトの指定だと gcc は 4バイトアライメントを行い、 utime と ltime の間に2バイトのパディ ングを挿入します。このため、48ビットデータが連続して参照できることを期 待しているアセンブラソースの ___add_systime() と ___add_tim() および ___cmp_tim() の動作が正常に行えません。
このためこれらの関数を timer.c の中に Cの関数として書き直しました。 将来速度が気になるのならインラインアセンブラに書き直せば良いでしょう。

$Id: porting-hos-h8.html,v 1.2 2003/06/16 16:15:48 hoso Exp $


[HOME] [AKI-H8のページ]