Everything
13.5 スタック・サイズの見積もり
13.5.1 システムのスタック・サイズ
システムのスタック・サイズの計算式を以下に示します。
【式1:システム・スタック・サイズ】
sys_stk = MAX(sys_stkA, sys_stkB, sys_stkC)+2 (バイト)
【式2:システム・スタック・サイズが使用されるパターンA】
sys_stkA = tsksvc+int0+int1+int2+int3
【式3:システム・スタック・サイズが使用されるパターンB】
sys_stkB = アイドル・ルーチン上のユーザ使用サイズ
【式4:システム・スタック・サイズが使用されるパターンC】
sys_stkC = 初期化ルーチン上のユーザ使用サイズ
【式5:タスクで実行したサービス・コール中,最大のシステム・スタック使用サイズ】
タスクで実行したサービス・コール中,最大のシステム・スタック使用サイズ
【式6:int0,int1のサイズ】
Intx = レベルxの割り込みの中で,最もスタックが使用される割り込みのサイズ
= 割り込み上のユーザ使用サイズ
【式7:int2,int3のサイズ】
intx = レベルxの割り込みの中で,最もスタックが使用される割り込みのサイズ
= 割り込み上のユーザ使用サイズ+allsvc+18
【式8:割り込み上で使用するサービス・コールの使用サイズ合計】
allsvc = 発行元スタック引数用+発行元スタック内部処理用+システム・スタック内部処理用
システム・スタック・サイズは,システム・コンフィギュレーション・ファイルへ指定します。ただし,実際はコンフィギュレータに指定する値+2バイトのサイズが確保されます。よって,実際にシステム・コンフィギュレーション・ファイルに指定する値は式1で求めたsys_stkから2バイトを減算したものとなります。
なお,システム・スタック・サイズは,スタックのオーバフローの危険を減らすため,この見積もり結果よりも多めに取ることを推奨します。
以下に,例を示します。
【条件】
- タスクtask1はpol_flgサービス・コールを実行。
- タスクtask2はsnd_mbxサービス・コールを実行。
- 割り込みint0はレベル0のOS管理外の割り込み処理。割り込み上でスタック使用なし。
- 割り込みint2はレベル2のOS割り込みハンドラ。snd_mbxサービス・コールを実行,割り込み上で12バイトのスタック使用。
- 割り込みint3Aはレベル3のOS割り込みハンドラ。pol_flgサービス・コールを実行,割り込み上で16バイトのスタック使用。
- 割り込みint3Bはレベル3のOS割り込みハンドラ。Timer_Handlerを実行,割り込み上でスタック使用なし。
- アイドルidlはスタック使用なし。
- 初期化ルーチンiniは初期化ルーチン上で24バイトのスタック使用。
【計算式】
tsksvc = MAX(pol_flg のシステム・スタック使用サイズ,snd_mbx のシステム・スタック使用サイズ)
= MAX(16,8) = 16バイト
int0 = 0+0 = 0バイト
int1 = 定義なし = 0バイト
int2 = 12+( 0+6+4 )+18 = 40バイト
int3 = MAX(int3A, int3B) = MAX(56,32) = 56バイト
int3A = 16+( 0+6+16 )+18 = 56バイト
int3B = 0 +( 0+0+14 )+18 = 32バイト
sys_stkA = tsksvc+int0+int1+int2+int3
= 16+0+0+40+56
= 112バイト ※sys_stkA,B,C内で最大なので,このサイズを確保
sys_stkB = アイドル・ルーチンのユーザ使用スタック・サイズ = 0バイト
sys_stkC = 初期化ルーチンのユーザ使用スタック・サイズ = 20バイト
sys_stk = MAX(sys_stkA, sys_stkB, sys_stkC)+2
= MAX(112, 0, 20)
= 112+2 = 114バイト
以上から,システム・スタック・サイズはsys_stkAの112バイトです。
システム・コンフィギュレーション・ファイルへ指定するサイズは,この112バイトとなります。
備考 以下に,例で使用するサービス・コール/関数のスタック使用サイズを示します。
発行元スタック
引数用
発行元スタック
内部処理用
システム・スタック
内部処理用
pol_flgサービス・コール
0
6
16
twai_flgサービス・コール
4
6
16
snd_mbxサービス・コール
0
6
4
Timer_Handler関数
0

