Hi,
die Frage ist mir ja fast schon peinlich, aber gibt es eine EINFACHE
(2-3 Zeiler) Möglichkeit, die Bits 6 und 7 einer Variable (in meinem
Fall "counter") auf den PORTB PB0 und PB1 auszugeben (also 6->PB0,
7->PB1), OHNE PB2...PB7 zu beeinflussen?
Ich könnte jetzt pruefen, ob die Bits gesetzt sind und je nach dem an
eine Sprungmarke springen und den entsprechenden Port mit SBI bzw. CBI
setzen bzw. loeschen.
Aber das muss doch einfacher gehen oder nicht!?
Sorry fuer meine auf-dem-Schlauch-Steherei ;-)
Danke
Franz
Franz M. wrote:
> ach noch vergessen: Ich progge in Assembler
die beiden Bitposition von counter mittels einer AND Maskierung
freistellen. Um 6 Positionen nach unten schieben. PORTB einlesen, PB0
und PB1 definiert auf 0 setzen. Die vorher geschobenen beiden Bits mit
einem Oder drüberschreiben. Das Resultat wieder auf PORTB ausgeben.
-> die Lösung mit cbi/sbi dürfte einfacher sein. Vor allem das
Schieben um 6 Positionen wird viel Zeit verschlingen.
Michael wrote:
> Wieso um 6 Stellen schieben? Ich komm auf drei, einfach durchs Carry> schieben, man kann ja nach links und rechts schieben ;)
Hast recht.
(Ich hol mir jetzt noch einen Kaffee)
Die Lösung wird auch davon abhängen, wo man atomar sein will/muss
-- wenn man an den Ausgängen atomar sein muss, also Zwischenzustände
vermeiden, die man garnicht ausgeben will, muss man auf den ganzen Port
schreiben und sbi/cli ist obsolet
-- wenn man intern atomar sein muss, weil auch eine ISR auf dem Port
rumnudelt, dann ist ein Lesen/Schreiben des Ports problematisch: Es muss
dann in cli/sei o.ä. oder man nimmt die sbi/cli-Lösung.
Johann
Ist garantiert, dass in count3 keine anderen Bits gesetzt sind?
swap count3
lsr count3
lsr count3
in temp, PORTB
andi count3, 0x03
ori temp, 0x03
or temp, count3
out PORTB, temp
Hm, und immer noch ein 8-Zeiler. Mikki Mertens Vorschlag scheint mir die
beste Lösung zu sein werden doch nur Bits gesetzt, die gesetzt werden
sollen und man benötigt auch weiteren Variablen ;)
Ich merke grade, dass das oben von mir ja gar nicht funktioniert!
Die nach dem SWAP sind die 4 low-bits ja im high-nibble und werden dann
mit ver-odert.
Aber man kann ja eh nicht "gleichzeitig" beide PBs aendern, ohne wie
gesagt auf den ganzen PORTB zu schreiben. Also hat man immer einen
"undefinierten" Zustand zwischendurch.
Oder halt ziemlich großen Aufwand....
Ich mach jetz erstmal Fruehstueck und danach schreib ich euch meine
Loesung
Stefan Ernst wrote:
> Über die ori-Zeile würde ich nochmal nachdenken. ;-)
Grrrrr. Brauch gleich noch einen Kaffee.
Beim Überlegen war das noch anders. Aber die Finger haben dann
ganz was anderes geschrieben.
swap count3
lsr count3
lsr count3
in temp, PORTB
andi count3, 0x03
andi temp, 0xFC
or temp, count3
out PORTB, temp
Karl heinz Buchegger wrote:
> Das ist trickreich :-)> Endlich hab ich mal verstanden, was so typische Einsatzfälle für das> T-Flag sind.
Naja, ich finde, bst und bld fristen zu Unrecht ein Nischendasein.
Ich vermute fast, dass sich selbst erfahrenere Assembler-Programmierer
der Existenz dieser beiden Befehle oft übehaupt nicht bewusst sind. Ich
finde die aber oft ziemlich praktisch. Wie oft hat man das Problem, dass
man Bitzustände irgendwo herbekommt und in einer völlig anderen
Reihenfolge woanders augeben muss. Und wie man sieht, gibt es bei
wenigen Bits sogar bei Beibehaltung der Reihenfolge Codegrößen- und
Performance-Vorteile.
Ich musste es aber auch erst hinschreiben, um zu sehen, dass es
tatsächlich kürzer ist als die anderen Vorschläge. Habe schon ziemlich
lange nichts ernsthaftes mehr in Assembler programmiert...
> Merci für den Denkanstoss!
Keine Ursache. Weiß nicht, wie oft ich schon Denkanstöße von Dir
bekommen habe (und ich glaube, das geht den meisten, die sich schon
länger hier im Forum rumtreiben, so)...
Franz M. wrote:
> ja das is echt tricky :P>> Wenn sich jetzt nicht zwischen "in r16, PORTB" und "out PORTB, r16" was> am PORTB aendert, ist alles OK ;-)
Das Problem haste bei Read-Modify-Write-Zugriffen dummerweise immer. In
dem Falle wäre tatsächlich die Methode mit sbi und cbi die einzig
empfehlenswerte. Die ist aber länger...
EDIT:
OK, meist genügt es natürlich, für die Zeit vom in bis zum out die
Interrupt-Bearbeitung zu sperren. Nur wenn irgendwelche Hardware (Timer,
serielle Interfaces) auf PORTx zugreifen, genügt das nicht mehr.
Johann L. wrote:
> Die Lösung wird auch davon abhängen, wo man atomar sein will/muss>> -- wenn man an den Ausgängen atomar sein muss, also Zwischenzustände> vermeiden, die man garnicht ausgeben will, muss man auf den ganzen Port> schreiben und sbi/cli ist obsolet
Ganz genau umgekehrt ist es richtig, man muß SBI/CBI nehmen, um atomar
zu sein!
Nimmt man IN,AND,OR,OUT ist das nicht mehr atomar.
Dann muß mit CLI/SEI geklammert werden, wenn auch Interrupts den Port
benutzen.
Peter
Peter Dannegger wrote:
> Johann L. wrote:>> Die Lösung wird auch davon abhängen, wo man atomar sein will/muss>>>> -- wenn man an den Ausgängen atomar sein muss, also Zwischenzustände>> vermeiden, die man garnicht ausgeben will, muss man auf den ganzen Port>> schreiben und sbi/cli ist obsolet>> Ganz genau umgekehrt ist es richtig, man muß SBI/CBI nehmen, um atomar> zu sein!>> Nimmt man IN,AND,OR,OUT ist das nicht mehr atomar.> Dann muß mit CLI/SEI geklammert werden, wenn auch Interrupts den Port> benutzen.>>> PeterALLES lesen, was ich schrieb :-)
Ein wenn sich das "atomar" auf die Signale bezieht (keine seltsanmen
Zwischenzustände), heisst das wohl "glitch" oder so im Fachchinesisch?
Beispiel: mit sbi/cbi kommt man nicht ohne Zwischenzustand von 00 nach
11 oder 01 nach 10 etc.
Das ist u.a. auch dann von Belang, wenn im Programm nicht asynchron auf
die Ports gegriffen wird.
Wenn asynchron auf die Ports gegriffen wird, dann "atomar" mit sbi/sbi
wie ich schon schrieb.
Beispiel: In der Anwendung werden .0 und .1 gesetzt, in einer ISR .6.
Dann braucht man cli/sei.
Johann
Johann L. wrote:
> ALLES lesen, was ich schrieb :-)>> Ein wenn sich das "atomar" auf die Signale bezieht (keine seltsanmen> Zwischenzustände), heisst das wohl "glitch" oder so im Fachchinesisch?
Du kannst nicht einfach dem Begriff "atomar" ne falsche Bedeutung geben.
Wenn Du glitch meinst, dann ist das was völlig anderes als atomar.
Atomar bedeutet nicht unterbrechbar, hat mit Glitches überhaupt nichts
zu tun.
Nicht atomar ist etwas, wenn ein Interrupt dazwischen haut und dann die
Änderung des Interrupts verloren geht.
> Beispiel: mit sbi/cbi kommt man nicht ohne Zwischenzustand von 00 nach> 11 oder 01 nach 10 etc.
Das hat überhaupt nichts mit "atomar" zu tun, ist ne völlig andere
Baustelle.
Gleichzeitig ist eh nie ein Wechsel zweier Signale, Du hast immer
unterschiedliche Schaltzeiten und wenn es nur Picosekunden sind.
Wenn Du das willst, mußt Du Graycode nehmen oder die Signale mit einem
Takt latchen, nachdem sie stabil sind.
Schau Dir mal die NXP ARM7-TDMI an, die haben getrennte Set- und
Clear-Register, d.h. Du kannst dort nichtmal im gleichen Maschinenzyklus
mehrere Pins setzen und löschen.
Sie sind aber extra dazu eingeführt worden, um atomar zuzugreifen, da
bei den ARM7 ein Interrupt-Disable eine ziemliche Verrenkung ist (nicht
im Usermode möglich).
Sowohl atomar als auch (fast) gleichzeitig kann der ARM-Cortex M3, da er
spezielle Bitbefehle hat.
Peter
Peter Dannegger wrote:
> Johann L. wrote:>> Beispiel: mit sbi/cbi kommt man nicht ohne Zwischenzustand von 00 nach>> 11 oder 01 nach 10 etc.>> Das hat überhaupt nichts mit "atomar" zu tun, ist ne völlig andere> Baustelle.
Schon klar. Mir fehlt(e) da lediglich eine Vokabel. Wie heisst es denn
korrekt?