cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L476: Code runs into Reset Handler if Interrupts get activated although no Interrupts are triggered

Dominik Lorych
Associate III

Hi,

I have some code running on a Nucleo-STM32L476 which keeps running into the Reset Handler. But this does not cause a boot loop, instead the code just gets stuck there (the PC register points to the first line of assembler of the reset handler).

I modified the Systick to read a hardware-based timer so it works without interrupts. But the Code shows the same behaviour when using the default Systick implementation.

The conditions under which the reset handler gets called are really weird:

  1. If interrupts are enabled, the code gets stuck after switching on the LED (which gets called directly after initializing the hardware). The LED then stays on until I reset the board. It seems like it gets stuck at the beginning of the HAL_Delay function because If i call HAL_Delay(0) the LED gets disabled before it gets stuck, but at HAL_Delay(1) it gets stuck before the LED is disabled.
  2. If I debug this code, the code instead gets stuck earlier - usually somewhere in SystemClock_Config.
  3. If I disable interrupts before executing the initialization functions everything works fine. But if i enable them again, the Code gets stuck again immediately (the next line of code does not get executed).
  4. It I disable interrupts after executing the initialization, but before the LED is turned on, then it works fine if I just execute it, but if I debug it then it gets stuck at the initialization functions.
  5. My code jumps into a second firmware layer at its end. Vector Table and Stack pointer are redirected before jumping. If I have interrupts disabled in the first layer and enable them in the second layer, then the code immediately enters the reset handler of the first layer after the interrupts get activated.
  6. If I check for pending Interrupts before switching on the interrupts (both in the first and the second firmware layer) there are no pending interrupts.

Does anyone have an idea why this happens? I essentially want to have interrupts disabled in the first firmware layer and have them enabled in the second layer. This works if I execute them individually, but if i execute them after another I cannot enable interrupts at any point.

Thank you.

9 REPLIES 9

Hello

It seems that Systick IRQ handler is missing or is not linked.

Dominik Lorych
Associate III

Yeah, that could be the case because it is not in the assembler code (I am using the default Systick IRQ Handler). In fact the ADC1_2_IRQHandler is the only IRQ Handler in the assembler code, but it is basically empty (consisting of one assembler instruction). I tried including it in the startup code (I am using the default file from CubeMX) with the following:

.word   HAL_SYSTICK_IRQHandler
.weak HAL_SYSTICK_IRQHandler
        .thumb_set HAL_SYSTICK_IRQHandler,Default_Handler

This did not work (I also tried it without "HAL_" in front of it, but that did not work either).

On the other hand, the second firmware layer also does not have the Systick IRQ Handler in its assembler code. It has an UART, RNG, TIM and ADC1_2 IRQ Handler, but thats due the CubeMX settings I made. And this firmware works fine with interrupts, so why does the other one not work?

Piranha
Chief II

So basically even a blinky doesn't work... Make a copy of the project and strip it down until you get it working. That includes stripping off the HAL and CubeMX generated junk.

Just some ideas... To what value is the stack pointer initialized? What's with the use of float/double types and FPU hardware?

What is " first firmware layer" and "second layer"?

JW

Dominik Lorych
Associate III

I have two binaries in the memory where the first binary jumps into the second binary when it has finished its execution. Basically the first firmware layer is similar to a bootloader and the second one is the application.

Dominik Lorych
Associate III

I now found that it is indeed the SysTick IRQ causing this. But the handling of the IRQ is weird: By default a proper SysTick Handler is linked in the startup file, but this just gets ignored. I found that the code just ignores anything that is linked as the first Handler.

These are the default Handlers for SysTick:

.weak	SysTick_Handler
	.thumb_set SysTick_Handler,Default_Handler

Here the executable just ignores my changes if I exchange the SysTick_Handler, but if i switch the Default_Handler then it gets called properly. So my solution is to just set the SysTick_Handler to the second Handler like this:

.weak	SysTick_Handler
	.thumb_set ShouldBeNeverCalled,SysTick_Handler

Does anyone have an idea why the first entry gets ignored? By the way I also checked the ICSR register, but it was also displaying incorrect information (it said IRQ 15 - DMA1_Channel5_IRQn - was the interrupt causing this).

How do you manage the vector tables/VTOR when going from "one layer" to the "other layer"?

JW

Dominik Lorych
Associate III

I set the SCB->VTOR accordingly before jumping to the next layer. But this problem is unrelated to the jumping because this problem only exists in the first layer, before the code jumps.

But I am fine with using the workaround, I am just curious why the first entry is ignored.

The "first entry" is the default handler and normaly is a branch instruction to the same address.

This default handler is defined as weak

In case there is another function defined with the same name , the linker will links the handler without weak symbol.

So the "first entry" will never be called , in case the handler is defined in another module.

To debug startup file note that the compiler's optimisation level should be at minimum ....Oo