mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik LPC2368 Uart löst keinen IRQ aus


Autor: Christian J. (elektroniker1968)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Spezies,

mir fällt nichts mehr ein, warum meine Uart zwar sauber schreibt aber 
keinen IRQ auslöst.

Testweise habe ich einen Software IRQ erzwungen und der wird auch 
ausgelöst

VICSoftInt = (1<<UART2_INT);
test = U2IIR;
test = U2IIR;

Die Bits in test verändern sich exakt nach Vorschrift, beim zweiten 
Lesen ist das THRE Bit wieder gelöscht. Trotzdem springt er die IRQ 
nicht an. Das funktioniert bei allen anderen ISRs einwandfrei.

Wenn ich schnell nacheinander Zeichen in U2THR schreibe nimmt er 16 an 
und "vergisst" die anderen, auch klar, weil der TX Fifo nur 16 Bytes 
hat. Er müsste aber einen IRQ auslösen, sobald zB der TX Fifo leer wird. 
Tut er aber nicht, die Bits, die das anzeigen sind aber gesetzt. Bei 
anderen ISR springt der Debug Cursor sofort nach einem Software INT 
direkt in die jeweilige ISR rein.

Gibt es noch irgendwo ein geheimnes Bit, was ich vergessen habe?

Es gibt die geheinmisvolle Funktion bei Rowley __ARMLIB_enableIRQ() die 
dafür sorgt, dass überhaupt ISR laufen. Aber ich habe kein Bit finden 
können, was einen globalen INT Stop auslöst. Die anderen ISR arbeiten ja 
auch.

Idee?


Hier die Init
void uart2_init (uint32_t baud)
{
    uint32_t fdiv;

   // Konfiguriere die GPIO's als UART Pins
  PCONP |= (1 << PCUART2);  // Uart 2 einschalten

   // Pinsel Bits für UART2 Funktion setzen
  PINSEL0 &= ~ ( (0x03<<PINSEL_BITPIN_TX) | (0x03<<PINSEL_BITPIN_RX) ) ;
  PINSEL0 |=  (PINSEL_UART_FUNC << PINSEL_BITPIN_RX) |
        (PINSEL_UART_FUNC << PINSEL_BITPIN_TX);


    U2IER = 0x00;        // Alle IRQ absschalten
    U2IIR = 0x00;           // IIR ID Register löschen

    fdiv = (F_apb / 16) / baud;

    // Baudrate etc einstellen
    U2LCR = 0x83;           // divisor latch einschalten
    U2DLM = fdiv / 256;     // set for baud low byte
    U2DLL = fdiv % 256;     // set for baud high byte
    U2FDR = 0x10;           // Fractional Divider ausschalten

    U2LCR = 0x03;           // Format N81 setzen und divisor latch abschalten
  U2FCR = 0x07;           // Uart FIFO ein (RX Triggerlevel 1 Zeichen)
    U2TER = 0x80;           // TX einschalten

    // Die ISR installieren
    install_irq (UART2_INT, (void*)Isr_UART2,LOWEST_PRIORITY);

  // alternativ:
  //VICVectAddr28 = (uint32_t)&Isr_UART20;
  //VICVectCntl28 = LOWEST_PRIORITY;
  //VICIntEnable = 1 << 28;

    // RBR,THRE,RX Line Status IRQs einschalten
    U2IER |= 0x07;
}

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Pinsel-Bits stimmen garantiert? Immerhin hat der Chip mehr als eine 
UART und hier wird die zweite verwendet - aber das steht da nicht in den 
Namen der Bits drin.

Das vor dir gesuchte globale Disable-Bit befindet sich im Statusregister 
des Prozessors. Und muss üblicherweise explizit im Code freigegeben 
werden, denn ab Reset sind IRQs und FIQs abgeschaltet. Aber wenn der 
Soft-Int funktioniert ist das bereits ok.

