スタックの設定

私の経験だと、none-OS組み込みプログラミングでスタックを確保、設定するところでは、C言語風に書くと


#define STACK_SIZE (8*1024) // [byte]
static unsigned short stack_area[STACK_SIZE / sizeof(unsigned short)];
stackpointer = stack_area + STACK_SIZE / sizeof(unsigned short);
みたいにすると思う(スタックが低アドレス方向へ成長、16bit CPU、pushする前にstackpointerを移動)。

PIC24はこれらと異なり、スタックが高アドレス方向へ成長したり、スタック末尾登録(SPLIM)してオーバーフローしたらハードウェアでトラップを発生する仕組みがある。
またスタック領域の確保もリンカが、指定サイズ以上を空き領域から自動で割り付けるようになっている。サイズを指定していないと、最大空き領域を割り付ける。最初スタックを使用しないサンプル・プログラムを組んだら、勝手にstackリージョンが取られて驚いた。
先に書いたようにユーザが確保する必要は無い。やってもいいんだろうけど。

stackリージョンの先頭と末尾はシンボル__SP_init、__SPLIM_initで宣言されているので、これらを使ってスタック・ポインタ(W15)とSPLIMを初期化することが出来る。


mov #__SP_init, w15 ; initialize w15
mov #__SPLIM_init, w0
mov w0, _SPLIM ; initialize SPLIM
ここまでは便利なんだけど、ちょっと嫌なのがスタックサイズの指定方法。リンカにオプション指定する必要がある。実際にはMPLABの「Project」→「Build Options...」→「Project」からタブ「MPLAB LINK30」の「Generate Command Line」にある「Min stack size」に値を設定すればよい。初期値のように空欄であれば、最大空き領域をスタックに使ってくれる。

何が嫌なのかというと、固定値をプロジェクトに登録するのが嫌。ソースコードに書きたい。計算式で記述できない(マクロ定義によって可変にできない)、重要な値なのでソースコード側と一緒に管理したいということ。
リンカ・スクリプトをカスタマイズして、そのスクリプトをソースとして管理すればいいんだけど、複数CPUに対応しようとすると、CPU毎にスクリプトを分けるしかなさそう。
C言語プリプロセッサのように#includeとか#ifも、条件判断のif文も無いみたい。
このリンカ・スクリプト、そもそもCPU固有情報(アドレス等)と、ユーザが変更する情報を一緒に記述しているところがいまいちだ。

*追記(2009/05/25)
と思っていたらアセンブラ・ソースから指定方法があった。
「MPLAB ASM30, MPLAB LINK30 and Utilities User's Guide」の「10.10 STACK ALLOCATION」の記述から。


.global STACKSIZE
.equiv STACKSIZE, 0x100
ASM30じゃなくてLINK30に説明してあった。
よかった、よかった。