Forum: Mikrocontroller und Digitale Elektronik Highspeed SPI Übertragung


von Dominik B. (matyro)


Lesenswert?

Hi,
ich habe genau 2048 AVR CPU Takte(16Mhz) Zeit um 864 Bits per USART 
(SPI-Mode) zu schreiben. Die Daten liegen in 3 Array's (hier a,b,c).
Die SPI Schnittstelle läuft mit 8MHz.

Aktuell arbeitet mein Code so:
[0xCE bzw. 206 ist das USART Puffer-Register]
1
 
2
asm volatile (  "lds r24,a"    "\n\t"      //206 = r[0][0];  2Tick
3
                "sts 0xCE,r24"  "\n\t"      //          2Tick
4
                "nop"      "\n\t"
5
                "nop"      "\n\t");
6
  
7
asm volatile (  "lds r24,a+1"  "\n\t"    //206 = r[0][1];  2Tick
8
                "sts 206,r24"  "\n\t"      //          2Tick
9
                "nop"      "\n\t"      //          1Tick
10
                "nop"      "\n\t"      //          1Tick
11
                "nop"      "\n\t"      //          1Tick
12
                "nop"      "\n\t"      //          1Tick
13
                "nop"      "\n\t"      //          1Tick
14
                "nop"      "\n\t"      //          1Tick
15
                "nop"      "\n\t"      //          1Tick
16
                "nop"      "\n\t"      //          1Tick
17
                "nop"      "\n\t"      //          1Tick
18
                "nop"      "\n\t"      //          1Tick
19
                "nop"      "\n\t"      //          1Tick
20
                "nop"      "\n\t"      //          1Tick
21
                "nop"      "\n\t"      //          1Tick
22
                "nop"      "\n\t");    //          1Tick    
23
asm volatile (  "lds r24,a+2"  "\n\t"    //206 = r[0][2];  2Tick
24
                "sts 206,r24"  "\n\t"      //          2Tick
25
                "nop"      "\n\t"      //          1Tick
26
                "nop"      "\n\t"      //          1Tick
27
                "nop"      "\n\t"      //          1Tick
28
                "nop"      "\n\t"      //          1Tick
29
                "nop"      "\n\t"      //          1Tick
30
                "nop"      "\n\t"      //          1Tick      
31
                "nop"      "\n\t"      //          1Tick
32
                "nop"      "\n\t"      //          1Tick
33
                "nop"      "\n\t"      //          1Tick
34
                "nop"      "\n\t"      //          1Tick
35
                "nop"      "\n\t"      //          1Tick
36
                "nop"      "\n\t"      //          1Tick
37
                "nop"      "\n\t"      //          1Tick
38
                "nop"      "\n\t");    //          1Tick  
39
...
40
//Array b und c analog

Leider bin ich mir unsicher ob er funktioniert, daher ob nach 16 Ticks 
das Puffer-Register wieder frei ist.
Zudem verbrauche ich so 18 Ticks pro Byte, was mit Overhead grob 
2000Ticks in Summe macht. Könnte ziemlich knapp werden...

Kennt jemand eine bessere Methode/Verbesserungen?

Ps. Später reiner ASM, das ganze soll in eine Interrupt Funktion

von Spess53 (Gast)


Lesenswert?

Hi

>Kennt jemand eine bessere Methode/Verbesserungen?

UDRE abfragen.

MfG Spess

von Dominik B. (matyro)


Lesenswert?

Ich hab mir bis jetzt gedacht das UDRE abfragen mit
1
zurueck:
2
sbis    UCSRA,UDRE                                       
3
rjmp    zurueck
langsamer ist.
rjmp braucht 2 Ticks, sbis 1/2/3 je nachdem.

Da fande ich 14 nop's besser.

Dabei zu erwähnen ist vielleicht noch das ich einen AT90 mit nur einem 
USART-Port nutze.

von Spess53 (Gast)


Lesenswert?

Hi

> sbis 1/2/3 je nachdem.

Bei rjmp nach sbis wohl eher 1/2 Takte.

