geht es noch schneller in ASM?

Gast #885454
Lesenswert?

Hallo, ich versuche, möglichst schnell in AVR-Assembler Datenbytes aus 
einem Portpin in ein Schieberegister zu schieben, so ähnlich wie das SPI 
tut. In meinem speziellen Fall kann ich SPI nicht verwenden. Also ich 
habe das Register R17 und 2 Ausgangs-Pins Port_daten und Port_clock. Ich 
bin mit dem Befehlssatz noch nicht 100% vertraut. Meiner Meinung nach 
wäre folgende Vorgehensweise die schnellste, oder geht es noch 
schneller?

   'erstes BIT (MSB first)
      cbi port_data    '2 Takte
      sbrc R17,7       '2 oder 3 Takte
      sbi port_data    '(2 Takte)
      sbi port_clock   '2 Takte
      cbi port_clock   '2 Takte
      rol R17          '1 Takt

   'zweites BIT
      cbi port_data
      sbrc R17,7
      sbi port_data
      sbi port_clock
      cbi port_clock
      rol R17

   'drittes Bit
      cbi port_data
      sbrc R17,7
      sbi port_data
      sbi port_clock
      cbi port_clock
      rol R17

   'usw.

Also in 8*11 Takten maximal wäre das Register bzw. 1 Byte gesendet. Ein 
bischen unschön finde ich dabei, daß ich auf der Datenleitung eine 
Frequenz erzeuge, auch wenn ich &HFF in R17 stehen hab (da könnte die 
datenleitung eigentlich permanent auf H bleiben). Wer bietet weniger?
Gast #885484
Lesenswert?

Ja, da hast Du recht :-) das war früher mal dazu da, um den text 
mehrfach verwenden zu können..

Irgendwie hab ich gerade 'nen Knoten im Kopf, es müßte doch mit Sprüngen 
machbar sein, daß man sich das Umschalten spart, wenn das nächste 
Datenbit den gleichen Wert hat.. (ohne daß man durch das Testen wieder 
Zeit verliert)
Gast #885506
Lesenswert?

@Düsentrieb

ok es ist genauso schnell - 11 Takte in jedem Fall


   sbrc R17,7       '2 oder 3 Takte
   sbi port_data    '(2 Takte)
   sbrs R17,7       '2 oder 3 Takte
   cbi port_data    '(2 Takte)
   sbi port_clock   ' 2 Takte
   cbi port_clock   ' 2 Takte

zwar nicht schneller, aber schöner :-)
Persönliche Seite #885507
Lesenswert?

Die Sequemz CBI-SBRC-SBI (6-7 T) kann ersetzt werden durch BST-BLD-OUT 
(3 T)

Dazu wird das auszugebende Byte in ein REG (a) gespeichert und der 
Port-Zustand des Ausgabe-Ports in ein Zweites (b)
1
; init
2
in  Rb, <port>
3
ldi Ra, <wert>
4

5
; out
6
bst  Ra, 0
7
bld  Rb, <pad>
8
out  <port>
9
sbi  <clock>
10
cbi  <clock>
11
...

Vorteil: schneller und keine Clock auf serdata bei 0xff
Nachteil: Nicht IRQ-sicher
#885521
Lesenswert?

Dürfen clock und Date auf dem gleichen Port liegen?
1
  in  r17,port  ;1 get port data
2
  bst  datareg,7  ;1 get pix 7
3
  bld  r17,dpin  ;1 set data
4
  ori  r17,cmask  ;1 mask for set clock
5
  out  port,r17  ;1 out
6
  andi  r17,invcmask  ;1 mask for clear clock
7
  out  port,r17  ;1
8
  
9
  bst  datareg,6  ;1 get pix 7
10
  bld  r17,dpin  ;1 set data
11
  ori  r17,cmask  ;1 mask for set clock
12
  out  port,r17  ;1 out
13
  andi  r17,invcmask  ;1 mask for clear clock
14
  out  port,r17  ;1
15
  ...
