Smalight OSを使おう 5タスク目 スタックの設定 [Smalight OS]
久しぶりにオフロードバイクのレースに出て、思いっきり転倒した際に、ハンドルのバーエンドが脇腹に突き刺さって、、、うー脇腹がいてえ。やっぱりアバラいっちゃっているかな。
それはさて置き。
この記事は、某SNSで書いているものを転載しています。
HOS本でも書きましたが、結局の所組み込みマイコンではスタックの設定から逃れられない訳です。
その為、smalight osのマニュアルにもきっちりスタックの使用サイズについて書かれています。
タスクスタックサイズの算出
タスクで必要なスタックサイズは、OSが使用する40byteと、タスクの中で必要とされる最大のスタックサイズを加算した値となります。
※E8エミュレータを使用した場合、このエミュレータ用に更に8byte必要となる。
OSが使用するスタックの内、20byteはRUN状態以外の状態の時のコンテキスト保存用に使用され、20byteは割り込みのエントリ時に必要とされます。
また、タスク自身が使用するサイズは、HEWのビルド時のコンパイルオプションで-finfoを有効にしておくとスタック情報が生成されます。
今最も新しい評価版ソフトウエアのバージョンは、ツールチェインバージョンで言えば5.43.00ですが、このバージョンからはCall Walkerで読み込めるようになりました。
http://japan.renesas.com/fmwk.jsp?cnt=evaluation_software_mid_level_landing.jsp&fp=/products/tools/evaluation_software/
Call Walkerで生成オブジェクトのなんとか.sniファイルをロードすれば、各関数の使用スタックサイズが一発で判りますので、このサイズを使用して下さい。
例えばtsk01では関数のネストを含めて11byte使用していますので、12byteとし、それにOS側で必要とする40byte( + E8エミュレータの8byte)で、計52byte(60byte)となります。
ディスパッチ無し割り込みスタックサイズの算出
ディスパッチ無し割り込みを使用するのは、NMI割り込みと、OS管理外の割り込みを使用する時です。割り込み中にOSの機能を使いたい時は、ディスパッチ有り割り込みを使用してください。
割り込みエントリでは、スタックの切り替えを行うまでは、現行のコンテキストのスタックを使用します。
以下はディスパッチ無し割り込みの前処理、後処理部分のサンプルですが、
; ******* _int1 ******* ; Ex)Maskable Interrupt sample(Dispatch) _int1: PUSHM R0,R1,R2,R3,A0,A1,SB,FB STC SP,R1 LDC #_INT1stack,SP ; change INTstack PUSHM R1 FSET I ; Multiplex interrupt Enable ; JSR.A _intProc1 ; call interrupt proc ; POPM R1 LDC R1,SP POPM R0,R1,R2,R3,A0,A1,SB,FB REIT
最初に現行のコンテキストのレジスタを保存して、その後、ディスパッチ無し割り込み専用スタックに切り替えています。
一旦多重割り込みを許可してから、intProc1は割り込み処理関数本体ですが、この関数をコールします。
終了時は、割り込みスタックから元のスタックに戻し、レジスタを復帰させて割り込み処理を終了しています。
つまりここまでで必要なスタックサイズは、スタック切り替え後の処理で必要となるサイズ+多重割り込みを許可する場合は、その多重割り込みのスタックに切り替わるまでで使用するスタックサイズと言う事が出来ます。
付属のサンプルではディスパッチ無し割り込みは使用されていないので、この割り込みのスタックサイズは0ですが、勿論割り込みを使用する場合は、この例ならintProc1で使用するサイズ+多重割り込みに入るまでの20byte + 5byte( + E8エミュレータの8byte)として下さい。
なお、多重割り込みを使用する時は、割り込みの優先レベル毎に割り込みスタックを用意する必要が有ります。
ディスパッチ有り割り込みスタックサイズの算出
ディスパッチ有り割り込みのエントリ部分も無しの場合とほぼ同じですが、若干異なる部分も有ります。
以下はディスパッチ有り割り込みの前処理、後処理部分のサンプルですが、
; ******* _int2 ******* ; Ex)Maskable Interrupt sample(Dispatch) _int2: INTPUSH _INT2stack ; register save JSR.A $intProc2 ; call interrupt proc INTPOP ; register load ; --------------------------------------- ; MACRO ; --------------------------------------- INTPUSH .MACRO wksp PUSHM R0,R1,R2,R3,A0,A1,SB,FB STC SP,R1 LDC #wksp,SP ; change INTstack PUSHM R1 JSR.A $knl_spSave MOV.B R0L,R1L FSET I ; Multiplex interrupt Enable .ENDM INTPOP .MACRO POPM R1 LDC R1,SP POPM R0,R1,R2,R3,A0,A1,SB,FB REIT .ENDM
まあ途中がマクロになっていますが、ほぼ同じ様ですね。
ただマクロの中のknl_spSaveが何を行っているのか具体的な説明を見つけられなかったので判らないのですが、基本的には割り込みスタックに切り替え後、多重割り込みの許可を行い、関数intProc2を呼んでいます。
つまり、ディスパッチ無し割り込みと同じ様に計算し、適切なサイズを設定して下さい。と思ったのですが、E8エミュレータのメモリダンプを見てみると、割り込みスタックを35byte程度使った形跡が見られます。
intTimが6byte、スタック切り替え後の処理で5byte、エミュレータが8byte使ったとしても全部で19byteと20byteには達していないので、残りの16byteは一体何処で使用したのか?。取りあえず少し多めに、40byte以上辺りで設定してみてください。
なお付属サンプルではタイマー割り込みのみ使用し、その割り込みへのエントリーを別に用意しています。
; ********** USER TIMER INT ********** ; _tim: INTPUSH _TIMstack ; register save JSR.A $intTim ; call interrupt proc INTPOP ; register restore
しかし何故かsect30.iniの中で4byteしかスタックを確保しておらず、
.blkb 04h _TIMstack:
これは戴けないですね。まあ上の_INT2stackが未使用な為に助かっている訳ですが。
コメント 0