dポイントプレゼントキャンペーン実施中!

 皆さん、有難う御座います。時々質問させて頂いています。

 今回は、ベクターアドレスをC言語で書く方法について質問します。
 ルネサスのH8マイコンを使っています。モニターを使うとRAM上に割り込みの仮想ベクターを作れます。
 仮想ベクターには、割り込みのジャンプ先アドレスが書かれます。
 現在アセンブラで書いているのですが、C言語で書く方法は無いでしょうか。
 二つの方法で書きたいと思っています。
 アセンブラで次の二つの方法に相当するC言語命令を知りたい。

(1)ORGとEQU命令を使った方法
(2)ムーブ(Z80ならロード)命令で関数のアドレスをメモリに書く方法

 ルネサスにはHEWと言うソフトが有りますが、HEW特有の命令によらず、一般的なコンパイラが持っている機能で実現したい。

 以上宜しくお願いします。

A 回答 (19件中11~19件)

>そうなんです。

C言語の本に載っているような一般性のある方法を探っています。

#1さんも 割り込み機能のないものはちょっと想像つきませんが、いいこと言っています。
割り込みベクタのないものはありますよね。SH3

ルネサスのスーパーH では、 SH1 SH2までベクタありますが、SH3以降上位のものは
ベクタテーブルは存在しません。
ベクタテーブルそのものは、アークテクチャ依存なのです。
アークテクチャ依存部分を、一般的方法でC言語で記載しても、貴殿の言う共通部品には
ならないですね。

少なくとも、ベクタテーブルの構成が同じアークテクチャのCPU間では共通部品となる
場合はありますが、管理上、共通部品とすると思わぬバグになるほうが危険だと思います。
    • good
    • 0
この回答へのお礼

 R32Cさん、こんにちは

 ヘッダ・ファイルは共通に使えるようになっていますよね。
 それと同様にC言語に伴うアセンブラ・ソフト部分も変更せず、C言語部分の変更だけで対処出来ないかなという事です。

お礼日時:2009/05/27 00:21

>アセンブラ・ソフトは変更せず、C言語ソフトだけで対応する方法を探している次第です。



とりあえずC言語中にベクタのセクション名が指定可能なgccかHEWに変更すれば全て解決します。あえてC38H.exeを使う理由は無いはずですよね?
    • good
    • 0
この回答へのお礼

 zwiさん、こんにちは

 「何でも出来るは、何も出来ない」と言う格言が有りまして、複雑なソフトは使い難い。
 C38H.exeはマニュアルが単純で理解しやすい。
 コンパイルが速いので、こまめにコンパイルしても苦にならない。

 MS-DOS時代のソフトなので、自分でバッチファイルを作れないと使いこなせませんが。

 でも私の質問は、「アセンブラなら実現方法が分かるけど、C言語で実現する方法を知りたい」という事です。
 割り込みテーブルの事は、その質問の背景です。

 関数のアドレスを知る事により、例えばスイッチ文のようにして配列に入った関数アドレスから関数を呼ぶ方法などに発展する訳です。

お礼日時:2009/05/26 23:37

> main関数に飛ぶ前にstart_cと言うアセンブラ・ソフトで、スタックポインタの設定や、割り込みベクタの設定をしています。


> C言語プログラムに割り込みが有ったり無かったりすると、start_cも書き換えなければなりません。
> start_cは変更せず、C言語プログラムだけで処理する方法を探っている次第です。

これの事ですかね?
> .ORG H'000070 ;IMIA1
> .DATA.L _timer1INT
> .END

(2)の通り、割り込み関数のアドレスをベクタに同様設定で(1)も解決のはずですね。割り込みを開始する前に設定しておけば問題ないです。
    • good
    • 0
この回答へのお礼

 回答有難う御座います。

 C言語に付随するアセンブラ・ソフトとかサブコマンド・ファイルなどは、出来るだけ共通化してどのプロジェクトでも同じ物を使いたい。
 割り込み処理が増えたときアセンブラ・ソフトも変えるのでは、ソフトが共通部品にならず専用部品となってしまいます。
 アセンブラ・ソフトは変更せず、C言語ソフトだけで対応する方法を探している次第です。

お礼日時:2009/05/25 23:07

もし差支えが無いようでしたら、お使いのコンパイラーとか開発環境を教えていただけると、もっとベストな回答が得られるのではと思います。

    • good
    • 0
この回答へのお礼

 回答有難う御座います。

 開発環境は秋葉原の秋月電商で売っているH8/3048用の
コンパイラです。

 MS-DOSベースで古いのですが、シンプルでコンパイル時間が短いので気に入っています。

 ルネサスのHEWは機能が多過ぎて、まだ使いこなしていません。

お礼日時:2009/05/24 16:59

>>一般的なコンパイラが持っている機能で実現したい


何をもって「一般的なコンパイラ」と解釈すれば良いかわからないです。
エンベデッド系では、やはりそれなりに特化してしまうのではないでしょうか?
例えば、VCでもやはりi386系に特化した命令(#pragma等)ありますし、gccでもBorland Cでも同じです。
また、関数の終わりはアセンブラいうと「rts」命令ですが、割り込み処理の関数の場合「rte」でないとNGです。やはり#pragma interrupt等で、この関数は割込み処理だから「rte」でリターンしてね!みたいに指示しないといけません。だからと言ってゴリ押してきなコーディングはやめた方が良いと思います。

それはさておき、私が知っている限り、HEWやgccで用いている方法なのですが、ベクターのテーブル化です。
具体的には、
--------------------------------
typedef void (*fp) (void);
#define VECT_SECT__attribute__ ((section (".vectors")))

const fp HardwareVectors[] VECT_SECT = {
start,
(fp)0,
(fp)0,
(fp)0,
(fp)0,
(fp)0,
(fp)0,
INT_NMI,
INT_TRAP1,
INT_TRAP2,
INT_TRAP3,
INT_TRAP4,
・・・
--------------------------------
としてベクターテーブルを「vectors」という名前でセクション化します。
そして、リンク時にLDスクリプトを用い仮想ベクタアドレスを割り当ててやるという方法です。
--------------------------------
MEMORY
{
ex_ram: o = 0x400000, l = 0x10000
vectors: o = 0xffc000, l = 0x0100
}
SECTIONS
{
.vectors : {
*(.vectors)
} > vectors
・・・
--------------------------------
という感じです。
本家RenesasのHEWやgccでも用いているので、ある意味一般的ではとおもうのですが。
以上、あくまでも、ご参考程度に。
    • good
    • 0
この回答へのお礼

 回答有難う御座いました。

 質問者自身は解答欄に投稿できないようなので、此処をお借りして皆さんに今までの報告をします。

 皆さんの回答のおかげで、次の二つが分かりました。

(1)関数のアドレスの配列
void (* const vectors[64])() = { &test }

(2)関数のアドレスをベクタアドレスに直接書き込む方法
*(void **)(0xFFE130) = &test ;

 (1)を仮想ベクタに配置するために
#pragma section VEC_TEST
としましたが上手く行きません。サブ・コマンドも対応するようにしてあります。
 これはアセンブラ・ソフトの中で VEC_TEST セクションを作る事で対応出来そうです。
 ところが此処で、伏兵が現れました。

 #pragma interrupt (test) とすると、(1)(2)両方とも使えないのです。
 (1)と(2)同時ではなく、単独に書いて試験しても駄目でした。
 割り込み関数のアドレスは、求められないのです。

 せっかく良い所まで行ったのに残念です。
 でも皆さんのおかげで、色々な事が分かりました。
 有難う御座いました。

 アセンブラ・ソフトなら対応出来るので、挑戦はこの辺で中止にしようと思います。

 どうも有難う御座いました。

お礼日時:2009/05/25 23:49

回答1


ルネサスのCコンパイラ特有の命令
#pragma interrupt
でベクターを書くことが可能です。

-----------------------------------------------------------------------------------
H8S、H8/300シリーズ C/C++コンパイラ、
アセンブラ、最適化リンケージエディタ
コンパイラパッケージVer.6.01 ユーザーズマニュアルP.256

・ ベクタテーブル指定(vect=)をした場合は指定したベクタテーブル番号へその関数アド
レスを割り付けます。
 例:(cpu=300 の時)
 #pragma interrupt (f2(vect=4)) /* 関数f2 のアドレスを8 番地   */
 void f1(void) /* (ベクタ番号4)へ割り付けます */
 {
   :
 }
-----------------------------------------------------------------------------------

ですが、ご希望の回答ではないと思います。
1.ルネサスCコンパイラ特有の命令で一般的コンパイラではない。
2.いわゆるROMモニター用の仮想ベクタ用ではない。


回答2
一般的な方法では、結局リンカー、ロケーターの指示は必要に
なりますが、仮想ベクタなら関数アドレステーブルなので、

typedef void (*FP)(void);

const FP VECT[] =
{
(FP)handler1,
(FP)handler2,

};
という感じで書いて、仮想ベクタに割り付けられるように(ロケータ指示)
すればできるように思います。

>(1)ORGとEQU命令を使った方法
Cの一般記述方法には、ありませんが、ルネサスCの#pragma命令で
あったように思います。

>(2)ムーブ(Z80ならロード)命令で関数のアドレスをメモリに書く方法
??
FP fnc;
fnc = &handler1;
とか書けばよいのでは?
    • good
    • 0
この回答へのお礼

 回答有難う御座います。

>ですが、ご希望の回答ではないと思います。
>1.ルネサスCコンパイラ特有の命令で一般的コンパイラではない。
>2.いわゆるROMモニター用の仮想ベクタ用ではない。

 そうなんです。C言語の本に載っているような一般性のある方法を探っています。
 「アセンブラなら書けるけど、C言語ではどのように書くのか」を探っています。

お礼日時:2009/05/25 23:17

割り込みベクタ自体は単なる配列ですので、記述することはそれほど難しくありません(説明の必要はありませんね)。



問題は、ORGに相当する機能がC言語の標準規格では規定されていないことです。したがって、これについては、どうしても処理系の独自拡張か、アセンブラまたはリンカの機能に頼らざるを得ません。
ただし、モニタによっては、任意のアドレスに仮想割り込みベクタを配置できるようになっているかもしれませんので、モニタの仕様を調べてみることをお勧めします。

なお、割り込みハンドラに関しても、本来であれば標準的なC言語で記述することができません。
H8に限定するなら、レジスタの退避・復帰やリターン命令をハンドアセンブルした内容を配列として定義してから、強引にキャストして関数とみなしてやれば何とかなります。
    • good
    • 0
この回答へのお礼

 jacta さんにはお世話になっています。


 (2)については、下記のように解決しました。test関数のアドレスをベクタアドレス領域の 0xFFE130 に書き込んでいます。

-----------------------------------
voidtest(void)
{
*(void **)(0xFE130) = &test;
}
-----------------------------------------------
FF3C4 7A01000FF3C4 MOV.L #H'000FF3C4:32,ER1
FF3CA 01006B81E130 MOV.L ER1,@H'FE130:16
FF3D0 5470 RTS
----------------------------------------------




>割り込みベクタ自体は単なる配列ですので、記述することはそれほど難しくありません(説明の必要はありませんね)。

 関数のアドレスを書き込む方法が分からないと配列に出来ません。
 しかし(2)が解けたので、もう少し頑張れば(1)も出来るかなと思っています。
 配列の先頭は サブ・コマンド ファイルをいじります。


 どうも有難う御座いました。

お礼日時:2009/05/24 13:14

>アドレスを指定して関数を呼び出す方法は有りますか


の人ですよね。

(1)ORGとEQU命令を使った方法
一般にはC言語に該当する命令体系はありません。
マイコン専用C言語コンパイラでは特別に#pragma等で設けている場合があります。HEWにもその機能があります。下記サイトなどを参考に。
http://wave.iobb.net/doc/summary/h8wiki/wifky.cg …
ちなみにH8用のgccでは記述方法が異なります。

(2)ムーブ(Z80ならロード)命令で関数のアドレスをメモリに書く方法
仮想ベクターはRAM上にあるはずですから、ポインタを仮想ベクターのアドレスにセットして書き換えれば割り込みベクタを変更できます。
ですが、将来ROM化する場合に問題になりますので好ましい方法ではありません。
    • good
    • 0
この回答へのお礼

>アドレスを指定して関数を呼び出す方法は有りますか
の人ですよね。

 そうです。その節はお世話になりました。


 (2)については、下記のように解決しました。test関数のアドレスをベクタアドレス領域の 0xFFE130 に書き込んでいます。

-----------------------------------
voidtest(void)
{
*(void **)(0xFE130) = &test;
}
-----------------------------------------------
FF3C4 7A01000FF3C4 MOV.L #H'000FF3C4:32,ER1
FF3CA 01006B81E130 MOV.L ER1,@H'FE130:16
FF3D0 5470 RTS
----------------------------------------------




>(2)ムーブ(Z80ならロード)命令で関数のアドレスをメモリに書く方法
>仮想ベクターはRAM上にあるはずですから、ポインタを仮想ベクターのアドレスにセットして書き換えれば割り込みベクタを変更できます。
>ですが、将来ROM化する場合に問題になりますので好ましい方法ではありません。


 main関数に飛ぶ前にstart_cと言うアセンブラ・ソフトで、スタックポインタの設定や、割り込みベクタの設定をしています。
 C言語プログラムに割り込みが有ったり無かったりすると、start_cも書き換えなければなりません。
 start_cは変更せず、C言語プログラムだけで処理する方法を探っている次第です。



 (2)が解けたので、もう少し頑張れば(1)も出来るかなと思っています。

 どうも有難う御座いました。

お礼日時:2009/05/24 12:48

>今回は、ベクターアドレスをC言語で書く方法について質問します。



ベクターアドレスを書く方法ですか?
ベクターアドレスといってもアドレスには変わりないですよね
(メモリ・マップドI/Oの場合)

単に16進で表記すればよいのでは?
char* p ;
p = 0x12345678;
みたいに
ま、10進がお好きなら10進でも構わないわけですが....

こんなことは常識なので
おそらく質問なさらないと思います。

おそらく

ベクターアドレス

というのは
勘違い、もしくは、誤記
の類で

本当は
割り込みルーチンの記述法
を知りたいと推測します

間違いでしたらごめんなさい

結論を申し上げます。
割り込みルーチンを書くための”規約"はC言語に定められていません。

割り込みの手順は完全にCPU依存ですし、
そもそも
割り込み機能のないCPUだってあり得ます。

脱"CPUアーキティクチャ"を目指すC言語が
割り込みを標準に取り入れないのは当然です。

ということで
各処理系に完全に委ねられています。

ですので

>一般的なコンパイラが持っている機能で実現したい。

は不可能です。
    • good
    • 0
この回答へのお礼

 早速の回答有難う御座います。

 (2)については、下記のように解決しました。test関数のアドレスをベクタアドレス領域の 0xFFE130 に書き込んでいます。

-----------------------------------
voidtest(void)
{
*(void **)(0xFE130) = &test;
}
-----------------------------------------------
FF3C4 7A01000FF3C4 MOV.L #H'000FF3C4:32,ER1
FF3CA 01006B81E130 MOV.L ER1,@H'FE130:16
FF3D0 5470 RTS
----------------------------------------------



>単に16進で表記すればよいのでは?
>char* p ;
>p = 0x12345678;

 関数のアドレスなので、「char *」で無く他の何かと思っていたのですが、上の例によると、「void **」のようです。

 (1)の課題は、「char* p ;」に相当する変数の書かれるアドレスを指定したいと言うことです。それがアセンブラの「ORG」相当と言う事です。

 (2)が解けたので、もう少し頑張れば(1)も出来るかなと思っています。

 どうも有難う御座いました。

お礼日時:2009/05/24 12:36

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!