MISPOさんのNORTiをRX SmartConfiguratorと一緒に使いたい場合の課題と対策を考察してみるスレッド

こんにちは。NoMaYです。

ひとつ立てても良さそうな気がしましたので立ててみました。

もっとも、その前に気になる問い掛け、が無いわけでは無いですけれども、、、

● マイコンベンダ提供のソフトウェア開発フレームワークと共存させることが苦痛な実装のRTOSを今後も新規プロジェクトで使う予定がありますかね

[関連スレッド]

スマートコンフィグレータの自動生成をカスタマイズしたい
japan.renesasrulz.com/cafe_rene/f/forum5/8248/thread

FITの割込みハンドラの実装について
japan.renesasrulz.com/cafe_rene/f/forum5/8212/fit

RX72Nで簡易I2C通信をしたい。DATAは出力されているがCLKが何故か正しく出力されない。。
japan.renesasrulz.com/cafe_rene/f/forum5/7129/rx72n-i2c-data-clk

FITでのSCI使用時に文字を1文字送信すると、プログラムが固まります。
japan.renesasrulz.com/cafe_rene/f/forum5/7071/fit-sci-pc-1
 


RX SmartConfiguratorで気になった点とか改善する案とか報告してみるスレッド
japan.renesasrulz.com/cafe_rene/f/forum5/7536/rx-smartconfigurator/42599#42599
 

