Forum: Mikrocontroller und Digitale Elektronik PIC32MX795 und UART4: Kein Interrupt beim Empfang von Zeichen.


von Seppl (Gast)


Lesenswert?

Ich verwende einen PIC32MX795F512L.

Ich versuche gerade mit UART4 einen Interrupt-gesteuerten Empfang
zu realisieren.

Ich kann den UART4 initialisieren, sehe die richtigen Sende-Daten.
Ich kann Empfangs-Daten via Polling abfragen, nur die Interrupt-Routine
wird nicht aufgerufen, wenn Zeichen empfangen werden.
Ich habe UART1 und UART2 am Laufen,
UART1 auch mit funktionierender Interrupt-Routine
(kopierter und für UART4 angepasster Code, hoffentlich mittlerweile
nicht kaputt debugged).

UART_MODULE SerialUartModule = UART4;

/*
    Initialize Serial Port

    Returnvalue: a value of 1 if successful
                 negative value if there was an error
*/
int SerialInit(void)
{
    // Disable UART interrupt, because we (re-)configure UART
    INTEnable(INT_SOURCE_UART_RX(SerialUartModule), INT_DISABLED);

    // Disable UART, because we (re-)configure UART
    UARTEnable(SerialUartModule, UART_DISABLE_FLAGS(UART_PERIPHERAL | 
UART_RX | UART_TX));

    // This is for pins TX and RX only (no RTS/CTS)
    UARTConfigure(SerialUartModule, UART_ENABLE_PINS_TX_RX_ONLY);

    // This is for pins TX, RX, RTS, CTS
    // UARTConfigure(SerialUartModule, UART_ENABLE_PINS_CTS_RTS);

    // UARTSetFifoMode(SerialUartModule, UART_INTERRUPT_ON_TX_NOT_FULL | 
UART_INTERRUPT_ON_RX_NOT_EMPTY);
    UARTSetFifoMode(SerialUartModule, UART_INTERRUPT_ON_RX_NOT_EMPTY);
    // 8N1
    UARTSetLineControl(SerialUartModule, UART_DATA_SIZE_8_BITS | 
UART_PARITY_NONE | UART_STOP_BITS_1);
    // Set Baudrate
    UARTSetDataRate(SerialUartModule, GetPeripheralClock(), 19200);
    // Enable UART
    UARTEnable(SerialUartModule, UART_ENABLE_FLAGS(UART_PERIPHERAL | 
UART_RX | UART_TX));

    // Configure UART RX Interrupt
    INTEnable(INT_SOURCE_UART_RX(SerialUartModule), INT_ENABLED);
    INTSetVectorPriority(INT_VECTOR_UART(SerialUartModule), 
INT_PRIORITY_LEVEL_2);
    INTSetVectorSubPriority(INT_VECTOR_UART(SerialUartModule), 
INT_SUB_PRIORITY_LEVEL_0);

    // Enable multi-vector interrupts
    INTConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR);
    INTEnableInterrupts();
}


void __ISR(_UART_4_VECTOR, ipl2) IntUart4Handler(void)
{
  -> Hier ist eine Debug-Ausgabe, die aber nicht kommt
}

Ich bin leider gezwungen, mit dem alten MPLAB zu arbeiten,
mit einem alten C-Compiler, im Legacy-Mode.

Legacy ist ein gutes Stichwort:
Was hat es damit auf sich, dass die UARTs einmal mit
UART1...UART6 bezeichnet werden, dann aber wieder mal mit
UART_1A, UART_1B, UART_2A, UART_2B, UART_3A, UART_3B?

UART4 muesste UART_2A sein?

Ich habe mal den Wert von _UART_x_VECTOR ausgegeben (dezimal):

_UART_1_VECTOR=24
_UART_2_VECTOR=32
_UART_3_VECTOR=31
_UART_4_VECTOR=49
_UART_5_VECTOR=51
_UART_6_VECTOR=50
_UART_1A_VECTOR=24
_UART_1B_VECTOR=49
_UART_2A_VECTOR=31
_UART_2B_VECTOR=50
_UART_3A_VECTOR=32
_UART_3B_VECTOR=51

