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


von Christian J. (elektroniker1968)


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
1
void uart2_init (uint32_t baud)
2
{
3
    uint32_t fdiv;
4
5
   // Konfiguriere die GPIO's als UART Pins
6
  PCONP |= (1 << PCUART2);  // Uart 2 einschalten
7
8
   // Pinsel Bits für UART2 Funktion setzen
9
  PINSEL0 &= ~ ( (0x03<<PINSEL_BITPIN_TX) | (0x03<<PINSEL_BITPIN_RX) ) ;
10
  PINSEL0 |=  (PINSEL_UART_FUNC << PINSEL_BITPIN_RX) |
11
        (PINSEL_UART_FUNC << PINSEL_BITPIN_TX);
12
13
14
    U2IER = 0x00;        // Alle IRQ absschalten
15
    U2IIR = 0x00;           // IIR ID Register löschen
16
17
    fdiv = (F_apb / 16) / baud;
18
19
    // Baudrate etc einstellen
20
    U2LCR = 0x83;           // divisor latch einschalten
21
    U2DLM = fdiv / 256;     // set for baud low byte
22
    U2DLL = fdiv % 256;     // set for baud high byte
23
    U2FDR = 0x10;           // Fractional Divider ausschalten
24
25
    U2LCR = 0x03;           // Format N81 setzen und divisor latch abschalten
26
  U2FCR = 0x07;           // Uart FIFO ein (RX Triggerlevel 1 Zeichen)
27
    U2TER = 0x80;           // TX einschalten
28
29
    // Die ISR installieren
30
    install_irq (UART2_INT, (void*)Isr_UART2,LOWEST_PRIORITY);
31
32
  // alternativ:
33
  //VICVectAddr28 = (uint32_t)&Isr_UART20;
34
  //VICVectCntl28 = LOWEST_PRIORITY;
35
  //VICIntEnable = 1 << 28;
36
37
    // RBR,THRE,RX Line Status IRQs einschalten
38
    U2IER |= 0x07;
39
}

von (prx) A. K. (prx)


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.

von Matthias N. (vbchaos)


Lesenswert?

Christian J. wrote:
>
1
> void uart2_init (uint32_t baud)
2
> {
3
>    // Pinsel Bits für UART2 Funktion setzen
4
>   PINSEL0 &= ~ ( (0x03<<PINSEL_BITPIN_TX) | (0x03<<PINSEL_BITPIN_RX) ) ;
5
>   PINSEL0 |=  (PINSEL_UART_FUNC << PINSEL_BITPIN_RX) |
6
>         (PINSEL_UART_FUNC << PINSEL_BITPIN_TX);
7
>
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)
>
1
>     // Die ISR installieren
2
>     install_irq (UART2_INT, (void*)Isr_UART2,LOWEST_PRIORITY);
3
> 
4
>   // alternativ:
5
>   //VICVectAddr28 = (uint32_t)&Isr_UART20;
6
>   //VICVectCntl28 = LOWEST_PRIORITY;
7
>   //VICIntEnable = 1 << 28;
8
>

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.

von (prx) A. K. (prx)


Lesenswert?

IIR löscht man durch Lesen, nicht durch Schreiben.

von Matthias N. (vbchaos)


Lesenswert?

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

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

von (prx) A. K. (prx)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

Der Vollständigkeit halber: PCLKSEL0 gibt's auch noch.

von Christian J. (elektroniker1968)


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.

von (prx) A. K. (prx)


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?

von (prx) A. K. (prx)


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.

von Christian J. (elektroniker1968)


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.
1
 // APB Teiler einstellen
2
  switch (apb_div)
3
  {
4
    case 1: PCLKSEL0 = 0x55555555;
5
            PCLKSEL1 = 0x55555555;
6
            break;
7
8
  case 2: PCLKSEL0 = 0xAAAAAAAA;
9
            PCLKSEL1 = 0xAAAAAAAA;
10
            break;
11
12
  case 4: PCLKSEL0 = 0x00000000;
13
            PCLKSEL1 = 0x00000000;
14
            break;
15
  }

1
void __attribute__ ((interrupt("IRQ"))) Isr_UART2 (void)
2
{
3
    uint32_t d,zeichen, idx, cnt,int_stat, foo;
4
5
    // Wiederhole solange Pending IRQ anliegen
6
    while (1)
7
    {
8
        // Liegen IRQs an? (zufällige IRQs abfangen)
9
        int_stat = U2IIR;
10
    if (int_stat & UIIR_PEND)
11
      goto exit_isr;
12
13
    int_stat = (int_stat >> 1) & 0x07;     // Pending IRQ Bit brauchen wir nicht mehr
14
15
        // ---- RLS (Receive Line status) (Es sind Fehler aufgetreten)
16
        if (int_stat == UIIR_RLS_INT ) {
17
            zeichen = U2LSR;                            // IRQ durch lesen löschen
18
            zeichen = U2RBR;                            // FIFO entleeren
19
      goto exit_isr;
20
        }
21
22
        // ---- RDA (Receive Data available)
23
        else if (int_stat == UIIR_RDA_INT) {
24
           idx = RxFifo.wptr;
25
           cnt = RxFifo.count;
26
27
          // Solange RX Fifo nicht leer ist...
28
           while (U2LSR & ULSR_RDR) {
29
               zeichen = U2RBR;                     // Zeichen aus Uart RX FIFO abholen
30
               if (cnt < BUFFER_SIZE) {         // Im User RX FIFO speichern, solange nicht voll
31
                   RxFifo.buff[idx] = zeichen;
32
                   cnt++;
33
                   idx = (idx + 1) % BUFFER_SIZE; // Bei Fifo TOP rollen auf 0
34
               }
35
           }
36
        }
37
38
        // ---- CTI (Character Time-out indicator) wird nicht beachtet
39
        else if (int_stat == UIIR_CTI_INT) {
40
            foo = U2LSR;        // IRQ durch lesen löschen
41
            foo = U2RBR;
42
        }
43
        // ---- THRE Interrupt (Uart TX FIFO leer: U2LSR auslesen für weitere Infos)
44
        else if (int_stat == UIIR_THRE_INT)
45
        {
46
            // Hw TX FIFO wieder auffüllen
47
            cnt = TxFifo.count;                        // Anzahl Zeichen im User TX FIFO holen
48
            if (cnt>0) {
49
                idx = TxFifo.rptr;
50
                for (d = 12; d && cnt; d--, cnt--) {    // Maximal 12 Zeichen im Fifo speichern
51
                   U2THR = TxFifo.buff[idx];           // Uart FIFO beschreiben
52
                   idx = (idx + 1) % BUFFER_SIZE;       // Bei Fifo TOP rollen auf 0
53
                }
54
55
                // Fifo anpassen
56
                TxFifo.rptr = idx;
57
                TxFifo.count = cnt;
58
59
            } else TxRun = 0;                          // Run Flag löschen, wenn alle Daten gesendet
60
        }
61
        // was immer es auch sonst ist...
62
        else {
63
            foo = U2LSR;        // IRQ durch lesen löschen
64
            foo = U2RBR;        // FIFO entleeren
65
        }
66
    }
67
68
69
exit_isr:
70
71
     VICVectAddr = 0;
72
73
}

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.