www.mikrocontroller.net

Forum: Compiler & IDEs Werden 2 "|=" optimiert?


Autor: Philipp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

ich habe ein wenig mit dem EEPROM aus dem Mega8 gespielt. Lesen lief
dann endlich irgendwann (siehe Thread im anderem Forum), aber schreiben
wollte einfach nicht gehen.

Es müssen 2 Bits NACHEINANDER gesetzt werden. Der Code sah zunächst so
aus:

  EECR |= (1<<EEMWE);
  EECR |= (1<<EEWE);

dann hab ich mal versucht es so zu lösen:

  asm("sbi 0x1C, 2");
  asm("sbi 0x1C, 1");

und damit läuft es nun. Fasst der Compiler die beiden Befehle oben
zusammen und setzt die beiden Bits gleichzeitig?

Vielen Dank
Gruß Philipp

Autor: Philipp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achso Optimierung ist auf size gestellt

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Fasst der Compiler die beiden Befehle oben zusammen und setzt die
> beiden Bits gleichzeitig?

Nein. Die I/O-Register sind in der avr-libc als volatile deklariert,
d.h. jeder einzelne Zugriff, der im Quellcode steht, muß auch
tatsächlich durchgeführt werden.
Dein C-Code und die Assembler-Variante machen übrigens verschiedene
Dinge. Deine Bitwertigkeiten stimmen nicht.

Übrigens: Warum benutzt du nicht gleich die EEPROM-Funktionen der
avr-libc?

Autor: Philipp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wollte es gern zu Fuss machen mit dem EEPROM. Gibt es einen echten
Vorteil durch die libc?

Was ist denn der Unterschied zwischen C Variante und ASM?

(Beides übrigens aus dem Datenblatt) Mit der C Variante funktioniert es
leider nicht, mit dem ASM schon. Deshalb dachte ich das es evtl.
zusammengefasst wird.

EEMWE ist Bit 2 laut Datenblatt und im iom8.h auch als 2 definiert. Und
ich dachte set bit in register macht braucht dann als parameter auch bit
2?

Oder was meinst du als unterschied zwichen der C und er ASM version?

Vielen Dank
Gruß Philipp

Autor: Andreas Schwarz (andreas) (Admin) Benutzerseite Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andere Frage: gibt es einen Vorteil es von Hand zu machen?

Autor: Philipp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja. Man weiß ganz genau was der Controller tut, weiß wo welches Byte
liegt, kann es dadurch leicht über den ISP bearbeiten usw und man
bleibt näher an der Hardware, was ich nicht schlecht finde, weil ich ab
und zu gezwungen werde etwas mit ASM zu tun.

Und es ja nun wirklich nicht aufwendiger.

Gruß Philipp

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

Bewertung
0 lesenswert
nicht lesenswert
> Ja. Man weiß ganz genau was der Controller tut, weiß wo welches
> Byte liegt, kann es dadurch leicht über den ISP bearbeiten usw
> und man bleibt näher an der Hardware, was ich nicht schlecht
> finde, weil ich ab und zu gezwungen werde etwas mit ASM zu tun.

Dann solltest du alles in Assembler programmieren.

Du benutzt so viele Dinge aus der Bibliothek, aber ausgerechnet
die Dinge, bei denen es auf eine `timed sequence' ankommt, willst
du unbedingt zu Fuß schreiben, obwohl die Bibliothek dir dafür
eine fertige (und getestete) Implementierung liefert.  Das
widerspricht sich irgendwie.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> EEMWE ist Bit 2 laut Datenblatt und im iom8.h auch als 2
> definiert. Und ich dachte set bit in register macht braucht dann
> als parameter auch bit 2?

Hast recht. Ich habe Mist erzählt.

Autor: Thorsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

Ich hatte vor 6 Monaten das selbe Problem. Im Datenblatt steht, daß die
beiden Operationen in einem bestimten maximalen Abstand ( 4 Takte)
nacheinander stattfinden müssen.

Ich hab es zuerst mit dem Code aus der Atmel Appnote versucht, das ging
aber nicht. Der Grund ist der, daß es der GCC nicht schafft Code zu
kompilieren der in den 4 Takten ausgeführt wird. Darum funktionen die
Zugriffe nicht.

Ich habs damals so gelöst:

void write_config(void)
{
  uint8_t address = 0;
  uint8_t* source = (uint8_t*) &DataToBeWritten;
  uint8_t i;
  uint8_t eecr_t1;
  uint8_t eecr_t2;

  cli();

  for ( i = 0; i < sizeof(DataToBeWritten); i++)
  {
    // Wait for completion of previous write
    while(EECR & (1<<EEPE))
      ;

    // Set up address and Data Registers
    EEARH = 0;
    EEARL = address;
    EEDR = *source;

    // prepare values. needed since write has to be initiated within 4
clocks
    // doing other ways causes the compiler to compile too slow code
    eecr_t1 = EECR | 0b00000100;
    eecr_t2 = eecr_t1 | 0b00000010;

    EECR = eecr_t1;

    // Start eeprom write by setting EEPE
    EECR = eecr_t2;

    // write next byte to next address
    address++;
    source++;
  }

  sei();
}

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

Bewertung
0 lesenswert
nicht lesenswert
> Der Grund ist der, daß es der GCC nicht schafft Code zu
> kompilieren der in den 4 Takten ausgeführt wird.

Optimierung ausgeschaltet?

Anyway, derartige timed sequences sind ein wesentliches
Anwendungsfeld von inline asm, vorzugsweise in der
Bibliothek verpackt.  Damit ist man nämlich komplett
unabhängig von der Optimierung.

Genau das ist letztlich das, was die EEPROM-Bibliotheksroutinen
tun.

Autor: Thorsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

Nein. Im Gegenteil ich hab es mit mereren Optimierungsvarianten
versucht. Das ganze innerhalb von 4 Takten ging sich mit keiner
Variante aus.

Nachdem ich herausgefunden hatte warum das Schreiben nicht geht hab ich
mich dann aber auch nicht mehr lange mit dem Problem herumgeschlagen
sondern hab eben den workaround gemacht.

lg,
Thorsten

Autor: Philipp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab nun die Option -S entdeckt beim gcc ;)

also bei mir liefert

EECR |= (1<<EEMWE);
EECR |= (1<<EEWE);

exakt das gleiche in ASM wie

asm("sbi 0x1C, 2");
asm("sbi 0x1C, 1");

nochmal zur Lib:

Kann die auch große Daten IRQ gesteuert schreiben oder ist da diese
Warteschleife benutzt worden?

Vielen Dank
Gruß Philipp

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

Bewertung
0 lesenswert
nicht lesenswert
Thorsten:

Welche Appnote eigentlich?  AVR100 kommt nur mit Assemblercode.

Philipp:

> Kann die auch große Daten IRQ gesteuert schreiben oder ist da diese
> Warteschleife benutzt worden?

Nein, die Bibliothek macht das im polled mode.  Wenn du das via
Interrupt schreiben willst, musst du das wirklich selbst bauen
(oder mal im Internet gucken, vielleicht hat ja AVRlib schon was
dafür?).

Autor: Thorsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Philipp

Da hast du mir etwas voraus :-) Ich hatte die Option nicht entdeckt.
Ich geb aber auch zu, daß ich mit den diversen Compileroptionen - egal
bei welcher Umgebung und für welches BS - seit eh und je etwas auf
Kriegsfuß stehe.

"-S
    Stop after the stage of compilation proper; do not assemble."

In welcher Weise löst das das Problem?



@Jörg

Appnote triffts wohl nicht zu 100% Ich hatte es dem Datenblatt des AVR
den ich damals verwendet hab entnommen. Welcher das war kann ich aber
im Augenblick nicht sagen da ich momentan nicht an den PC komme.

Wenn ich nicht irre habe ich den Code aufgehoben. Sollte es von
Interesse sein schau ich zu Hause auch gern nach was der der GCC
ursprünglich gemacht hat.


lg,
Thorsten

Autor: Patrick Dohmen (oldbug) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich denke, er meint '-Os' für die Optimierung auf Speichergröße
(size)...

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

Bewertung
0 lesenswert
nicht lesenswert
> Appnote triffts wohl nicht zu 100% Ich hatte es dem Datenblatt des
> AVR den ich damals verwendet hab entnommen. Welcher das war kann ich
> aber im Augenblick nicht sagen da ich momentan nicht an den PC
> komme.

Ich habe mir eben den Code aus dem Datenblatt für den ATmega1281
genommen und ihn durch den GCC geschickt.  Mit -Os generieren mir
daraus sowohl GCC 3.4.6 als auch 4.1.0 gleichlautend:

EEPROM_write:
.L3:
        sbic 63-0x20,1
        rjmp .L3
        out (65)+1-0x20,r25
        out 65-0x20,r24
        out 64-0x20,r22
        sbi 63-0x20,2
        sbi 63-0x20,1
        ret

> Ich denke, er meint '-Os' für die Optimierung auf Speichergröße
> (size)...

Nö, mit -S kann man sich den generierten Assemblercode ansehen.  Das
ist das, was ich hier auch zitiert habe.  Ist für meine Begriffe
oftmals übersichtlicher als die Disassembler-Ausgabe.

Autor: Patrick Dohmen (oldbug) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das war mir bekannt, ich hatte das wohl irgendwie anders verstanden...

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.