14

13.5.2 タスクのスタック・サイズ
タスクのスタック・サイズの計算式を以下に示します。
【式1:タスク上で割り込みが発生しない場合】
タスク・スタック・サイズ = ユーザ使用サイズ+サービス・コールの引数用サイズ+6 (バイト)
【式2:タスク上で割り込みが発生する場合】
タスク・スタック・サイズ = ユーザ使用サイズ+サービス・コールの引数用サイズ+6+20 (バイト)
タスク・スタック・サイズはシステム・コンフィギュレーション・ファイルへ指定します。ただし,実際は“コンフィギュレータに指定した値+6バイト”のサイズが確保されます。よって,実際にシステム・コンフィギュレーション・ファイルに指定する値は,式1または式2で求めた値から6バイトを減算したものとなります。
この6バイトには,サービス・コール発行時に使用されるスタック・サイズが含まれています。ただし,サービス・コール発行時に使用されるスタック・サイズの中でも,引数用スタック・サイズは6バイトとは別にユーザ使用サイズとして確保する必要があります。なお,各サービス・コールで使用される引数用スタック・サイズは異なります。その一覧表は表12-1 にまとめてあります。
タスク・スタック・サイズは“対象タスク上で最もスタックが使用される場合のスタック・サイズ”ですので,サービス・コールで,引数用スタックが4バイトのものと,8バイトのものがあれば,よりスタックが使用されるパターンの8バイト分を確保します。
以上は,割り込みを受け付けない(すべて割り込み禁止の)タスクに関するものです。割り込みを受け付けるタスクに関しては,さらに20バイトの領域を確保する必要があります。
なお,この20バイトの中には,割り込み開始時に呼び出しが必要な関数_kernel_int_entry呼び出し時のスタック・サイズも含まれています。_kernel_int_entryは20バイトのデータをスタックへ退避しただけで復帰は行いません。復帰は割り込み終了時に呼び出しが必要な関数_kernel_int_exit呼び出し時に行われます。
例1 タスクtask1でtwai_flgサービス・コールとsnd_mbxサービス・コールを使用し,ほかにスタックを使用する関数や処理がなく,タスク上で割り込みは受け付けられない場合
task1上で割り込みは受け付けられないので,使用する計算式は式1です。
スタックを使用する関数や処理はないことから,ユーザ使用サイズは0バイトです。
全サービス・コールの引数用サイズを調査すると,以下となります。
サービス・コールの引数用サイズ(twai_flg) = 4バイト
サービス・コールの引数用サイズ(snd_mbx) = 0バイト
最もスタックが使用されるのは,twai_flg呼び出し時のスタック・サイズなので,この値を式1へ指定します。
タスク・スタック・サイズ = ユーザ使用サイズ+サービス・コールの引数用サイズ(twai_flg)+6
= 0+4+6
= 10バイト
システム・コンフィギュレーション・ファイルへ指定するサイズは,上記から6を減算した4バイトとなります。
例2 タスクtask1で関数A(スタックを12バイト使う)上からtwai_flgサービス・コールを呼び出し,関数B(スタックを20バイト使う)上からsnd_mbxサービス・コールを呼び出し,タスク上で割り込みが受け付けられる場合
task1上で割り込みは受け付けられるので,使用する計算式は式2です。最もスタックが使用されるパターンを見つけるため,パターンを列挙します。
パターンA = ユーザ使用サイズ(関数Aの場合)+サービス・コールの引数用サイズ(twai_flg)+6+20
= 12+4+6+20
= 42バイト
パターンB = ユーザ使用サイズ(関数Bの場合)+サービス・コールの引数用サイズ(snd_mbx)+6+20
= 20+0+6+20
= 26バイト
以上のパターンAとパターンBを比較し,最もスタックが使用されるものはパターンAの42バイトです。
システム・コンフィギュレーション・ファイルへ指定するサイズは,上記から6を減算した36バイトとなります。