Forum: Compiler & IDEs inline Assembler "NOP" wird wegoptimiert in I2C-Routine


von Christian S. (roehrenvorheizer)


Angehängte Dateien:

Lesenswert?

Hallo,

mein Ziel war es, mit AVR-GCC (AVR Studio 4.18.684) ein Programm zu 
schreiben, mit dem ein 24C08 EEPROm am I2C-Bus angesteuert werden kann
und zwar nicht über das TWI-Interface, sondern nur über zwei Pins, damit 
es mit "allen" AVR-Typen funktioniert.

Übertragen eines Bytes klappt bereits, nur das Aufnehmen des 
Acknowledge-Bits bringt bereits Probleme mit sich, weil die NOP-Befehle
überhaupt nicht im Assembler-Listing auftauchen und das in allen 
Optimierungsstufen. In ASM prorammiert würde es wahrscheinlich schon
funktionieren:-)

Nach Übertragung der korrekten Adresse (und nur dann) war auf dem 
Oszilloskop nach dem 8. Bit eine fallende Flanke zu sehen, die dann in 
eine waagrechte Linie auf halber Betriebsspannung über ging. Vermutlich 
das Acknowledge vom EEPROM, das gegen den Ausgangs-Pin ankämpft, der auf 
higt liegt.

Nachlesen half auch nichts, deshalb hier meine Frage:

Wie kann ich verhindern, daß die NOP-Befehle wegoptimiert werden, bzw 
wie kann ich die Zeitverzögerungen ohne _delay_us() bewirken?

Oder werde ich die NOPs in die hex-Datei manuell eintragen???

MfG

von Christian S. (roehrenvorheizer)


Lesenswert?

higt soll "high" heißen

von Amateur (Gast)


Lesenswert?

>Oder werde ich die NOPs in die hex-Datei manuell eintragen???

Der originale Code enthält ja auch Sprungmarken. Wenn Du da etwas 
dazwischen Bappst ist das Ergebnis bestenfalls lustig und nur mit Glück 
lauffähig. Vor allem, wenn da noch if's rumhängen.

von Klaus (Gast)


Lesenswert?

Christian S. schrieb:
> Vermutlich
> das Acknowledge vom EEPROM, das gegen den Ausgangs-Pin ankämpft, der auf
> higt liegt.

Das kann nicht sein, I2C geht über Open Collector Treiber. Die dazu 
gehörenden Pullups erzeugen das High und Low gewinnt immer.

MfG Klaus

von Stefan E. (sternst)


Lesenswert?

Christian S. schrieb:
> überhaupt nicht im Assembler-Listing auftauchen und das in allen
> Optimierungsstufen.
1
 23c:  2f 98         cbi  0x05, 7  ; 5
2
  ...
3
asm volatile ("nop");
4
asm volatile ("nop");
5
asm volatile ("nop");
6
7
8
if( bitfolge & ( 1 << x ) )
9
 246:  ca 01         movw  r24, r20
Achte auf die Adressen. Die ... sind deine NOPs.

von Timmo H. (masterfx)


Lesenswert?

Die Nops sind schon da. Sobald du mehr als 4 nops drin hast werden die 
im list-File als "..." angezeigt.

von Stefan E. (sternst)


Lesenswert?

Nachtrag:
Wenn du die NOPs im Listing sehen willst, dann füge dem objcopy-Aufruf 
ein -z hinzu.

von Christian S. (roehrenvorheizer)


Lesenswert?

Achso, die NOPs verstecken sich hinter dem "..." ! Gut zu wissen. Aus 
dem Sprung der fortlaufenden Adressen konnte ich mir keinen Reim machen. 
Ich dachte, da müßte eine Adresse mit NOP nebendran stehen.

Ein als Ausgang geschalteter AVR-Pin ist aber kein 
open-collector-Treiber. Und das Umschalten klappt noch nicht zeitgenau 
passend. Deshalb meine Vermutung mit dem "Kurzschluß".

Trifft das mit den durchaus vorhandenen NOPs auch hier zu (236-238)?
Ausgang_DDR |= (1<<Ausgang_SDA) | (1<<Ausgang_SCL);    //Portpins auf 
Ausgang schalten
 22e:  94 b1         in  r25, 0x04  ; 4
 230:  90 6c         ori  r25, 0xC0  ; 192
 232:  94 b9         out  0x04, r25  ; 4
 234:  27 e0         ldi  r18, 0x07  ; 7
 236:  30 e0         ldi  r19, 0x00  ; 0
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");


if( bitfolge & ( 1 << x ) )
 238:  48 2f         mov  r20, r24
 23a:  50 e0         ldi  r21, 0x00  ; 0

von Stefan E. (sternst)


Lesenswert?

Christian S. schrieb:
> Trifft das mit den durchaus vorhandenen NOPs auch hier zu (236-238)?

Da sind keine NOPs, auch im Sourcecode nicht. Da ist nur das 
"Source-Einmischen" etwas durcheinander geraten.

Du hast im Source drei NOP-Blöcke, und im Listing auch.

von Christian S. (roehrenvorheizer)


Lesenswert?

file:///C:/WinAVR-20100110/doc/gcc/HTML/gcc-4.3.2/gcc/Link-Options.html# 
Link-Options

-z gibt es bei der von mir verwendeten Version anscheinend nicht.

OK, danke für's Helfen. Anscheinend werde ich "betriebsblind".

von Stefan E. (sternst)


Lesenswert?

Christian S. schrieb:
> file:///C:/WinAVR-20100110/doc/gcc/HTML/gcc-4.3.2/gcc/Link-Options.html#
> Link-Options
>
> -z gibt es bei der von mir verwendeten Version anscheinend nicht.

Was soll das Link-Options mit objcopy zu tun haben?

Ok, ich habe mich allerdings auch vertan. ;-)
Es geht natürlich um objdump, nicht objcopy.

https://sourceware.org/binutils/docs-2.23.1/binutils/objdump.html

von Christian S. (roehrenvorheizer)


Lesenswert?

So einer bin ich dann also, wenn ich das -z benutze:

This information is mostly useful to programmers who are working on the 
compilation tools, as opposed to programmers who just want their program 
to compile and work.

Ich bin also keiner, der nur kompilieren und arbeiten möchte :-)Wäre 
langweilig.

--disassemble-zeroes
Normally the disassembly output will skip blocks of zeroes. This option 
directs the disassembler to disassemble those blocks, just like any 
other data.

Wieder etwas gelernt.

Dort im Makefile müßte man das -z wohl noch hinzu fügen:
%.lss: $(TARGET)
  avr-objdump -h -S $< > $@


MfG

von Christian S. (roehrenvorheizer)



Lesenswert?

Für die Experimentatoren mal hier per Webinterface die Bildschirmfotos 
zum Anschauen:

oben SDA, unten SCL, alle drei Datenpakete auf dem Schirm, beide Signale 
ineinander geschoben,
erster, zweiter und dritter Acknowledge-Puls mit 10-fach Dehnung 
aufgenommen

device code A0, adress C3, data 07,      EEPROM 24C08 an 5 Volt

Leider etwas dunkle Fotos, nur wollte ich nicht länger mit der Kamera 
hantieren.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Stefan Ernst schrieb:
> asm volatile ("nop");
> asm volatile ("nop");
> asm volatile ("nop");

Wobei das "volatile" hier redundant ist, denn inline asm ohne Argumente 
ist implizit immer volatile.

Da NOP als 0x0000 codiert wird, wird es im disassemble jedoch nicht 
angezeigt, es sei denn man ruft objdump mit -z aka. --disassemble-zeroes 
auf.

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.