AnsweredAssumed Answered

Help On Hard Fault Possibly By Heap-Stack Overlap

Question asked by chao dong on Jun 16, 2019
Latest reply on Jun 16, 2019 by Erich Styger

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.

 

 

 

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

Attachments

Outcomes