STM32 WWDG interrupt firing when not configured
Asked Answered
C

9

24

I have an application that I am porting from the Keil IDE to build with the GNU toolchain due to license issues. I have successfully be able to set up, build, flash and run the application on the device.

The application on the GNU side is for some reason is getting stuck in the weak linked IRQ handler for the WWDG which is an infinite loop. The application does not enable the WWDG, and it is disabled at reset by default. I have also verified that the configuration registers are at their default startup values.

The only difference, other than compilers, are the linker and startup files. However, both the startup files, and linker files used by both toolchains are defaults generated by STM.

Any idea what may be causing this? I'm about at my wits end here.

Using the stm32f103XX, let me know if any other information would be helpful.

EDIT: Using the comments below I was able to ascertain that it is, in fact, the HardFault_Handler that is being triggered. I have included the backtrace output below if that may be of help

GDB BT:

0 HardFault_Handler ()

1 (signal handler called)

2 0x720a3de in ?? ()

3 0x80005534 in foo ()

Backtrace stopped: previous frame identical to this frame (corrupt stack?)

2 things stand out to me, though im no gdb expert. 1) foo is not a function, it is a const array of chars and 2) 0x0720a3de is not a valid memory address the flash address range starts at 0x08000000

Cyna answered 23/12, 2014 at 16:4 Comment(3)
Are you sure it's really the WWDG? Another while(1); may be sharing that code due to optimization. Does the map file show only the WWDG at that address?Gantry
You may be on to something. It appears that in the .elf file all the default irq symbols point to the same address, which I suppose means it's just a coincidence that the WWDG_IRQ name is ues in the debugger. I will add stong link functions for the irq's so I can figure out which one exactly is the culprit.Cyna
I got stuck in the HardFault_Handler too, I spend the whole day and night to figure out the reason, it turned out that I forgot to compile all peripheral files(stm32f10x_adc.o, stm32f10x_bkp.o, stm32f10x_can.o, stm32f10x_cec.o... misc.o) and link them, I feel I'm a fool🤦🏻‍♂️Edithe
C
15

So thanks to the kick in the pants by D Krueger. I was able to figure out that the HardFault_Handler was what was actually being called. So, anyone that stumbles on this post, verify which IRQ is truly being called by writing temporary functions to cover the likely culprits i.e. HardFault. The true issue for the IRQ call is a bad memory access by memcpy which I am on my way to solving next.

Cyna answered 23/12, 2014 at 17:54 Comment(3)
I am pretty sure that you will find that the bad memory access is not "by memcpy", but rather your call to memcpy.Kassie
The final culprit turned out to be my failure to link with the correct options I was compiling with. I forgot to link with -mthumb and -mcpu=cortex-m3 options. So I was linking with the incorrect c libraries.Cyna
What do you put in the "temporary functions" to know which one is called? LED on through GPIO? Breakpoint?Contreras
T
9

I had exactly the same error as OP (apparent WWDG interrupt, but actually the HardFault_Handler firing) when porting an example for the STM32F3 Discovery board to compile in CooCox CoIDE 1.7.7 with STM32Cube F3 libraries (v1.1.0). The code ran fine as long as I didn't try using any interrupts, but as soon as I turned on the SysTick timer interrupt, the HardFault exception tripped.

The problem was that I had neglected to include the stm32f3xx_it.h and stm32f3xx_it.c files in the project. Their absence wasn't causing any compiler warnings/errors. Once they were compiled & linked in, the code with interrupts ran fine.

Tuesday answered 2/2, 2015 at 2:34 Comment(1)
This was the case for me, as well, when trying to break up the cmake executable target into a library, and an executable with just main.cpp. Turns out the "stm32l4xx_it.c" is essentially part of the main executable, and not sufficient as part of its linked library.Whey
S
8

I've had this problem due to the same root cause as awilhite. I'm using Atollic TrueStudio 8.0.0. I used it to start a project for STM32F030 and (probably manually) added libraries folder with stm32f0xx.h, which defines ADC1_IRQn (IRQ channel number used in NVIC setup).

And I implemented ADC1_IRQHandler(void) in my main.c (as I'm used to and it always worked so far -- x_IRQn -> x_IRQHandler)

But after 2 days frustration, I found out, that startup_stm32f0xx.s in my project defines ADC1_COMP_IRQHandler.

So, ultimately, my ADC interrupt handler was undefined and when the ADC generated the interrupt, the program crashed (WWDG interrupt).

I hope this helps to people like me, who think they did implement their handler but in fact, they did not.

Shirleneshirley answered 30/10, 2017 at 8:28 Comment(1)
Thanks to you I had only one day of frustration :) The startup_xxx.s defines the function names expected for interrupt vectors. When blindly copy-pasting sources from one project to another, it is easy to miss that part, when the original code is using ADC1_IRQHandler() but the STM32 is in fact calling ADC1_COMP_IRQHandler().Contreras
S
6

I had a very similar problem when merging two projects generated separately by STM32CubeMX for an STM32F2XX processor. One project was using the Ethernet peripheral, while the other was not. Besides that one difference, the two projects used the same set of peripherals.

