GPIO Pin Interrupt -- What am I doing wrong?

Go To Last Post
3 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So, I've spent a couple nights reading the manual and through the drivers supplied with Atmel Studio ASF. It's been about 3 years since I last programmed with uC's so I'm a bit lost.

 

All I'm attempting to do is toggle an LED after a button press (change on GPIO pin). I'm able to toggle the LED without an issue on a button press using a polling method but I really need to use an interrupt so I can apply that knowledge to other problems.

 

I'm attaching my code below. The polling in this method does not function because as soon as push button 0 is pressed the uC hangs. 

 

#include <asf.h>

static void pin_irq(void){
	LED_Toggle(LED1);
	gpio_clear_pin_interrupt_flag(GPIO_PUSH_BUTTON_0);
}

int main (void)
{
	board_init();
	//Set the base initial state of the LED to Off
	LED_Off(LED0);

	//Enable GPIO pin mode on the push button
	gpio_enable_gpio_pin(GPIO_PUSH_BUTTON_0);
	//Enable pin interrupt on the push button 0 pin in pin change mode
	gpio_enable_pin_interrupt(GPIO_PUSH_BUTTON_0, GPIO_PIN_CHANGE);
	//Initialize the interrupts
	INTC_init_interrupts();
	//Register the interrupt to call the desired function and operate off of the correct interrupt port
	INTC_register_interrupt(&pin_irq, AVR32_GPIO_IRQ_0 + (GPIO_PUSH_BUTTON_0/8), AVR32_INTC_INT0);
        //Enable interrupts
        Enable_global_interrupt();
	//Poll push button and toggle the pin if pressed
	bool button1Pressed = false;
	while(1){
                button1Pressed = gpio_get_pin_value(GPIO_PUSH_BUTTON_0);
		if(button1Pressed == true){
			LED_Off(LED0);
		}
		else{
			LED_On(LED0);
		}
	}

 

Last Edited: Sat. Feb 25, 2017 - 05:41 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I believe I've got it fixed. It's functioning as I'd expect at least. The fix was __attribute__((__interrupt__)) prior to the interrupt function call. Has anyone experienced this before? I've come from a 8 bit AVR background and had no idea this would cause this.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Q: What should happen when an interrupt occurs ?
A: (1) The current machine state is saved, (2) the interrupt-handler runs, (3) the machine state is restored.


There are some processor brands/architectures that will 100% do (1) and (3) in hardware, but most will only partially save/restore the total machine state.
eg., the AVR8 family only saves the PC., the AVR32A family only saves PC, SR, R8, R9, R10, R11, R12, LR.


Generally speaking, your interrupt handler will need to use a few registers to set a flag, increment a counter, whatever, ..., therefore some code must be added to save/restore those registers.
You can write the code to do that within the interrupt-handler,
or,
you can let the compiler do it.


If you decide to let the compiler generate the code to save/restore the machine state then you must tell the compiler that your interrupt-handler is a 'special' procedure.
Every brand of compiler has a different way to tag procedures as 'special'.
For interrupt-handlers the Atmel AVR8/AVR32 compilers supply a macro called ISR()
On an AVR8 the ISR()[/i] macro appends something like __attribute__ ((signal, used)) to the procedure declaration.
On an AVR32 the ISR() macro prefixes __attribute__ ((__interrupt__)) to the procedure declaration.