で、再びおかしな所を発見してしまった!(というか嵌った!)
非タスクコンテキスト用スタックの割り当てがおかしいようだ。場合によっては、他で使っている領域の上にSPが割り当てられるので、カーネル自体の実行や非タスクコンテキストの実行中にメモリをブチ壊すことがあるので要注意だ。
問題の箇所は、arch/arm_m_gcc/prc_config.h内でマクロTOPPERS_ISTKPTを#defineしているところだ。
(誤)#define TOPPERS_ISTKPT(istk, istksz) ((STK_T *)((istk) + (istksz)))
(正)#define TOPPERS_ISTKPT(istk, istksz) ((STK_T *)((char_t*)(istk) + (istksz)))
ここは上のように(char_t*)へのキャストが必要だ。
引数istkに渡されるポインタ(スタック領域の先頭アドレス)はSTK_T*型を持つので、そのままスタックサイズ(=istksz:バイト単位)を足すと32bit CPUであるCortex-M3では計算が4倍違ってくる。
このTOPPERS_ISTKPTマクロはシステム起動時のSPの初期設定に使われるから、立ち上がった時点から本来アクセスしてはいけない部分をSPとして使って起動することになる。
このTOPPERS_ISTKPTマクロはシステム起動時のSPの初期設定に使われるから、立ち上がった時点から本来アクセスしてはいけない部分をSPとして使って起動することになる。
ついでに、もひとつ。
target/cq_starm_gcc/target_config.hで定義されているスタックサイズDEFAULT_ISTKSZの#define部分、
(誤)#define DEFAULT_ISTKSZ (0x1000/8U) /* 4KByte */
は、8Uで割る必要はない。ここで指定するのはバイト単位。
(正)#define DEFAULT_ISTKSZ (0x1000) /* 4KByte */
直前の行で「 デフォルトの非タスクコンテキスト用のスタック領域の定義。8byte単位で取得される」というコメントが入っているが、これも微妙。Cortex-M3では8バイト境界(ダブルワード境界)でSPを設定したほうがよいとなっているので、もう少し厳密にコメントするなら「8byte単位で取得される」ではなく、「8の倍数を設定する」とでもコメントすべきではないか?
ああ、いろんなトラップを仕掛けてくれなぁ・・・。もうヤダ。
0 件のコメント:
コメントを投稿