Forum: Mikrocontroller und Digitale Elektronik TX UART Problem Peter Fleury


von Thomas (Gast)


Lesenswert?

Hallo,

ich habe ein Problem mit der UART Lib von Peter Fleury:
1
void uart_putc(unsigned char data)
2
{
3
    unsigned char tmphead;
4
5
    
6
    tmphead  = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;
7
    
8
    while ( tmphead == UART_TxTail ){
9
        ;/* wait for free space in buffer */
10
    }
11
    
12
    UART_TxBuf[tmphead] = data;
13
    UART_TxHead = tmphead;
14
15
    /* enable UDRE interrupt */
16
    UART0_CONTROL    |= _BV(UART0_UDRIE);
17
18
}/* uart_putc */

Wenn ich mittels uart_puts("dsadkljK") etwas verschicken will bleibt der 
Controller auf der Zeile
1
while ( tmphead == UART_TxTail ){
stehen. In beiden Variablen steht dann eine 0x12...

Wieso ist das so? Wieso while() ohne darin was zu tun?

Vielleicht kann mir jemand weiterhelfen, in jedem Fall vielen Dank!
Thomas

von Stefan B. (Gast)


Lesenswert?

Das Programm wartet - wie dokumentiert - an dieser Stelle, weil im 
Sendepuffer momentan kein weiterer Platz ist. Weiterer Platz wird erst 
geschaffen, wenn Zeichen von der UDRE Interruptroutine gesendet werden.

In deinem unbekannten Programm werden anscheinend von der UDRE 
Interruptroutine keine Zeichen gesendet. Das kann an einem Fehler im 
selbst geschriebenen Programmteil liegen, den wir nicht sehen. 
Möglicherweise die Fleury Library ist von dir nicht richtig 
initialisiert und/oder Interrupts sind noch nicht global aktiviert.

von Stefan E. (sternst)


Lesenswert?

Das wahrscheinlichste ist, dass an der Stelle die Interrupts nicht 
aktiviert sind, entweder weil sie explizit deaktiviert sind, oder 
implizit. Du versuchst nicht etwa innerhalb einer ISR was zu senden, 
oder?

von Thomas (Gast)


Lesenswert?

Hm gute Frage mit in einer ISR. Ich rufe aus einem Timer eine Funktion 
auf die dann was ausgeben will... das zählt dann wohl als aus einer ISR.

von Karl H. (kbuchegg)


Lesenswert?

In einer ISR werden grundsätzlich keine länger andauernden Operationen 
durchgeführt. Weder wird auf irgendetwas gewartet, noch macht man 
Ausgaben. Das ist eine einfache Regel, die nur dann zu Problemen führt, 
wenn man sie nicht beachtet.

von Thomas (Gast)


Lesenswert?

Naja drum hätte ich ja auch gerne ein paar Zeichen in den Ausgangspuffer 
geschrieben und fertig.

von Stefan E. (sternst)


Lesenswert?

Thomas schrieb:
> Naja drum hätte ich ja auch gerne ein paar Zeichen in den Ausgangspuffer
> geschrieben und fertig.

Das funktioniert aber nur, wenn auch entsprechend Platz im Puffer ist. 
Wenn kein Platz mehr ist, hast du den von dir beobachteten Deadlock.

von Thomas (Gast)


Lesenswert?

Ja danke euch beiden... Da muss ich wohl was umbauen.

von daniel (Gast)


Lesenswert?

mach doch so ...
1
uINT8 flags;
2
#define SHOULD_SEND    0
3
#define SHOULD_DO_XYZ  1
4
...
5
6
7
ISR(..._vect) {
8
    flags |= 1UL << SHOULD_SEND;
9
}
10
11
int main(void) {
12
    while(1) {
13
        if(flags & (1UL << SHOULD_SEND)) {
14
            flags &= ~(1UL << SHOULD_SEND);
15
            call_send_routine();
16
        }
17
        // ...
18
    }
19
}

von Simon K. (simon) Benutzerseite


Lesenswert?

Beim Löschen des Flags muss/müssen der/die Interrupt/s gesperrt werden. 
Man kann auch statt den Flags + Interrupts nur das Interruptflag 
abfragen in der main-loop (Aber dann die Interrupts deaktivieren).

von Thomas (Gast)


Lesenswert?

Ja ich habe in etwa die Lösung von Daniel umgesetzt.
Ich setzt nur noch Flags in der ISR für 10/100ms Tasks die dann in der 
Main abgearbeitet werden...

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.