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


von Gregor Z. (greg)


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:
1
uart_putc(RxByte);

Funktion dazu:
1
int uart_putc(unsigned char c) {
2
    while (!(UCSRA & (1<<UDRE))); // warten bis Senden moeglich    
3
4
    UDR = c;
5
    return 0;
6
}

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

Erstaunlicherweise kommt damit NICHT MEHR das Richtige hinten raus (u.A. 
falsche Bytereihenfolge). Wenn ich dagegen Folgendes schreibe, dann 
KOMMT das Richtige hinten raus:
1
if (RxByte > 0x7F)
2
{ 
3
  // tu dies
4
} else {
5
  // tu das
6
}
7
  
8
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

von Johann L. (gjlayde) Benutzerseite


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

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> RxByte
Ist das ein signed oder unsigned char?

von Oliver (Gast)


Lesenswert?

>Wird da etwas hin-/weg-optimiert (Optimierung ist ausgestellt)?

Bei -O0 wird nichts optimiert.

Mit Optimierung dürfte
1
if (RxByte > 0x7F)
2
{
3
  uart_putc(RxByte);
4
} else {
5
  uart_putc(RxByte);
6
}

auf eine Zeile geschrumpft werden:
1
  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

von Gregor Z. (greg)


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.

von Gregor Z. (greg)


Angehängte Dateien:

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.

von Gregor Z. (greg)


Lesenswert?

Lothar Miller schrieb:
>> RxByte
> Ist das ein signed oder unsigned char?

unsigned char

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


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.

von Gregor Z. (greg)


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

von Mark B. (markbrandis)


Lesenswert?

Gregor Z. schrieb:
> Ich will nun die MidiBytes unterscheiden. Dazu dachte ich mir:
>
1
> if (RxByte > 0x7F)
2
> {
3
>   uart_putc(RxByte);
4
> } else {
5
>   uart_putc(RxByte);
6
> }
7
>

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

von Gregor Z. (greg)


Lesenswert?

Mark Brandis schrieb:
> Gregor Z. schrieb:
>> Ich will nun die MidiBytes unterscheiden. Dazu dachte ich mir:
>>
1
>> if (RxByte > 0x7F)
2
>> {
3
>>   uart_putc(RxByte);
4
>> } else {
5
>>   uart_putc(RxByte);
6
>> }
7
>>
>
> 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>

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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

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

von Mark B. (markbrandis)


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

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.