Forum: Mikrocontroller und Digitale Elektronik AVR32 - IRQ Wert für GPIO Interrupt ermitteln


von PeterPanisch (Gast)


Lesenswert?

Hallo Leute,

Ich komme an einer bestimmten Stelle nicht weiter. Ich arbeite mit Atmel 
Studio 6.2 und dem ASF. Es handelt sich um einen AT32UC3B0256 auf einem 
Custom PCB.

Ich möchte am PB02 den GPIO-Interrupt bei einer steigenden Flanke 
verwenden und dabei einen Wert inkrementieren. So weit nichts 
besonderes.

Ich komme leider nicht mal bis zum Interrupt Handler und vermute das es 
am falschen IRQ Wert liegt. Das Datenblatt gibt leider gar nichts dazu 
her.

Das einzige was ich bis jetzt verstanden habe ist, das sich die GPIO 
Ports in 4 IRQ-Gruppen a 8 Pins aufteilen.
Demnach wären GPIO 0-7 -> IRQ0 ,... GPIO 32-40 -> IRQ4
Laut Datenblatt hat der AT32UC3B0256 GPIO=43/8=5, als müsste der PB02 
sich in der IRQ4-Gruppe befinden. Der IRQ4 ist im uc3b0256-Headerfile 
mit 68 hinterlegt.

Ich habe im AVR32 Tutorial eine Formel mit Beispiel gefunden, leider 
kann ich die Begriffe Gruppe und Linie nicht deuten bzw. anwenden
1
Interrupt-Gruppe * 32 + Interrupt-Line

AVR32 Tutorial: Interrupt

