Forum: FPGA, VHDL & Co. Mehrere Interruptquellen in NIOS II registrieren.


von MemY (Gast)


Lesenswert?

Hallo,

ich habe eine Frage bezgl. der Registrierung von mehreren 
Interruptquellen in NIOS II.

Und zwar sollen insgesamt sechs GPIO-Ports mit jeweils einer Breite von 
32 Bit Interruptfaehig gemacht werden.
In QSYS habe ich hierbei folgende Interruptprioritaeten vergeben:

-  Input_0 (Messwert A speichern); Prioritaet: 2
-  Input_2  (Messwert B speichern); Prioritaet: 3
-  Input_3 (Messwert C speichern); Prioritaet: 4
-  Input_4 (Messwert D speichern); Prioritaet: 5
-  Input_5 (Messwert E speichern); Prioritaet: 6
-  Input_6 (Messwert auslesen ); Prioritaet: 7


Ueber ein Interrupt an den ersten fuenf GPIO-Ports (Input_0, Input_2, 
Input_3, Input_4, Input_5) werden Daten (Messwerte zu unbestimmten 
Zeitpunkten) in ein RAM geschrieben.
Mit einem Interrupt an dem sechsten GPIO-Port (Input_6) sollen die Daten 
(zu unbestimmten Zeitpunkten) aus dem RAM gelesen werden.


Mein Ansatz zur Registrierung sieht wie folgt aus:
1
// ERSTER INTERRUPT INITITALISIEREN
2
 /* Recast the edge_capture pointer to match the alt_irq_register() function prototype. */
3
// siehe http://www.mikrocontroller.net/topic/229699
4
 void* edge_capture_ptr = (void*) &edge_capture;
5
 /* Enable first 31 interrupts. */
6
 IOWR_ALTERA_AVALON_PIO_IRQ_MASK(INPUT_0_IRQ_BASE, 0xFFFFFFFF);
7
 /* Reset the edge capture register. */
8
 IOWR_ALTERA_AVALON_PIO_EDGE_CAP(INPUT_0_IRQ_BASE, 0x00000000);
9
 /* Register the interrupt handler. */
10
 alt_irq_register(INPUT_0_IRQ_IRQ, edge_capture_ptr, handle_pio_interrupts);
11
12
// ZWEITER INTERRUPT INITITALISIEREN
13
 /* Recast the edge_capture pointer to match the alt_irq_register() function prototype. */
14
// siehe http://www.mikrocontroller.net/topic/229699
15
 void* edge_capture2_ptr = (void*) &edge_capture2;
16
 /* Enable first 31 interrupts. */
17
 IOWR_ALTERA_AVALON_PIO_IRQ_MASK(INPUT_2_IRQ_BASE, 0xFFFFFFFF);
18
 /* Reset the edge capture register. */
19
 IOWR_ALTERA_AVALON_PIO_EDGE_CAP(INPUT_2_IRQ_BASE, 0x00000000);
20
 /* Register the interrupt handler. */
21
 alt_irq_register(INPUT_2_IRQ_IRQ, edge_capture2_ptr, handle_pio2_interrupts);
22
23
.
24
.
25
.
26
27
// SECHSTER INTERRUPT INITITALISIEREN
28
 /* Recast the edge_capture pointer to match the alt_irq_register() function prototype. */
29
// siehe http://www.mikrocontroller.net/topic/229699
30
 void* edge_capture6_ptr = (void*) &edge_capture6;
31
 /* Enable first 31 interrupts. */
32
 IOWR_ALTERA_AVALON_PIO_IRQ_MASK(INPUT_6_IRQ_BASE, 0xFFFFFFFF);
33
 /* Reset the edge capture register. */
34
 IOWR_ALTERA_AVALON_PIO_EDGE_CAP(INPUT_6_IRQ_BASE, 0x00000000);
35
 /* Register the interrupt handler. */
36
 alt_irq_register(INPUT_6_IRQ_IRQ, edge_capture6_ptr, handle_pio6_interrupts);
37
  
38
  
