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


von Philipp (Gast)


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

von Philipp (Gast)


Lesenswert?

Achso Optimierung ist auf size gestellt

von Rolf Magnus (Gast)


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?

von Philipp (Gast)


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

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Andere Frage: gibt es einen Vorteil es von Hand zu machen?

von Philipp (Gast)


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

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


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.

von Rolf Magnus (Gast)


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.

von Thorsten (Gast)


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();
}

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


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.

von Thorsten (Gast)


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

von Philipp (Gast)


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

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


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?).

von Thorsten (Gast)


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

von Patrick D. (oldbug) Benutzerseite


Lesenswert?

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

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


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.

von Patrick D. (oldbug) Benutzerseite


Lesenswert?

Das war mir bekannt, ich hatte das wohl irgendwie anders verstanden...

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.