how to use GPIO interrupt in AVR32UC3B

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

dear all

I use the UC3B software framework v1.30 and try to use gpio interrupt....But I can't jump into the interrupt sub fuction...I have no idea where's the problem.....

Here is my source code

#include "compiler.h"
#include "gpio.h"
#include "board.h"

#include "intc.h"

#define GPIO_PIN_EXAMPLE_1 LED2_GPIO
#define GPIO_PIN_EXAMPLE_2 LED3_GPIO
#define GPIO_PIN_EXAMPLE_3 GPIO_PUSH_BUTTON_0

#if __GNUC__
__attribute__((__interrupt__))
#elif __ICCAVR32__
__interrupt
#endif
static void gpio_int_handler(void)
{
gpio_clr_gpio_pin(LED0_GPIO);
gpio_clr_gpio_pin(LED1_GPIO);
gpio_clr_gpio_pin(LED2_GPIO);
gpio_clr_gpio_pin(LED3_GPIO);
}

/*! \brief This is an example of how to access the gpio.c driver to set, clear, toggle... the pin GPIO_PIN_EXAMPLE.
*/
int main(void)
{
U32 state = 0;
U32 i;

gpio_enable_pin_glitch_filter(GPIO_PIN_EXAMPLE_3);
gpio_enable_pin_glitch_filter(GPIO_PUSH_BUTTON_1);
gpio_enable_gpio_pin ( GPIO_PUSH_BUTTON_1 ) ;
Disable_global_interrupt();
INTC_init_interrupts();
//INTC_register_interrupt(&gpio_int_handler, AVR32_EIC_IRQ_7, AVR32_INTC_INT0);
INTC_register_interrupt(&gpio_int_handler, AVR32_GPIO_IRQ_1, AVR32_INTC_INT0);
gpio_enable_pin_interrupt ( GPIO_PUSH_BUTTON_1, GPIO_FALLING_EDGE );
Enable_global_interrupt();

while (1)
{
switch (state)
{
case 0:
// Access with GPIO driver gpio.c with clear and set access.
gpio_clr_gpio_pin(GPIO_PIN_EXAMPLE_1);
state++;
break;

case 1:
gpio_set_gpio_pin(GPIO_PIN_EXAMPLE_1);
state++;
break;

case 2:
// Note that it is also possible to use the GPIO toggle feature.
gpio_tgl_gpio_pin(GPIO_PIN_EXAMPLE_1);
state++;
break;

case 3:
default:
gpio_tgl_gpio_pin(GPIO_PIN_EXAMPLE_1);
state = 0;
break;
}

// Poll push button value.
for (i = 0; i < 1000; i += 4)
{
if (gpio_get_pin_value(GPIO_PIN_EXAMPLE_3) == 0)
gpio_clr_gpio_pin(GPIO_PIN_EXAMPLE_2);
else
gpio_set_gpio_pin(GPIO_PIN_EXAMPLE_2);
}
}
}

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

See this example for EVK1101,

-sma

// Purpose of this example:
// Explanation of GPIO and INTC modules on AVR32 UC3 chips.

// Hardware requirements:
// EVK1101 & JTAGICE mkII.

// Application description:
// LED0 always blinks steadily.
// Press on PB2 and LED1 is turned on. Release PB2 and LED1 is turned off.
// Press on PB3 and LED2 is turned on. Release PB3 and LED2 is turned off.


//_____  I N C L U D E S ___________________________________________________

#include "compiler.h"
#include "board.h"
#include "gpio.h"
#include "pm.h"
#include "intc.h"



//--------------------------------------------------------------------------
__attribute__((__interrupt__))
static void int_handler_port1_line0 (void)
{
  if( gpio_get_pin_interrupt_flag( GPIO_PUSH_BUTTON_0 ) )
  {		// PB2 generated the interrupt.
		LED_Toggle( LED1 );
		// Clear the interrupt flag of the pin PB2 is mapped to.
		gpio_clear_pin_interrupt_flag(GPIO_PUSH_BUTTON_0);
  }
  if( gpio_get_pin_interrupt_flag( GPIO_PUSH_BUTTON_1 ) )
  {		// PB3 generated the interrupt.
	  LED_Toggle( LED2 );
	  // Clear the interrupt flag of the pin PB3 is mapped to.
		gpio_clear_pin_interrupt_flag(GPIO_PUSH_BUTTON_1);
  }
}  
//--------------------------------------------------------------------------