braucht beide Leitungen am gleichen Port, benötigt dafür aber nur
8x6+1 = 49 Takte. Ausserdem darf kein Interrupt dazwischenkommen,
der etwa andere Portpins am gleichen Port ändert...

Gruß Jörg

...OK, da war je´mand schneller...
Gast #885534
Lesenswert?

nee, irq kommt da nicht vor. Gut wenn man den ganzen Befehlssatz kennt! 
BST ist mir noch nicht aufgefallen - sehr geschickt!

macht also 8*7 Takte für die Bits + 2 Takte fürs Init. danke, ich 
glaube, besser geht's nicht!

Doch: jetzt könnte man noch  daten und clock auf verschiedene Ports 
legen und den Trick mit dem Einlesen des Ports auch da anwenden, dann 
kann man für SBI und CBI noch 2x OUT (mit vorbelegten registern) 
schreiben und spart nochmal 2 Takte je bit.

Ich danke Euch für die Befreiung aus der Gedankenklemme und für BST! 
:-)
Persönliche Seite #885549
Lesenswert?

Falls Port_daten und Port_clock beide aufm gleichen Port liegen, geht's 
noch schneller. Hier, weil man das SBI in das OUT ziehen kann. Das OUT 
setzt also <serdata> und <clock>. Dies, wenn <clock> 
neg-flankengetriggert ist. Wenn <clock> pos-flankengetriggert ist, dann 
ist die Sequenz OUT-SBI, ansonsten wie gesagt OUT-CBI.

Ohne Initialisierung (3-4 T) dauert die Ausgabe dann 8*5T = 40T.
1
; out.0
2
bst  Ra, 0
3
bld  Rb, <pad>
4
out  <port>  ;; <clock>=1, <data>=.0
5
cbi  <clock> ;; <clock>=0
6

7
; out.1
8
bst  Ra, 1
9
bld  Rb, <pad>
10
out  <port>  ;; <clock>=1, <data>=.1
11
cbi  <clock> ;; <clock>=0
12

13
...

und indem man das CBI bzw. SBI durch OUT mit entsprechendem Wert ersetzt 
ist man bei 8*4 T = 32 T :-)
#885565
Lesenswert?

Man kann es mit 5 Takten pro Bit:

1
.nolist
2
.include "tn2313def.inc"
3
.list
4

5
.equ    SPI_PORT = PORTD
6
.equ    SPI_DATA = PD0
7
.equ    SPI_CLK = PD1
8

9
.def    data_lo = r16
10
.def    data_hi = r17
11
.def    wreg    = r18
12

13
spi_out:
14
        ldi     data_lo, 0
15
        ldi     data_hi, 1<<SPI_DATA
16

17
        out     SPI_PORT, data_lo
18
        sbrc    wreg, 7
19
        out     SPI_PORT, data_hi
20
        sbi     SPI_PORT, SPI_CLK
21

22
        out     SPI_PORT, data_lo
23
        sbrc    wreg, 6
24
        out     SPI_PORT, data_hi
25
        sbi     SPI_PORT, SPI_CLK
26

27
        out     SPI_PORT, data_lo
28
        sbrc    wreg, 5
29
        out     SPI_PORT, data_hi
30
        sbi     SPI_PORT, SPI_CLK
usw.

Schneller geht es nicht, da man das SBI für den Takt nicht durch ein OUT 
ersetzen kann, weil ja die Daten stabil sein müssen während der 
Taktflanke.


Peter
Gast #885574
Lesenswert?

also so sieht es jetzt aus (das Datenregister R17 sei vorher geladen):

'init:
'portb.4 ist data
'portc.2 ist clock

   in R19, portb   '1
   in R20, portc   '1
   andi R20, &HFB  '1   für clock=0
   in R21, portc   '1
   ori R21, &H04   '1   für clock=1
   out portc, R20  '1

'erstes bit

   bst R17, 7      '1
   bld R19, 4      '1
   out portb, R19  '1
   out portc, R21  '1
   out portc, R20  '1

'zweites bis 8. bit genauso..

