Я работаю над Silabs ARM Cortex M3 (EFM32PG12).
Я хочу объявить раздел компоновщика XXX между кучей и стеком, поместить туда переменную и посмотреть позже (тема аппаратного сбоя), если эта переменная загрязнится.
.heap (COPY):
{
__HeapBase = .;
__end__ = .;
end = __end__;
_end = __end__;
KEEP(*(.heap*))
__HeapLimit = .;
} > RAM
.xxx (NOLOAD): /* my DEBUG section */
{
. = ALIGN(4);
__xxx_start__ = .;
KEEP(*(.xxx*))
__xxx_end__ = .;
} > RAM
/* .stack_dummy section doesn't contains any symbols. It is only
* used for linker to calculate size of stack sections, and assign
* values to stack symbols later */
.stack_dummy (COPY):
{
KEEP(*(.stack*))
} > RAM
/* Set stack top to end of RAM, and stack limit move down by
* size of stack_dummy section */
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
PROVIDE(__stack = __StackTop);
/* Check if data + heap + stack exceeds RAM limit */
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
/* Check if FLASH usage exceeds FLASH size */
ASSERT( LENGTH(FLASH) >= (__etext + SIZEOF(.data)), "FLASH memory overflowed !")
теперь в моем коде я объявил такую переменную
__attribute__((section(".xxx"))) volatile uint32_t dirtyvar = 0x12345678;
но файл карты показывает довольно странно, кажется, что регион XXX все еще находится перед HEAP
*(COMMON)
COMMON 0x20000c7c 0x6004 ./src/dbg_malloc.o
0x20000c7c dbgMallocData
COMMON 0x20006c80 0x4 ./src/drv_uart.o
0x20006c80 frames
COMMON 0x20006c84 0x4 ./src/error.o
0x20006c84 __stack_chk_guard
COMMON 0x20006c88 0x4 c:/siliconlabs/simplicitystudio/v5/developer/toolchains/gnu_arm/7.2_2017q4/bin/../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/lib/thumb/v7e-m/fpv4-sp/softfp\libc_nano.a(lib_a-reent.o)
0x20006c88 errno
0x20006c8c . = ALIGN (0x4)
0x20006c8c __bss_end__ = .
.heap 0x20006c90 0x2000
0x20006c90 __HeapBase = .
0x20006c90 __end__ = .
0x20006c90 end = __end__
0x20006c90 _end = __end__
*(.heap*)
.heap 0x20006c90 0x2000 ./CMSIS/EFM32PG12B/startup_gcc_efm32pg12b.o
0x20008c90 __HeapLimit = .
.xxx 0x20006c8c 0x4 load address 0x00009b88
0x20006c8c . = ALIGN (0x4)
0x20006c8c __xxx_start__ = .
*(.xxx*)
.xxx 0x20006c8c 0x4 ./src/error.o
0x20006c8c dirtyvar
0x20006c90 __xxx_end__ = .
.stack_dummy 0x20006c90 0x80
*(.stack*)
.stack 0x20006c90 0x80 ./CMSIS/EFM32PG12B/startup_gcc_efm32pg12b.o
0x20040000 __StackTop = (ORIGIN (RAM) + LENGTH (RAM))
0x2003ff80 __StackLimit = (__StackTop - SIZEOF (.stack_dummy))
0x20040000 PROVIDE (__stack, __StackTop)
0x00000001 ASSERT ((__StackLimit >= __HeapLimit), region RAM overflowed with stack)
0x00000001 ASSERT ((LENGTH (FLASH) >= (__etext + SIZEOF (.data))), FLASH memory overflowed !)
OUTPUT(5GNR_EFM32.axf elf32-littlearm)
Как правильно объявить этот регион, чтобы я мог видеть при сбое, если HEAP только что повредил мой STACK?
Я сделал все, что мог:
- Я написал оболочку для malloc/free, она работает как положено.
- Я компилировал с -fstack-protector-all, вроде тут все ок
- Я пытался написать такой обработчик HARD FAULT, но содержимое CFSR совершенно не имеет значения.
void debugHardfault(uint32_t *sp)
{
uint32_t cfsr = SCB->CFSR;
uint32_t hfsr = SCB->HFSR;
uint32_t mmfar = SCB->MMFAR;
uint32_t bfar = SCB->BFAR;
uint32_t r0 = sp[0];
uint32_t r1 = sp[1];
uint32_t r2 = sp[2];
uint32_t r3 = sp[3];
uint32_t r12 = sp[4];
uint32_t lr = sp[5];
uint32_t pc = sp[6];
uint32_t psr = sp[7];
printf("HardFault:\n");
printf("SCB->CFSR 0x%08lx\n", cfsr);
/*
* HFSR
* 0x1b4b09b3
*
*
* 00011011 01001011 00001001 10110011
*
*/
printf("SCB->HFSR 0x%08lx\n", hfsr);
printf("SCB->MMFAR 0x%08lx\n", mmfar);
printf("SCB->BFAR 0x%08lx\n", bfar);
printf("\n");
printf("SP 0x%08lx\n", (uint32_t)sp);
printf("R0 0x%08lx\n", r0);
printf("R1 0x%08lx\n", r1);
printf("R2 0x%08lx\n", r2);
printf("R3 0x%08lx\n", r3);
printf("R12 0x%08lx\n", r12);
printf("LR 0x%08lx\n", lr);
printf("PC 0x%08lx\n", pc);
printf("PSR 0x%08lx\n", psr);
while(1);
}
Notice: This fault gets more often (still random) when I compile with -O3.
Еще одна проблема, которую я заметил, заключается в том, что malloc() никогда не возвращает NULL, как будто у меня неограниченная куча, поэтому я подозреваю переполнение стека.
Заранее спасибо,
malloc() never returns NULL like I have unlimited HEAP
Сверху — какую стандартную библиотеку вы используете? Какую реализациюmalloc()
вы используете? Он звонитsbrk()
? Вы задаете вопрос XY - вы спрашиваете о каком-то регионе - не намерены ли вы конкретно спросить, как обнаружить переполнение / недополнение HEAP / стека на вашей платформе? - person KamilCuk   schedule 21.06.2021static
в вашsbrk()
для проверки на перераспределение, проверьте размер стека вsbrk()
на предмет переполнения, см. mcuoneclipse.com/2019/09/28/, скомпилируйте с помощью-finstrument-functions
и проверьте, не переполнен ли стек /близок к переполнению в__cyg_profile_func_*
функциях. - person KamilCuk   schedule 21.06.2021