//--------------------------------------------------------------------------
int main(void)
{
	int i = 0;
  int j = 0;
  int x = 0;
  
  
  // switch to oscillator 0
  pm_switch_to_osc0(&AVR32_PM, FOSC0, OSC0_STARTUP);

  // Set all leds initial state.
  LED_Off( LED0 | LED1 | LED2 | LED3 );
  
  // GPIO config
  // configure push button to produce IT on input change
  // NOTE 1: GPIO_PUSH_BUTTON_0 & GPIO_PUSH_BUTTON_1 are defines you can find in
  // evk1101.h under /BOARDS/EVK1101/.
  // See the implementation of gpio_enable_pin_interrupt() in gpio.c under 
  // /DRIVERS/GPIO/.
  gpio_enable_pin_interrupt(GPIO_PUSH_BUTTON_0 , GPIO_PIN_CHANGE);	// PB2
  gpio_enable_pin_interrupt(GPIO_PUSH_BUTTON_1 , GPIO_PIN_CHANGE);	// PB3
  // NOTE 2: GPIO_PUSH_BUTTON_0 & GPIO_PUSH_BUTTON_1 are in the same port.
  // (i.e. port 1, cf section 21.5 of the UC3B0256 datasheet for the computation
  // of a port knowing the pin, and see the evk1101 schematics (or the evk1101.h
  // file) + the section 12.8 of the UC3B0256 datasheet to know the pin mapping
  // of the pushbuttons). 
  // Consider GPIO_PUSH_BUTTON_0 as an example: from evk1101.h, we see that
  // GPIO_PUSH_BUTTON_0 is AVR32_PIN_PB02. Open the UC3B0256 datasheet, go to 
  // section 12.8, in the array look for pin PB02, we see that it is mapped to
  // GPIO 34. Using section 21.5, the formula to know the port of a pin is: 
  // GPIO port = floor((GPIO number) / 32), so for GPIO_PUSH_BUTTON_0 we get:
  // floor(34/32) = 1.
  // Applying the same reasoning for GPIO_PUSH_BUTTON_1 (which is GPIO 35), we 
  // find that it belongs to port 1 too.
  
  // NOTE 3: the 32 in the formula 'GPIO port = floor((GPIO number) / 32)' 
  // corresponds to the fact that "The pins are managed as 32-bit ports" (see 
  // section 21.5 second sentence): i.e. every port holds 32 pins max.
  
  // Interrupts config
  Disable_global_interrupt ();
  INTC_init_interrupts ();
  // register push button handler for PB2 and PB3
  INTC_register_interrupt( &int_handler_port1_line0, AVR32_GPIO_IRQ_0 + (GPIO_PUSH_BUTTON_0/8), INT0);
  INTC_register_interrupt( &int_handler_port1_line0, AVR32_GPIO_IRQ_0 + (GPIO_PUSH_BUTTON_1/8), INT0);
  // NOTE 4: reading section 21.4.7, paragraph 2:
  // "In every port there are four interrupt lines connected to the interrupt 
  // controller. Every eigth interrupts in the port are ored together to form an
  // interrupt line."
  // So, for example, for port 1 : 
  // 	GPIO32->GPIO39 : port 1 interrupt line 0 (for int-of-pin32, int-of-pin33, 
  // 									 int-of-pin34, int-of-pin35, int-of-pin36, int-of-pin37, 
  //									 int-of-pin38 and int-of-pin39) 
  // 	GPIO40->GPIO47 : port 1 interrupt line 1, 
  // 	GPIO48->GPIO55 : port 1 interrupt line 2,
  // 	GPIO56->GPIO63 : port 1 interrupt line 3.
  // 
  // That is why we use the formula "AVR32_GPIO_IRQ_0 + (GPIO_PUSH_BUTTON_0/8)"
  // to register the PB2; AVR32_GPIO_IRQ_0 is used as the base interrupt line 
  // and we add '(GPIO_PUSH_BUTTON_0/8)' to register the corresponding interrupt
  // line.
  
  // NOTE 5: Since PB2 and PB3 are mapped to the GPIO pin GPIO34 and GPIO35, we
  // see that they belong to the same interrupt line. Two consequences in this 
  // particular case:
  // 	1) it's no use to register both. We left both registration in the code for
  //		 clarity's sake. 
  //  2) we'll discriminate the cause of the interrupt (PB2 or PB3) in the 
  //	   interrupt handler looking at the gpio_port1.ifr register. 
  //	   See int_handler_gpio0() implementation.
  
  Enable_global_interrupt ();
   
  while (TRUE)
  {
  	if  (i == 100000)
    {
      i = 0;
      if (j == 2)
      {
      	x = !x;
        if (x == 0)
        {
        	LED_Off (LED0);
        }  
        else
        {
        	LED_On (LED0);
        }  
        j = 0;
      }
      j++;
    }
    i++;
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks a lot sma........
where is the example code in the software framework ?

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

In case there is someone as confused as me with the GPIO IRQ's, the above code and a beer got this:

This formula:
'AVR32_GPIO_IRQ_0 + ( GPIO_PUSH_BUTTON_0/8 )' confused me, as if you look at the header, there are AVR32_GPIO_IRQ_0-13.

On the uc3x, the maximum GPIO=105. 105/8 = 13. So by using the above formula, mapped from IRQ0, you get the proper IRQ line. Alternatively, you can lose the formula and just enter the actual IRQ line. But, should you change the #define for the pin, you'd have to look back through the code to fix the mapping.

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

Very nice, tested successfully!