Forum: Mikrocontroller und Digitale Elektronik Wer kann mir das einmal vorlesen? (geht schnell - hoffentlich)


von Stephan (Gast)


Lesenswert?

Hallo!
(Nachdem fälschlicherweise im falschen Forum gepostet- hier nochmal)

Der angehängte Programmmcode ist von Fleury und schon vielfach
angesprochen. Ich frage mich:
Wo zum Henker wird hier gesendet, sprich, das UDR- Register mit einem
Wert beschrieben?!
(Ergänzende Erklärung:  #define UART0_CONTROL  UCSR0B)

void uart_putc(unsigned char data)
{
    unsigned char tmphead;

    tmphead  = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;

    while ( tmphead == UART_TxTail ){
        ;/* wait for free space in buffer */
    }

    UART_TxBuf[tmphead] = data;
    UART_TxHead = tmphead;

    /* enable UDRE interrupt */
    UART0_CONTROL    |= _BV(UART0_UDRIE);

}

von g457 (Gast)


Lesenswert?

> Wo zum Henker wird hier gesendet

Gar nicht, hier wird nur gewartet bis in der Sendewarteschlange ein 
Platz frei ist. Schau Dir den..

> /* enable UDRE interrupt */
>  UART0_CONTROL    |= _BV(UART0_UDRIE);

UartDataRegisterEmpty-Interrupt an, der wo hier aktiviert wird. Ebendort 
wird dann wirklich gesendet.

von MN (Gast)


Lesenswert?

UART_TxBuf[tmphead] = data;

von Stephan (Gast)


Lesenswert?

MN schrieb:
> UART_TxBuf[tmphead] = data;

da wird leider nix gesendet.

Aber der Interrupt Tip war gut "da war doch was"!
Jene ISR von Fleury sieht aus wie folgt:
(Ergänzung:   #define UART0_TRANSMIT_INTERRUPT  USART1_RX_vect)

ISR(UART0_TRANSMIT_INTERRUPT)
{
    unsigned char tmptail;

    if ( UART_TxHead != UART_TxTail) {
        /* calculate and store new buffer index */
        tmptail = (UART_TxTail + 1) & UART_TX_BUFFER_MASK;
        UART_TxTail = tmptail;
        /* get one byte from buffer and write it to UART */
        UART0_DATA = UART_TxBuf[tmptail];  /* start transmission */
    }else{
        /* tx buffer empty, disable UDRE interrupt */
        UART0_CONTROL &= ~_BV(UART0_UDRIE);
    }
}

Kann es sein dass der vector falsch bezeichnet ist? Im datenblatt meines 
Atmega2560 ist dieser USART0_UDRE benannt. Macht dasn Unterschied?

von Stephan (Gast)


Lesenswert?

Ich gebs auf, ich fange an Schwachsinn zu schreiben.
Morgen wird weitergeforscht.
Gute N8!

von Stephan (Gast)


Lesenswert?

Habe ich bei Fleury etwa tatsächlich Unstimmigkeiten gefunden?


  #define UART0_RECEIVE_INTERRUPT   USART0_RX_vect
  #define UART1_RECEIVE_INTERRUPT   USART0_UDRE_vect
  #define UART0_TRANSMIT_INTERRUPT  USART1_RX_vect
  #define UART1_TRANSMIT_INTERRUPT  USART1_UDRE_vect

von Stephan (Gast)


Lesenswert?

Nachts um halb zwei führt man schonmal Selbstgespräche...

Nun, nachdem ich die Bezeichnungen der ISR umbenannt habe (sie sind auch 
an anderen Stellen der uart.c fehlerhaft) klappt alles.

Hab ich womöglich eine steinzeitliche Downloadquelle benutzt?

von Adib (Gast)


Lesenswert?

der Code enthält aber eine Gefährliche Stelle:

der Interrupt wird pauschal am Ende von putc freigegeben.

Zumindest das Setzen des neuen Buffer-index und das Freigeben des 
Interrupts sollten /müssen atomar sein.
Also um das ganze ein atomic block oder den Sende-Interrupt am Anfang 
sperren.

Adib.
--

von Peter II (Gast)


Lesenswert?

Adib schrieb:
> Zumindest das Setzen des neuen Buffer-index und das Freigeben des
> Interrupts sollten /müssen atomar sein.

warum? die ISR liest ihn nur, wenn er noch nicht gesetzt ist dann 
passiert auch nichts und die 8bit werden auch auf einmal gesetzt das 
gibt es keinen zwischenschritt.

von Adib (Gast)


Lesenswert?

... hmm, okay, hast recht.

Ich habe eine andere Implementierung und hatte mal das Problem, dass ich 
halt einen Bufferüberlauf bekam, und dann einen kompletten Buffer 
ausgegeben habe.

Hier testet die ISR das potentielle Problem und vermeidet den Überlauf:
    if ( UART_TxHead != UART_TxTail) {
In einem zusätzlichen (eigentlich unnötigen) ISR wird est der Interrupt 
gesperrt.

Adib.
--

von Hans Ulli K. (Gast)


Lesenswert?

Versuche es doch mal mit

strace -f $progname

da wird jeder Syscall mit seinen Parametern auf der Console ausgegeben.
Der Parameter -f ist für follow Forks.

von Karl H. (kbuchegg)


Lesenswert?

wenn elektromann keinen Einwand erhebt, dann lösche ich seinen Beitrag 
wieder.
Grund: Ich kann keinerlei Zusammenhang zum Thema dieses Threads 
erkennen.

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.