Guten Abend liebe Experten! Ich wollte mal fragen ob mir jemand sagen kann wie man einen einzelnen Pin invertiert statt dem gesamten Port wie z.B. so: PORTD ^= 0xFF; PORTD = ~PORTD; Also ich möchte z.B. nur PD0 umkippen. ich hatte es erst mit if (PD0) {pin einschalten}else{pin ausschalten} und if (PD0) {pin ausschalten}else{pin einschalten} ausprobiert aber das geht so gar nicht.
Du warst doch schon nahe dran: PORTD ^= _BV(PD0); Neuere AVRs können ein Portpin umschalten, indem man eine 1 auf das (eigentlich nur für die Eingabe sinnvolle) PINx-Register schreibt: PIND = _BV(PD0); Idealerweise würde der Compiler aus der ersten Sequenz oben intern die zweite Sequenz ableiten wenn er weiß, dass der entsprechende AVR das kann, aber sowas hat dem AVR-GCC noch niemand beigebracht.
erste Variante funktionert. Zweite jedoch nicht. Danke dir für die schnelle Antwort Jörg!
Wenn die zweite nicht geht, benutzt du keinen der moderneren AVRs, bei denen das implementiert ist. Du hast nicht dazu geschrieben, was für einen Controller du hast.
einen Mega8. aber das spielt ja auch keine Rolle denn es funktioniert ja so prima :)
"Idealerweise würde der Compiler aus der ersten Sequenz oben intern die zweite Sequenz ableiten wenn er weiß, dass der entsprechende AVR das kann, aber sowas hat dem AVR-GCC noch niemand beigebracht." Lieber nicht. Dazu müsste der Compiler die I/O-Ports soweit verinnerlichen, dass für jeden neuen AVR ein neuer Compiler fällig wird. Statt dessen sind sämtliche Ports nur ganz normale C-Makros, und bei denen darf der Compiler so etwas nicht.
A.K. wrote: > Lieber nicht. Dazu müsste der Compiler die I/O-Ports soweit > verinnerlichen, dass für jeden neuen AVR ein neuer Compiler fällig > wird. Nicht zwingend. Alle neuen AVRs scheinen das auf gleiche Weise zu implementieren, man bräuchte also nur ein Flag "ist ein neuer AVR". Der ATmega8 ist zu alt dafür, ein ATmega88 könnte es. > Statt dessen sind sämtliche Ports nur ganz normale C-Makros, und bei > denen darf der Compiler so etwas nicht. Die Optimierung von memory-mapped IO auf den separaten IO space macht er doch auch, genau wie die Optimierung auf SBI/CBI, wenn diese möglich ist.
> "Alle neuen AVRs scheinen das auf gleiche Weise zu implementieren, > man bräuchte also nur ein Flag "ist ein neuer AVR". Das ist nicht der Punkt. Woher weiss der Compiler, dass PORTD und PIND irgendwie zusammenhängen? Stand heute sind das 2 getrennte #defines in einem Include-File, die für den Compiler in keinerlei Zusammenhang stehen. Damit wäre Schluss, man müsste diesem Zusammenhang auf höchst spezielle Weite in den Compiler integrieren, per Attribute, Pragma, direkt ins config/avr/avr.c, oder so. > Die Optimierung von memory-mapped IO auf den separaten IO space macht > er doch auch, genau wie die Optimierung auf SBI/CBI, wenn diese > möglich ist. Das ist etwas völlig anderes. Damit wählt der Compiler nur die Adressierungsart aus. Das I/O-Register bleibt das gleiche.
A.K. wrote: > Damit wäre Schluss, man müsste diesem Zusammenhang auf höchst spezielle > Weite in den Compiler integrieren, per Attribute, Pragma, direkt ins > config/avr/avr.c, oder so. Da müsste man mal recherchieren, welche Möglichkeiten dafür in Frage kommen. Solange sich das sauber hinter einem #include <avr/io.h> verstecken ließe, wäre es komplett transparent für den Benutzer. > Das ist etwas völlig anderes. Damit wählt der Compiler nur die > Adressierungsart aus. Das I/O-Register bleibt das gleiche. Es ist etwas anderes, aber etwas völlig anderes? Nee. Liegt im gleichen Bereich, auch wenn SBI/CBI allgemeiner implementierbar sind (weil der Adressbereich, für den die Optimierung machbar ist, ein einfacher großer Block ist).
Ist schon was anderes. Denn ebendieser Zusammenhang zwischen den Datenadressen steckt ja im Compiler hardcoded drin. Der Zusammenhang zwischen PIND und PORTD hingegen (noch) nicht. Willst du, dass der Compiler bei einem Mega16 im Fall von TIMSK ^= 0x40; einfach 1 auf die Adresse addiert und GIFR = 0x40; daraus macht, weil er die gleiche Regel wie bei I/O-Ports anwendet? Stand heute hat der Compiler ja keinerlei Ahnung, ob es sich bei PORTD um einen I/O-Port oder um Interrupt-Flags handelt. Genau diese Kenntnis müsstest du ihm erst beibringen. Also: Erweitere dem GCC so, dass man ihm mitteilen kann "PORTD ist der Output zu PIND der Input" und schon geht's. Vorher nicht.
A.K. wrote: > Also: Erweitere dem GCC so, dass man ihm mitteilen kann > "PORTD ist der Output zu PIND der Input" > und schon geht's. Vorher nicht. Genau, auf so etwas müsste es hinauslaufen. Sei's nun, dass man in der Definition von PORTD ein _attribute_ dranklebt, das er dann intern auswertet oder was auch immer. Kann man im Headerfile ja bei Bedarf noch von der Compilerversion abhängig machen, damit ist man rückwärtskompatibel zu einem Compiler, der das noch nicht versteht. (Ich glaube, du hast auf mein 30 Sekunden später zurückgezogenes Posting geantwortet, aber das macht nix. :)
Solche Optimierungen werden doch für gewöhnlich in den Peephole Optimizer gelegt. Und die sind aus der Natur der Sache heraus sowieso hardwarespezifisch.
Warum den Compiler ändern? 2 Szenarios: Fall 1: Der Programmierer weiss was er tut und kennt die neue Option. Dann benutzt er sie auch und schreibt den Pin-Toggle selbsst so hin. Fall 2: Der Programmierer weiss nichts von der neuen Option. Der Compiler macht das zukünftig automatisch für ihn. Beim Debuggen schaut er sich den Assemblercode an und wundert sich. Verstehen tut er leider nichts. Danach postet er hier "gcc hat schon wieder einen Bug". Vorteil wäre natürlich: Da so ein Post sehr gerne gelesen wird, verbreitet sich die neue Option viel schneller in den Köpfen als ohne Compileränderung. Und nun? Grüße von Stefan
Karl heinz Buchegger wrote: > Solche Optimierungen werden doch für gewöhnlich in den > Peephole Optimizer gelegt. Und die sind aus der Natur > der Sache heraus sowieso hardwarespezifisch. Aber bislang eben doch auf höherem Niveau.
> Solche Optimierungen werden doch für gewöhnlich in den > Peephole Optimizer gelegt. Und die sind aus der Natur > der Sache heraus sowieso hardwarespezifisch. Auch der Peehole-Optimizer müsste irgendwoher wissen, dass auf I/O-Adresse 0x00 je nach Controller-Modell mal TWI-Register, mal Portregister stehen. Er ändert also nichts an der Notwendigkeit, dies dem Compiler mitzuteilen. Ein Peephole Optimizier repariert Dinge, die man auf normalem Weg nicht so ohne weiteres gebacken kriegt. Die Optimierung hier liesse sich problemlos in der normalen Codegenerierung des Compilers unterbringen, als gewöhnliches instruction template für XOR, das eben nur unter bestimmten Randbedingungen greift.
> Er ändert also nichts an der Notwendigkeit, dies > dem Compiler mitzuteilen. Das sicherlich nicht. Aber wenn man dem P-O je nach Prozessortyp eine andere Tabelle mit Ersetzungsregeln unterjubelt, ist das doch eine schöne Lösung, ohne dass man allzusehr in die generelle Compilerlogik eingreifen müsste.
Verstehst du unter diesem P-O ein separates Tool, das nach dem Compiler aber vor dem Assembler des Code "repariert"? Ja, so kann man das schon machen. Würde ich aber eher als Hack ansehen, im Compiler gefällt mir das sehr viel besser, dafür sind die insns ja da. Nur: Lohnt das wirklich???
Karl heinz Buchegger wrote: > Aber wenn man dem P-O je nach Prozessortyp eine andere > Tabelle mit Ersetzungsregeln unterjubelt, ist das doch > eine schöne Lösung, ohne dass man allzusehr in die > generelle Compilerlogik eingreifen müsste. Doch, es wäre ein ziemlicher Eingriff. Bisher weiß das AVR-Backend nichts in diesen Details über den Prozessor, sondern es klassifiziert die einzelnen AVRs nur nach den Fähigkeiten ihres CPU-Cores. Man muss zwar immer noch den GCC für jeden einzelnen AVR patchen, aber das sind zwei oder drei Tabellen bislang. Die gesamte Belegung der IO-Ports jedoch ist in den durch <avr/io.h> hereingezogenen Headerdateien festgelegt.
> Verstehst du unter diesem P-O ein separates Tool, das nach dem > Compiler aber vor dem Assembler des Code "repariert"? In allen Compilern, die ich bisher gesehen habe, war das so. Ich muss allerdings gestehen, mich noch nie im Detail mit dem gcc auseinandergesetzt zu haben. > Bisher weiß das AVR-Backend nichts in diesen Details über > den Prozessor Das ist interessant. Bisher bin ich immer naiv davon ausgegangen dass die ganze sbi/cbi Umsetzung durch den P-O gemacht würde. Oder auch die Spezialbehandlung für die Extended Register (die heissen doch so, oder). Wenn das natürlich nicht so ist, dann wäre es natürlich Blödsinn da jetzt einen neuen Mechanismus einzuführen. Ich ziehe mich zurück und lausche der weiteren Unterhaltung mit grossem Interesse.
Karl heinz Buchegger wrote: > Das ist interessant. Bisher bin ich immer naiv davon ausgegangen > dass die ganze sbi/cbi Umsetzung durch den P-O gemacht würde. Ja, sicher. Aber da braucht's eben auch keinerlei Unterscheidung zwischen den AVRs. Wenn die Adresse zwischen 0x20 und 0x5f liegt, dann kann man sie mittels IN/OUT durch Subtraktion von 0x20 ebenfalls erreichen. Wenn die Adresse nach dem Subtrahieren zwischen 0 und 0x1f liegt und nur ein einzelnes Bit zu setzen oder zu löschen ist, kann man CBI/SBI benutzen. Dafür muss man überhaupt nicht wissen, ob man auf einem uralten AT90S2333 oder auf dem allerneuesten ATmega644P arbeitet.
>> Das ist interessant. Bisher bin ich immer naiv davon ausgegangen >> dass die ganze sbi/cbi Umsetzung durch den P-O gemacht würde. > Ja, sicher. Für mich sieht das eher nach einem ganz normalen instruction template für &= aus, mit Randbedingung "I/O-Adressraum" (avr_io_address_p) und "Einzelbit". (define_insn "*cbi" [(set (mem:QI (match_operand 0 "const_int_operand" "n")) (and:QI (mem:QI (match_dup 0)) (match_operand 1 "const_int_operand" "n")))] "avr_io_address_p (operands[0], 1 + 0x20) && exact_log2 (~INTVAL (operands[1]) & 0xff) >= 0" { operands[2] = GEN_INT (exact_log2 (~INTVAL (operands[1]) & 0xff)); return AS2 (cbi,%0-0x20,%2); } [(set_attr "length" "1") (set_attr "cc" "none")])
Ich glaube übrigens nicht, dass es im GCC überhaupt einen P-O gibt, wie er oben beschrieben wird. Und was im MD-File "peephole" genannt wird, scheint mit eher ein Mechanismus zu sein, bestimmte Sequenzen zu erkennen, die im Rahmen von normalen Templates nicht erfasst werden können. Insofern nicht direkt vergleichbar zu den oben skizzierten P-Os.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.