Naknet blog

Nothing to believe, nothing else to believe.

<< Digital Photo Frame Screen Saver (dpf.scr) v0.05 | main |

TOPPERS/ASPのサンプルプログラムが動かない件

国産組み込み向けリアルタイムOSとして、TOPPERSというものがあります。先日、秋月のH8/3069F LANボードを購入したのですが、付属のH8/OSがいかにも古く、また後継のものも既にSHシリーズに開発がシフトしているようだったので、TOPPERS/ASP 1.6.0の導入を検討しました。

以下は、うちの環境でサンプルプログラム(sample1)が動作するようになるまでの過程です。

開発環境

まず開発環境の構築です。せっかくならば開発環境も(対応する範囲で)最新のものにしたいと思い、まずはCygwinで構築を試みました。
一応gccもbinutilsもnewlibもビルド+インストールはできたのですが、色々と問題が発生してしまいました。

まず第一の問題は、コンフィギュレータ(cfg)です。ビルドが面倒だったので、公式サイトからバイナリを落としてきたのですが、うちのCygwin-1.7.9-1では起動しませんでした。

そこでソースからビルドしたのですが、まず、簡易パッケージに含まれていたcfgは、boostの最新バージョンに対応していません(native_file_string()がおかしい云々)。そこで公式サイトから別途ダウンロードしたものを使用したのですが、使用したboostのバージョン(1.48.0)が、公式で動作確認が取れているものより新しかったため、問題が発生しました。それは、boost::filesystemのpathが、パスの区切り文字をご丁寧に '/' ではなく '\' と認識するため、cfgが変なエスケープシーケンスを含んだC言語のソースコードを生成します。この結果、コンパイルが通らなくなるというものです。これに対しては、cfgを頑張って修正するか、出力されたファイル cfg1_out.c をsedで修正するくらいしか方法がありません。

次に、Makefileで最適化(-O2)が行われていたため、genoffsetが認識できない.Sが出力されてエラーが出てしまいました。
この対策としては、../configureした後にMakefileを手動で編集し、COPTSに-O2としている箇所を-O0とすれば回避できます。しかし、このようにするとmakeoffset.cだけではなくすべてのファイルで最適化が無効になってしまうため、makeoffset.cだけを特別扱いするような別の対策が必要と考えられます。

以上の修正によりsample1はなんとかビルドできました。しかし、これを苫小牧高専の簡易モニタ上で実行すると、"task1 is running (xxx)."という表示は出るのですが、キーを入力すると固まってしまうという現象が発生しました。

この現象は、調べてみると他の人も遭遇しているようでした。しかも全く別のCPUでも発生しているようで、全く原因不明でした。

調べた方によれば、文字入力があった後でmain_task()がdispatchされていないということらしく、カーネルのバグを疑いました。

OSの変更

ただ、単純に開発環境がいけないだけという可能性もあります。そもそも、単純にmakeするだけではだめで、色々とファイルの修正が必要になる(しかも汚い方法で…)時点でCygwinの限界を感じたため、新たにVM上にCentOS 6.0 (x86)をインストールしました。ここでx86_64ではgccがビルドできません。x86(i686)版でやる必要があります。そういうわけでOSを2回インストールした後、この上にgcc-3.4.6+binutils-2.16.1+newlib-1.19.0で開発環境を改めて構築しました。

付属の各種txtによれば、hms(Hitachi Micro System)形式ではなくelf(Executable and Linking Format)形式をターゲットに指定する(--target=h8300-elf)こともできるそうです。そこで最初はそちらで環境を構築することにしました。しかしながら、構築した環境でsample1をビルドし、RAMに転送して実行しようとしても、全く動きませんでした。おそらく別の個所の修正が必要になるんだと思いますが、面倒なのでh8300-hmsで環境を構築しなおしました。

Linux上ではboost::filesystemのパスの問題も起きず、修正もMakefileの-O2の部分だけでmake dependもmakeも通ります。というわけなのでこれから環境を構築される方はCygwinではなくネイティブのLinux OSを用いることをおすすめします。

それでも動かない

そこで改めてsample1をビルドして実行してみたのですが、やはりキー入力をすると固まってしまいます。タスク切り替えに問題があるのかとtest_task1を実行してみましたが、すべてpassします。同様にtest_sem1、test_sem2もpassします。

make cleanをしてからビルドなど色々やってみたのですが、解決しません。

warningが出ていた

何日かブランクを開けた後、ふと、make中に"warning: function called through a non-compatible type"が出ていることに気付きました。これはgcc-3.4から導入された機能で、別の型からキャストされて得た関数ポインタを経由して関数を呼ぼうとすると、問答無用で落ちるというものらしいです。

原因はこれでした。TOPPERSのカーネルでは、自動生成された割込みハンドラ(kernel_cfg.c内)でキャストした関数ポインタを使用して関数をコールしており、この部分でabortしていたのでした。生成された関数は、具体的には

void
_kernel_inthdr_53(void)
{
	i_begin_int(53);
	LOG_ISR_ENTER(53);
	((ISR)(sio_rx_isr))((intptr_t)(USER_PORTID));	// ← HERE
	LOG_ISR_LEAVE(53);
	i_end_int(53);
}

のようになっており、文字が入力され、受信され、割込みが発生するとこの関数内でabortしてしまいます。

対策としては、kernel/kernel.tfを次

818a819,821
> $             ///// gcc3.4 /////
>               $TAB$ISR fp;$NL$
> $             ///// /gcc3.4 /////
830c833,836
<
$TAB$((ISR)($ISR.ISR[order]$))((intptr_t)($ISR.EXINF[order]$));$NL$
---
> $             ///// gcc3.4 /////
>                       $TAB$fp = (ISR) ($ISR.ISR[order]$);$NL$
>                       $TAB$(*fp)((intptr_t)($ISR.EXINF[order]$));$NL$
> $             ///// /gcc3.4 /////

のように書き換え、コンパイラを欺くか、あるいはgcc-3.4以前を使用します。私は前者の方法を採りました。この修正により、生成されるソースコードは次

void
_kernel_inthdr_53(void)
{
    ISR fp;	// **
    i_begin_int(53);
    LOG_ISR_ENTER(53);
    fp = (ISR) (sio_rx_isr); // **
    (*fp)((intptr_t)(USER_PORTID));	// **
    LOG_ISR_LEAVE(53);
    i_end_int(53);
}

のようになります。注意点として、同様のkernel.tfはextension/ovrhdr/kernelとextension/mutex/kernelにもありますので、これらの拡張を使用する際にも同様の修正が必要になることが挙げられます。

これで無事に3系gccの最新版でsample1が動くようになりました。タスク切り替えもちゃんと動いています。

これだけで1週間は悩みました…。最初から動作確認が取れている環境でビルドしなかったのが悪いんですが、最新のコンパイラを使う際は気をつけようということで。

参考サイト

開発環境構築にあたって参考とさせて頂いたサイトです。

他にも「h8300-hms-gcc」などで検索すればたくさん出てきます。



comments (0) | trackbacks (0)

Comments

Comment Form

  • "http"等はNGワードになっています。
  • どうしても投稿できない場合・返信が必要な場合は、メールでお願いします(nospam.を削除してください)。

Trackbacks