Forum: Mikrocontroller und Digitale Elektronik Optimierungsproblem UART


von Pascal E. (nimmzwei)


Lesenswert?

Hallo Gemeinde,

mit folgender Funktion möchte ich ein Array über UART senden:
1
void sendRS232(volatile uint8_t data[2000], volatile uint16_t DataLenght)
2
{
3
  for (volatile uint16_t i = 0; i < DataLenght;i++)
4
  {
5
    UDR1 = data[i];
6
    while ((UCSR1A & (1<<TXC1)) == 0)
7
    {
8
      
9
    }
10
  }
11
    
12
}

nun, da es auch vorkommt, dass zwei Bytes nacheinander 0xFF als Wert 
haben, wird die for-Schleife nicht ausgeführt, wenn dies eintrifft.

Wenn ich das Ganze debugge, wird die Schleife richtig ausgeführt.

Beispiel:

Array = {0xAB, 0xFF, 0xFF, 0xFF}
DataLenght = 3

Wie kann ich dem Compiler mitteilen, dass er da nicht optimieren soll, 
ohne die Optimierung auf -none zu stellen.

Besten Dank

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Pascal E. schrieb:
> nun, da es auch vorkommt, dass zwei Bytes nacheinander 0xFF als Wert
> haben, wird die for-Schleife nicht ausgeführt, wenn dies eintrifft.

Warum sollte dies so sein?

Btw., man testet besser auf UDRE als auf TXE.  Ab dem Zeitpunkt, da
UDRE auf 1 steht, kann man das nächste Byte in den Puffer schreiben.
Auf diese Weise erreicht man eine echte Zeichen-an-Zeichen-Übertragung.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Pascal E. schrieb:
> nun, da es auch vorkommt, dass zwei Bytes nacheinander 0xFF als Wert
> haben, wird die for-Schleife nicht ausgeführt, wenn dies eintrifft.

Wieso sollte das so sein?




> Array = {0xAB, 0xFF, 0xFF, 0xFF}
> DataLenght = 3

Da stehen vier Bytes, Du lässt aber nur drei ausgeben.

Was denn nun?




(Übrigens schreibt man length nicht "lenght")

von Pascal E. (nimmzwei)


Lesenswert?

Jörg Wunsch schrieb:
> Pascal E. schrieb:
>> nun, da es auch vorkommt, dass zwei Bytes nacheinander 0xFF als Wert
>> haben, wird die for-Schleife nicht ausgeführt, wenn dies eintrifft.
>
> Warum sollte dies so sein?
>
> Btw., man testet besser auf UDRE als auf TXE.  Ab dem Zeitpunkt, da
> UDRE auf 1 steht, kann man das nächste Byte in den Puffer schreiben.
> Auf diese Weise erreicht man eine echte Zeichen-an-Zeichen-Übertragung.

Der Test auf UDRE war das ausschlaggebende Problem.

Danke dir für die schnelle Hilfe!

von Falk B. (falk)


Lesenswert?

>  for (volatile uint16_t i = 0; i < DataLenght;i++)

volatile ist hier vollkommen unsinnig. Siehe Interrupt.

von Karl H. (kbuchegg)


Lesenswert?

> mit folgender Funktion möchte ich ein Array über UART senden:
>
1
> void sendRS232(volatile uint8_t data[2000], volatile uint16_t DataLenght)
2
> {
3
>   for (volatile uint16_t i = 0; i < DataLenght;i++)
4
>   {
5
>     UDR1 = data[i];
6
>     while ((UCSR1A & (1<<TXC1)) == 0)
7
>     {
8
>       
9
>     }
10
>   }
11
>     
12
> }
13
>

Üblicherweise hat man auch eine Funktion zur Verfügung, die ein 
einzelnes Byte per UART verschickt. Diese Funktion ist sozusagen der 
einfachst mögliche Baustein, auf dem man andere Dinge aufbauen kann. 
Deine Funktion sollte dann eigentlich so aussehen
1
void sendRS232( uint8_t data[], uint16_t DataLenght )
2
{
3
  for (uint16_t i = 0; i < DataLenght; i++)
4
  {
5
    sendRS232Byte( data[i] );
6
  }
7
}
... denn warum soll sich die Array Funktion damit rumschlagen, wie man 
korrekt ein einzelnes Byte verschickt? Dafür gibt es eine Funktion, die 
das weiß. Und wenn die erst mal korrekt ist, dann ist damit (zumindest 
in diesem Teil) auch das versenden eines ganzen Arrays oder das 
versenden eines Strings oder das versenden eines int oder das Versenden 
eines long automatisch insofern korrekt, dass die Einzelbytes korrekt 
über die UART abgewickelt werden.

von Cyblord -. (cyblord)


Lesenswert?

Falk Brunner schrieb:
>>  for (volatile uint16_t i = 0; i < DataLenght;i++)
>
> volatile ist hier vollkommen unsinnig. Siehe Interrupt.

Was erwartest du? Wenn das Programm nicht tut weil man auf das völlig 
Flag testet dann wird gleich mal direkt der Compiler und dessen 
Optimierung als Problem "erkannt". Das sagt mir schon alles. Noch 
schnell ein paar unsinnige volatile eingestreut, so programmiert man per 
try&error.

gruß cyblord

von Pascal E. (nimmzwei)


Lesenswert?

cyblord ---- schrieb:
> Falk Brunner schrieb:
>>>  for (volatile uint16_t i = 0; i < DataLenght;i++)
>>
>> volatile ist hier vollkommen unsinnig. Siehe Interrupt.
>
> Was erwartest du? Wenn das Programm nicht tut weil man auf das völlig
> Flag testet dann wird gleich mal direkt der Compiler und dessen
> Optimierung als Problem "erkannt". Das sagt mir schon alles. Noch
> schnell ein paar unsinnige volatile eingestreut, so programmiert man per
> try&error.
>
> gruß cyblord

Naja, nicht jeder ist mit der Materie so gut vertraut wie du. Solange es 
einen Lerneffekt gibt, bin ich auf gutem Weg :-)

Ja, ein wenig voreilig über den Compiler gelästert. Wenn man vor lauter 
Bäume den Wald nicht mehr sieht, probiert man halt mal was aus.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Pascal E. schrieb:
> Ja, ein wenig voreilig über den Compiler gelästert. Wenn man vor lauter
> Bäume den Wald nicht mehr sieht, probiert man halt mal was aus.

Solange du das hinterher wieder rauswirfst, ist das sicher OK.  Hat
als Nebeneffekt, dass man die Variable i auf diese Weise im Debugger
auch wirklich beobachtbar bekommt.  Normalerweise würde der Compiler
sie ja nur in einem Registerpaar halten, und je nach Qualität des
benutzten Debuggers und Debugging-Formats ist sie für den Debugger
dann wegoptimiert.  (Moderne Debugging-Formate können dem Debugger
allerdings auch vorübergehend in Registern abgebildete Variablen
mitteilen.)

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.