RAMパリティエラー発生箇所の特定

Kirinさん

現在、RL78での開発をしています。

単体動作でRAMパリティエラーが発生しています。
オンチップデバッグではRAMパリティエラーが発生しないみたいなのでオンチップデバッグによるチェックができません。

何処でRAMパリティエラーが発生しているか確認できる方法はあるのでしょうか?

RAMの初期化は出来ているはずなのですが・・・
  • yutyuさん

    私もRAMパリティエラーが出せなくて悩んだことありますけど
    オンチップデバッグ中にRAMパリティを出す方法を知っていますよ。

    やり方は、プログラムをRUNさせた後にターゲットボードの電源を一旦OFFにしてから、ONにしてください。
    そうすると電源OFFによって、チップの内部が初期化されて
    パリティを含めてRAMの状態が不定値になります。
    電源をONするとリセットベクタからプログラムが走り出し、ブレークポイントを設定したアドレスまで実行してくれますよ。


    電源OFFで不定値になるのは、CMOSプロセスならではの挙動ですね。
  • Kirinさん

    回答ありがとうございます。

    プログラムをRUNさせた後に、ターゲットボードの電源をOFFにしてから、ONにして実行し、RPEFにアクセス・ブレークをかけて、調べていますがRAMパリティエラーが出ないみたいです。
    現在、理由がわかりませんが
    「_stkinit」スタック領域初期化関数内で無限ループに陥っています。
  • yutyuさん

    電源OFF-ON操作で、少し現象に近づきましたね。

    ちなみに、RPEFにアクセスブレークを設定してもブレークは掛かりません。RAMパリティが発生してもCPUがRPEFに1をライトしているわけではないので、、

    おそらくスタートアップルーチンを修正して使っていらっしゃると思いますけれども、ライトする前にリードしている個所があると思います。

    一旦ブレークすると再RUNさせても、もうRAMパリティが出なくなる可能性があるのでブレーク毎に毎回電源のOFF/ONが必要かと思います。


    PS
    デバッグ手順に不備があったの削除しました。
    代わりに、スタートアッププログラムの先頭に
    RPERFが1(RPEFによるリセット)だったら分岐するようなアセンブラコードを埋め込んで、そこにブレークポイントを設定してみてください。
    RAMパリティ(内部リセット)が発生したらそこに分岐するはずです。

    ;----------------------------------------------------------------
    ; setting the register bank RB0 as work register set
    ;----------------------------------------------------------------
    MOV A,RESF
    CMP0 A
    SKZ
    BR $$ ;ここにブレークポイント設定

    SEL RB0
    ;----------------------------------------------------------------
    ; setting the mirror area
    ;----------------------------------------------------------------

  • Kirinさん

    RAMパリティエラーによる分岐を確認しました。
    ただ、ブレークポイントに設定しても、STOPせず、手動で停止ボタンを押下するとブレーク設定ポイントで停止するような状態です。

    zzVwo2oDwKDa0TyY-0_A0225.jpg

  • yutyuさん

    ブレークポイントは、
    > BR $$ ;ここにブレークポイント設定
    のある行でソースパネルの「指マーク」のところをクリックしてください。
    「手のひらマーク」が表示されると思います。
    そしたらブレークが有効になります。


    ここからのデバッグは、
    >MOV A,RESF
    >CMP0 A
    >SKZ
    >BR $$ ;ここにブレークポイント設定
    の命令群の挿入位置を少しずつ後ろの方に移動させていきながら様子を見てください。

    途中まではブレークするかと思いますけれども、ある個所を過ぎたところに挿入してもブレークしなくなると思います。
    そしたら、今までブレークしていた個所から、あたらにブレークしなくなった個所までの間に原因があると思います。

  • Kirinさん


    「 CALL
    !!_stkinit」

    の前後でブレークの有無を発見しました。
    丁度、最初に無限ループに陥っていた所です。


    原因はスタートアップの最初からstkinit迄に含まれているということでしょうか?

    Jx5UiUkq8TOvDxN0-0_A0226.jpg

  • yutyuさん

    > 原因はスタートアップの最初からstkinit迄に含まれているということでしょうか?

    そうですね。
    ステップ実行で、あやしい部分の命令コードを1つずつ追っていき
    リード命令があれば、どこをリードしているかを追い詰めると良いと思います。


    まさか、RETの時にスタックリードでRAMのパリティエラーが出てはいないと思いますけれども、
    もし該当部分が無ければ、試しにCALLする前に、

    PUSH AX ;追加
    PUSH AX ;追加
    POP AX ;追加
    POP AX ;追加
    MOVW HL,#LOWW _@STEND ;HL <- stack end address
    CALL !!_stkinit

    という感じで4命令を埋め込んでみてください。

    あとは、stkinitに渡すHLの値が妥当な値かも確認しておいたほうがいいですね。余計なところまで初期化されてしまうと大変なので。

  • Kirinさん

    回答ありがステップ実行を実行したのですが
    ブレイクポイントを設定したのにもかかわらずブレイクせず、「_stkinit」内まで進んでしまいます。
    「手のひらマーク」が表示をさせたのですが・・・

    >PUSH AX ;追加
    >PUSH AX ;追加
    >POP AX ;追加
    >POP AX ;追加
    >MOVW HL\,#LOWW _@STEND ;HL <- stack end address
    >CALL !!_stkinit

    >あとは、stkinitに渡すHLの値が妥当な値かも確認して
    >おいたほうがいいですね。余計なところまで初期化さ
    >れて、しまうと大変なので。

    どういった意味なのでしょうか?
    知識がない為、このような質問ですみません
  • yutyuさん

    >ステップ実行を実行したのですが
    >ブレイクポイントを設定したのにもかかわらずブレイクせず、
    >「_stkinit」内まで進んでしまいます。
    >「手のひらマーク」が表示をさせたのですが・・・

    ソフトブレークだとブレークポイントを設定した命令で止まりますけれども
    ハードウェアブレークの場合3命令くらい滑る(余分に実行する)仕様のようです。

    ソフトブレークとハードブレークでアイコンの形がちょっと違います。
    ソフトブレークは「手のひら」だけ
    ハードブレークは「手のひらに緑色のICのマークが付く」表示になります。
    よーーく見てみてください。
    左クリックではなく、右クリックにするとハードかソフトブレークかを選ぶこともできます。


    >PUSH AX ;追加
    >PUSH AX ;追加
    >POP AX ;追加
    >POP AX ;追加
    >MOVW HL,#LOWW _@STEND ;HL <- stack end address
    >CALL !!_stkinit

    これの意味は、
    CALL命令は、呼び出し元のアドレスをスタックに退避しますけれども、
    アドレスは3バイト長なので、消費したスタックの4バイトのうち1バイトが使われていません(SP-1のアドレスが初期化されていない)。
    そのため、RETした時に初期化されていないスタックの1バイトをリードすることでRAMパリティが発生してるのではなかと想像しています。


    >あとは、stkinitに渡すHLの値が妥当な値かも確認して
    >おいたほうがいいですね。余計なところまで初期化さ
    >れて、しまうと大変なので。

    stkinitは現在のSPからHLに渡したアドレスの範囲を初期化するので、HLに変な値が入っているとSFR領域まで初期化されたり
    逆にスタック領域が狭すぎると、スタックが完全に初期化されないため
    のちのちCALL/RETした際に(前述の)SP-1のアドレス未初期化でRAMパリティが発生する可能性が残ります。
    (これはスタックオーバーフローなのでソフトの設計的にまずいとは思いますけども)

  • スタッフのチョコです。

    Kirin様の「Re9:RAMパリティエラー発生箇所の特定」にコメントさせていただきます。

    >CALL命令は、呼び出し元のアドレスをスタックに退避しますが、
    アドレスは3バイト長なので、消費したスタックの4バイトのうち1バイトが使われていません(SP-1のアドレスが初期化されていない)。
    そのため、RETした時に初期化されていないスタックの1バイトをリードすることでRAMパリティが発生してるのではなかと想像しています。

    _stkinit部分を逆アセンブルして確認したところ,その最初で「MOV [SP+3]\,#0」とやっているので,Kirin様が懸念した問題はございません。(もっとも,それ以前に,このCALLの前にhdwinitから戻ってきているので,この点は問題にはなりません。)以下に逆アセンブルしたものに分岐先がわかるようにしたものを示します。最初に32バイト単位でクリアし,残りは2バイト単位でクリアしています。特に初期化されてないRAMを読み出しているとこはございません。気になる点は,2バイト単位でのクリアを行っている部分の完了チェックです。AXとHLを比較して,「RZ」で抜けるようになっています。つまり,HLの値が奇数に設定されていたら抜けられなくなります。その点から,「LOWW _@STEND 」がきちんと偶数になっているかをご確認ください。(私が確認したRL78/G14(64k品)ではきちんと抜けてきました。

    _stkinit:
    c80300 MOV [SP+3H]\,#0H
    aef8 MOVW AX\,SP
    27 SUBW AX\,HL
    dd3b BZ $_stkinit+0x43
    dc39 BC $_stkinit+0x43
    315e SHRW AX\,5H
    12 MOVW BC\,AX
    f6 CLRW AX
    ;_stkinit+0xe
    43 CMPW AX\,BC
    dd27 BZ $_stkinit+0x38
    bb MOVW [HL]\,AX
    bc02 MOVW [HL+2H]\,AX
    bc04 MOVW [HL+4H]\,AX
    bc06 MOVW [HL+6H]\,AX
    bc08 MOVW [HL+8H]\,AX
    bc0a MOVW [HL+0AH]\,AX
    bc0c MOVW [HL+0CH]\,AX
    bc0e MOVW [HL+0EH]\,AX
    bc10 MOVW [HL+10H]\,AX
    bc12 MOVW [HL+12H]\,AX
    bc14 MOVW [HL+14H]\,AX
    bc16 MOVW [HL+16H]\,AX
    bc18 MOVW [HL+18H]\,AX
    bc1a MOVW [HL+1AH]\,AX
    bc1c MOVW [HL+1CH]\,AX
    bc1e MOVW [HL+1EH]\,AX
    37 XCHW AX\,HL
    042000 ADDW AX\,#20H
    37 XCHW AX\,HL
    b3 DECW BC
    efd6 BR $_stkinit+0xe
    ;_stkinit+0x38
    aef8 MOVW AX\,SP
    47 CMPW AX\,HL
    dd06 BZ $_stkinit+0x43
    f6 CLRW AX
    bb MOVW [HL]\,AX
    a7 INCW HL
    a7 INCW HL
    eff5 BR $_stkinit+0x38
    ;_stkinit+0x43
    d7 RET