Help On Hard Fault Possibly By Heap-Stack Overlap

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

Help On Hard Fault Possibly By Heap-Stack Overlap

1,172件の閲覧回数
15023091155
Contributor I

I designed an embedded software (written in C++ and almost all C++ objects are dynamically linked using heap) targeting on MKE02 MCU(64KB Flash with 4KB SRAM), but it has a serious bug causing hard fault occasionally.

 

This is a bug when the code size and data size of the application software approaches its maximum, and corruptions of data structures created by "new" operator were observed before. I had to upgrade the MCU from MKE02Z32 (32KB Flash with 4KB SRAM) to MKE02Z64 (64KB Flash with 4KB SRAM) because of this bug recently, and this upgrade did solve the problem.

 

Unfortunately, the application size is now getting big enough to hit the bug again. In order to find a complete solution for this bug, please help me understand more about the runtime memory map of this MCU.

 

As shown in the snapshot (from ProcessorExpert, KDS 3.0 platform) below, the starting address of the software is 0x4600 with max code length of 0xB1F0, the code space ends at 0xFBFF, 0xFC00 - 0xFFFF is used for data storage, and 0x0 – 0x45FF is used for a bootloader designed by ourselves.

pastedImage_1.png

The result from compiler (with optimization level –O0) and linker is as below:

Text 42760  data 140  bss 3584  dec 46484  hex B594

 

The map file and linker file are attached.

The following are taken from the map file:

 

                0x0000ef7c                ___ROM_AT = .

.data        0x1ffffc00       0x68 load address 0x0000ef7c

.bss         0x1ffffc68      0x300 load address 0x0000efe4

 

._user_heap_stack

                0x1fffff80      0xb00    load address 0x0000effc

                0x1fffff80                      __heap_addr = .

                0x1fffff80                      __HeapBase = .

                0x20000680                . = (. + __heap_size)

 *fill*         0x1fffff80      0x700

                0x20000680                __HeapLimit = .

                0x20000a80                . = (. + __stack_size)

 *fill*         0x20000680  0x400

 

                0x20000c00                _estack = 0x20000c00

                0x20000c00                __SP_INIT = _estack

                0x20000c00                __stack = _estack

                0x00000700                __heap_size = 0x700

                0x00000400                __stack_size = 0x400

 

However, I tested the heap pointer using the code which looks like the following:

int main(void)

{

  PE_low_level_init();

  uint32_t* heapPtr = (uint32_t*) _sbrk(0);

  myDebugger.Print("HeapStart = 0x%X", (uint32) heapPtr);

  MyApp *myApp = new MyApp();

heapPtr = (uint32_t*) _sbrk(0);

  myDebugger.Print("heapPtr = 0x%X", (uint32) heapPtr);

}

 

It prints out:

HeapStart = 0x200003B8

heapPtr = 0x20000864

 

based upon above information, now I have questions below:

  1.        Why the heap addresses defined in the map file (0x1fffff80 – 0x20000680) are different from that returned by         _sbrk(0) (0x200003B80x20000864)?
  2.        Why the Stack address has different definition in the map file (0x20000a80 vs 0x20000c00) while startup.c loads     0x20000c00 into SP?
  3.        How to safely get the stack pointer while application is running?

 

Thanks a lot for any replies.

Chao Dong

0 件の賞賛
返信
1 返信

1,079件の閲覧回数
BlackNight
NXP Employee
NXP Employee

It might depend on which ARM toolchain (or library) you are using, so it might be helpful to share which IDE you are actually using.

One thing to note is that by default the stack and heap are growing towards each other: which means that the stack could potentially run into the heap and the heap could potentially run into the stack. Depending on your sbrk() implementation, you might get a fault there (see FreeRTOS, malloc() and SP check with GNU Tools | MCU on Eclipse).

About your questions:

1) I assume you are calling indirectly some constructors already (in the startup code)? Then there already can be memory allocated in the heap.

2) what is the value of SP in the vector table? at address 0x0 there should be 0x20000c00 as initial stack pointer.

3) I'm using the following from the 'KinetisTools' Processor Expert component:

/*
** ===================================================================
**     Method      :  GetSP (component KinetisTools)
**
**     Description :
**         returns the stack pointer
**     Parameters  : None
**     Returns     :
**         ---             - stack pointer
** ===================================================================
*/
void* KIN1_GetSP(void)
{
#ifdef __GNUC__
  void *sp;

  __asm__ __volatile__ ("mrs %0, msp" : "=r"(sp));
  return sp;
#else
  #warning "only for GCC"
  return NULL;
#endif
}

I hope this helps,

Erich

0 件の賞賛
返信