Hier ist 1->1A,2->3A,3->2A,4->1B,5->3B,6->2B.

Warum ist jetzt die UART4_VECTOR Nummer 49
aber UART_1B hat auch Nummer 49 und
UART4_VECTOR ist nicht gleich mit dem von UART_2A?

Ich habe mittlerweile auch mal auf allen UART Interrupt Vektoren
eine ISR installiert, aber keine davon wird aufgerufen...

Errata habe ich schon durchgeschaut, nichts dazu gefunden.
Ich habe auch schon anderen Beispiel-Code probiert,
aber leider auch kein Durchbruch, alle verhalten sich gleich,
keine Interrupt.

Kann hier jemand weiterhelfen und mich vor der Verzweifelung retten?

von Chris B. (dekatz)


Lesenswert?

Für den alten C32 Compiler wirst du dir die UART4-Routinen selbst 
schreiben müssen, denn:
pic32-libs/peripheral/uart/legacy enthält nur die Funktionen für UART1 
und UART2.

>Hier ist 1->1A,2->3A,3->2A,4->1B,5->3B,6->2B.

In pic32-libs/include/peripheral/uart/legacy/uart_legacy.h finden sich 
die
Zuweisungen....habe aber das nicht weiterverfolgt

von Seppl (Gast)


Lesenswert?

UART4 geht ja grundsätzlich, nur der Interrupt nicht...
Es kann natürlich durchaus sein, dass eine der Interrupt-Funktionen
mit dem UART4 nicht zurecht kommt?
Ich bin doch aber bestimmt nicht der 1.,
der den Interrupt mit UART4 auf dem alten Compiler/der alten MPLAB IDE
nutzt?

von Somebody123 (Gast)


Lesenswert?

Hallo,

als Fehlerquellen fällt mir folgendes ein:
- beim PIC32 muss man multi vector Interrupts erst einschalten. Wird das 
gemacht?
- Ich würde mal beim Debuggen schauen, ob die IE-Flags für den Interrupt 
wirklich gesetzt werden (U4TXIE/U4RXIE= 1)
- Schau mal, ob die Interrupt Flags kommen (U4TXIF/U4RXIF = 1)
- Ist die Priorität des Interrupts < 7 (U4IP)? Bei 7 passier nichts, 
wenn ich mich richtig erinnere.
- sind irgendwo die Interrupts deaktiviert oder so?

Ich muss aber sagen, dass ich ohne Peripheral lib arbeite und daher 
deren Tücken nicht kenne.

von Stephan (Gast)


Lesenswert?

Hi,
hier mal mein Code, kannst ja mal schauen ob das mit deinem überein 
stimmt.

PS: habs mal bei mir raus kopiert...
1
// Init
2
   UARTConfigure(UART4, UART_ENABLE_PINS_TX_RX_ONLY);
3
   UARTSetLineControl(UART4, UART_DATA_SIZE_8_BITS | UART_PARITY_NONE | UART_STOP_BITS_1);
4
   UARTSetDataRate(UART4, GetPeripheralClock(), 38400);
5
   UARTEnable(UART4, UART_ENABLE_FLAGS(UART_PERIPHERAL | UART_RX | UART_TX));
6
   
7
   UARTSetFifoMode(UART4, UART_INTERRUPT_ON_TX_BUFFER_EMPTY | UART_INTERRUPT_ON_RX_NOT_EMPTY);
8
      
9
   // Configure Com1Parameter Interrupt
10
  INTEnable(INT_SOURCE_UART(UART4)       , INT_DISABLED);
11
  INTEnable(INT_SOURCE_UART_TX(UART4)    , INT_DISABLED);
12
  INTEnable(INT_SOURCE_UART_ERROR(UART4) , INT_DISABLED);
13
  INTEnable(INT_SOURCE_UART_RX(UART4)    , INT_ENABLED);      // <- active
14
   
15
   INTSetVectorPriority(INT_VECTOR_UART(UART4), INT_PRIORITY_LEVEL_2);
