EmbDev.net

Forum: ARM programming with GCC/GNU tools Troubles hunting down a Hard Fault Exception


Author: Marco ... (borealis_1427)
Posted on:

Rate this post
1 useful
not useful
Hi,

I am having trouble finding the reason for a hard fault exception on my 
cortex-M3 (STM32F107). I have implemented the exception handler 
according to the book "The definiteve guide to the ARM Cortex-M3".

The assembler part:
__asm void HardFault_Handler(void)
{
  IMPORT hard_fault_handler_c
  TST LR, #4
  ITE EQ
  MRSEQ R0, MSP
  MRSNE R0, PSP
  B hard_fault_handler_c
}

And the C part:
void hard_fault_handler_c(unsigned int * hardfault_args)
{

  volatile unsigned int stacked_r0;
  volatile unsigned int stacked_r1;
  volatile unsigned int stacked_r2;
  volatile unsigned int stacked_r3;
  volatile unsigned int stacked_r12;
  volatile unsigned int stacked_lr;
  volatile unsigned int stacked_pc;
  volatile unsigned int stacked_psr;

  stacked_r0 = ((unsigned long) hardfault_args[0]);
  stacked_r1 = ((unsigned long) hardfault_args[1]);
  stacked_r2 = ((unsigned long) hardfault_args[2]);
  stacked_r3 = ((unsigned long) hardfault_args[3]);

  stacked_r12 = ((unsigned long) hardfault_args[4]);
  stacked_lr = ((unsigned long) hardfault_args[5]);
  stacked_pc = ((unsigned long) hardfault_args[6]);
  stacked_psr = ((unsigned long) hardfault_args[7]);
  
  printf ("[Hard fault handler]\n");
  printf ("R0 = %08x\n", stacked_r0);
  printf ("R1 = %08x\n", stacked_r1);
  printf ("R2 = %08x\n", stacked_r2);
  printf ("R3 = %08x\n", stacked_r3);
  printf ("R12 = %08x\n", stacked_r12);
  printf ("LR = %08x\n", stacked_lr);
  printf ("PC = %08x\n", stacked_pc);
  printf ("PSR = %08x\n", stacked_psr);
  printf ("BFAR = %08x\n", (*((volatile unsigned long *)(0xE000ED38))));
  printf ("CFSR = %08x\n", (*((volatile unsigned long *)(0xE000ED28))));
  printf ("HFSR = %08x\n", (*((volatile unsigned long *)(0xE000ED2C))));
  printf ("DFSR = %08x\n", (*((volatile unsigned long *)(0xE000ED30))));
  printf ("AFSR = %08x\n", (*((volatile unsigned long *)(0xE000ED3C))));
  while (1)
  {} 
} 

When the CPU traps, I get the follwing output:
[Hard fault handler]
R0 = 00000000
R1 = 00000000
R2 = 00000004
R3 = 00000004
R12 = 01010101
LR = 08002987
PC = 08000768
PSR = 61000000
BFAR = e000ed38
CFSR = 00000400
HFSR = 40000000
DFSR = 00000000
AFSR = 00000000

From this I can see that in CFSR's BFSR part bit bit 2 (IMPRECISERR) is 
set. According to the book this means:
"Bus error during data access. Bus error could be caused by device not 
being initialized, access of privileged-only device in user mode, or the 
transfer size is incorrect for the specific device."

I was also able to find the source code line that causes the exception:
uint8_t err;

devData[minorNum]->writeMutex = OSMutexCreate(2, &err);
if (OS_ERR_NONE != err) {
  return DRV_ERR;
}

The assebler code for this is:
   124:   devData[minorNum]->writeMutex = OSMutexCreate(2, &err); 
0x0800074C 4669      MOV      r1,sp
0x0800074E 2002      MOVS     r0,#0x02
0x08000750 F002F8D5  BL.W     OSMutexCreate (0x080028FE)
0x08000754 494A      LDR      r1,[pc,#296]  ; @0x08000880
0x08000756 F8511024  LDR      r1,[r1,r4,LSL #2]
0x0800075A 6048      STR      r0,[r1,#0x04]
   125:   if (OS_ERR_NONE != err) { 
0x0800075C F89D0000  LDRB     r0,[sp,#0x00]
0x08000760 B110      CBZ      r0,0x08000768
   126:     return DRV_ERR; 
   127:   }

The exception occurs when executing
if (OS_ERR_NONE != err)
 or more exactly on instruction
LDRB     r0,[sp,#0x00]

Register sp conatains 0x200010f4 (before executing the LDRB 
instruction), which is in the RAM area.

Any ideas on what's going wrong here?

Thanks in advance for your tips and help!

P.S.: I am using the RealView compiler.

--
Regards,
 Marco

Author: Marcus Harnisch (mharnisch)
Posted on:

Rate this post
0 useful
not useful
I'd recommend having a look at this instruction
STR      r0,[r1,#0x04]

Author: A. K. (prx)
Posted on:

Rate this post
0 useful
not useful
No.

LDR      r1,[pc,#296]  ; @0x08000880
  loads the address of devData from the constant pool
LDR      r1,[r1,r4,LSL #2]
  loads devData[minorNum]
STR      r0,[r1,#0x04]
  devData[minorNum]->writeMutex = ...

Correct so far. But we lack information about R4=minorNum. Most likely 
the STR instruction fails because the address loaded in the 2nd LDR is 
invalid (0).

Author: Marco ... (borealis_1427)
Posted on:

Rate this post
0 useful
not useful
Marcus Harnisch wrote:
>
> STR      r0,[r1,#0x04]
> 
r0 = 0x20001174
r1 = 0x00000000

RAM starts at 0x20000000 and is 64 KB long.

So that assembler instruction should store 0 to RAM area.

Author: Marcus Harnisch (mharnisch)
Posted on:

Rate this post
0 useful
not useful
Marco ... wrote:
> r0 = 0x20001174
> r1 = 0x00000000
>
> RAM starts at 0x20000000 and is 64 KB long.
>
> So that assembler instruction should store 0 to RAM area.

No. It stores 0x20001174 to 0x4.

Author: Marco ... (borealis_1427)
Posted on:

Rate this post
1 useful
not useful
A. K. wrote:
[...]
> Correct so far. But we lack information about R4=minorNum. Most likely
> the STR instruction fails because the address loaded in the 2nd LDR is
> invalid (0).

r4 = 0 before executing
LDR      r1,[r1,r4,LSL #2]

Debugger shows that minorNum = 0 too.

Author: Marco ... (borealis_1427)
Posted on:

Rate this post
0 useful
not useful
Thanks to your hints, I found the trace to follow and solved the problem 
now.

--> Dangling pointer for devData...

Many thanks for your help!

--
Regards,
 Marco

Reply

Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]




Bild automatisch verkleinern, falls nötig
Note: the original post is older than 6 months. Please don't ask any new questions in this thread, but start a new one.