FreeRTOS + TCP is crashing in prvEMACHandlerTask()

FreeRTOS + TCP project based on STM32F407 is crashing after running for few seconds even without any communication. I was able to trace it to the source:
prvEMACHandlerTask() <- ulTaskNotifyTake() in NetworkInterface.c
and then to taskEXIT_CRITICAL() in task.c, but what the reason for crashing?

Can you please provide more information on how the crash manifests itself. Is it simply hitting an assert(), or overflowing its stack? This page will provide more information on both of those: https://www.freertos.org/FAQHelp.html

It jumps to Infinite_Loop in start_stm32.s
I verified configASSERT_DEFINED is 1

Is the forever loop inside an interrupt handler ? Maybe the HardFault_Handler ?
That should be visible in your debugger. If not check the backtrace/callstack in the debugger.
Did you setup the configASSERT macro correctly ?

I’m running in debugger mode and when crashed it jumped to the Infinite_Loop of assembly code in start_stm32.s (line 102) not to HardFault_Handler.
configASSERT macro is defined in FreeRTOSConfig.h (line 119)
Checked all 3 interrupts handlers:
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler

They all present in …/ARM_CM4F/port.c

Sorry - only you know your start_stm32.s and FreeRTOSConfig.h files :wink:

Which assembler routine is there ? Or is the CPU executing random stuff/no useful code due to bug/crash ? Do you see a useful callstack in the debugger after stopping the CPU ?

In attached screenshot is what is displayed in debugger thread after the crash.

So as suspected it’s in an interrupt handler. The Windowed WatchDog IRQ has fired.
It’s unrelated to FreeRTOS at the first place. What’s the WWDG ISR supposed to do ?
If unsure just disable the WWDG for now to proceed or find out its timeout configuration and maybe increase it accordingly.
If this your very 1st try with a FreeRTOS application I’d disable the WWDG at the beginning and verify that your application starts and works as expected.

Thanks, will work on it.

In the beginning of main() placed WWDG_DeInit() function, which disables clock for WWDG, but it’s still continuing crashing the same way.

Try power cycle the board. I think the watchdog can’t be disabled once activated. At least it’s the case for the IWDG…
The WWDG ISR shouldn’t be entered if the WWDG is not activated.

Recycled power, disable WWDG by WWDG->CR = 0 statement, but still the same. My guess, that there is something else leading to crash.

Hmm … strange. Do you still end up in the WWDG_IRQHandler even if it’s not enabled ?
No idea :frowning: I afraid it’s on you to narrow down what’s going wrong…
You should make use of all the FreeRTOS debug features like stack overflow checking etc.
Good luck Steven !

You’re right it’s on me, thanks for help.

One quick question, is the WWDG_IRQHandler() a separate ISR, or is this the default vector with all the other undefined interrupt. If the latter, you need to figure out which ISR is actually being triggered.

I find it is often worth the memory cost to make each ISR have its own unimplemented loop so you know which one got triggered.

Hi Richard, thanks for responding.
I didn’t find WWDG_IRQHandler() function in my project, which, as I hope, has all necessary files. But 3 other ISR, which I mentioned above, are present in port.c and it looks like they all are running, because they respond to break points inside. You are right, I need to figure which event triggers which interrupt. I only know that systick should be triggered by one of the CPU timers.

If you’re using ST Cube the file with the WWDG_IRQHandler might be part of the generated files. Since the symbol is defined as seen in the debugger call stack there must be the corresponding code somewhere in your project.
If using Cube is there a provided FreeRTOS demo project (known to work out of the box) helping to get familiar with it ?
As far as I know there is some documentation or an application note from ST regarding FreeRTOS applications (generated by Cube).

Your stack trace shows the function to be in startup_stm32.s, which is probably a system provided file. Typically, this file will only have a default entry for each interrupt, to catch interrupts which do not have handlers provided, but which occur. Also, typically there is but one routine which is shared for ALL interrupts as a default. If this is the case here (as I suspect), the fact that it calls it the Watch Dog Interrupt irrelevant, as the debugger doesn’t know which interrupt occurred.

What I will do to these files is change that file so that each interrupt gets its own version of the infinite loop, so when this happens, you can see by which loop it gets caught in, what ISR was triggered. There are also registers in the processor that you can read to figure this out, but that requires digging through the processor documentation and understanding more of the details.

Undefined interrupts will end up in a for ever loop in Default_Handler. It is difficult to see which interrupt has occurred.
When in doubt, you can also include the following file: stm_interrupts.c (5.0 KB)
With these defines, you can press pause and see where it is looping for ever.
You must exclude interrupt definitions that you have already defined. The linker will warn about double definitions…

Thanks Hein, it looks like I found the source of crashing, which was enabling ethernet interrupt in HAL_ETH_MspInit( ETH_HandleTypeDef * heth ) function, which looks like this:
NVIC_InitStructure.NVIC_IRQChannel = ETH_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 13;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
In HAL_ETH_MspInit() I also included all GPIO initialization to interface with RMII transceiver chip. I’ve tried to change interrupt priority, but it didn’t help. As long as interrupt is enabled the software crashed.