Previous: 8.2.1. スタック領域残量の確認 |
Up: 8.2. スタックオーバーフローの検知 |
Next: 9. FreeRTOSを利用したマウスロボット |
FreeRTOSにはスタックオーバーフローの発生を検知する機能が備わっています。下記のプロトタイプに従ったvApplicationStackOverflowHook関数を作成しておくと、FreeRTOSがスタックオーバーフローを検出したときに、vApplicationStackOverflowHook関数が呼び出されます。この関数の呼び出しの際には、スタックオーバーフローを発生させたタスクハンドラとタスク名が引数として渡されますから、これらをターミナルに表示させるなどして、スタックオーバーフローの原因タスクを特定することができます。なおスタックオーバーフローの検知機能は完全ではなく、スタックオーバーフローが発生しても、vApplicationStackOverflowHook関数が呼び出されない可能性があります。またこの機能を実行させると、プログラム全体の実行速度が遅くなります。
関数名 |
vApplicationStackOverflowHook関数 |
|
関数プロトタイプ |
void vApplicationStackOverflowHook(xTaskHandle *pxTask, signed portCHAR *pcTaskName ) |
|
動作 |
スタックオーバーフローが発生したときに実行したい任意の処理をユーザーが定義します。 |
|
引数 |
*pxTask |
スタックオーバーフローを発生させたタスクのハンドラ |
*pcTaskName |
スタックオーバーフローを発生させたタスクのタスク名 |
|
戻り値 |
無し |
繰り返しますが、この関数はFreeRTOSに備わっている関数ではなく、FreeRTOSが呼び出す関数ですので、自分でコーディングしてプログラム中に含めておく必要があります。
スタックオーバーフロー発生時にvApplicationStackOverflowHook関数が呼び出されるようにしたい場合には、FreeRTOSConfig.h中のマクロconfigCHECK_FOR_STACK_OVERFLOWが1又は2に定義されている必要があります。
1か2かはスタックオーバーフローを検知する方式の違いです。1の場合は、コンテキストスイッチ時に、スタック領域にデータを保存したポインタが確保したスタック領域の範囲内にあるかどうかをチェックします。2にすると、1のチェックに加えて、予めスタック領域の後尾に一定のデータパターンを書き込んでおき、このパターンが書き換えられていないかをチェックします。1より2の方法の方がスタックオーバーフローを検知できる可能性は上がりますが、実行速度はより遅くなります。
サンプルプログラムでは以下のようにして、スタックオーバーフローの発生時にメッセージを表示させています。引数でタスクのハンドラとタスク名が得られるという仕様ですが、これも確実ではなく、渡されたハンドラやポインタが正しい値とならない場合があります。
void vApplicationStackOverflowHook(xTaskHandle *pxTask, signed portCHAR *pcTaskName) { ? cprintf("\r\nStack Overflowed.\r\n");
? cprintf("The name of the task make its stack overflowed is :"); ? cprintf((int8_t *)pcTaskName); ? cprintf("\r\n");
? if (pxTask == xHandlerTaskHandle) ??? { ????? cprintf ("The name of the task make its stack overflowed is : HandlerTask\r\n"); ??? } } |
スタック領域を192にして実行した場合には、スタックオーバーフローは発生しません。プログラムは停止せず、実行し続けます。
Handler task called. 89 stack spaces available. Handler task called. 67 stack spaces available. Handler task called. 67 stack spaces available. Handler task called. 67 stack spaces available. ~~~~~~~~~~~~~ |
スタック領域を128にした場合には、スタックオーバーフローが発生しますが、プログラムが突然停止するだけで、検知できませんでした。
Handler task called. 7 |
スタック領域を64にした場合にはスタックオーバーフローを検知できました。ただし引数は正しくなく、正常に表示されませんでした。
Hellow Cortex-M3/STM32 and FreeRTOS World! Expand your creativity and enjoy making.
Handler task called. 36 stack spaces available.
Stack Overflowed. The name of the task make its stack
overflowed is :,
|
この通りこの検知機能はまだ完全なものではありませんが、大変便利なものですので、今後の改善を期待したいと思います。
コラム 1?2 configTOTAL_HEAP_SIZE
FreeRTOSConfig.hにはconfigTOTAL_HEAP_SIZEという設定項目があります。これはFreeRTOSが使用することのできるRAMの最大領域です。タスクを増やしていって、使用しているスタック領域の総量がconfigTOTAL_HEAP_SIZE を超えると、タスクの生成に失敗します。そのためconfigTOTAL_HEAP_SIZE は大きめにしておく方がよいのですが、RAMの総量ぎりぎりにしてしまうと、今度はグローバル変数や、OSの管理外の関数が使用するローカル変数の領域が足りなくなります。領域確保に失敗する場合には、リンクエラーになります。コンパイル時リンクエラーが出た場合には、configTOTAL_HEAP_SIZEを増やしすぎではないかチェックするようにしてください。 |
Previous: 8.2.1. スタック領域残量の確認 |
Up: 8.2. スタックオーバーフローの検知 |
Next: 9. FreeRTOSを利用したマウスロボット |