-1

I'm trying to simply turn of an LED with a Button, using a falling edge EXTI Interrupt. Unfortunately, the LED is blinking without touching the button, debugging with gdb also shows, that the ISR is called repeatedly. As I tested the LED (PA5) and the Button (PC13: Input mode with pull-up resistor) before, their configuration is correct.

So I think there must be something wrong with the EXTI Interrupt configuration.

The configuration is done in assembly before calling main with the following function:

@ r0 = EXTI-line (0 .. 15)
@ r1 = Trigger Seleetion, LSBs (... : b1 : b0),
@        b0 = 1 -> Rising Trigger enabled, 
@        b1 = 1 -> Falling Trigger enabled 
.global  ConfigureEXTI
.type    ConfigureEXTI, %function
ConfigureEXTI:
   push  { r4, lr } 

   @ register value for bit $r0 in r4
   mov   r4, #1
   lsl   r4, r0
   ldr   r2, =EXTI

   ldr   r3, [r2, #EXTI_IMR]
   orr   r3, r4
   str   r3, [r2, #EXTI_IMR]

   tst   r1, #1
   ittt  ne 
   ldrne r3, [r2, #EXTI_RTSR]
   orrne r3, r4
   strne r3, [r2, #EXTI_RTSR]

   tst   r1, #2
   ittt  ne
   ldrne r3, [r2, #EXTI_FTSR]
   orrne r3, r4
   strne r3, [r2, #EXTI_FTSR]

   @ First 4 EXTI lines with own ISR
   cmp   r0, #4
   bhi   1f

   add   r0, #6
   b     2f
1: 
   cmp   r0, #9
   ite   ls 
   movls r0, #23     @ combined ISR for EXTI 5-9 (23) and EXTI 10-15 (40)
   movhi r0, #40
2:
   bl   EnableIRQ

   pop   { r4, pc }
.ltorg

EnableIRQ enables the Interrupt in the NVIC_ISER1 register, using the following code:

@ r0 = IRQ Number
.global  EnableIRQ
.type    EnableIRQ, %function
EnableIRQ:
   ldr   r1, =NVIC_ISER0

   movs  r2, #1
   and   r3, r0, #0x1f  @ r3 <- r0 mod 32
   lsls  r2, r2, r3

   @ calculating n = r0/32 to choose register NVIC_ISERn
   lsrs  r3, r0, #5
   lsls  r3, r3, #2

   str   r2, [r1, r3]

   bx    lr 
.ltorg

ConfigureEXTI is called from the Reset_Handler:

Reset_Handler:
   @ ...
   mov   r0, #13
   mov   r1, #2
   bl    ConfigureEXTI

   b     main

main contains simply an endless loop while(1) __WFI();

The ISR is implemented in C:

void  EXTI15_10_IRQHandler(void)
{
   if((EXTI->PR & (1 << BUTTON_PIN)))
   {
      GPIOA->ODR ^= (1 << LED_PIN);  
      EXTI->PR |= (1 << BUTTON_PIN);
   }
}

So I'm doing the steps I extracted out the reference manual:

  • Programming trigger registers EXTI_RTSR and EXTI_FTSR
  • Enabling the Interrupt request in EXTI_IMR
  • Configuring the Interrupt at the NVIC

I'm not really sure why the Interrupt isn't working properly, is there maybe a step in setting it up, that I missed?

Edit: I just noticed something weird, the blinking of the LED only happens when connecting with gdb (over openocd), but if I just flash the .elf, the led doesn't blink (the button doesn't work nevertheless). commands used for flashing/debugging:

$ openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg -c "program 
main.elf verify reset exit"

or debug

$ openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg
$ arm-none-eabi-gdb main.elf
(gdb) target remote :3333
artless noise
  • 21,212
  • 6
  • 68
  • 105
some_user
  • 179
  • 11
  • are you properly clearing the interrupt in the isr so that it doesnt re-trigger? long before actually allowing the interrupt into the core, did you resolve all of this via polling? poll the peripheral see how to make the interrupt status change? next project how to clear the interrupt status in the peripheral? next project see the interrupt in the nvic? next project see the interrupt clear in the nvic? next enable the interrupt in the nvic (but not to the core)? see that change, and clear, then lastly write the isr and let the core see it – old_timer Nov 11 '20 at 10:25
  • this isnt something that gdb would help with anyway...is this like a blue pill (stm32f103) and thus openocd instead of a nucleo board for example where you can opt to just copy a binary file over, drag and drop... – old_timer Nov 11 '20 at 10:28
  • does program ... do the same thing as flash write_image erase main.elf? (well reset halt, flash write_image erase main.elf, reset) – old_timer Nov 11 '20 at 10:29
  • and you have resolved the debouncing of the button? – old_timer Nov 11 '20 at 10:31

1 Answers1

0

PC13: Input mode with pull-up resistor

Don't use the internal pullups, these are (usually) too high resistance. Use an external pullup in the 1k-10k range.

Turbo J
  • 7,563
  • 1
  • 23
  • 43