Wer kann mir das einmal vorlesen? (geht schnell - hoffentlich)

Gast #2981721
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);

}
Gast #2981723
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.
Gast #2981727
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?
Gast #2981735
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
Gast #2981737
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?
Gast #2982559
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.
--
Gast #2982568
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.
Gast #2982665
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.
--

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren