Actions
DetectStackOverflow » History » Revision 1
Revision 1/12
| Next »
mole lord, 09/09/2020 02:39 PM
DetectStackOverflow¶
FreeRTOSスケジューラ起動前のスタックオーバフロー検出¶
STM32F4には Core Coupled Memory (以降CCM) が 0x1000_0000 番地にあります。(リファレンスマニュアルを参照)
リンカスクリプトをいじってCCMの先頭部分にスタック領域を配置すれば、スタックオーバフローがRAMが存在しない領域へのWriteとなり、 Hard Fault を起こします。
乱暴ですが、Hard Faultをもってスタックオーバフロー検出ができます。
(グローバル変数を破壊して摩訶不思議な挙動をされるよりはよいです)
CCMRAMにスタックを置くデメリットは、スタック上の値をDMACが扱えなくなることですが、
具体的には、 STM32F429ZITx_FLASH.ld を開いて、
/* Highest address of the user mode stack */
_estack = 0x20030000; /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x0; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */
を以下のように書き換えます。
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x0; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */
/* Highest address of the user mode stack */
_estack = 0x10000000 + _Min_Stack_Size;
また、._user_heap_stackの部分を削除し、
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(8);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(8);
} >RAM
その代わりに >CCMRAM
に挿入します。
.ccmram :
{
. = ALIGN(4);
_sccmram = .; /* create a global symbol at ccmram start */
. = ALIGN(8);
_user_heap_stack = .;
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(8);
*(.ccmram)
*(.ccmram*)
. = ALIGN(4);
_eccmram = .; /* create a global symbol at ccmram end */
} >CCMRAM
動作確認は、無限再帰の関数を作ってそれをmain()から呼び出してやることで行えます。
static int32_t
recurse(int32_t x)
{
return recurse(x + 1);
}
int main()
{
...
int32_t x = recurse(0);
int32_t i;
for (i = 0; i < x; i++) ;
...
FreeRTOSのタスクのスタックオーバフロー検出¶
FreeRTOS自体にもスタックオーバフロー検出の仕組みが備わってはいます。しかし、いまいち信用ならないので、Memory Protection Unit(以降MPU)を使ってアクセス不能な領域を作ることで検出を行います。
デメリットは、スタック領域1つごとに32バイトの使用不可領域ができることです。
続く
累計表示回数:279
Updated by mole lord 5 months ago · 1 revisions