Troubles hunting down a Hard Fault Exception

OP #1703285
Rate this post
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:
1
__asm void HardFault_Handler(void)
2
{
3
  IMPORT hard_fault_handler_c
4
  TST LR, #4
5
  ITE EQ
6
  MRSEQ R0, MSP
7
  MRSNE R0, PSP
8
  B hard_fault_handler_c
9
}

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

4
  volatile unsigned int stacked_r0;
5
  volatile unsigned int stacked_r1;
6
  volatile unsigned int stacked_r2;
7
  volatile unsigned int stacked_r3;
8
  volatile unsigned int stacked_r12;
9
  volatile unsigned int stacked_lr;
10
  volatile unsigned int stacked_pc;
11
  volatile unsigned int stacked_psr;
12

13
  stacked_r0 = ((unsigned long) hardfault_args[0]);
14
  stacked_r1 = ((unsigned long) hardfault_args[1]);
15
  stacked_r2 = ((unsigned long) hardfault_args[2]);
16
  stacked_r3 = ((unsigned long) hardfault_args[3]);
17

18
  stacked_r12 = ((unsigned long) hardfault_args[4]);
19
  stacked_lr = ((unsigned long) hardfault_args[5]);
20
  stacked_pc = ((unsigned long) hardfault_args[6]);
21
  stacked_psr = ((unsigned long) hardfault_args[7]);
22
  
23
  printf ("[Hard fault handler]\n");
24
  printf ("R0 = %08x\n", stacked_r0);
25
  printf ("R1 = %08x\n", stacked_r1);
26
  printf ("R2 = %08x\n", stacked_r2);
27
  printf ("R3 = %08x\n", stacked_r3);
28
  printf ("R12 = %08x\n", stacked_r12);
29
  printf ("LR = %08x\n", stacked_lr);
30
  printf ("PC = %08x\n", stacked_pc);
31
  printf ("PSR = %08x\n", stacked_psr);
32
  printf ("BFAR = %08x\n", (*((volatile unsigned long *)(0xE000ED38))));
33
  printf ("CFSR = %08x\n", (*((volatile unsigned long *)(0xE000ED28))));
34
  printf ("HFSR = %08x\n", (*((volatile unsigned long *)(0xE000ED2C))));
35
  printf ("DFSR = %08x\n", (*((volatile unsigned long *)(0xE000ED30))));
36
  printf ("AFSR = %08x\n", (*((volatile unsigned long *)(0xE000ED3C))));
37
  while (1)
38
  {} 
39
}

When the CPU traps, I get the follwing output:
1
[Hard fault handler]
2
R0 = 00000000
3
R1 = 00000000
4
R2 = 00000004
5
R3 = 00000004
6
R12 = 01010101
7
LR = 08002987
8
PC = 08000768
9
PSR = 61000000
10
BFAR = e000ed38
11
CFSR = 00000400
12
HFSR = 40000000
13
DFSR = 00000000
14
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:
1
uint8_t err;
2

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

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

The exception occurs when executing
1
if (OS_ERR_NONE != err)
 or more exactly on instruction
1
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
#1703319
Rate this post
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).

Reply

Please log in before posting.

or

Log in with Google account

Registration is free and takes only a minute.

Register now