After integrating the two projects together by manually copying files, the application would end up in the WWDG_IRQHandler after starting the first task (when interrupts are enabled for the first time). I first confirmed that the WDGA bit of the WWDG register was indeed not set and, therefore, that the WWDG peripheral was disabled. Next, I verified that the interrupt vector table was initialized correctly. Finally, after several hours of digging, I realized that I had not defined the ETH_IRQHandler function in stm32f2xx_it.c, which provoked the Ethernet interrupt to be handled by the default handler, masking itself as the WWDG_IRQHandler -- likely due to optimization.

Sodamide answered 20/10, 2017 at 13:34 Comment(0)
C
4

The core problem is that the Default Handler is called instead of another irq handler. I doubt that our situations are the same but here is my solution:

I was working on a c++ project, the same happened to me. This was the first time I made a project from scratch & with CMSIS. After some unsuccessful attempts I went through a generated project when I noticed that in the stm32xxxx_it.h the IRQ handler function prototypes are guarded by these:

extern "C"
{
    void TIM7_IRQHandler(void);
}

With these guards the linker could find my own interrupt handler functions.

Candleberry answered 27/4, 2019 at 23:45 Comment(2)
Just the exact Issue I'veCanty
I'm using platformio, I had to manually change stm32f1xx_it.c to stm32f1xx_it.cpp too. I don't know the header file doesn't catch the __cplusplus definition, and why it's compiled with C compiler. That could be a PlatformIO issue. or my lack of understanding... maybe.Canty
C
2

I'll expand a bit on what led me here, and how I use the insight from @Mike to correct it.

I had a project running fine on a demo project in Eclipse SW4STM32, but with sources and headers scattered all over the place so I wanted to have a more "compact" project easier to customize and use as a base for minor modifications (and easier to follow in Git).

I created an empty AC6 project targetting the same board. It generated the HAL drivers, the startup_stm32.s and LinkerScript.ld. I then copied all of the .c and corresponding .h from the original project to my new project (which was a pain in itself because they were scattered in BSP, CMSIS, Components, Middlewares, etc. directories). Everything compiled and seemed to work, until I started modifying a bit.

In the debugger, it seemed all function calls were working until the while(1) main loop where I ended up in the Default_Handler defined in the startup_stm32.s, seemingly from WWDG_IRQHandler. That was, in fact, the default IRQ handler for not-user-defined handlers (WWDG_IRQHandler being the first one declared, it was reported as such by gdb, as indicated by @D Krüger).

I started looking at compiler and linker options or linker script, without much luck, until I realized the only file I didn't check was the startup_stm32.s, which was indeed different.

I blindly copy-pasted it and voilà!

The explanation I could give is that the STM32 is calling IRQ handlers defined in the startup_stm32.s when interrupt occur, all of them initially pointing to Default_Handler() (later overriden by the linker). So if a .c file you copied defines a handler with a slightly different name (but consistent with its own startup_xxx.s), you'll end up with the Default_Handler() being called (which is an infinite loop) instead of the one you defined. And things go wrong.

See https://www.freertos.org/Debugging-Hard-Faults-On-Cortex-M-Microcontrollers.html for more information.

N.B. I'm not happy to blindly copy-paste without fully understanding, but time constraints and milestones usually push you to territories you're not happy to explore...

Contreras answered 12/12, 2018 at 15:55 Comment(0)
S
0

Will add my 5 cents. I had this issue on stm32h7, but for me the cause was that the cube "forgot" to add TIM16_IRQHandler when TIM16 is used as the timebase source. It was not happening at the beginning but after several code regenerations. Looks like a bug in the cube, as the TIM16 was still set, but the interrupt handler got removed. So toggking to TIM17 and back resolved the issue.

Stlouis answered 1/4, 2020 at 19:57 Comment(0)
W
0

In my case, I had a function written in the GCC assembly that was migrated from the ARM assembly. The problem went away after I had added the .thumb_func line to the assembly file.

I was getting this error:

(gdb) c
+c
Continuing.

Program received signal SIGINT, Interrupt.
WWDG_IRQHandler () at ...startup_stm32f40_41xxx.s:121

(gdb) bt
#0  WWDG_IRQHandler () at ...startup_stm32f40_41xxx.s:12
#1  <signal handler called>
#2  RTOS_SysTick_Handler () at ...osKernel.s:18
#3  <signal handler called>
#4  0x0800021a in task0 () at ...main.cpp:10
#5  0x08000214 in frame_dummy ()
#6  0x00000000 in ?? ()

RTOS_SysTick_Handler is a function written in assembly and the WWDG_IRQHandler was always triggered before any first assembly instructions in that function (tried different instructions and it didn't change anything).

I was doing some tweaks around the C code and at some point, I hit another handler: UsageFault which led me to the .thumb_func hint: ARM Cortex M4 SVC_Handler "UsageFault".

Wiper answered 16/6, 2020 at 22:44 Comment(0)
U
0

Similar problem. I have moved my old project from Atollic TrueStudio to CubeIDE, updated CMSIS. Then while debugging this problem happened: whenever some IRQ was to fire the Default one was used instead. Had to update stm32..._it.h file, put declarations of my custom IRQ handlers in it(ones I defined myself). Should work, but did not ... until ... I included this _it.h header file in the sources where my IRQ handlers were defined.

Unaccustomed answered 7/6 at 22:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.