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:
Thanks a lot for any replies.
Chao Dong
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