Hallo zusammen, uint8_t src = gegebener variabler wert uint portB00 = PORTB & 0b11111100; Ich will die ersten 2 Bits von src nach PORTB schieben und danach src um 2 Stellen nach rechts shiften. Also so: PORTB = portB00 | (src & 0b00000011); src >>= 2; PORTB = portB00 | (src & 0b00000011); src >>= 2; PORTB = portB00 | (src & 0b00000011); src >>= 2; PORTB = portB00 | (src & 0b00000011); src >>= 2; Das muss aber in 4 Takten geschehen. C macht daraus jedoch mov, andi, or, out, lsr, lsr und das sind leider 2 Takte zu viel. Kennt jemand einen Trick? Wenn es nur 1 Bit wäre, würde ich bst, bld nehmen, aber es sind halt zwei Bits....
Möchtest du vielleicht noch sagen um welchen Mikrocontroller es sich handelt?
Kaj G. schrieb: > Möchtest du vielleicht noch sagen um welchen Mikrocontroller es sich > handelt? Sorry. Geht um den ATtiny84A-PU.
Christian S. schrieb: > Das muss aber in 4 Takten geschehen. C macht daraus jedoch mov, andi, > or, out, lsr, lsr und das sind leider 2 Takte zu viel. Kennt jemand > einen Trick? Jegliche Art von "Trick" in C ist unzuverlässig. Wenn es taktzyklengenau sein muss, ist zwingend Assembler erforderlich. Christian S. schrieb: > Wenn es nur 1 Bit wäre, würde ich bst, bld nehmen, aber es sind halt > zwei Bits.... Dann nimm eben zweimal bst und bld. Macht dann genau die gewünschten 4 Taktzyklen.
Rolf Magnus schrieb: > Dann nimm eben zweimal bst und bld. Macht dann genau die gewünschten 4 > Taktzyklen. Geht nicht, da es ein IO-Port ist, braucht es noch ein out am Ende. Naja, wahrscheinlich ist es in 4 Takten einfach nicht möglich...
Christian S. schrieb: > Das muss aber in 4 Takten geschehen. C macht daraus jedoch mov, andi, > or, out, lsr, lsr und das sind leider 2 Takte zu viel. Kennt jemand > einen Trick? Der Compiler hat schon ausgetrickst, schneller geht es nicht.
1 | in r16, PortB |
2 | andi r16, 0xFC |
3 | or r16, SrcReg |
4 | out PortB, r16 |
5 | lsr SrcReg |
6 | lsr SrcReg |
Sagte ich ja bereits im Eingangsposting. Dachte, es gäbe noch einen Geheimtrick mit noch nicht unterstützten ASM Befehlen, aber habe selber im Instruction Set nichts gefunden... naja, habs jetzt mit einem Vorbuffer gelöst. Trotzdem danke.
Marc Vesely schrieb: > Der Compiler hat schon ausgetrickst, schneller geht es nicht. Doch. Der IN Befehl wird nur einmal gebraucht.
1 | in r16, PortB |
2 | |
3 | andi r16, 0xFC |
4 | or r16, SrcReg |
5 | out PortB, r16 |
6 | lsr SrcReg |
7 | lsr SrcReg |
8 | |
9 | andi r16, 0xFC |
10 | or r16, SrcReg |
11 | out PortB, r16 |
12 | lsr SrcReg |
13 | lsr SrcReg |
14 | |
15 | andi r16, 0xFC |
16 | or r16, SrcReg |
17 | out PortB, r16 |
18 | lsr SrcReg |
19 | lsr SrcReg |
20 | |
21 | andi r16, 0xFC |
22 | or r16, SrcReg |
23 | out PortB, r16 |
Und wenn es hauptsächlich daum geht, die 2 Bits in exaktem Abstand zu erzeugen, nicht um die Gesamtlaufzeit, dann kann man 4 Register passend vorbereiten und kommt bis runter auf einen Abstand von 1 Takt.
A. K. schrieb: > Doch. Der IN Befehl wird nur einmal gebraucht. Nein. SrcReg wird geschoben, r16 OR SrcReg setzt nur die Einsen, kann aber keine löschen. Wenn SrcReg am Anfang 0x11000011 ist, wird PortB nach 4*Schieben auf 0x11111111 stehen, das soll aber nicht so sein. A. K. schrieb: > Und wenn es hauptsächlich daum geht, die 2 Bits in exaktem Abstand zu > erzeugen, nicht um die Gesamtlaufzeit, dann kann man 4 Register passend > vorbereiten und kommt bis runter auf einen Abstand von 1 Takt. Stimme ich zu, nur soll es aber gar nicht in 1 Takt Abstand gehen.
Marc Vesely schrieb: > A. K. schrieb: >> Doch. Der IN Befehl wird nur einmal gebraucht. > > Nein. > SrcReg wird geschoben, r16 OR SrcReg setzt nur die Einsen, > kann aber keine löschen. > Wenn SrcReg am Anfang 0x11000011 ist, wird PortB nach 4*Schieben > auf 0x11111111 stehen, das soll aber nicht so sein. Für das Löschen steht jeweils zu Beginn > andi r16, 0xFC
Eine weitere Variante mit 5 Takten könnte ich anbieten:
1 | sbrs src,0 |
2 | cbi PORTB,0 |
3 | sbrc src,0 |
4 | sbi PORTB,0 |
5 | sbrs src,1 |
6 | cbi PORTB,1 |
7 | sbrc src,1 |
8 | sbi PORTB,1 |
9 | |
10 | sbrs src,2 |
11 | cbi PORTB,0 |
12 | sbrc src,2 |
13 | sbi PORTB,0 |
14 | sbrs src,3 |
15 | cbi PORTB,1 |
16 | sbrc src,3 |
17 | sbi PORTB,1 |
18 | ;... |
19 | ;... |
Vorteil: keine weiteren Resourcen nötig, weder Register noch Flags Nachteile: 'schwammiges' Zeitverhalten, am Ende ist src nicht 0
Und jetzt wäre es schön, wenn ich editieren könnte: Entschuldigung, das sind natürlich 2*5= 10 Takte pro Block.
S. Landolt schrieb: > Für das Löschen steht jeweils zu Beginn >> andi r16, 0xFC Ja, damit löschst du aber nur die zwei niedrigsten bits:
1 | SrcReg = 0x11000011 r16 = 0x yyyyyy00 |
2 | OR r16, SrcReg |
3 | SrcReg = 0x11000011 r16 = 0x 11yyyy11 |
4 | lsr SrcReg |
5 | lsr SrcReg |
6 | andi r16, 0xFC |
7 | SrcReg = 0x00110000 r16 = 0x 11yyyy00 |
8 | OR r16, SrcReg |
9 | SrcReg = 0x00110000 r16 = 0x 1111yy00 |
10 | lsr SrcReg |
11 | lsr SrcReg |
12 | andi r16, 0xFC |
13 | SrcReg = 0x00001100 r16 = 0x 1111yy00 |
14 | OR r16, SrcReg |
15 | SrcReg = 0x00001100 r16 = 0x 11111100 |
16 | lsr SrcReg |
17 | lsr SrcReg |
18 | andi r16, 0xFC |
19 | SrcReg = 0x00000011 r16 = 0x 11111100 |
20 | OR r16, SrcReg |
21 | SrcReg = 0x00000011 r16 = 0x 11111111 |
Klarer ?
Die wollen zum Mars fliegen und können noch nicht mal Prozessoren designen, die unabhängig vom Problem immer nur einen Takt brauchen... tsts..
> C macht daraus jedoch mov, andi, or, out, lsr, lsr > Der IN Befehl wird nur einmal gebraucht. Pardon, ich verstehe immer weniger, mag daran liegen, dass ich kaum C kann. Sowohl Marc Vesely als auch A.K. machen zu Beginn ein in r16,PORTB wo finde ich das in der Eingangsfragestellung? Für mich sieht es so aus, als würden die PORTB-Bits 7..2 immer gesetzt.
S. Landolt schrieb: > wo finde ich das in der Eingangsfragestellung? uint portB00 = PORTB & 0b11111100; => IN r16, PORTB ANDI r16, 0xFC > Für mich sieht es so aus, > als würden die PORTB-Bits 7..2 immer gesetzt. Nein, hier nicht: PORTB = portB00 | (src & 0b00000011); => MOV r17, src ANDI r17, 3 OR r17, r16 OUT PORTB, r17
Also in der Summe 26 Takte, ohne allfällige push/pop. Mir reicht's erstmal, einen schönen Abend allerseits.
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.