ルモーリン

スケジューラー起動がメインスタックを全解放

投稿:2014-08-21、更新:2014-09-01

いやあ、エラいものを見つけてしまいました。
発端は、FreeRTOS環境下でのスタック使用状況を把握したかったのです。 そこでスタックポインタの設定する所を探していました。 LPC1769はスタックポインタを2個持っています。
  • メインスタックポインタmsp
  • プロセススタックポインタpsp
FreeRTOSでの使い方は
  • mspを初期化処理、例外処理に使用
  • pspをタスクに使用
です。 FreeRTOSにタスクを走行させるときは、vTaskStartSchedulerを呼びます。 その延長で呼ばれるvPortStartFirstTaskはこんな処理です。
void vPortStartFirstTask( void )
{
	__asm volatile(
					" ldr r0, =0xE000ED08 	\n" /* Use the NVIC offset register to locate the stack. */
					" ldr r0, [r0] 			\n"
					" ldr r0, [r0] 			\n"
					" msr msp, r0			\n" /* Set the msp back to the start of the stack. */
					" cpsie i				\n" /* Globally enable interrupts. */
					" svc 0					\n" /* System call to start first task. */
					" nop					\n"
				);
}
はい? 真ん中辺の「msr msp, r0」でもって、mspを初期位置に戻しているじゃありませんか。 これじゃあ、スタック全解放(笑)。 初期化処理でタスクに渡すつもりでスタックに確保してあるデータが壊れます。 メインスタックのデータが壊れるタイミングは、例外発生のレジスタ保存や例外処理がスタックを使った時ですね。 自分のプログラムで破壊される(正しくは解放したスタックを参照する)ことがあるか、調べます。 今まで呼び出し元のスタックが解放される環境でプログラミングしたことないので(いや、してたけど自覚がなかった)、 書いたソースのうち、スケジューラー起動までに走る所を全部読み直しますよ(ぐすん)。 LPCXPresso(LPC1769版)を使い始めて4年になるけれど、今頃分かってしまいました(大泣き)。 2014.09.01 スケジューラー起動までステップ実行で追跡、メインスタックのデータをタスクへ渡す所がない事を確認しました。 あーよかった。
スタック使用状況はこんな感じです。 スタック使用状況の図解
このページ全部(ぐったり)。