cancel
Showing results for 
Search instead for 
Did you mean: 

HardFault when using IAR 6.50

ariel2
Associate II
Posted on April 13, 2015 at 19:57

Noticed an ''interesting'' issue that I was unable to trackdown.

If I compile the example LwIP_UDPTCP_Echo_Server_Netconn_RTOS using IAR 7.40 everything works fine YET when I compile the same code using IAR 6.50 I get an HardFault.

Tried to track down the cause but in vail...

I need to use 6.50 as thats the license we have, I use size limit with 7.40 (removed TCP to squeeze it in :))

Do you have any idea how to attack this issue?

Starting with Ethernet cable unplugged:

TaskUDP_ExeStart()

tcpip_init(NULL, NULL);

Netif_Config();

...

Enters ethernetif_input - once

low_level_input 

...

(netif_is_link_up(&gnetif)) is false

...

(... working fine, LED blinks ...)

Plugging in the Ethernet cable:

...

ethernetif_notify_conn_changed()

(netif_is_link_up(netif)) is True

netif_set_addr(...)

netif_set_up(...)

Enters ethernetif_input - many times

low_level_input, 2x244 bytes 2x187 2x92 244, 243, ...

HardFault_Handler

while (1)...
6 REPLIES 6
Posted on April 14, 2015 at 01:11

Consider implementing a handler that does more than loop. Joseph Yiu has published some good examples, start there, and identify what's actually faulting, and what the registers tell you about the problem.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
ariel2
Associate II
Posted on April 14, 2015 at 20:33

Thank you Clive,

Thats a nice reference, I will look into it.

ariel2
Associate II
Posted on April 17, 2015 at 22:28

I found some nice (and very old) links and I implemented their suggested code.

With optimization set to Medium or Low it ~didn't work (it cleared some of the registers, but still shows it's a BUS fault).

When optimization was set to High-Speed I was able to receive full data, yet I can't conclude the reason for the fault..

As suggested I also added static to the relevant variables.

What can you learn from this?

[Hard fault handler]

R0 = 20012f3c

R1 = 20011ea2

R2 = 20011e6c

R3 = 20011e8a

R12 = 20011e7c

LR = 20013004   -> Link register

PC = 20013008 -> Program counter -> gnetif

PSR = 8008534 -> N (GE-84) (ISR-134)

BFAR = bc01b51b -> Bus fault address (4.4.12, p223) -> ????? there is nothing there!

CFSR = 8200 -> Usage fault status register (4.4.11, p222): Bus Fault Address Register-> BFAR holds a valid fault address.

HFSR = 40000000 -> Hard fault status register (4.4.14, p225): Forced hard fault

DFSR = b -> ???

AFSR = 0 -> Auxiliary fault status register

ariel2
Associate II
Posted on April 17, 2015 at 22:31

The images as links.. Should I delete them from the post?

https://www.dropbox.com/s/kc15q186pz71qrj/hardfault.PNG?dl=0

Posted on April 18, 2015 at 00:43

Yeah, I'm not sure that's working, your code's in RAM?

The stack data isn't at a fixed address, and the LR code to get the right stack register in R0 needs to be outside the C code. ie assembler code at the Hard_Fault_Handler, then calling your C code. In Keil something like this...

; in startup.s
HardFault_Handler PROC
EXPORT HardFault_Handler
IMPORT HardFault_Handler_C
TST LR, #4
ITE EQ
MRSEQ R0, MSP
MRSNE R0, PSP
B HardFault_Handler_C
ENDP ; HardFault_Handler
// in main.c
void HardFault_Handler_C(unsigned int* hardfault_args)
{
unsigned int stacked_r0;
unsigned int stacked_r1;
unsigned int stacked_r2;
unsigned int stacked_r3;
unsigned int stacked_r12;
unsigned int stacked_lr;
unsigned int stacked_pc;
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 - all numbers in hex]

'');
printf(''R0 = %x

'', stacked_r0);
printf(''R1 = %x

'', stacked_r1);
printf(''R2 = %x

'', stacked_r2);
printf(''R3 = %x

'', stacked_r3);
printf(''R12 = %x

'', stacked_r12);
printf(''LR [R14] = %x subroutine call return address

'', stacked_lr);
printf(''PC [R15] = %x program counter

'', stacked_pc);
printf(''PSR = %x

'', stacked_psr);
printf(''BFAR = %x

'', (*((volatile unsigned long *)(0xE000ED38))));
printf(''CFSR = %x

'', (*((volatile unsigned long *)(0xE000ED28))));
printf(''HFSR = %x

'', (*((volatile unsigned long *)(0xE000ED2C))));
printf(''DFSR = %x

'', (*((volatile unsigned long *)(0xE000ED30))));
printf(''AFSR = %x

'', (*((volatile unsigned long *)(0xE000ED3C))));
printf(''SCB_SHCSR = %x

'', SCB->SHCSR);
while(1);
}

You'll have to adapt for your IAR chains
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
ariel2
Associate II
Posted on April 23, 2015 at 11:47

Thank you again for your hints! 

Using LR I've been able to track down the problem to a macro in FreeRTOS\tasks.c (which seems to run from memory, hence the address).

Since I can put a breakpoint I added a debug variable to find the problematic line.

If I try to debug further (adding more debug code) the location of the hard-fault changes..

Can't figure out how to track it down, in the vast RTOS/LwIp code..

taskSELECT_HIGHEST_PRIORITY_TASK()

... \

df=5; \

listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) );\

df=6; \ ...