39
void handle_pio_interrupts(void* context, alt_u32 id)
40
{
41
    /* Cast context to edge_capture's type. It is important that this be
42
     * declared volatile to avoid unwanted compiler optimization. */
43
    volatile int* edge_capture_ptr = (volatile int*) context;
44
45
    /* Store the value in the PIO's edge capture register in *context. */
46
    *edge_capture_ptr = IORD_ALTERA_AVALON_PIO_EDGE_CAP(INPUT_0_IRQ_BASE);
47
48
    //Wenn ein IR auftritt, dann in Buffer speichern
49
    SendeDaten = IORD_ALTERA_AVALON_PIO_DATA(INPUT_0_IRQ_BASE);
50
    BufferIn(SendeDaten);
51
52
    /* Reset the PIO's edge capture register. */
53
    IOWR_ALTERA_AVALON_PIO_EDGE_CAP(INPUT_0_IRQ_BASE, 0);
54
55
56
}
57
58
59
void handle_pio2_interrupts(void* context, alt_u32 id)
60
{
61
    /* Cast context to edge_capture's type. It is important that this be
62
     * declared volatile to avoid unwanted compiler optimization. */
63
    volatile int* edge_capture2_ptr = (volatile int*) context;
64
65
    /* Store the value in the PIO's edge capture register in *context. */
66
    *edge_capture2_ptr = IORD_ALTERA_AVALON_PIO_EDGE_CAP(INPUT_2_IRQ_BASE);
67
68
    //Wenn ein IR auftritt, dann in Buffer speichern
69
    SendeDaten = IORD_ALTERA_AVALON_PIO_DATA(INPUT_2_IRQ_BASE);
70
    BufferIn(SendeDaten);
71
72
    /* Reset the PIO's edge capture register. */
73
    IOWR_ALTERA_AVALON_PIO_EDGE_CAP(INPUT_2_IRQ_BASE, 0);
74
75
76
}
77
.
78
.
79
.
80
void handle_pio6_interrupts(void* context, alt_u32 id)
81
{
82
    /* Cast context to edge_capture's type. It is important that this be
83
     * declared volatile to avoid unwanted compiler optimization. */
84
    volatile int* edge_capture6_ptr = (volatile int*) context;
85
86
    /* Store the value in the PIO's edge capture register in *context. */
87
    *edge_capture6_ptr = IORD_ALTERA_AVALON_PIO_EDGE_CAP(INPUT_6_IRQ_BASE);
88
89
  //Lese aus Buffer (aus der letzten belegten Stelle)
90
  check = BufferOut(EmpfangsDaten);
91
  if(check == 0){
92
    IOWR_ALTERA_AVALON_PIO_DATA(OUTPUT_0_BASE, 0xCAFEAFFE);
93
  }
94
  else{
95
    IOWR_ALTERA_AVALON_PIO_DATA(OUTPUT_0_BASE, *EmpfangsDaten);
96
  }
97
    /* Reset the PIO's edge capture register. */
98
    IOWR_ALTERA_AVALON_PIO_EDGE_CAP(INPUT_6_IRQ_BASE, 0);
99
100
101
}

Mein Problem ist nun, dass ich manche Interrupt „Anfragen“ (Auslesen aus 
dem RAM) verloren gehen. Kann das an meiner Registrierung liegen? Ist 
mein Konzept falsch? Habt Ihr eine Idee?

Vielen Dank schonmal,
MemY

von MemY (Gast)


Lesenswert?

Hat keiner eine Idee?

Bisher konnte ich keinen Fehler finden...
Ausschließen kann ich, dass die ISR (handle_pio6_interrupts() ) zu lange 
durchlaeuft und dadurch einen neuen IRQ ignoriert.

von Kest (Gast)


Lesenswert?

Ich denke, Deine Fragestellung ist etwas komplex, deshalb kommen keine 
Anworten bzw. keine Hinweise. Versuch mal Dein Problem bzw. Frage auf 
wenige Zeilen zusammenzuschrumpfen. Vielleicht sogar ein Screenshot von 
QSYS, vielleicht weis dann jemand mehr.

Ich selber habe nie (oder selten) was mit Interrupts und NIOS gemacht, 
kann also nicht helfen. Aber als Tipp: reduziere die Anzahl der 
Interrupts und schaue, ob da welche verloren gehen oder nicht.

Kest

von MemY (Gast)


Lesenswert?

Hallo Kest!

Kest schrieb:
> Ich denke, Deine Fragestellung ist etwas komplex, deshalb kommen keine
> Anworten bzw. keine Hinweise.

Ja sry...

Kest schrieb:
> Ich selber habe nie (oder selten) was mit Interrupts und NIOS gemacht,
> kann also nicht helfen. Aber als Tipp: reduziere die Anzahl der
> Interrupts und schaue, ob da welche verloren gehen oder nicht.

Es scheint nun zu funktionieren und die Registrierung der Interrupts 
ist/war soweit korrekt.

Problem war ein anderer Interrupt-Eingang (von einem weiteren Nios) der 
den Interrupt des sechsten GPIO-Ports (Input_6) generiert.

Gruß
MemY

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.