das macht also 6 Takte für die Init und 8*5 für die Bits = 46 Takte. Ich 
glaube, schneller geht's nicht. Wer unter 44 kommt, kriegt einen Preis! 
:-)
Gast #885609
Lesenswert?

nee, der AVR ist der SPI Slave. Weil ich also nicht wissen kann, wann 
der SPI-Master Daten haben will (der setzt SS und schon clockt er los 
wie wild), schiebe ich sie vorher in ein Schieberegister, dadurch habe 
ich den fehlenden Buffer zur Augangsseite hin ersetzt (MISO). 
Eingangsseitig benutze ich SPI, aber da gibt's ja nen Puffer, ich kann 
mit spif abfragen etc. kein Problem. Das SPDR konnte ich leider nicht 
als Schieberegister mißbrauchen, das hab ich vorher probiert, aber dann 
komme ich ich konflikt mit meiner eingangsseitigen Beschaltung.

Das Schieberegister ist ein MC14557B / ich hoffe, es ist geeignet.

Schade, daß Du in der Pampa wohnst. Berlin ist immer ne Reise wert!
#885622
Lesenswert?

Georg johann Lay wrote:
> Was hängt denn für ein SPI-Slave dran? Wenn es ein 74*595 o.ä. ist dann
> werden die Daten per +-Flanke übernommen, und man könnte die
> 4T/Bit-Version verwenden.

Hast Du es denn schon mal ausprobiert?

Die Holdtime des 595 ist zwar 0, aber ich halte es für sehr riskant, die 
Daten gleichzeitig mit der übernehmenden Flanke zu ändern.

Die kleinste Leitungskapazität und Dein 595 läuft Amok.


Peter
Persönliche Seite #885707
Lesenswert?

Peter Dannegger wrote:
> Georg johann Lay wrote:
>> Was hängt denn für ein SPI-Slave dran? Wenn es ein 74*595 o.ä. ist dann
>> werden die Daten per +-Flanke übernommen, und man könnte die
>> 4T/Bit-Version verwenden.
>
> Hast Du es denn schon mal ausprobiert?
>
> Die Holdtime des 595 ist zwar 0, aber ich halte es für sehr riskant, die
> Daten gleichzeitig mit der übernehmenden Flanke zu ändern.
>
> Peter

Die übernehmende +-Flanke kommt ja erst 1T später. Die fallende Flanke 
sollte zusammen mit einem Wechsel an sdata ok sein.

Bei einem AVR als HW-SPI-Slave muss man allerdings bestimmte 
SPI-Taktraten einhalten, die unter denen der vom HW-SPI-Master 
erzeugbaren liegen (bei gleicher F_CPU). Ob die Einschränkungen beim 
hiesigen SW-SPI relevant sind,  ist noch zu prüfen.

Georg-Johann
Persönliche Seite #885736
Lesenswert?

shifter wrote:
> nee, der AVR ist der SPI Slave. Weil ich also nicht wissen kann, wann
> der SPI-Master Daten haben will (der setzt SS und schon clockt er los
> wie wild), schiebe ich sie vorher in ein Schieberegister, dadurch habe
> ich den fehlenden Buffer zur Augangsseite hin ersetzt (MISO).
> Eingangsseitig benutze ich SPI, aber da gibt's ja nen Puffer, ich kann
> mit spif abfragen etc. kein Problem. Das SPDR konnte ich leider nicht
> als Schieberegister mißbrauchen, das hab ich vorher probiert, aber dann
> komme ich ich konflikt mit meiner eingangsseitigen Beschaltung.
>
> Das Schieberegister ist ein MC14557B / ich hoffe, es ist geeignet.

http://www.datasheetcatalog.com/datasheets_pdf/M/C/1/4/MC14557B.shtml

sagt, der MC14557B ist bei VDD=5V maximal bis f_CL = 1.7 MHz 
spezifiziert. Je nachdem, wie fix der AVR rennt, musst den µC eher 
bremsen als das asm zu tunen...

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren