プロが教える店舗&オフィスのセキュリティ対策術

ルネサスのマイコンH8Sのプログラムを組んでおります。
プログラムの構成がBoot部分とアプリケーション部分に分かれており、
Bootはアドレス0番地から、アプリは3000番地以降の領域を使用するようになっています。
完成されたBootを使用してアプリケーションのプログラムを組まなければならなく、また、Bootは変更できないことになっています。
このBootの中のベクターテーブル上で、割り込みが発生した場合の飛び先のアドレスがRAM上になるように設定してあります。

このため、アプリケーションソフトでは、
割り込みが発生した場合のRAM上の飛び先に
FLASH ROM上の指定したアドレスにジャンプする命令を書き、
FLASH ROMのジャンプ先には、実行したい関数を書きたいのですが、

(1)RAM上の特定のアドレスからFLASH ROM上の指定したアドレスにジャンプさせる方法。
(2)FLAH ROM上の指定したアドレスに関数を記述する方法。
を知りたいのですが、
どなたか教えて頂けないでしょうか?
開発環境はHew4 言語はC言語を使用しております。
私自身が理解不足であるため質問内容が伝わりにくいかと思いますが、
宜しくお願い致します。

A 回答 (3件)

特定のアドレスに特定のデータを書き込む方法。



例:6000番地から、順に、16進数の01,23,45,67を書き込む
unsigned char *addr;
addr = 0x6000;
addr[0] = 0x01;
addr[1] = 0x23;
addr[2] = 0x45;
addr[3] = 0x67;

もし「3014番地にジャンプするアセンブラコード」が「5A 00 14 30」であって、RAMの飛び先が6004番地なら
unsigned char *addr;
addr = 0x6004;
addr[0] = 0x5A;
addr[1] = 0x00;
addr[2] = 0x30;
addr[3] = 0x14;
と書けば良いです。

また「関数のアドレスにジャンプ」の場合は
unsigned char *addr;
addr = 0x6004;
int int_var;
void (*func_addr)(void);
func_addr = function_name; /*関数void function_name(void)のアドレスを受け取る*/
int_var = (int)func_addr); /*intにキャストする*/
addr[0] = 0x5A; /*JMP命令の1バイト目*/
addr[1] = 0x00; /*JMP命令の2バイト目*/
addr[2] = (int_var >> 8) & 0xff; /*アドレスの上位をセット*/
addr[3] = int_var & 0xff; /*アドレスの下位をセット*/

*注意*
上記の「0x5A 0x00」の命令コードは「たとえばの値」です。本当のJMP命令が何になるかは、アセンブラの命令コード表で調べて下さい。
また、上記では、16ビットアドレスを「上位、下位」の順にしていますが、H8Sでは順番が異なるかも知れません。命令コード表を良く見て「正しい順番」を確認して下さい。

この回答への補足

済みません。上記の訂正なのですが、

unsigned char *addr;
addr = 0xffb418;(RAM上の割り込みが発生した場合の飛び先アドレス)

がコンパイルエラーの原因のようです。
記述方法を以下のようにに変えてみたのですがやはり上手く行きません。

addr = (char*)0xffb418;

どなたか、お分かりの方いましたら、お願い致します。

補足日時:2010/01/29 10:07
    • good
    • 0
この回答へのお礼

折角回答頂いたのですが、試すことが出来ずお礼が遅くなってしまい申し訳ございません。
回答頂いた例に従い記述したのですが、
void (*func_addr)(void); の行で、
以下のようなコンパイルエラーとなってしまいます。
何か解決策がお分かりでしたら教えていただけないでしょうか?

C2500 (E) Illegal token "void"
C2230 (E) Illegal function call
C1000 (W) Illegal pointer assignment

宜しくお願いいたします。

お礼日時:2010/01/28 19:12

(1)(2)ともにC言語仕様で簡易に記述するすべはありません,


コンパイラ, リンカの仕様に依存する記述となりますが, Hew環境であれば仕組みさえ分かってしまえば, 割りと簡単に構築可能です.
以下, 参考になりそうなポイントです.

(1) RAM上の特定アドレスにジャンプ命令が記述されており, オペランドとしてROM上のアドレスを示すメモリ空間のオフセットが示されていれば実現します.

RAMは揮発性のため, あらかじめプログラムコード(以下, コード)を置いておくことはできませんので, スタートアップ処理内にてコードをROM上からRAM上へ展開(コピー)する必要があります.

Bootの処理内にてH'3000以降のコードをRAM上へコピーする処理が書かれているだろうと推測します. 例えば初期値付きの変数などはRead/Write可能とするためにスタートアップ処理にてRAM上へコピーする必要がありますが, 同様の処置をコードに対しても実施し実稼動中はRAM上にコピーされたコードで動作します. このような手間を掛ける理由は, ROM上のコードで動作している場合はその領域からフェッチする為ROMをイレースすることができず, ファームウェアを更新することができません.(イレースした途端暴走します)

(2) アセンブラであれば, オペランドに即値を記述すればいいのですが, C言語ベースで開発する場合リンカに割付アドレスを指定しておくことで簡易に実現が可能です.

Hew環境で実施するのであれば, ツールチェーンのリンカ設定にてセクションを追加し, ソースコード上で"#pragma section <セクション名>"を記述することで割付セクションを指定します.

既存のファームウェアを読み解く場合, 関数記述による処理フローを追うよりも リンカによるセクション管理がどのように設定されているかを意識して読み解く方が幸せになれると思います.
    • good
    • 0

 ルネサス提供のモニタを使っていますか?そのモニタの仮想ベクタを使っていますか?


 
    • good
    • 0

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