www.mikrocontroller.net

Forum: Compiler & IDEs Optimierungsproblem


Autor: Steffen Graap (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Für einen Bootloader benutze ich die folgenden Zeilen
volatile register UINT8_t R0 asm("r0");
volatile register UINT8_t R1 asm("r1");
volatile register UINT8_t R30 asm("r30");
volatile register UINT8_t R31 asm("r31");
volatile UINT16_t u16Buffercount;

for (u16Buffercount = 0 ; u16Buffercount < PAGE_BYTE ; u16Buffercount += 2)
  {              //solange ausführen, bis alle Bytes der Page beschriebn wurden
  R0 = u8Com_RX_Buffer[u16Buffercount];
  R1 = u8Com_RX_Buffer[u16Buffercount + 1]; //Daten aus Puffer in R0 & R1 laden
  R30 = (UINT8) u16Buffercount; //Wordadresse in Z-Pointer laden
  while (SPMCSR & 1);      //warten, das letzte spm beendet
  SPMCSR = 1;          //Pagepuffer schreiben vorbereiten
  asm volatile ("spm");    //Pagepuffer schreiben ausführen
  }
Da Register R30 für den Compiler anscheinend in der Schleife nicht 
benutzt wird, wird erst nach Beendigung der Schleife in R30 ein Wert 
gelanden.
Was mache ich falsch, oder was muss ich machen???

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Steffen Graap wrote:

[Ist offenbar AVR]

>
> volatile register UINT8_t R0 asm("r0");
> volatile register UINT8_t R1 asm("r1");
> volatile register UINT8_t R30 asm("r30");
> volatile register UINT8_t R31 asm("r31");
> 

Don't do it.  All diese Register sind tabu für dich.

Du darfst r2 bis r7 (glaub' ich) relativ gefahrlos benutzen,
die Register ab r8 noch zusätzlich, falls du keine Funktionen
mit großen Argumentlisten benutzt.

r0, r1 und der Z-Zeiger ,,gehören'' dem Compiler.

Autor: Steffen Graap (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
genau ist AVR (GCC über eclipse)

die Register brauch man für den "spm"-Aufruf. in R0 & R1 steht das 
Datenword das in den FLASH-Page-Puffer geschrieben werden soll. In R30 
steht die Wordadresse innerhalb des FLASH-Page-Puffer. Das ist ja gerade 
mein Problem das man unbedingt diese Regiter benutzen muss.

Für R30 & R31 hat mich der Compiler mit folgender Warnmeldung auf die 
Nutzung der Register aufmerksamm gemacht. (call-clobbered register used 
for global register variable)

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schon mal einen Blick in <avr/boot.h> riskiert?

Autor: Steffen Graap (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist ja zu einfach, könnte aber funktionieren. Ich werd mich mal 
daran versuchen. Bin halt von meinem letzten Compiler (CodeVision) von 
den mitgelieferten Funktionen nicht so beeindruckt, das ich das meiste 
selbst geschrieben habe. Ich muss mich jetz bei eclips/GCC erst mal 
daran gewöhnen, das es für fast alles fertige Funktionen gibt.

Auch wenn das Problem gelöst ist, aber die Frage bleibt weiter, wie 
bekomme ich den Compiler überzeugt, die Codezeile innerhalb der Schleife 
nicht rauszuoptimiern. (theorethisch, versteht sich)

Danke Steffen

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Steffen Graap wrote:

> Auch wenn das Problem gelöst ist, aber die Frage bleibt weiter, wie
> bekomme ich den Compiler überzeugt, die Codezeile innerhalb der Schleife
> nicht rauszuoptimiern. (theorethisch, versteht sich)

Du kannst mit einer fehlerhaften Eingabe nicht erwarten, dass der
Compiler anschließend das tut, was du dir vorstellst.

Die korrekte Lösung für dieses Problem ist halt ein Stückchen
inline-Assembler-Code, und genau das hast du ja in <avr/boot.h>
bereits vorgefertigt drin.

Autor: Steffen Graap (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Lösung für dieses Problem ist natürlich die Verwendung der boot.h. 
Ist ja auch der einfachste Weg.

ABER:
Lass uns an diesem Beispiel das Problem trotzdem lösen.
Wenn ich eine fehlerhafte Eingabe gemacht habe, was meines Wissens nicht 
so ist, wo ist dann der Fehler, schließlich soll man ja aus seinen 
Fehlern lernen.
Prinzipiell funktioniert der oben stehende Code ja auch. Wenn ich den 
Code wie unten stehend abändern würde, würde der Compiler die Verwendung 
von R30 erkennen und in jedem Schleifendurchlauf R30 laden. Allerdings 
füge ich nicht gerne Code ein, der eigentlich nicht benutz wird
#define EXT_RAM  (* (UINT8 volatile *) 0x2000)
for (u16Buffercount = 0 ; u16Buffercount < PAGE_BYTE ; u16Buffercount += 2)
  {              //solange ausführen, bis alle Bytes der Page beschriebn wurden
  R0 = u8Com_RX_Buffer[u16Buffercount];
  R1 = u8Com_RX_Buffer[u16Buffercount + 1]; //Daten aus Puffer in R0 & R1 laden
  R30 = (UINT8) u16Buffercount; //Wordadresse in Z-Pointer laden
  EXT_RAM = R30;           //R30 zum schein in den ext. Ram schreiebn
  while (SPMCSR & 1);      //warten, das letzte spm beendet
  SPMCSR = 1;          //Pagepuffer schreiben vorbereiten
  asm volatile ("spm");    //Pagepuffer schreiben ausführen
  }
Es muss doch eine bessere Lösung geben, um den Compiler von der 
Benutzung des Registers zu überzeugen.

Gruß Steffen

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aliases für vom Compiler implizit verwendete Register sind nun einmal 
ein Tabu. Jede neue Version des Compilers kann dir diesen schön zurecht 
getrimmten Code über den Haufen schmeissen.

Wenn sowas gemacht werden muss, dann mit asm() Statements. Die sind 
sauber definiert und da darf man diese Register verwenden, wenn man 
bestimmte Regeln einhält. Genau so und nicht anders ist deshalb 
avr/boot.h implementiert.

Autor: Steffen Graap (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann ist also der Fehler die Benutzung der Aliasse.

Den Tip mit den Aliassen habe ich von hier:
http://www.nongnu.org/avr-libc/user-manual/FAQ.htm...

Eine Frage zu der boot.h
In den Funktionen boot_page_erase() & boot_page_fill() wird eine 16bit 
Adresse benutzt. Beim ATMEGA256 benötige ich aber insgesammt eine 18bit 
Adresse. Wie nutze ich nun diese 16 bit Adresse?
bei boot_page_erase() entsprechen die 16 Bit nur der Pageadresse?
bei boot_page_fill() entsprechen die 16 Bit der Wordadress im 
Pagebuffer?

Gruß Steffen

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Steffen Graap wrote:

> Dann ist also der Fehler die Benutzung der Aliasse.

Ja. Nämlich derjeniger, die man nicht verwenden darf.

> Den Tip mit den Aliassen habe ich von hier:

Da steht aber auch: "Typically, it should be save to use r2 through r7 
that way.". Und das ist zwar orthografisch falsch, inhaltlich sollte man 
sich daran aber halten. Weil es umgekehrt bedeutet, dass die Verwendung 
der anderen Register höchst unsicher ist.

> In den Funktionen boot_page_erase() & boot_page_fill() wird eine 16bit
> Adresse benutzt. Beim ATMEGA256 benötige ich aber insgesammt eine 18bit
> Adresse. Wie nutze ich nun diese 16 bit Adresse?

Ich habe das Include-File grad nicht zu Hand, aber von der Doku her den 
Eindruck, dass die Breite der Adresse abhängig vom Prozessortyp ist. 
Steht nicht ausdrücklich in der Doku drin, aber schau mal ins File rein.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Kaiser wrote:

> Da steht aber auch: "Typically, it should be save to use r2 through r7
> that way.". Und das ist zwar orthografisch falsch, inhaltlich sollte man
> sich daran aber halten.

Was ist daran ortografisch falsch?

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jörg Wunsch wrote:

> Was ist daran ortografisch falsch?

OK, gesehen. ;-)

...und repariert.  Danke.

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.