Project

General

Profile

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