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
or more exactly on instruction
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