Skip to main content
JFarr.4
Associate
July 9, 2022
Solved

SIGTRAP on ISR on "bare-metal" STM32F413ZH Nucleo-144

  • July 9, 2022
  • 5 replies
  • 1799 views

Hi guys,

I'm a mechatronics student learning the basics of STM32s in my own time through the excellent series of guides by Vivonomicon. I'm currently learning interrupts, but my program seems to trigger a SIGTRAP fail when the interrupt fire.

The code consists of main.c for the main loop and setup code, and nvic.c for holding the ISRs. There are a few header files for the volatile led_on variable and pin constants, It's running on an STM32413ZH Nucleo-144 board (I plan to use an 8080 LCD soon). All it does is watch the global led_on variable in the main loop, and on a rising edge on the on-board button (PC13) it'll toggle this variable (or at least that's what it's supposed to do)

// Main.c
 
#include "main.h"
 
int main(void){
 
 
 RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN; // Enable GPIO bank B
 RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN; // Enable GPIO bank C
 
 GPIOB->MODER = 0x1; // set Pin 0 to output mode
 // GPIOC is already in all input mode
 
 GPIOB->OSPEEDR = 0x0;
 GPIOB->PUPDR = 0x0;
 GPIOB->OTYPER = 0x0;
 
 // uint8_t button_down = 0;
 
 
 RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; // Enable system configuration peripheral
 SYSCFG->EXTICR[3] &= ~(SYSCFG_EXTICR4_EXTI13_Msk); // Turn off all bits in EXTICR4 for pin 13 in all GPIO registers
 SYSCFG->EXTICR[3] |= (SYSCFG_EXTICR4_EXTI13_PC); // Turn on the relevant bits for bank C
 
 EXTI->IMR |= (1 << BUTTON_PIN); // Enable button's EXTI line
 EXTI->FTSR &= ~(1 << BUTTON_PIN); // Disable falling edge trigger (button release)
 EXTI->RTSR |= (1 << BUTTON_PIN); // Enable rising edge trigger
 
 NVIC_SetPriority(EXTI15_10_IRQn, 0x03);
 NVIC_EnableIRQ(EXTI15_10_IRQn);
 
 while (1) {
 if (led_on) {
 GPIOB->ODR |= (1 << LED_PIN);
 }
 else {
 GPIOB->ODR &= ~(1 << LED_PIN);
 }
 }
}
// nvic.c
 
#include "nvic.h"
 
void EXTI15_10_IRQHandler(void){
 if (EXTI->PR & (1 << BUTTON_PIN)) {
 // Clear the EXTI status flag.
 EXTI->PR |= (1 << BUTTON_PIN);
 // Toggle the global 'led on?' variable.
 led_on = !led_on;
 }
}
 
void HardFault_Handler(void)
{
 /* Go to infinite loop when Hard Fault exception occurs */
 while (1)
 {
 }
}

0693W00000QKmsKQAT.pngThis sequence is press button > sitgtrap pauses gdb > backtrace shows the above. Looks like it calls my ISR, but then there's an unknown error handler in there afterwards?

It's my first time posting here, so if I've left something off, apologies, let me know and I'll add it immediately. If I'm in the wrong place, lemme know.

Keen to get to the bottom of this one!

-James

Code .zip attached

This topic has been closed for replies.
Best answer by waclawek.jan

Indeed.

0693W00000QKnloQAD.png 

To see, which section is located where, it's useful to have the linker to generate a so called mapfile during linking, add this into makefile:

LFLAGS += -Wl,-Map=$(TARGET).map,--cref

I also don't like the gdb's built-in disassembler, I have this rule in makefile:

lss: $(TARGET).lss
 
# Create extended listing file from ELF output file.
%.lss: %.elf
	@echo Generating $@ ...
	$(OD) -h $< > $@
	$(OD) -d -z -j .isr_vector $< >> $@
	$(OD) -S $< >> $@

(note that this explicitly uses the vector table section name, for a reason...)

so then when needed, I generate the list/disasm file simply by typing 'makefile lss' and then I can browse it as any textfile.

JW

5 replies

Piranha
Principal III
July 9, 2022

Check whether the IRQ handler name actually corresponds to the one in the vector table.

EXTI->PR |= (1 << BUTTON_PIN);

This code clears all set bits in PR register. Currently it's not your problem, but will be, when you'll use more EXTI interrupts. Just read the reference manual and replace the |= with a simple = operation.

For GPIO output pin setting and resetting it's better and simpler to use the BSRR register.

JFarr.4
JFarr.4Author
Associate
July 10, 2022

Hi Piranha,

Thank you for the excellent advice.

I definitely saw the matching of the names being an issue, so I did check that, but they line up, so it's something else :(

0693W00000QKneTQAT.pngAs for the PR register, my understanding was that the |= operator is a bitwise OR assignment, wouldn't that result in any existing 1s staying as 1s, and if 1 << 13 is a zero, it gets flipped to 1? Wouldn't an = assignment write 0x2000 to the register, disrupting the other bits?

Good call on the BSRR register, had no idea that was a thing, and I'll be using it in the future. Just to be sure, I confirmed my GPIO code worked OK, and lit the on-board LED.

I'll keep cracking at this one and let you guys know if I solve it.

waclawek.jan
Super User
July 9, 2022

You don't compile/link nvic.c. Add it to the sources in makefile.

JW

JFarr.4
JFarr.4Author
Associate
July 10, 2022

Hi JW,

Thanks for the advice. Could you go into a bit more detail about how this changes things from the M4s perspective? What would this look like in the makefile?

-James

EDIT:

While poking around in the assembly to see if my ISR was linking back to the main program properly, I found that the EXTI15_10_IRQHandler function wasn't making it into my main.elf:

0693W00000QKngoQAD.pngI'm guessing this has something to do with my linking/including errors you mentioned, is that right?

Thanks again for your help

-James

waclawek.jan
Super User
July 10, 2022

0693W00000QKnlPQAT.png 

But as described there, as long as you don't explicitly define an ISR function in your code, the "weak" definition will prevail, and that leads to DefaultHandler which is an infinite loop. So, I can't explain the SIGTRAP and why the stack went wild (as witnessed by the backtrace in gdb). The binary you provided is also suspicious, does not contain the vector table at its beginning as it should, so you probably messed up the sections and linker file somehow.

JW

waclawek.jan
waclawek.janBest answer
Super User
July 10, 2022

Indeed.

0693W00000QKnloQAD.png 

To see, which section is located where, it's useful to have the linker to generate a so called mapfile during linking, add this into makefile:

LFLAGS += -Wl,-Map=$(TARGET).map,--cref

I also don't like the gdb's built-in disassembler, I have this rule in makefile:

lss: $(TARGET).lss
 
# Create extended listing file from ELF output file.
%.lss: %.elf
	@echo Generating $@ ...
	$(OD) -h $< > $@
	$(OD) -d -z -j .isr_vector $< >> $@
	$(OD) -S $< >> $@

(note that this explicitly uses the vector table section name, for a reason...)

so then when needed, I generate the list/disasm file simply by typing 'makefile lss' and then I can browse it as any textfile.

JW

JFarr.4
JFarr.4Author
Associate
July 10, 2022

Hi JW,

Well, seems you've caught me using code without reading it fully... Fixed the issues you found and it works!

Thanks for pointing this out so explicitly, and taking the time to dig through the mess I made.

I'll be sure to try and return the favour to this community once I've learnt and experimented more

waclawek.jan
Super User
July 10, 2022

And as for EXTI->PR, Piranha is 100% right; read carefully the RM; and maybe read this or end of this.

JW