hi,
gibt's eigentlich eine möglichkeit, dem compiler beizubringen, zb das
folgende automatisch zu optimieren? da kann man ja so einiges
zusammenfassen. von hand wäre das aber mühsam und fehleranfällig.
normalerweise schreibe ich ja nicht "PORTB |= _BV(PB5);" sondern habe
makros für sowas.
claudia schrieb:> gibt's eigentlich eine möglichkeit, dem compiler beizubringen,> zb das folgende automatisch zu optimieren?
Ja, du könntest ein Patch einreichen, das GCC dahingehend ändert, daß
der Compiler nicht mehr volatile-korrekt ist :-;
> da kann man ja so einiges zusammenfassen.
Nö, das darf ein korrekter C-Compiler nicht.
> ich nehme an, das liegt daran, daß PORTB usw. volatile sind.
Genau,
> kann man keine ausnahmen definieren oder sowas?
Du jannst die Definition von PORTB so machen, daß es nicht mehr volatile
ist:
schreibst, möchtest du, dass alle Bits gleichzeitig gesetzt werden.
Würde der Compiler nach eigenem Gutdünken die eine Variante durch die
andere ersetzen, könnte das die korrekte Funktion des Programms beein-
trächtigen.
Yalu X. schrieb:> Würde der Compiler nach eigenem Gutdünken die eine Variante durch die> andere ersetzen, könnte das die korrekte Funktion des Programms beein-> trächtigen.
Man stelle sich nur sowas vor:
1
PORTB&=~(1<<STROBEPIN);// assert strobe signal
2
PORTB|=(1<<STROBEPIN);
Der "intelligente" Compiler würde nun feststellen, dass der Gesamt-
effekt beider Zeilen sich ja aufhebt und man folglich gar keinen
Code dafür emittieren müsste. ;-)
hi jungs,
mensch, mir ist ja klar gewesen, woran es liegen könnte. es gibt doch
aber anwendungsfälle, wo es einfach wichtiger ist, daß die veroderungen
zusammengefasst werden, auch wenn ich sie einzeln schreiben muss. ich
steuere zb ein lcd an. da benutze ich nicht _BV(PB2) und _PV(PB3) usw.
sondern eben makros, damit der code lesbar bleibt und sich kein fehler
einschleicht. und dann brauche ich einfach mehrere befehle
hintereinander (die aber gerne gleichzeitig ausgeführt werden dürfen).
ich denke, der eine hinweis war schon gut. nur sollte ich das ganze dann
nicht PORTB nennen sondern zb NVPORTB
claudia schrieb:> ich> steuere zb ein lcd an. da benutze ich nicht _BV(PB2) und _PV(PB3) usw.> sondern eben makros, damit der code lesbar bleibt und sich kein fehler> einschleicht.
Und darin kommt's dann auf jeden Takt und jedes Byte Code an?
Wenn sowas einmalig während der Initialisierung der Fall ist, würde
ich mir da keine großen Gedanken drum machen und Lesbarkeit einfach
über Effizienz gehen lassen.
claudia schrieb:> hi jungs,>> mensch, mir ist ja klar gewesen, woran es liegen könnte. es gibt doch> aber anwendungsfälle, wo es einfach wichtiger ist, daß die veroderungen> zusammengefasst werden, auch wenn ich sie einzeln schreiben muss. ich> steuere zb ein lcd an. da benutze ich nicht _BV(PB2) und _PV(PB3) usw.> sondern eben makros, damit der code lesbar bleibt und sich kein fehler> einschleicht. und dann brauche ich einfach mehrere befehle> hintereinander (die aber gerne gleichzeitig ausgeführt werden dürfen).
Und was hindert dich daran, für diese Zusammenfassung wieder sinnvolle
Makros zu benutzen? Dann hat man die Dinge an einer Stelle beisammen.
Im übrigen ist da noch etwas zu bedenken
PORTB |= (1<<PD2) | (1<<PD3);
(oder wie dann auch immer) ist ganz sicher KEINE atomare Operation. D.h.
wenn da ein Interrupt dazwischenfunkt und in der ISR am PORTB gefummelt
wird, dann gibt es Ärger.
Wenn der Compiler aber
PORTB |= (1<<PD2);
PORTB |= (1<<PD3);
zu jeweils einem sbi compiliert, dann sind das 2 atomare Operationen.
Ganz abgesehen davon, dass letztere Sequenz dann sogar noch kürzer als
die generelle Oder-Lösung ist.
claudia schrieb:> mensch, mir ist ja klar gewesen, woran es liegen könnte. es gibt doch> aber anwendungsfälle, wo es einfach wichtiger ist, daß die veroderungen> zusammengefasst werden, auch wenn ich sie einzeln schreiben muss.
Dann benutze eine lokale Variable (z.B. portb) zum
Nacheinander-Verodern.
Du schreibst:
1
uint8_tportb=0;
2
3
portb|=_BV(PB5);
4
...
5
portb|=_BV(PB3);
6
7
PORTB=portb;
Damit setzt Du dann den Wert von PORTB auf einen Schlag, wobei der
Compiler die Volatilität von PORTB auch weiterhin korrekt behandelt.
claudia schrieb:> mensch, mir ist ja klar gewesen, woran es liegen könnte. es gibt doch> aber anwendungsfälle, wo es einfach wichtiger ist, daß die veroderungen> zusammengefasst werden
Und wie soll der Compiler wissen, wo ein solcher Anwendungsfall
vorliegt?
claudia schrieb:> ich> steuere zb ein lcd an. da benutze ich nicht _BV(PB2) und _PV(PB3) usw.> sondern eben makros, damit der code lesbar bleibt und sich kein fehler> einschleicht. und dann brauche ich einfach mehrere befehle> hintereinander (die aber gerne gleichzeitig ausgeführt werden dürfen).
Du mußt eh warten, da kommt es nicht auf den Zyklus an.
Du gewinnst daher beim Zusammenfassen garnichts.
Fürs LCD nehme ich die völlig freie Pinzuordnung:
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=102296
Dann werden Spezialfunktionen der Pins nicht behindert.
Peter
das problem ist längst gelöst.
freie pinzuordnung verwende ich auch, allerdings gewinne ich mit der
neuen methode jetzt im init alleine 16 bytes, bei gleichem resultat und
gleicher übersichtlichkeit.
claudia schrieb:> das problem ist längst gelöst.>> freie pinzuordnung verwende ich auch, allerdings gewinne ich mit der> neuen methode jetzt im init alleine 16 bytes, bei gleichem resultat und> gleicher übersichtlichkeit.
Na wenn das nicht nach einem Turing Award schreit. Wer übernimmt die
Nominierung ;-)
claudia schrieb:> das problem ist längst gelöst.
Möchtest Du uns auch an der Lösung teilhaben?
Ist so üblich in Foren.
claudia schrieb:> freie pinzuordnung verwende ich auch
Dann ist eine Zusammenfassung doch nicht möglich.
Es müssen alle 4 Datenpins auf dem selben Port sitzen.
Peter
> Möchtest Du uns auch an der Lösung teilhaben?
Hat sie doch schon.
>> ich denke, der eine hinweis war schon gut. nur sollte ich das ganze dann>> nicht PORTB nennen sondern zb NVPORTB>> #define NVPORTB (*((uint8_t*) 0x25))
Uwe schrieb:> Hat sie doch schon.>>>> ich denke, der eine hinweis war schon gut. nur sollte ich das ganze dann>>> nicht PORTB nennen sondern zb NVPORTB>>>> #define NVPORTB (*((uint8_t*) 0x25))
das diese lösung sauber funktionert bezweife ich, dann der compiler kann
auf die Idee kommen den wert komplett in einem register zu behalten.
Oder aus zwei zuweisungen eine machen.
Peter II schrieb:> Oder aus zwei zuweisungen eine machen.
Vermutlich das E=1 und E=0, d.h. es erfolgt kein Puls.
Oder die Reihenfolge umsortieren (erst der E-Puls und dann die Daten).
Wegen nur 8 Befehlen würde ich mir nicht solche faulen Eier ins Nest
legen.
Peter
Peter II schrieb:> Oder aus zwei zuweisungen eine machen.
Das war doch das Zeil der Übung. Hauptsache der Code ist optimal.
Und wenn er nicht mehr funktioniert, kann man schön über den Compiler
schimpfen :-)
Peter Dannegger schrieb:> Peter II schrieb:>> Oder aus zwei zuweisungen eine machen.>> Vermutlich das E=1 und E=0, d.h. es erfolgt kein Puls.> Oder die Reihenfolge umsortieren (erst der E-Puls und dann die Daten).
na ja, sie hat von der Initialisierung gesprochen. (faiererweise
angemerkt).
Vermutlich so was in der Art
DDR_D_0 |= (1 << DB0);
DDR_D_1 |= (1 << DB1);
DDR_D_2 |= (1 << DB2);
DDR_D_3 |= (1 << DB3);
DDR_D_4 |= (1 << DB4);
DDR_D_5 |= (1 << DB5);
DDR_D_6 |= (1 << DB6);
DDR_D_7 |= (1 << DB7);
und wenn diese Einzelbits jetzt alle an ein und demselben Port liegen,
dann kann der Compiler das zusammenfassen.
> Wegen nur 8 Befehlen würde ich mir nicht solche faulen Eier ins Nest> legen.
Würd ich auch nicht. Es sei denn ich finde nirgends mehr sonst was, wo
ich ein paar Bytes sparen kann um das Pgm doch noch gerade so ins Flash
zu bekommen. Aber dann würde ich es auf C Ebene selbst umschreiben.