16
   INTSetVectorSubPriority(INT_VECTOR_UART(UART4), INT_SUB_PRIORITY_LEVEL_0);   
17
18
19
void __ISR(_UART_4_VECTOR, ipl2) IntUart4Handler(void)
20
{
21
   u08 byte;
22
  // Is this an RX interrupt?
23
  if(INTGetFlag(INT_SOURCE_UART_RX(UART4)))
24
  {
25
    // Clear the RX interrupt Flag
26
      INTClearFlag(INT_SOURCE_UART_RX(UART4));
27
      // .. things to do
28
      if (UARTReceivedDataIsAvailable(UART4) != 0)
29
      { 
30
         byte= UARTGetDataByte(UART4);
31
         UART_CharOut(UART4, byte);
32
      }
33
  }
34
35
  // We don't care about TX interrupt
36
  if ( INTGetFlag(INT_SOURCE_UART_TX(UART4)) )
37
  {
38
    INTClearFlag(INT_SOURCE_UART_TX(UART4));     
39
  }
40
   
41
   // We don't care about ERROR interrupt
42
   if ( INTGetFlag(INT_SOURCE_UART_ERROR(UART4)))
43
   {
44
    INTClearFlag(INT_SOURCE_UART_ERROR(UART4));
45
  }
46
   
47
   // We don't care about this interrupt
48
   if ( INTGetFlag(INT_SOURCE_UART(UART4)))
49
   {
50
    INTClearFlag(INT_SOURCE_UART(UART4));
51
  }
52
}

Also für mich war der PIC32 auch sehr verwirrend.
Da Microchip auch kein Interesse hat da die Kunden zu unterstützen, bis 
du ziemlich auf dich alleine gestellt. (kein Interesse -> hab ich damals 
sogar per Mail vom Support bekommen!, lol)

Versuch im Forum von denen einen Admin zu finden und sprich den direkt 
an!!! Sonst wird das da auch nichts!

viellllll Spasssssssss

von Seppl (Gast)


Lesenswert?

@Stephan:
Vielen Dank für Hinweise und Beispiel-Code.
Leider löst auch dieser bei mir keinen Interrupt aus,
aber normaler Empfang mit deinem Code per Polling funktioniert
weiterhin.

Ich bin mittlerweile auch schon einen Schritt weiter:
(aber immer noch kein Interrupt)

Ich gebe die IEC0...IEC2 jetzt mal vor

   // Configure Com1Parameter Interrupt
>  INTEnable(INT_SOURCE_UART(UART4)       , INT_DISABLED);
>  INTEnable(INT_SOURCE_UART_TX(UART4)    , INT_DISABLED);
>  INTEnable(INT_SOURCE_UART_ERROR(UART4) , INT_DISABLED);
>  INTEnable(INT_SOURCE_UART_RX(UART4)    , INT_ENABLED);      // <- active

und dann mal hinterher aus, damit ich die Inhalte prüfen kann.

Durch den Code auf meiner Maschine/Umgebung wird

IEC1 von 0x04000000 auf 0x04000040 verändert.
Gebe ich alle Interrupt (der 4 oben genannten von UART4) frei,
dann steht 0x040000E0 im Register IEC1. IEC2 bleibt auf 0.

Aber UART4 ist laut Datenblatt im IEC2!?!
An der Stelle, an der der INTEnable Bit setzt, wäre UART3...

Was macht die Zeile in Registern?

> INTEnable(INT_SOURCE_UART(UART4)       , INT_DISABLED);

oder auch

> INTClearFlag(INT_SOURCE_UART(UART4));

Welches Bit (welche Bits) wird/werden hier bedient?
Vielleicht ist dies mein fehlendes Bit
(weil sich INTEnable verrechnet...)...

Die Interrupt-Level

>   INTSetVectorPriority(INT_VECTOR_UART(UART4), INT_PRIORITY_LEVEL_2);
>   INTSetVectorSubPriority(INT_VECTOR_UART(UART4), INT_SUB_PRIORITY_LEVEL_0);

