今まで、RXマイコンで、挙動が怪しい事があって、その原因が判らなかったが、
やっと判明した・・・
症状としては、
・スタックに配置した変数が書き換わる場合
・割り込みが多重に起動するような場合に多く発生
・多重じゃなくても割り込み関連が絡む場合など
どうもスタックが壊れている感じではあるけど、プログラムを追っても、問題無
さそう・・・
RXマイコンでは、スタックは、割り込み用スタック(ISP)と、ユーザース
タック(USP)に分かれていて、起動時、「start.s」のアセンブラプログラム
で設定されている。
ISPをメモリーの後半に置き、その手前にUSPを設定している。
当初、ISPの容量は32バイトくらいしか無かったので、256バイトにした
が、症状に変化は無い・・・
.text .global _start .type _start,@function _start: # スタックの設定(SP:__stack、USP:__stack - 128) mov.l #__stack, r0 mvtc r0, isp sub #128,r0 mvtc r0, usp
ソフトウェアーマニュアルを読み直していたら、何と「R0」レジスタと「SP」
は扱いが同一となっていた!
汎用レジスタ R0 には、汎用レジスタとしての機能に加えて、スタックポインタ (SP)としての機能が割り当てられています。
あ!、「R0」は使ったら駄目なんだ・・・・・・・・・
そこで、単純に、レジスタ名を変更
.text .global _start .type _start,@function _start: # スタックの設定(SP:__stack、USP:__stack - 128) mov.l #__stack, r5 mvtc r5, isp sub #128,r5 mvtc r5, usp
この修正後、今までのおかしな挙動が直った。
今まで、結構大きなプログラムを動かしていたけど、よく動いてたなぁ・・・
経験的に、レジスターセットの後ろ(R15とか)にSPを置いてあるのが普通と
思っていたから、何も考えずに、R0を使ったのが間違いだった・・・
※ソフトウェアーマニュアルを良く読まなかったのが悪いのだけど・・・
-----
RXマイコンでは、スーパーバイザーモードとユーザーモードのRUNレベルがあり、
通常はユーザーモードで動作させる。
ユーザーモードで特権命令を実行すると、「特権違反例外」が発生する。
ユーザーモードに移行するには、「rte」命令などを実行した場合に、退避してあった
ステータスレジスターを復帰するが、その際、ユーザーモードフラグが有効になって
いれば、ユーザーモードに移行する為、以下のような、少しキワドイプログラムで移
行する。
# PMレジスタを設定し、ユーザモードに移行する、ユーザースタックに切り替わる mvfc psw,r1 or #0x00100000, r1 push.l r1 # UレジスタをセットするためにRTE命令を実行する mvfc pc,r1 add #10,r1 push.l r1 rte nop
※PCにオフセットを加える事で、RTE命令の下に復帰する。