This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

alloc ram causes hardfault

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:

Parents
  • 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
    

Reply
  • 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
    

Children
  • I haven't found anything in the manuals about why this wouldn't work. You?!

  • 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.