werden aber korrekt in IPC12 Bits U4IP und U4IS reingeschrieben.
(IPC12 vorher 0, nachher 0x00000800).

Ich habe jetzt statt den (fehlerhaften?) INTEnable
direkt das Register beschrieben:  IEC2SET = (1 << 4);

Damit bleibt jetzt IEC1 wie es ist und IEC2 hat den Wert 0x00000010.

Leider kommt dann aber immer noch kein Interrupt.
Müssen die Level und Sublevel eigentlich eindeutig sein,
oder darf ein anderer UART die gleichen Setting benutzen?

@Somebody123

> - beim PIC32 muss man multi vector Interrupts erst einschalten.
>   Wird das gemacht?

Hab ich mittlerweile als erste Aktion gleich in main(),
bevor die ganzen Init-Routine aufgerufen werden.
Was würde denn passieren, wenn es Code gibt, der es
kurz ausschaltet und wieder einschaltet?
Werden dann die ganzen Multi-Vector Einstellungen zurückgesetzt?

> - Ich würde mal beim Debuggen schauen, ob die IE-Flags
>   für den Interrupt wirklich gesetzt werden (U4TXIE/U4RXIE= 1)

siehe oben, sollte ich jetzt manuell richtig gesetzt haben?

> - Schau mal, ob die Interrupt Flags kommen (U4TXIF/U4RXIF = 1)

Meintest du U4TXIF und U4RXIF in IFS2? Ich habe die mal ausgegeben,
wurden aber nie gesetzt...

> - Ist die Priorität des Interrupts < 7 (U4IP)?
>   Bei 7 passier nichts, wenn ich mich richtig erinnere.

Sollte richtig sein

> - sind irgendwo die Interrupts deaktiviert oder so?

Kann man diese noch irgendwo selektiv deaktivieren?
Weil auf einem anderen UART kommen (zeitgleich) die UART-Interrupts,
wenn ich Daten empfange.

> Ich muss aber sagen, dass ich ohne Peripheral lib
> arbeite und daher deren Tücken nicht kenne.

Kannst du mir ein Beispiel posten,
wie es ohne Peripheral-Lib geht? Hilft mir vielleicht bei
Aktionen, die außerhalb des "UART Aufsetzens" stattfinden...

von Somebody123 (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe mal ein funktionierendes Beispiel für den PIC24 angehängt, für 
PIC32 habe ich nichts, auch keine HW mit UART zum testen. Prinzipiell 
ist das aber meistens das gleiche.

Ich würde das für den PIC32 wie folgt initialisieren (RX):

[c]
        U4STAbits.URXISEL = 0b00;   //interrupt, if RX-Buffer is not 
empty
        IPC9bits.U4IP = 3;          //set interrupt priority to 3
        IFS2bits.U4RXIF = 0;        //reset flag
        //TODO: flush buffer
        IEC2bits.U4RXIE = 1;        //enable UART4 RX Interrupt
[\c]

In dem Fall müsste er in die UART 4 ISR springen, wenn er Daten 
empfangen hat. Das genaue Verhalten stellt man mit UXISL ein.
Kann sein, dass die Bits in deinem PIC woanders sind, ich hab das kurz 
in ein Projekt für einen PIC32MX470 eingetippt - die Flags (U4IP etc) 
sollten aber gleich heißen.

TX müsste analog gehen.

von Seppl (Gast)


Lesenswert?

Ich habe es mittlerweile komplett auf Register-Zugriffe umgebaut,
so hat es dann funktioniert (U2A mit _UART_2A_VECTOR).
Vielen Dank für all eure Hilfe und Tipps!
Die Peripheral Lib hat sich je nach IDE/Compiler
(MPLAB mit altem Compiler, MPLAB-X mit neuem Compiler)
unterschiedlich verhalten, hat dann teilweise auch einen anderen
UART bedient, wie ich wollte. Dort scheint es Fehler in
der Peripheral Libs zu geben, die ich dann aber nicht näher untersucht
habe.

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.