Autor: Matthias Nix (vbchaos)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Christian J. wrote:
>
> void uart2_init (uint32_t baud)
> {
>    // Pinsel Bits für UART2 Funktion setzen
>   PINSEL0 &= ~ ( (0x03<<PINSEL_BITPIN_TX) | (0x03<<PINSEL_BITPIN_RX) ) ;
>   PINSEL0 |=  (PINSEL_UART_FUNC << PINSEL_BITPIN_RX) |
>         (PINSEL_UART_FUNC << PINSEL_BITPIN_TX);
> 
Es wäre toll, die Masken dazu zu sehen (sprich: die #defines). Der UART 
auf P0.10 und P0.11 ist die erste alternative Beschaltung. Kommt das mit 
deinen Masken so hin?

Und dann das hier: (weiss aber nicht, obs nur n Tippfehler is)
>
>     // Die ISR installieren
>     install_irq (UART2_INT, (void*)Isr_UART2,LOWEST_PRIORITY);
> 
>   // alternativ:
>   //VICVectAddr28 = (uint32_t)&Isr_UART20;
>   //VICVectCntl28 = LOWEST_PRIORITY;
>   //VICIntEnable = 1 << 28;
> 

Was denn nu? Isr_UART2 oder Isr_UART20? Ist mir nur so aufgefallen. Da 
Der Interrupt ja scheinbar gar nicht erst auslöst wird dies der Fehler 
nicht sein.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
IIR löscht man durch Lesen, nicht durch Schreiben.

Autor: Matthias Nix (vbchaos)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. wrote:
> IIR löscht man durch Lesen, nicht durch Schreiben.

Japp! Hier aus meiner Uart2_Init:
  U2IER = 0x00;                         // disable all interrupts
  U2IIR;                                      // clear interrupt ID
  U2RBR;                                    // clear receive register
  U2LSR;                                    // clear line status register

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist zwar das gleiche, sieht aber nicht so blöd aus:
  (void) U2IIR;

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Vollständigkeit halber: PCLKSEL0 gibt's auch noch.

Autor: Christian J. (elektroniker1968)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke,

ich habs schon, ich habe Init_VIC(); vergessen, bzw stand das unter dem 
init_uart und hat daher alle Einstellungen wieder platt gemacht. Kein 
Wunder.... (zwei Stunden Suchen fürn A..... kopfvordiewandschlag)

Aber danke für den Hinweis mit dem Lesen, das scheiben aber viele 
Beispiele falsch zu haben, die klar in RO Register schreiben.

PCLKSEL habe ich überall für alle APB Geräte auf 1/4 gesetzt und 
verändere das auch nicht um kein Chaos zu erzeugem.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Christian J. wrote:

> Wunder.... (zwei Stunden Suchen fürn A..... kopfvordiewandschlag)

Für'n A* wäre es gewesen, wenn du es nicht gefunden hättest.

Nur: Wieso soll dann der Soft-Int funktioniert haben?

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Christian J. wrote:

> PCLKSEL habe ich überall für alle APB Geräte auf 1/4 gesetzt und
> verändere das auch nicht um kein Chaos zu erzeugem.

Chaos erzeugst du, wenn ohne Not der Takt an anderer Stelle definiert 
wird als der daraus abgeleitete Teiler für die Bitrate. Was zusammen 
gehört, das gehört zusammen.

Autor: Christian J. (elektroniker1968)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dudelt einwandfrei    jubelhochdrei die in der Konsole eingegeben 
Zeichen taucht im RX Fifo wieder auf.

Ich betreibe den uC mit 60 Mhz, habe auch tausendmal überlegt ob ich das 
variabel gestalte und die APB Clocks immer neu berechne. Das gab nur 
Chaos, vor allem mit ohne ohne PLL. Also alle Peripherals auf 1/4 Fcclk 
gesetzt und diesen Wer fassen die Init Routinen nur an, wenn notwendig. 
Die Uart funktioniert zB für 56700 nicht mehr unter 12 Nhz APB Takt.
 // APB Teiler einstellen
  switch (apb_div)
  {
    case 1: PCLKSEL0 = 0x55555555;
            PCLKSEL1 = 0x55555555;
            break;

  case 2: PCLKSEL0 = 0xAAAAAAAA;
            PCLKSEL1 = 0xAAAAAAAA;
            break;

  case 4: PCLKSEL0 = 0x00000000;
            PCLKSEL1 = 0x00000000;
            break;
  }

void __attribute__ ((interrupt("IRQ"))) Isr_UART2 (void)
{
    uint32_t d,zeichen, idx, cnt,int_stat, foo;

    // Wiederhole solange Pending IRQ anliegen
    while (1)
    {
        // Liegen IRQs an? (zufällige IRQs abfangen)
        int_stat = U2IIR;
    if (int_stat & UIIR_PEND)
      goto exit_isr;

    int_stat = (int_stat >> 1) & 0x07;     // Pending IRQ Bit brauchen wir nicht mehr

        // ---- RLS (Receive Line status) (Es sind Fehler aufgetreten)
        if (int_stat == UIIR_RLS_INT ) {
            zeichen = U2LSR;                            // IRQ durch lesen löschen
            zeichen = U2RBR;                            // FIFO entleeren
      goto exit_isr;
        }

        // ---- RDA (Receive Data available)
        else if (int_stat == UIIR_RDA_INT) {
           idx = RxFifo.wptr;
           cnt = RxFifo.count;

          // Solange RX Fifo nicht leer ist...
           while (U2LSR & ULSR_RDR) {
               zeichen = U2RBR;                     // Zeichen aus Uart RX FIFO abholen
               if (cnt < BUFFER_SIZE) {         // Im User RX FIFO speichern, solange nicht voll
                   RxFifo.buff[idx] = zeichen;
                   cnt++;
                   idx = (idx + 1) % BUFFER_SIZE; // Bei Fifo TOP rollen auf 0
               }
           }
        }

        // ---- CTI (Character Time-out indicator) wird nicht beachtet
        else if (int_stat == UIIR_CTI_INT) {
            foo = U2LSR;        // IRQ durch lesen löschen
            foo = U2RBR;
        }
        // ---- THRE Interrupt (Uart TX FIFO leer: U2LSR auslesen für weitere Infos)
        else if (int_stat == UIIR_THRE_INT)
        {
            // Hw TX FIFO wieder auffüllen
            cnt = TxFifo.count;                        // Anzahl Zeichen im User TX FIFO holen
            if (cnt>0) {
                idx = TxFifo.rptr;
                for (d = 12; d && cnt; d--, cnt--) {    // Maximal 12 Zeichen im Fifo speichern
                   U2THR = TxFifo.buff[idx];           // Uart FIFO beschreiben
                   idx = (idx + 1) % BUFFER_SIZE;       // Bei Fifo TOP rollen auf 0
                }

                // Fifo anpassen
                TxFifo.rptr = idx;
                TxFifo.count = cnt;

            } else TxRun = 0;                          // Run Flag löschen, wenn alle Daten gesendet
        }
        // was immer es auch sonst ist...
        else {
            foo = U2LSR;        // IRQ durch lesen löschen
            foo = U2RBR;        // FIFO entleeren
        }
    }


exit_isr:

     VICVectAddr = 0;

}


Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.