Parents
  • ふぐりんです
    NoMaYさんこんにちは。


    以下のスレッドでNoMaYさんに作っていただいたプログラムで
    NORTiをRX SmartConfiguratorと一緒に使えるようになったようです。
    NORTiユーザとしてFITとの同居という念願がかないました。(共存させることが苦痛な実装のRTOSじゃなくなった?w
    NoMaYさんありがとうございました!

    スマートコンフィグレータの自動生成をカスタマイズしたい
    japan.renesasrulz.com/.../thread

    ソース追いかけたり実験したりしてたので遅くなりましたが確認が取れました。
    詳しいやりかたなどは私のGitHUB(github.com/mkogax)に上げたいと思っていますが、NoMaYさんのソースを転載してもよろしいでしょうか?許可いただければ、ファイルとしてそのまま収録したいと思います。
    以下簡単なご報告です。

    ----------
    セットアップ
    ----------
    NoMaYさんの NORTi_interrupt.c (20220629_2版) をそのまま改変なしで使用しました。
    ただし、NORTi_interrupt.h で全て NORTiタイプを指定し、INTBにはNORTi管理のベクタテーブル(RAM)を登録します。
    NORTi側は初期化時に呼ばれる intini() (利用者が作るヘルパ関数のようなもの)を改造するだけです。

    ----------
    効果
    ----------
    ・FIT/CGは改変なしでそのままNORTiを利用できます。(コールバックでNORTi利用可)
    ・NORTiの割込みハンドラ(def_inh())をそのまま利用できます。
    ・NORTiの割込みサービスルーチン(cre_isr())をそのまま利用できます。(最初におまじない必要)
    ・FIT/CGの割込み処理はNORTi対応で少しオーバヘッドが増えますが、NORTiを使わないで高速に処理したい場合(nonOS)はdef_inh()で対応できます。

    ----------
    実験(Target Board for RX130,CS+)
    ----------
    ・r_cmt_rx(FIT)の10msec周期コールバックからNORTiのチックタイム通知(isig_tim())
    ・TMR0(CG)で#pragma interrupt の割込みルーチンからタスク起床(wup_tsk())
    ・TMR1(CG)の改造でdef_inh() のNORTi割込みハンドラからタスク起床(wup_tsk())
    ・TMR2(CG)の改造でcre_isr() のNORTi割込みサービスルーチンからタスク起床(wup_tsk())
    ・TMR3(CG)で#pragma interrupt の割込みルーチンを非NORTiとして再登録(def_inh())してカウンタ変数更新を確認

  • ふぐりん さん、こんにちは。NoMaYです。

    どうもありがとうございました。新たな技も開発されたみたいですね。そして、以下の件、もちろん転載して構わないです。

    > 詳しいやりかたなどは私のGitHUB(github.com/mkogax)に上げたいと思っていますが、NoMaYさんのソースを転載してもよろしいでしょうか?許可いただければ、ファイルとしてそのまま収録したいと思います。

  • Muraさん、こんにちは。NoMaYです。

    頂いたファイルとGitHubからダウンロードしたNORTi_interrupt.hとNORTi_interrupt.cを比較してみたところ、うっかりe2 studio上で手を滑らせてしまったのだと思いますが、NORTi_interrupt.cの以下の ?: の行が無くなっていましたよ。

        JMP R15 // Program will return to the next label from the interrupt service routine by RTE.
    ?:

     

  • あ!ほんとだw
    NoMaYさんさすが

  • NoMayさん、ふぐりんさん こんにちは。Muraです。

    すみません。本当ですね。失礼しました。

    あと当該関数含めたstatic宣言もいろいろ試しているうちに外したものお送りしてしまってます。

  • NoMayさん、ふぐりんさん こんにちは。Muraです。

    ご指摘の ?: を元通りに修正したら、ビルド通りました。ご教示ありがとうございました。

    正:     JMP R15 // Program will return to the next label from the interrupt service routine by RTE.
    ?:
    誤:     JMP R15 // Program will return to the next label from the interrupt service routine by RTE.?:
  • Muraさん
    解決できてよかったです!
    (いいねボタンが欲しいw)

  • ふぐりんさん

    お手間をお掛けしました。

    今回の問題はもとより、NORTiの併用に関して分かり易く説明頂いてすごく助かりました。

  • やっぱりBUSERRでトラブりました・・(勘は当たってしまいましたw)
    ご報告です。

    【前提】
    BUSERR(バスエラー割り込み,ベクタ番号16)は不正なアドレスをアクセスする等で発生します。
    スマートコンフィグレータでr_bspを入れてると割り込みレベル15で割込み許可になるようです。
    そのままでも、BUSERRの割込み処理 bus_error_isr() で BERCLRレジスタを使って割込み状態がクリアされるので、万一BUSERRが発生しても処理は続行できるようになってました。

    【発生現象】
    しかし、「NORTi を RX Smartconfigurator と一緒に使う方法」の手順でNORTi対応すると bus_error_isr() が呼ばれる前に v3_ent_int() をコールするため、v3_ent_int() の中で再度BUSERR割込みが発生して暴走します。(NORTiの許容割り込みレベルより高い割り込みレベルで、しかも割込みと同時に割り込み状態がクリアされないタイプの割り込みのため)

    【対策】
    NORTi_interrupt.h の INTERRUPT__16 を nonOS にします。
    これでv3_ent_int() が呼ばれなくなるので暴走しません。(ただし、BUSERR割込みのコールバックでNORTi のAPIは使えません)

    いやー半年以上前のことなんで、すっかり忘れてました。
    どうせまた忘れるのでw、もう「NORTi を RX Smartconfigurator と一緒に使う方法」の NORTi_interrupt.h を修正しちゃいます。

  • ふぐりん さん、こんにちは。NoMaYです。

    お久しぶりです。すみません、ちょっと知りたいです。再度BUSERR割込みが発生するカラクリが腑に落ちなかったのです。r_bspで割り込みレベル15になっていたとのことですが、自分の認識ですと、その割り込みが発生するとPSW.IPLが15になり、それ以降はその割り込みが終了するまで一切の(多重)割り込みが受け付けられない筈のような気がするのです。

    ひょっとして、v3_ent_int()の中でPSW.IPLの値を下げるようなことが行われていたりするのでしょうか?ちょっと気になるのです。

  • NoMaYさんおひさしぶりです!(半年ROMってましたw)

    割込み発生時 v3_ent_int() コール直前では PSW.IPL が 15 で、PSW.I は 0(割り込み禁止)でした。
    その後、v3_ent_int() のはじめあたりで PSW.IPL が カーネルレベル(KNL_LEVEL、defaultは6)になると同時に PSW.I が 0(割り込み許可)になってるようです。

    これは、NORTiのカーネル処理中であってもカーネルレベルを越える割り込みは受け付けるようにするためだと思います。

    以下はNoMaYさんはお判りでしょうから蛇足です。
    (高速とは言えカーネルは重いですからねえ・・)
    (もちろん、カーネル処理中はカーネルレベル以下の割り込み=NOPRTiのAPIが使える割り込みは受け付けません)

  • ふぐりん さん、こんにちは。NoMaYです。

    情報ありがとうございました。やっぱりそういうことなんですね。思ったのは、ベクタ割り込み全般に渡ってNORTiのAPIを使えるよう、くだんのやり方でフックする場合、基本はKNL_LEVEL=15へと設定変更しておくものであるような気がします。

    そして、特殊な高優先度の割り込みが必要となったところで、慎重に諸々の割り込み優先順位を調整しつつ、KNL_LEVEL=14とか13とかへ変更していくものかな、と、、、

    もし、v3_ent_int()の中を弄れるなら、そして、NORTi_interrupt.hをちょこまか変更するのが手間と感じるなら、ちょうど別スレッドで投稿しているコードのように、PSW.IPLとKNL_LEVELを比較し、少なくともPSW.IPLを下げないようにしておくと、多重割り込み全般で今よりも安全になるような気がしました。以下のような感じですけれども。(別スレッドから咄嗟に抜き出して書き換えたものですけれども。)

        if(KNL_LEVEL > (((R_BSP_GET_PSW()) >> 24) & 0xF))
        {
            R_BSP_SET_IPL(KNL_LEVEL);/* MVTIPL #IMM:4*/
        }
        R_BSP_SETPSW_I();

     

Reply
  • ふぐりん さん、こんにちは。NoMaYです。

    情報ありがとうございました。やっぱりそういうことなんですね。思ったのは、ベクタ割り込み全般に渡ってNORTiのAPIを使えるよう、くだんのやり方でフックする場合、基本はKNL_LEVEL=15へと設定変更しておくものであるような気がします。

    そして、特殊な高優先度の割り込みが必要となったところで、慎重に諸々の割り込み優先順位を調整しつつ、KNL_LEVEL=14とか13とかへ変更していくものかな、と、、、

    もし、v3_ent_int()の中を弄れるなら、そして、NORTi_interrupt.hをちょこまか変更するのが手間と感じるなら、ちょうど別スレッドで投稿しているコードのように、PSW.IPLとKNL_LEVELを比較し、少なくともPSW.IPLを下げないようにしておくと、多重割り込み全般で今よりも安全になるような気がしました。以下のような感じですけれども。(別スレッドから咄嗟に抜き出して書き換えたものですけれども。)

        if(KNL_LEVEL > (((R_BSP_GET_PSW()) >> 24) & 0xF))
        {
            R_BSP_SET_IPL(KNL_LEVEL);/* MVTIPL #IMM:4*/
        }
        R_BSP_SETPSW_I();

     

Children
  • NoMaYさん、こんにちは!

    KNL_LEVEL=15 や v3_ent_int()の修正もおっしゃるとおりではあるのですが・・

    「NORTi を RX Smartconfigurator と一緒に使う方法」を利用される方は、それぞれいろんな事情をお持ちだと想像すると、あんまりFIT/CGやNORTiのデフォルトをいじりたくないんですよねえ・・

  • ふぐりん さん、こんにちは。NoMaYです。

    いやいやいや、それでもPSW.IPLが小さくなっちゃうのはアカンと思うのです。もしかすると、以下の文面からして、何かそこに誤解があるような気がし始めました。

    > これは、NORTiのカーネル処理中であってもカーネルレベルを越える割り込みは受け付けるようにするためだと思います。

    私は、ミスポさんの前提は以下だと思うのですけれども、マニュアルのどこかに書いてないでしょうかね、、、

    (1) v3_ent_int()を呼ぶことが許されるのは割り込み優先順位がKNL_LEVEL以下の割り込みのみである
    (1') 言い換えると、割り込み優先順位がKNL_LEVELより高い割り込みはv3_ent_int()を呼んではいけない

    (2) その前提でミスポさんはv3_ent_int()の初めでPSW.IPL=KNL_LEVELにしてPSW.I=1に設定している
    (2') つまりミスポさんとしてはPSW.IPLを(たぶん排他制御目的かな?)割り込みの初めで一時的にPSW.IPL=KNL_LEVELへ上げるのみが設計意図である

    (3) ところが、今回はその前提を守らずにv3_ent_int()を呼んでしまっているのでPSW.IPLが小さくなってしまう事態が起きている
    (3') 私は、PSW.IPLを下げるというのはミスポさんの設計意図ではないと思う

    あるいは、こういうように書くと、事態の変さ具合が伝わるでしょうか、、、

    (4) PSW.IPLを下げるということは、高い優先度の割り込み処理中に低い優先度の割り込みを受け付けてしまう、ことになりますよ、、、

  • NoMaYさん、こんにちは!
    お返事ありがとうございます。

    (1)(1')はそのとおりです。MISPOさんの取説に書いてあります。
    KNL_LEVELより高い割り込みからは、v3_ent_intを含むNORTiのすべてのシステムコールを呼んではいけないことになっています。
    (2')の「KNL_LEVELへ上げるのみが設計意図」もそのとおりで、下げることは想定外です。
    ですので、(4)「PSW.IPLを下げる」という想定は成立しない気がしますが・・

  • ふぐりん さん、こんにちは。NoMaYです。

    いや、ですから、今回、割り込み優先度15で受け付けたBUSERR割込みの中でPSW.IPL=6へ下がってますよね、、、

  • NoMaYさん、すいません。なんか行き違いがあったようですね。

    今回、私はBUSERRの割り込みを nonOS に変更しました。(NORTi_interrupt.h)
    KNL_LEVELより高い割り込みのBUSERRでは v3_ent_int() は呼ばれません。
    ですので、(4)の「PSW.IPLを下げる」は発生しません。

    じつは BUSERRの割込みレベルを下げようとしたんですが、Config_BSC(設定)とr_bsp(固定)の2か所でセットしてるみたいで・・
    弱虫なので「あ、これは触らんでおこう・・」と思ってしまったんでしたw

  • ふぐりん さん、こんにちは。NoMaYです。

    ことはBUSERR割込みだけでなく、FIT/CGでKNL_LEVELより高くなっているものをきちんと洗い出して、それらはすべてNonOSへ変更する運用方法を取りましょうね、ということであり、それが億劫であれば、KNL_LEVEL=15へと設定変更しておくものだ、ということになると思った、ということだったのです。あるいは、FIT/CGの諸々の割り込み優先順位を慎重に調整しておく。

    そうしないと、高い優先度の割り込み処理中に低い優先度の割り込みを受け付けてしまう、という思ってもいなかった事態が起こり得ますよ、ということですね。(低い優先順位だけでなく同一優先順位の二重受け付けも含めて。)

  • NoMaYさん、こんにちは!
    まさしく。まさしくそのとおりです。

    そうなんですよね。ちゃんと割込みレベルを管理しないとすごい怖い。
    じつは RAMERR(ベクタ番号18)も怪しい(いつかFIT管理で固定でレベル15あたりになるんじゃないか)とにらんでて、nonOSにしちゃおうかと考えてました。(保留にしてますが)
    (RAMERR割り込みを扱うFIT/CGって見つからなかったんですが、ありましたっけ?)


    私はNORTiが長いのでKNL_LEVELをいじるのに抵抗があるもんで・・すいませんw
    もうFIT/CGと共存するときはKNL_LEVELは15にしちゃいますかねぇ・・そっちが良いかもしれないですねえ。(突然の心変わり)

  • GitHUBに、KNL_LEVELは15を推奨する注意書きを追加しました。

    「NORTi を RX Smartconfigurator と一緒に使う方法」
    https://github.com/mkogax/How-to-use-NORTi-with-RX-Smartconfigurator

    【注意3】NORTiのKNL_LEVELは15を推奨します。(2022.12.28追記)

  • ふぐりん さん、こんにちは。NoMaYです。

    今しがた頭に思い浮かんだのですけれども、ひとまず、そうしてしまっても良い話なのか、そういう話では無いのか、というのは脇へ置いて、NORTi_interrupt.cのコードの中でKNL_LEVELマクロ定義を参照して、PSW.IPLの方が大きい値だった場合には自動的にv3_ent_int()を呼ばないようにスキップしてしまう、というように出来るかも知れないなぁ、という気がしました。試しにコードを書いてみようかと思います。

    [メモ]

    ・ KNL_LEVEL以下であれば多重割り込みされない
    ・ KNL_LEVELより大きければ多重割り込みされてもv3_ent_int()は呼ばない
    ・ ならば、発生したベクタ割り込みのベクタ番号の値はv3_ent_int()の前後で単純素朴に変数に退避しておけば充分、なのでは、、、

    [追記]

    ・ いっそ、KNL_LEVELより大きいベクタ割り込みはNORTi_interrupt.cのコードの中で自動的にSETPSW Iしてしまうとか、、、

  • NoMaYさんこんにちは。今年もよろしくお願いいたします

    それいいですねえ!
    利用者がKNL_LEVELを最高レベルに変更し忘れること(注意3を見落とすこと)はかなり確実に発生するwと思われますから。自動で処理されるのは助かります。

    (KNL_LEVELの参照方法はのちほど確認します)