Hallo,
ich bin gerade dabei den Basich code des I2C-Slaves für Attiny13 aus
elector in c unzuschreiben.
Da ich mit c in kombination mit assambler überhaupt keine Ahnung habe,
habe ich mit das tutorial auf roboternetz und das inline asm cookbook
angeschaut... und habe auch schon den ersten teil in c umgeschrieben:
Könntest du zumindest entweder
a) Markieren in welcher Zeile die Fehler auftreten (Dein Post hat keine
Zeilennummern ... ) oder
b) Kompilierbaren Code posten(=anhängen)
Ich frag mich gerade, ob Inline-Asm bei sowas so viele Vorteile hat,
dass sich der Ärger mit dem Inline-Asm lohnt ...
hth, Jörg
zu a) der Fehler wird bei "asm volatile(" angezeigt, und der Code ist
compilierbar (bis zu den Fehlern), wenn man ihn in eine einfache main-
Funktion gibt.... das weg gekürzte hat nichts zu bedeuten... deswegen
ist es ja gekürzt.... ;)
ich hab es nämlich auskommentiert beim kompilieren....
ich persönlich denke, dass der Fehler beim zuweisen der Variablen liegt,
ich habe nämlich nicht genau verstanden wie das funktionieren soll, und
einfach darauf los geraten(geschrieben)...
danke
mfg.
1) Hast du den Teil nicht in einer Funktion stehen?
Für inline Assembler gilt dasselbe, wie für jeden anderen C-Code
auch: Ausführbarer Code gehört in eine Funktion
2) Wenn du das schon von Assembler auf C übersetzt, warum machst du
das dann nicht gleich richtig, und schreibst equivalenten C-Code?
Da hast du mehr davon und kommst dann auch nicht dem Compiler mit
der Registerallokierung in die Quere
Das hier
"1: \n\t" //i2c_get = 1
"sbis %[_PINB],%[_SCL]\n\t" //wait for SCL&SDA=1
"rjmp 1b \n\t"
"sbis %[_PINB],%[_SDA] \n\t"
"rjmp 1b \n\t"
übersetzt sich schon fast von alleine zu
1
//wait for SCL&SDA=1
2
while(((PINB&(1<<SCL))==0)||
3
((PINB&(1<<SDA))==0))
4
;
und wird (mit eingeschalteter Optimierung) vom Compiler höchst
wahrscheinlich zu ziemlich genau derselben Sequenz übersetzt, die du
auch im Assembler hattest.
Die ganze von dir gezeigte Sequenz lautet in reinem C
1
unsignedchari2c_address=123,
2
i2c_b1=12,
3
i2c_b2=23,
4
i2c_stop=23;
5
unsignedcharadress;
6
7
unsignedcharcSCL=PB4,
8
cSDA=PB3,
9
cACK=cSDA;
10
11
//wait for SCL&SDA=1
12
while(((PINB&(1<<SCL))==0)||
13
((PINB&(1<<SDA))==0))
14
;
15
16
//wait for SCL=1,SDA=0 (START)
17
while(((PINB&(1<<SCL))==0)||
18
((PINB&(1<<SDA))!=0))
19
;
20
21
i2c_address=0;
22
i2c_b1=0;
23
i2c_b2=0;
24
i2c_stop=0;
und das hat dann schon eine ganz andere Code-Qualität, als da mit
Inline-Assembler rumzumachen. Und du bringst dem Compiler seine
Registerallokierung auch nicht durcheinander.
Hallo,
natürlich ist das alles in einer Funktion verpackt, aber das ist hier
belanglos.... die wichtigen Sachen habe ich gepostet....
natürlich könnte ich das alles auch in c schreiben, aber im beigelegten
Artikel in der elektro steht, dass der Autor sich entschieden hat die
wichtigen Funktionen in asm zu schreiben, da sie Zeitkritisch sein
könnten... seine Meinung... ich wollte daran mal nicht zweifeln und
damit ich sicher bin, dass es funktioniert wollte ich den code einfach
von inline basic in inline c umwandeln...
aber leider bekomme ich die oben genannten Fehler... und ich bin mir
ziemlich sicher, dass das daran liegt, wie ich die Variablen übergeben
muss, aber wie auch oben schon geschrieben habe ich davon keine Ahnung,
und die Tutorials sind auch keine große Hilfe
z.B.:
Auf bekannte globale Symbole kann man direkt von Assembler aus
zugreifen:
Um zu sehen, was im asm falsch läuft, übersetzt du mit der gcc-option
-save-temps.
Dann ist die s-Datei nicht temporär und wird gelöscht, sondern bleibt
erhalten.
"undefined reference" ist eine Fehlermeldung des Linkers, nicht des
Compilers. Also erzeugt der Compiler wohl den falsches Assembler-Code
(bzw. es wird per inline asm falscher Code eingefühgt. Für i2c_address
ist die Constraint "r", d.h. gcc wird ein GPR dafür allokieren, STS
erwartet jedoch ein Immediate (also eine Linkzeit-Konstante) als
Destination-Operand. Der Assembler erzeugt also zB ein Reloc für ein
Symbol namens "r18". Ein Objekt dieses Namens gibt's aber nicht, also
meckert der Linker.
Zudem ist hat der Inline Assembler andere Effekte auf die Maschine als
sie behauptet (zb auf r22). Dazu ein Zitat aus dem usenet:
> If you lie to the compiler, the compiler will get its revenge.> Abusing GCC's asms is certainly one way to hang yourself.
B. H. schrieb:
> muss, aber wie auch oben schon geschrieben habe ich davon keine Ahnung,> und die Tutorials sind auch keine große Hilfe> z.B.:> Auf bekannte globale Symbole kann man direkt von Assembler aus> zugreifen:>
1
>externinteinInt;
2
>
3
>asmvolatile(
4
>"lds %A0, einInt""\n\t"
5
>"lds %B0, einInt+1"
6
>:"=r"(...)
7
>);
8
>
> das funktioniert auch nicht und stammt von> http://www.roboternetz.de/wissen/index.php/Inline-Assembler_in_avr-gcc
klar geht das, aber ein zugehörenden Objekt muss auch irgendwo
angelegt werden bzw. ein entsprechendes Symbol definiert sein (etwa
per cmd-line).
Davon ab bist du -- wie Karl Heinz schon schrieb -- mit C portabler,
korrekt und nicht langsamer.
Das hier ist ein reines Angst-asm oder dient dazu, das Getane
geheimnisvoller erscheinen zu lassen.
Johann
Johann L. schrieb:
> Das hier ist ein reines Angst-asm oder dient dazu, das Getane> geheimnisvoller erscheinen zu lassen.
Kann auch sein, dass der Originalautor seinem Basic-Compiler (war wohl
BASCOM) nicht so recht über den Weg traute. Mit gcc ist das aber wohl in
90% aller Fälle unbegründet. Zur Not kann man immer noch den Assembler
Output des Compilers studieren (so es denn tatsächlich zu langsam sein
sollte) und dann im C-Source Hand anlegen um dem Compiler noch besseren
Code zu entlocken.
> aber im beigelegten> Artikel in der elektro steht, dass der Autor sich entschieden hat> die wichtigen Funktionen in asm zu schreiben, da sie Zeitkritisch> sein könnten
*******
... und wahrscheinlich hat ihm das sein Bauchgefühl gesagt und er hat
keinerlei Beleg, als sein Bauchgefühl, dass die Routinen in einer
Hochsprache nicht schnell genug wären.
Karl heinz Buchegger schrieb:
> Johann L. schrieb:>>> Das hier ist ein reines Angst-asm oder dient dazu, das Getane>> geheimnisvoller erscheinen zu lassen.>> Kann auch sein, dass der Originalautor seinem Basic-Compiler (war wohl> BASCOM) nicht so recht über den Weg traute. Mit gcc ist das aber wohl in> 90% aller Fälle unbegründet. Zur Not kann man immer noch den Assembler> Output des Compilers studieren (so es denn tatsächlich zu langsam sein> sollte) und dann im C-Source Hand anlegen um dem Compiler noch besseren> Code zu entlocken.
Jo, stimmt. Ich hab einmal mir BASCOM-Code angeschaut. Da müsste man
dann alles in Assembler schreiben aus Zeitgründen :o)
> ... und wahrscheinlich hat ihm das sein Bauchgefühl gesagt und er hat> keinerlei Beleg, als sein Bauchgefühl, dass die Routinen in einer> Hochsprache nicht schnell genug wären.
Assembler ist ja immer noch von dem Nimbus umgeben, schneller zu sein
als Hochsprachen bzw. als der Code, den Hochsprachen-Compiler erzeugen.
Für BASCOM ist das uneingeschränkt der Fall. Für GCC muss man manchmal
staunen, daß der Code besser ist als handgeschrieben. Vor allem dann,
wenn er Optimierungen sieht, die einem verborgen blieben, oder wenn
Cache und Pipelines im Spiel sind oder der Maschine die Register
ausgehen...
Johann
Wenn es dann doch bei Assembler bleibt, mach es wenigsten pur, nicht
inline. Schau dir als Beispiel die I²C-Routinen von Peter Fleury an. Da
ist zwar nur der Master implementiert, aber als Vorlage zur Kombination
von C und Assembler lässt sich das nutzen.
Oliver