MfG Spess

von holger (Gast)


Lesenswert?

>Leider bin ich mir unsicher ob er funktioniert, daher ob nach 16 Ticks
>das Puffer-Register wieder frei ist.

Warum probierst du es dann nicht aus?

>Ich hab mir bis jetzt gedacht das UDRE abfragen mit
>
>zurueck:
>sbis    UCSRA,UDRE
>rjmp    zurueck
>
<langsamer ist.
<rjmp braucht 2 Ticks, sbis 1/2/3 je nachdem.
>Da fande ich 14 nop's besser.

Denken ist scheinbar nicht dein Ding.
Ausprobieren ist nicht dein Ding.

Warum lässt du es nicht gleich sein?

von Mark L. (m2k10) Benutzerseite


Lesenswert?

Wenn's sicher schnell gehen muss, mache ich das immer so, alle 16 Takte 
ein Byte 'blind'(ohne UDRE) schreiben, erstes Byte ggf. austesten, 
dauert manchmal 1-2 Takte länger weil der SPI aktiviert wird. Die 
UDRE-Abfrage-Variante benötigt selbst im günstigsten Fall immer 2 Takte 
für sbis+rjmp mehr.

Ich würde dir aber vorschlagen(eher dringend raten ;-) eine 
Schleife(16CK-Dauer!) und ld XYZ+ statt Unmengen lds+nop zu verwenden. 
Dann sind die Daten in 1728 Takten raus und du hast Platz für viel 
Overhead.

Grüße
Mark

von Ralph (Gast)


Lesenswert?

Nimm einem µc mit mehr Dampf, oder zumindest DMA für die SPI.

Per Hand wird das so niemals stabil funktionieren.

von Dominik B. (matyro)


Lesenswert?

@Holger Vielen Dank für deine sinn­ent­leerte Antwort,spiel das einfach 
per Hand durch und du wirst merken das du nie genau auf 16Takte kommst. 
Mit 16 nop's kommt man aber problemlos auf diese. Codegröße ist mir 
relativ egal.
Also denk vorher nach bevor du irgendeinen unsinn schreibst!
Ausprobieren würde ich gerne, nur leider habe ich gerade kein Oszi zur 
verfügung.

@Mark L. Danke, werde ich umsetzen :)

@Ralph leider stehen für das Projekt nur Atmega µC zu verfügung, 
allerdings hab ich mir auch schon Gedanken gemacht den 2560 zu nehmen 
und mit 4 USART-SPI parallel zu arbeiten. Dies würde aber Mehrkosten 
verursachen die ich eigentlich umgehen wollte ;)

von Peter D. (peda)


Lesenswert?

Dominik B. schrieb:
> ich habe genau 2048 AVR CPU Takte(16Mhz) Zeit um 864 Bits per USART
> (SPI-Mode) zu schreiben.

Dann ist das Senden gepuffert, d.h. Du hast 16 Takte Zeit zum Schreiben 
des nächsten Bytes.
Die NOP-Arie ist überflüssig, teste das UDRE.

von holger (Gast)


Lesenswert?

>@Holger Vielen Dank für deine sinn­ent­leerte Antwort,spiel das einfach
>per Hand durch und du wirst merken das du nie genau auf 16Takte kommst.
>Mit 16 nop's kommt man aber problemlos auf diese. Codegröße ist mir
>relativ egal.
>Also denk vorher nach bevor du irgendeinen unsinn schreibst!

Ich muss da nicht drüber nachdenken. Im Gegensatz zu dir
probiere ich solche Dinge erst mal selber aus bevor ich
Fragen stelle. Beim SPI Modul waren es glaube ich 17 Takte bevor
man wieder in SPDR schreiben durfte.

Da du den UART für SPI benutzt und der einen zwei Byte Fifo
hat kannst du ohne Probleme UDRE abfragen und sobald es frei
meldet wieder Daten in das UART TX Register schreiben.
Da kommst du sogar besser bei weg als mit deinen fixen NOPs.

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
Noch kein Account? Hier anmelden.