Versuche ich das SPI Dataregister (SPDR) in einer Funktion zu beschreiben, ohne es vorher in der main() einmal beschrieben zu haben, wird nichts auf den SPI Leitungen ausgegeben. Habe ich schon bei 2 Programmen feststellen können. Weiß jemand näheres dazu?
Gast
#285606
Poste mal den Code der Initialsiserung und der Ausgabe aufs SPDR Register.
Gast
#285607
Was issn mit SPSR, Bit SPIF/WCOL (Mega 128 datasheet S.168), wartest Du drauf, setzt Du zurück, Fragen über Fragen. Aber Compilerbug, nee! Cheers Detlef
Was? wo? nix Interrupt Flag ! Hier mal der Code:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
Ohne dem SPDR = 0xFF in der Main klappt garnix am SPI.
Auf SPIF kannst du erst warten, wenn du etwas auf SPDR ausgegeben hast, ansonsten ist es eifach erstmal noch nicht gesetzt.
müsste ich das while vor dem SPDR in der Funktion einfach weglassen? ;)
Ja, es gehört nach der Ausgabe auf das SPDR hin (es sei denn, man ist sich sicher, dass bis zur nächsten Ausgabe nach SPDR sowieso genug Zeit vergeht, dass alle Daten rausgeschoben sind).
Ich schreibe beim Init des SPI einmal auf SPDR: SPDR = 0; // Dummy-Write, damit SPIF gesetzt wird Dadurch kann ich VOR dem SPI-Transfer fragen und spare mir damit (ein kleines bischen) Zeit. Übrigens: Schreibst Du gcc-Bug nur in den Titel, damit es mehr lesen, oder hast Du das wirklich geglaubt? Ist wohl nicht Dein Ernst, dass eine so offensichtliche Sache ein Compiler-Bug sein könnte? Gruß, Stefan
Gast
#285613
Hi, SPIF wird laut datasheet durch Lesen von SPSR gelöscht. Vermutung: Schreiben auf SPDR scheint nicht zu gehen, wenn SPIF gesetzt ist, deswegen dummy-read auf SPSR, selbst wenn man sicher ist, daß das Byte draussen ist. Nachdem ich das gemacht habe, gings bei mir, habe aber nich genauer draufgekuckt. Cheers Detlef
Gast
#285614
>Vermutung: Schreiben auf SPDR scheint nicht zu gehen, wenn SPIF gesetzt
ist
Das stimmt teilweise:
Wenn man einen Wert in SPDR schreibt, während ein Transfer läuft, wird
der neue Wert ignoriert. Ob das SPIF gesetzt oder gelöscht ist spielt
dabei aber keine Rolle. Ein dummy Read ist nicht notwendig.
Noch was interessantes:
Wie lange dauert es bis man neue Daten in SPDR schreiben kann, wenn der
Takt auf fclk/2 eingestellt ist ?
Theoretisch 16 CPU Takte.
In der Praxis sind es aber 18, ansonsten funktioniert es nicht. Keine
Ahnung warum, aber es ist so.
Gast
#285615
In der Regel benötigen SPI-ICs auf /CS eine 1-0-Flanke nach Ende des Datentransfers. Es bringt also überhaupt nichts, vor dem Transfer auf das Ende des letzten Transfers zu testen. Daher einfach das Datenbyte ab in den Puffer und dann warten, bis es raus ist. Peter
Ich bin eigentlich der Ansicht das AVRGCC nicht mehr betreut wird. was weiß ich ob da nen bug drin ist oder nicht. @peter: ahoa, gut zu wissen. ich prüfe das mal bei meinem chip. @alle: danke, weiß jetzt bescheid! (danke frau rieger ;))
> Ich bin eigentlich der Ansicht das AVRGCC nicht mehr betreut wird.
Was bringt dich zu dieser Ansicht?
verwundert guck
Hab so den Eindruck, dass das unter die Räder gekommen ist. Wenn ich schon den "Bug" (ist wohl eher kein feature?), dass als return wert immer INT genommen wird, auch wenn man nur char brauch. Seh ich ehrlich gesagt keinen Sinn drin Aber ich kann mich auch täuschen ;)
> Wenn ich schon den "Bug" (ist wohl eher kein feature?), dass als > return wert immer INT genommen wird, auch wenn man nur char brauch. Ist ein Feature. Soll die Benutzung von MOVW vereinfachen. So haben sich das Marek Michalkiewicz und Denis Chertykov zumindest mal gedacht. Da es dieser Art Bestandteil des ABIs geworden ist, dürfte es ziemlich schwierig sein, dieses Feature wieder los zu werden.
Gast
#285620
@Simon, ja, der AVR-GCC ist sehr 16bit lastig. Wenns nur der Returnwert währe, ginge es ja noch. Aber bei zusammengesetzten Ausdrücken erweitert er oft erstmal schön umständlich alle Operanden auf 16Bit, rechnet 16Bit und schmeißt dann das High-Byte wieder weg. Selbst wenn man jeden einzelnen Ausdruck nach (unsigned char) castet, läßt ihn das völlig kalt. Erst wenn man eine Dummy-Variable nimmt, der man immer wieder die Zwischenergebnisse zuweist, bequemt er sich zu 8-bittigem Rechen. Bloß dann sieht die Source völlig unübersichtlich aus. Ich vermute mal diese 16Bit-Umständlichkeit ist ein Zugeständnis an kommerzielle Compilerhersteller, damit die ihre Produkte loswerden können. Denn darin liegt mit Abstand das größte Potential, um Code zu sparen und schneller zu sein. Daher wird sich daran wohl auch in zukünftigen Versionen des AVR-GCC leider nichts ändern. Peter
Na super, naja dafür ists Freeware. Was sind denn gute Compiler die sowas nicht machen und mindestens genausogut zu bedienen sind wie ein AVR-GCC ? ;)
> Ich vermute mal diese 16Bit-Umständlichkeit ist ein Zugeständnis an > kommerzielle Compilerhersteller, damit die ihre Produkte loswerden > können. > Daher wird sich daran wohl auch in zukünftigen Versionen des AVR-GCC > leider nichts ändern. Peter, meistens finde ich deine Beiträge gut und fundiert, auch wenn ich viele Dinge anders angehe als du. Aber hier hast du einfach nur riesigen Blödsinn von dir gegeben, sorry, anders kann man das nicht ausdrücken. Die 16Bit-Umständlichkeit ist in erster Linie das Erfordernis des C-Standards. Alle Ausdrücke mit ganzen Zahlen müssen erstmal im Wertebereich von `int' ausgeführt werden (oder mehr, falls ein Term mehr benötigt). Wenn du drüber nachdenkst, wo der GCC herkommt (er war ursprünglich ausschließlich für 32-bit-CPUs entwickelt worden), dann sollte dir auch sofort klar werden, dass der AVR einer der wenigen vom GCC unterstützten Prozessoren sein dürfte, bei dem es sich überhaupt irgendwie lohnen würde, anschließend noch eine Optimierung einzubauen, die die obere Hälfte des zu berechnenden int-Ausdrucks eliminiert, sofern aus den übrigen Randbedingungen klar ist, dass man sie weglassen kann, ohne die Standardkonformität zu gefährden. Diese Optimierung muss wohl schlicht und ergreifend einfach mal jemand schreiben -- dabei muss sie so geschrieben werden, dass sie sonst nichts kaputt macht, d.h. sie muss von ausgiebigen Testscripts begleitet sein, die nachweisen, dass die Standardkonformität davon nicht gefährdet wird. Ohne diese Testscripts bekommst du bei GCC (aus hoffentlich verständlichem Grund) nichts akzeptiert, was mehr als nur einen offensichtlichen Tippfehler korrigiert. Zum Glück, kann ich nur sagen: meinen 0b-Konstanten-Patch durfte ich nach dem Erstellen der Testscripts auch nochmal reparieren... Mit einer Gesamtquantität von vielleicht drei oder vier GCC-Hackern, die sich mit dem AVR auskennen (Denis Chertykov, Marek Michalkiewicz, Björn Haase, Svein Seldal fallen mir dabei so ein) ist es schlicht eine Frage der Manpower und der Prioritäten, wann ein derartiger Patch mal fertig sein könnte. Es gibt durchaus Dinge, nach denen viel mehr Leute rufen als nach den halben 16 bits: die Einführung von memory spaces (RAM vs. ROM vs. EEPROM vs. ...) zum Beispiel (dafür gibt's wohl einen standard proposal) oder den Support für ATmega256x. Rücksichtnahme auf irgendwelche kommerziellen Konkurrenten, noch dazu für einen Prozessor, der bei GCC eher unter ,,ferner liefen'' rangiert, ist sicher alles andere als ein Entwicklungsziel von GCC. Ganz davon abgesehen, der IAR schlägt ihn so ziemlich immer (wenngleich ich merken musste, dass das für die Codegeschwindigkeit zu meiner Verwunderung schon nicht so völlig gesetzt ist), aber die anderen Compiler dürften von ihrer Gesamtqualität (Standard- konformität, generierte Codegröße und -geschwindigkeit) bis auf pathologische Fälle, die sich natürlich immer konstruieren lassen, zumindest nicht nennenswert besser als AVR-GCC sein.
...es gibt da ja noch '-mint8'. Damit verschwinden auch die überflüssigen 'hi8(x)' konstrukte. Ich habe allerdings noch keinen blassen schimmer, was das an Nebenwirkungen mit sich bringt. Vielleicht kannst Du, Jörg, da ganz kurz was zu schreiben. Ich stelle mir das so vor, daß eben 8Bit berechnungen in einem extra Modul implementiert werden, welches mit dieser Option übersetzt wird. Natürlich nur, wenn man das auch wirklich braucht. Kleines Beispiel?
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
1. Kompiliert mit: $ avr-gcc -S -gdwarf-2 -Os -omint8.S mint8.c
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
2. Kompiliert mit: $ avr-gcc -mint8 -S -gdwarf-2 -Os -omint8.S mint8.c
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
Gast
#285624
@Jörg, manchmal provoziere ich gerne ein bischen :) Hier mal zwei Beispiele für die 16Bit-Umständlichkeit:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
Daß bei 16Bit ein simples swap in eine Zählschleife mutiert ist besonders extrem. Aber das ist nicht immer der Fall, manche Ausdrücke optimiert er ziemlich gut. Es ist aber schwer, dahinter ein System zu finden. Ich glaube bei Schiebeoperationen oder in if-Ausdrücken erweitert er besonders gerne auf 16Bit. Peter
Ich weiß, dass es die ,,16-Bit-Umständlichkeiten'' gibt. Ich wollte nur klarstellen, dass deine Verschwörungstheorien kompletter Unsinn sind. Wenn du da mit helfen willst, die Optimierung zu verbessern: nur zu. Nein, ,,ich weiß doch gar nicht, wie Compiler funktionieren!'' ist keine zugelassene Ausrede. Zur Geburt wussten wir's alle nicht, dennoch gibt es Leute, die sich da reingedacht haben -- viel mehr als die, die den GCC ursprünglich geschrieben haben. Kann also nicht undurchdringlich sein. Wenn es mal ein Dutzend AVR-GCC-Hacker statt einer Hand voll gibt, wird sich auch die Codeoptimierung verbessern. Ansonsten interessieren den größten Teil der GCC-Hacker wohl einfach nur die `mainstream'-Targets (IA32, AMD64, vielleicht noch UltraSPARC, PowerPC und ein bisschen MIPS). Deren Optimierungen am Compiler werden also alle nur an diesen Prozessoren gemessen.
Gast
#285626
AVR ist als GCC Target insofern eine Besonderheit (ebenso HC12), als die Zielmaschinen nicht mit Wortbreite arbeitet, sondern mit halber Wortbreite. Nun sind Shift-Operatoren nicht so leicht wegoptimierbar wie Und/Oder. So ist byte(irgendwas|1) immer identisch mit byte(irgendwas)|1, aber bei byte(irgendwas>>1) klappt das eben nicht mehr. Sicher, man könnte in den Compiler eine eher maschinenunabhängige Funktion einbauen, die ausgehend vom Typ des Ergebnisses alle Ausdrücke auf minimale Breite runterstuft, bei der das ohne Verfälschung vom Ergebnis geht. Aber diese Stufe wäre auf allen "normalen" Zielmaschinen bestenfalls überflüssig, oft sogar kontraproduktiv. Ohne eine solche Stufe sind 8bit-Optimierungen immer nur Einzelaktionen für bestimmte Fälle und blähen die Code-Templates auf.
Gast
#285627
> GCC Bug?
Ja, GCC ist ein Bug.
Gast
#285628
@A.K. wenn man sich mal diese Zeile ansieht:
1 | |
dann muß der Compiler aber schon sehr viel mitrechnen, damit er weiß, daß R25 und R19 unabhängig von a an dieser Stelle immer 0 sind, denn bei der 16Bit-Erweiterung eines unsigned char muß das High-byte ja immer 0 sein. D.h. er muß erkannt haben, daß vor dem Schieben um 1 mit 0x55 maskiert wurde und so kein High-Byte ungleich 0 ensteht. Dieser Aufwand erscheint mir viel größer, als sich gleich den Zieltyp zu merken. Bei der unteren Routine merkt er aber, daß ein High-Teil ungleich 0 ensteht und schmeißt ihn daher weg:
1 | |
Peter
Gast
#285629
"und schmeißt ihn daher weg" Das hat nichts mit Analyse zu tun. "a" ist 8bittig deklariert, return(a) ist per ABI 16bittig, also steht da eine 8->16bit Konvertierung von R18 nach R25:R24.
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.