mikrocontroller.net

Forum: Compiler & IDEs GCC,AVR: uart-send in if UND else = fehler? (gcc-Anfänger)


Autor: Gregor Z. (greg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe ein grundlegendes Verständnis-Problem bzg. if/else und 
bedingtem uart-send eines Bytes.

Mein Programm nimmt MidiBytes über die uart in einen Ringbuffer und gibt 
sie im mainloop wieder aus bis der Buffer leer ist (=Vorstufe zu etwas 
Sinnvollem). Das funktioniert soweit theoretisch wie praktisch 
fehlerfrei. Das aktuell bearbeitete Byte wird an die uart ausgegeben:
uart_putc(RxByte);

Funktion dazu:
int uart_putc(unsigned char c) {
    while (!(UCSRA & (1<<UDRE))); // warten bis Senden moeglich    

    UDR = c;
    return 0;
}

Ich will nun die MidiBytes unterscheiden. Dazu dachte ich mir:
if (RxByte > 0x7F)
{
  uart_putc(RxByte);
} else {
  uart_putc(RxByte);
}

Erstaunlicherweise kommt damit NICHT MEHR das Richtige hinten raus (u.A. 
falsche Bytereihenfolge). Wenn ich dagegen Folgendes schreibe, dann 
KOMMT das Richtige hinten raus:
if (RxByte > 0x7F)
{ 
  // tu dies
} else {
  // tu das
}
  
uart_putc(RxByte);

Wird da etwas hin-/weg-optimiert (Optimierung ist ausgestellt)? Ich 
dachte, nicht erfuellte Bedingungszweige sind 'unsichtbar' für den 
Programmablauf? Kann es sein dass die Mainschleife SO schnell ist, dass 
sie das uart-senden überholt weil der ggf. warten muss bis frei ist?

danke für Erhellung,
Gregor

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hmmm. hört sich sehr seltsam an das...

hast du ein compilierbares Beispiel samt gcc-Schalter, so daß man das 
nachvollziehen kann? Ist RxByte vielleicht signed?

Johann

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> RxByte
Ist das ein signed oder unsigned char?

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Wird da etwas hin-/weg-optimiert (Optimierung ist ausgestellt)?

Bei -O0 wird nichts optimiert.

Mit Optimierung dürfte
if (RxByte > 0x7F)
{
  uart_putc(RxByte);
} else {
  uart_putc(RxByte);
}

auf eine Zeile geschrumpft werden:
  uart_putc(RxByte);

Aber:

Da das gezeigte nicht vollständiges Programm ist, und die 
Fehlerbeschreibung in der Art "geht nicht" bzw. "geht" völlig 
unverständlich ist, kann alles so oder auch ganz anders sein.

Bitte vollstädigen Code, mit verständlicher Problembeschreibung.

Oliver

Autor: Gregor Z. (greg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johann L. schrieb:
> hmmm. hört sich sehr seltsam an das...
>
> hast du ein compilierbares Beispiel samt gcc-Schalter, so daß man das
> nachvollziehen kann? Ist RxByte vielleicht signed?
>
> Johann

Ähem, was sind denn gcc-schalter? Ich schicke die Mididaten vom 
controller-TX in mein Midiinterface und schaue mir die Daten dann auf 
dem PC mit einem MidiMonitor an.

Autor: Gregor Z. (greg)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Oliver schrieb:

>
> Aber:
>
> Da das gezeigte nicht vollständiges Programm ist, und die
> Fehlerbeschreibung in der Art "geht nicht" bzw. "geht" völlig
> unverständlich ist, kann alles so oder auch ganz anders sein.
>
> Bitte vollstädigen Code, mit verständlicher Problembeschreibung.
>
> Oliver

Hm, ok. Ist angehaengt. Zur Problembeschreibung kann ich nicht viel mehr 
hinzufügen. Im einen Fall erscheinen die Mididaten die der Controller 
durchschleust korrekt (NoteOn, NoteOff, Controllerchange, alles exakt 
wie es in den Controller reingeht).

Im 'nicht funktionierenden Fall' sind sporadisch und zufällig Bytes 
vertauscht, statt NoteOn kommt NoteOff usw.

Autor: Gregor Z. (greg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lothar Miller schrieb:
>> RxByte
> Ist das ein signed oder unsigned char?

unsigned char

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du hast ein Semaphorenproblem.
Was passiert wohl, wenn gerade beim Auslesen aus dem Ringpuffer ein 
RX-Interrupt kommt?

Sperr mal beim Auslesen der Bytes aus dem Puffer die Interrupts.

Autor: Gregor Z. (greg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lothar Miller schrieb:
> Du hast ein Semaphorenproblem.
> Was passiert wohl, wenn gerade beim Auslesen aus dem Ringpuffer ein
> RX-Interrupt kommt?

Vermutlich kommt der Vektor durcheinander? Hm, ich hoffte darum kuemmert 
sich der Ringpuffer von selber. Aber klar, 'der Interrupt unterbricht 
das laufende Programm an der aktuellen Stelle' oder so ähnlich ... muss 
ja eigentlich Ärger geben.

> Sperr mal beim Auslesen der Bytes aus dem Puffer die Interrupts.

Ich habe zwar ordentlich das Tutorial über Interrupts durchgeackert. Es 
wurde mir daraus aber nicht ganz ersichtlich, was mit ankommenden Bytes 
bei deaktivierten Interrupts passiert. Die werden doch nicht 
hardwaregepuffert, oder? Und dann kann es doch passieren daß incoming 
Bytes verloren gehen oder nicht?

Da ich Interrupts hier offen habe, habe ich auf die Schnelle mal die 
simple 'nichtSoGut'-cli()/funktion/sei()-Variante getestet - keine 
Besserung.

vielen Dank schonmal
Gregor

Autor: Mark Brandis (markbrandis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gregor Z. schrieb:
> Ich will nun die MidiBytes unterscheiden. Dazu dachte ich mir:
>
> if (RxByte > 0x7F)
> {
>   uart_putc(RxByte);
> } else {
>   uart_putc(RxByte);
> }
> 

Diese bedingte Verzweigung erzeugt bei manchem bedingte Verzweiflung. 
;-)

Autor: Gregor Z. (greg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mark Brandis schrieb:
> Gregor Z. schrieb:
>> Ich will nun die MidiBytes unterscheiden. Dazu dachte ich mir:
>>
>> if (RxByte > 0x7F)
>> {
>>   uart_putc(RxByte);
>> } else {
>>   uart_putc(RxByte);
>> }
>> 
>
> Diese bedingte Verzweigung erzeugt bei manchem bedingte Verzweiflung.
> ;-)

kicher, ja, da sollte allerdings noch was sinnvolles hin. War nur ein 
Testkonstrukt zur Fehlersuche. Fehler finden sich aber leichter, wenn 
das Grundverständnis stimmt, und da fehlt mir noch so einiges.

<offtopic>
Hey 'Mark Brandis' ... das war doch dieser ScienceFiction 
Weltraum-Testpilot, Taurus-Zerstörer und so... mann, dass es Dich echt 
gibt ??? Musst aber ganz schön alt sein mittlerweile ;)
</offtopic>

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Hm, ich hoffte darum kuemmert sich der Ringpuffer von selber.
Allein die Hoffnung trägt uns weiter?  :-/

Probiers einfach so:
RB_Read(void)
{
//Assert(RB_Entries > 0);
uint8_t res
  cli();
  RB_Entries--;
  if (r > t) r = b;
  res = *r++;
  sei();
  return res;
}
Und nein, hier ist der Interrupt nicht lange genug gesperrt, das du ein 
Byte verlierst. Eines wird von der Hardware gepuffert.

Autor: Mark Brandis (markbrandis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gregor Z. schrieb:
> <offtopic>
> Hey 'Mark Brandis' ... das war doch dieser ScienceFiction
> Weltraum-Testpilot, Taurus-Zerstörer und so... mann, dass es Dich echt
> gibt ??? Musst aber ganz schön alt sein mittlerweile ;)
> </offtopic>

Hab die Bücher gelesen als ich noch jung war ;-)
Hehe, die müsste man sich eigentlich mal wieder aus der Bücherei 
ausleihen... good times. seufz

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.