cancel
Showing results for 
Search instead for 
Did you mean: 

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

JFarr.4
Associate II

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

1 ACCEPTED SOLUTION

Accepted Solutions

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

View solution in original post

8 REPLIES 8
Piranha
Chief II

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.

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

JW

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.

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

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

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

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

JW

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