Hello,
I'm using a lpc1766 and made a very simple program to debug a hardfault exception.
After initiallisation the main routine is called where a array is allocated using the library function malloc().
When the malloc function is called a "bus fault" exception arises which ends up in a "hard fault" exception. In the hard fault exception handler I can read the exception registers using the debugger "fault reports" dialog.
When I double click on the topmost entry of the callstack it jumps to the following instruction: 0x00000280 4605 MOV r5,r0
Can somenone tell me why my code ends up in hardfault exception?
Below is the function in C and assembly.
void *alloc_ram(uint16 size) { void *ram; __disable_irq(); ram = malloc(size); __enable_irq(); return(ram); } 32: { 33: void *ram; 34: 0x00000274 B570 PUSH {r4-r6,lr} 0x00000276 4604 MOV r4,r0 35: __disable_irq(); 36: 0x00000278 B672 CPSID I 37: ram = malloc(size); 38: 0x0000027A 4620 MOV r0,r4 0x0000027C F000F840 BL.W malloc (0x00000300) 0x00000280 4605 MOV r5,r0 39: __enable_irq(); 40:
Have you provided and/or correctly configured all the support required by malloc to manage the heap, etc...?
The stack and the heap are initialised in the startup file that i use (see below).
I think that this should sufficient.
Stack_Size EQU 0x00000400 AREA STACK, NOINIT, READWRITE, ALIGN=3 Stack_Mem SPACE Stack_Size __initial_sp Heap_Size EQU 0x00000400 AREA HEAP, NOINIT, READWRITE, ALIGN=3 __heap_base Heap_Mem SPACE Heap_Size __heap_limit PRESERVE8 THUMB ............... ............... ............... ............... ;/***********************************************************************/ ; DEFINE STACK AND HEAP ;/***********************************************************************/ IF :DEF:__MICROLIB EXPORT __initial_sp EXPORT __heap_base EXPORT __heap_limit ELSE IMPORT __use_two_region_memory EXPORT __user_initial_stackheap __user_initial_stackheap LDR R0, = Heap_Mem LDR R1, =(Stack_Mem + Stack_Size) LDR R2, = (Heap_Mem + Heap_Size) LDR R3, = Stack_Mem BX LR ALIGN ENDIF END
But what do the manuals say?
I haven't found anything in the manuals about why this wouldn't work. You?!
http://www.keil.com/support/man/docs/armlib/armlib_cihfiabf.htm
I found the problem. In my assembly oode I have set my reset vector to init_lpc(). a function that sets up the pll and power control. It seems that when the reset vector is not set to __main you have to tell the linker what the entry point to the program is or else the heap and stack won't be initialised.
Kind regards. Sander Wiggers
Sander,
I have similar problem:
* The Ethernet ISR is setting an event using isr_evt_set(TASK_EVENT_RX_FLAG, gTaskEthernetRx_ID);
* the task is waking up on os_evt_wait_or(TASK_EVENT_RX_FLAG, 0xFFFF);
* the task is trying to allocate memory using "malloc" but its failing and the PC is jumping to the hard fault handler.
Questions:
1) any suggestion on how I should debug this problem?
2) what are the commands to "tell the linker what the entry point to the program is"? I would like to try it.
thanks. khaled.
Does the code die inside malloc()?
Might be due to an earlier allocation being overwritten, resulting in destroyed data structures for malloc() to process when locating a free block.
Or too little stack space when calling malloc().
Or the library is using a locking mechanism to make malloc() thread-safe, and that lock hasn't been initialized or have been overwritten.
If malloc() does return data but the program fails when you access the data, then you may try to access the buffer without first checking if you got a NULL pointer.
Or the malloc() data structures have been destroyed (for example buffer overruns) resulting in malloc returning a pointer to a forbidden memory region (or a region where other parts of the program stores (or things they are allowed to store) critical data.
Or you suffered a stack overflow, resulting in the processor being dazed and confused when returning from malloc().
There are probably other alternatives too.
If you write a "normal" C program, you will not need to tell the linker where the startup address is for your program. The hw reset (or boot loader) should find the startup address in the interrupt vector table. And the startup code should know what function to call when the assembler startup is done - normally an init call into the C RTL.
WOW, that was a quick response. Unfortunately, after reading your e-mail, I did more checks and found no reason why the code is failing. The only thing that I would like to explore more is the "blocking" (see below).
1) where it dies? most likely inside the malloc. When I step into malloc, the PC "arrow" does not come back. If I stop the program, its always in the hard fault interrupt loop (forever loop).
2) this is the first allocation in the program i.e. I should have enough memory. In all cases, 1) I do check for a NULL return before trying to access the data and 2) the jump to the fault handler is happening during alloc.
3) I thought that alloc uses heap not stack! but I have a heap size of 0x4000 and a stack size of 0x1000. Since its failing on the first call to alloc, I dont think that I have used all of that memory. In addition, no stack overflow is detected by the RTOS.
4) please explain further on the blocking. it might be the cause.
5) I dont think that the the malloc() data structures have been destroyed. Again, I did not get beyond the allocation command.
6) no stack overflow is reported. The os_stk_overflow (replaced by os_error) is not called.
7) yes I'm writing a normal C code.
One additional information, If I disable the RTX kernal, malloc works fine
khaled.
Did you call "init_mempool" ?