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); }
> 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.
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?
Ich gebs auf, ich fange an Schwachsinn zu schreiben. Morgen wird weitergeforscht. Gute N8!
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
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?
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. --
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.
... 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. --
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.