HardFault when using IAR 6.50 - Page 1
Forum section: electronics / general

author: tanffn
author_rank: Contributor
timestamp: April 13, 2015, 06:03:02 pm
content: Hello!I 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?Code:Starting with Ethernet cable unplugged:TaskUDP_ExeStart()tcpip_init(NULL, NULL);Netif_Config();...Enters ethernetif_input - oncelow_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 Truenetif_set_addr(...)netif_set_up(...)Enters ethernetif_input - many timeslow_level_input, 2x244 bytes 2x187 2x92 244, 243, ...HardFault_Handlerwhile (1)...

author: andersm
author_rank: Super Contributor
timestamp: April 13, 2015, 06:41:11 pm
content: You didn't say, but I'm assuming this is on some kind of Cortex-M device? Enable the different types of faults in the SHCSR register and you'll get a bit more granularity in the diagnosis. The usual cause is some kind of memory handling error. Look at the register and stack contents to see what the CPU was executing.

author: tanffn
author_rank: Contributor
timestamp: April 14, 2015, 06:29:04 pm
content: Thank you andersm,You are correct its an Cortex-M4 device (STM32F4).I will look into it! yet even if I find the region that raised the error, I don't see how I would handle it as I didn't write LwIp/FreeRTOS/.. :/

author: senso
author_rank: Frequent Contributor
timestamp: April 14, 2015, 08:17:46 pm
content: Maybe the code wants to use the hardware FPU and its still disabled, that can cause an hard-fault.

author: Jeroen3
author_rank: Super Contributor
timestamp: April 16, 2015, 12:26:44 pm
content: Quote from: senso on April 14, 2015, 08:17:46 pmDoesn't that cause a busfault that will get escalated if you didn't enable the busfault handlers.As said, first read the fault registers, and possibly the stackdump. So you'll know the exact instruction and it's arguments.http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/Cihieffb.htmlIt (or you) most likely messed up some pointer kung-fu that lwip used with numerous castings.

author: tanffn
author_rank: Contributor
timestamp: April 17, 2015, 08:30:15 pm
content: Thank you all for helping!Quote from: senso on April 14, 2015, 08:17:46 pmNo, Tested that, it's initialized correctly.Quote from: Jeroen3 on April 16, 2015, 12:26:44 pmThe exact same code does work with IAR 7.40..I found some nice (and very old) links and I implemented their suggested code.https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https%3a%2f%2fmy%2est%2ecom%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fcortex_mx_stm32%2fHardFault%20Exception%20Why%20oh%20why%21&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=9100I 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..Link to the IAR data:https://www.dropbox.com/s/kc15q186pz71qrj/hardfault.PNG?dl=0As suggested I also added static to the relevant variables.What can you learn from this?Code:[Hard fault handler]R0 = 20012f3cR1 = 20011ea2R2 = 20011e6cR3 = 20011e8aR12 = 20011e7cLR = 20013004-> Link registerPC = 20013008-> Program counter -> gnetifPSR = 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 faultDFSR = b-> ???AFSR = 0-> Auxiliary fault status register

author: donotdespisethesnake
author_rank: Super Contributor
timestamp: April 17, 2015, 09:55:53 pm
content: I think it's clear you have a stack corruption somewhere. Making variables static is what I call a "hackers fix", it might get past the immediate corruption, but doesn't fix the underlying cause. Stack corruption could also be caused if stack overflows into other region.The hardfault just shows the after effects of the corruption unfortunately, the registers will mostly be garbage. Clearly if you have a PC that is a RAM address then it has gone badly wrong. (You may have some code in RAM, but it should be easy to identify if it is valid for the PC to be in RAM or not from the link map).The registers end up with garbage because a function call attempted to return and restored registers of a corrupted stack. The only useful register is LR, which is where the fault came from. You will need to trace back by setting breakpoints to find the function which did the restore. Hopefully, the corruption is in that function, but often there is some other function call that causes the corruption (could be an ISR).So its a question of tracing through from before the corruption to narrow down the offending code. If you have a number of ways to repeatably create the fault that is good, I would start with the low optimisation version.

author: Jeroen3
author_rank: Super Contributor
timestamp: April 19, 2015, 12:17:09 pm
content: Did you check the callgraph of your functions to see if they fit stack?If you want to know why it crashed, you should track down the misbehaving instruction. Put a breakpoint on it, and verify if all locals are valid.Also, this piece of code is very helpful. Because it seems your stackdump reading is wrong. All R's are 0. That can't be true.It's for rvct, not iar. But thats not hard to fix. It is essential that you do not optimize this file, so -O0 for this file.It also happens to be for stm32f4, so the uart will work.If you're attempting to use lwip for commercial use, don't. Buy a stack somewhere, they're not expensive.

author: tanffn
author_rank: Contributor
timestamp: April 23, 2015, 09:45:17 am
content: 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..Code:taskSELECT_HIGHEST_PRIORITY_TASK()...\df=5;\listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) );\df=6;\ ...

author: tanffn
author_rank: Contributor
timestamp: April 26, 2015, 05:39:52 pm
content: No one? :/

author: Jeroen3
author_rank: Super Contributor
timestamp: April 26, 2015, 06:23:54 pm
content: The location the hardfault occurs is not the location the hardfault becomes inevitable.You'd need to examine upwards the program flow from the location of the hardfault to the location an state is created that will cause trouble.For example:What if inlistGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) );\pxCurrentTCB, isn't a valid pointer. Due to some casting somewhere back.Of what ifuxTopReadyPriorityis out of range.