Weiterhin habe ich noch einen Beitrag in einem anderen 
englischsprachigen Forum gefunden:
1
// Purpose of this example:
2
// Explanation of GPIO and INTC modules on AVR32 UC3 chips.
3
4
// Hardware requirements:
5
// EVK1101 & JTAGICE mkII.
6
7
// Application description:
8
// LED0 always blinks steadily.
9
// Press on PB2 and LED1 is turned on. Release PB2 and LED1 is turned off.
10
// Press on PB3 and LED2 is turned on. Release PB3 and LED2 is turned off.
11
12
13
//_____  I N C L U D E S ___________________________________________________
14
15
#include "compiler.h"
16
#include "board.h"
17
#include "gpio.h"
18
#include "pm.h"
19
#include "intc.h"
20
21
22
23
//--------------------------------------------------------------------------
24
__attribute__((__interrupt__))
25
static void int_handler_port1_line0 (void)
26
{
27
  if( gpio_get_pin_interrupt_flag( GPIO_PUSH_BUTTON_0 ) )
28
  {    // PB2 generated the interrupt.
29
    LED_Toggle( LED1 );
30
    // Clear the interrupt flag of the pin PB2 is mapped to.
31
    gpio_clear_pin_interrupt_flag(GPIO_PUSH_BUTTON_0);
32
  }
33
  if( gpio_get_pin_interrupt_flag( GPIO_PUSH_BUTTON_1 ) )
34
  {    // PB3 generated the interrupt.
35
    LED_Toggle( LED2 );
36
    // Clear the interrupt flag of the pin PB3 is mapped to.
37
    gpio_clear_pin_interrupt_flag(GPIO_PUSH_BUTTON_1);
38
  }
39
}  
40
//--------------------------------------------------------------------------
41
42
43
//--------------------------------------------------------------------------
44
int main(void)
45
{
46
  int i = 0;
47
  int j = 0;
48
  int x = 0;
49
  
50
  
51
  // switch to oscillator 0
52
  pm_switch_to_osc0(&AVR32_PM, FOSC0, OSC0_STARTUP);
53
54
  // Set all leds initial state.
55
  LED_Off( LED0 | LED1 | LED2 | LED3 );
56
  
57
  // GPIO config
58
  // configure push button to produce IT on input change
59
  // NOTE 1: GPIO_PUSH_BUTTON_0 & GPIO_PUSH_BUTTON_1 are defines you can find in
60
  // evk1101.h under /BOARDS/EVK1101/.
61
  // See the implementation of gpio_enable_pin_interrupt() in gpio.c under 
62
  // /DRIVERS/GPIO/.
63
  gpio_enable_pin_interrupt(GPIO_PUSH_BUTTON_0 , GPIO_PIN_CHANGE);  // PB2
64
  gpio_enable_pin_interrupt(GPIO_PUSH_BUTTON_1 , GPIO_PIN_CHANGE);  // PB3
65
  // NOTE 2: GPIO_PUSH_BUTTON_0 & GPIO_PUSH_BUTTON_1 are in the same port.
66
  // (i.e. port 1, cf section 21.5 of the UC3B0256 datasheet for the computation
67
  // of a port knowing the pin, and see the evk1101 schematics (or the evk1101.h
68
  // file) + the section 12.8 of the UC3B0256 datasheet to know the pin mapping
69
  // of the pushbuttons). 
70
  // Consider GPIO_PUSH_BUTTON_0 as an example: from evk1101.h, we see that
71
  // GPIO_PUSH_BUTTON_0 is AVR32_PIN_PB02. Open the UC3B0256 datasheet, go to 
72
  // section 12.8, in the array look for pin PB02, we see that it is mapped to
73
  // GPIO 34. Using section 21.5, the formula to know the port of a pin is: 
74
  // GPIO port = floor((GPIO number) / 32), so for GPIO_PUSH_BUTTON_0 we get:
75
  // floor(34/32) = 1.
76
  // Applying the same reasoning for GPIO_PUSH_BUTTON_1 (which is GPIO 35), we 
77
  // find that it belongs to port 1 too.
78
  
79
  // NOTE 3: the 32 in the formula 'GPIO port = floor((GPIO number) / 32)' 
80
  // corresponds to the fact that "The pins are managed as 32-bit ports" (see 
81
  // section 21.5 second sentence): i.e. every port holds 32 pins max.
82
  
83
  // Interrupts config
84
  Disable_global_interrupt ();
85
  INTC_init_interrupts ();
86
  // register push button handler for PB2 and PB3
87
  INTC_register_interrupt( &int_handler_port1_line0, AVR32_GPIO_IRQ_0 + (GPIO_PUSH_BUTTON_0/8), INT0);
88
  INTC_register_interrupt( &int_handler_port1_line0, AVR32_GPIO_IRQ_0 + (GPIO_PUSH_BUTTON_1/8), INT0);
89
  // NOTE 4: reading section 21.4.7, paragraph 2:
90
  // "In every port there are four interrupt lines connected to the interrupt 
91
  // controller. Every eigth interrupts in the port are ored together to form an
92
  // interrupt line."
93
  // So, for example, for port 1 : 
94
  //   GPIO32->GPIO39 : port 1 interrupt line 0 (for int-of-pin32, int-of-pin33, 
95
  //                    int-of-pin34, int-of-pin35, int-of-pin36, int-of-pin37, 
96
  //                   int-of-pin38 and int-of-pin39) 
97
  //   GPIO40->GPIO47 : port 1 interrupt line 1, 
98
  //   GPIO48->GPIO55 : port 1 interrupt line 2,
99
  //   GPIO56->GPIO63 : port 1 interrupt line 3.
100
  // 
101
  // That is why we use the formula "AVR32_GPIO_IRQ_0 + (GPIO_PUSH_BUTTON_0/8)"
102
  // to register the PB2; AVR32_GPIO_IRQ_0 is used as the base interrupt line 
103
  // and we add '(GPIO_PUSH_BUTTON_0/8)' to register the corresponding interrupt
104
  // line.
105
  
106
  // NOTE 5: Since PB2 and PB3 are mapped to the GPIO pin GPIO34 and GPIO35, we
107
  // see that they belong to the same interrupt line. Two consequences in this 
108
  // particular case:
109
  //   1) it's no use to register both. We left both registration in the code for
110
  //     clarity's sake. 
111
  //  2) we'll discriminate the cause of the interrupt (PB2 or PB3) in the 
112
  //     interrupt handler looking at the gpio_port1.ifr register. 
113
  //     See int_handler_gpio0() implementation.
114
  
115
  Enable_global_interrupt ();
116
   
117
  while (TRUE)
118
  {
119
    if  (i == 100000)
120
    {
121
      i = 0;
122
      if (j == 2)
123
      {
124
        x = !x;
125
        if (x == 0)
126
        {
127
          LED_Off (LED0);
128
        }  
129
        else
130
        {
131
          LED_On (LED0);
132
        }  
133
        j = 0;
134
      }
135
      j++;
136
    }
137
    i++;
138
  }
139
}

In dem Beispiel wird aber eine #Define GPIO_PUSH_BUTTON(1/8) verwendet, 
die ich nirgends finden kann und somit bringt mir die Gruppe auch 
nichts.
Hat jemand eine Idee wie sich der IRQ Wert zusammensetzt ?

Grüße,

Euer Peter

von PeterPanisch (Gast)


Lesenswert?

Hat sich damit noch keiner beschäftigt ? :-)

von Marcus H. (Firma: www.harerod.de) (lungfish) Benutzerseite


Lesenswert?

Doch, schon. Das letzte Mal vor ca. 8 Jahren. Sowohl AP, als auch UC.
Und aufgrund der Atmel-typischen Schlampereien und Fehler in den 
Datenblättern haben die Dinger auch richtig viel Schaden angerichtet.

Wenn Du keinen dringenden Grund hast, die Teile einzusetzen (z.B. 
Produktpflege), dann fährst Du, bei gleichem Einarbeitungsaufwand, mit 
STM32 besser.

Grüße,
 marcus

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.