Forum: Mikrocontroller und Digitale Elektronik C Programm zu langsam


von Peter Z. (Gast)


Lesenswert?

Hallo,

mein C Programm ist sehr langsam.
Die Ursache liegt in der SPI_Send_LL_Word Routine,
ich habe mit dem Osko nachgemessen,
die SCK-Impulse kommen mit 45µs Abstand.
1
void SPI_Send_LL_Word(unsigned long long int Word)
2
{
3
  for(unsigned char I=48;I;I--)
4
  {
5
    if (!(Word & 0x01))
6
    PORTB |=  (1 << SER);
7
    else
8
    PORTB &= ~(1 << SER);
9
10
    PORTB |=  (1 << SCK);
11
    Word >>= 1;
12
    PORTB &= ~(1 << SCK);
13
  }
14
  PORTB |=  (1 << RCK);
15
  PORTB &= ~(1 << RCK);
16
}
Der µC ist ein ATtiny84.
CKDIV8 habe ich ausgeschaltet.

von mouser (Gast)


Lesenswert?

aha...alles verstanden...und jetzt willst du den in ne rakete umbauen 
oder was...?

von Mischa (Gast)


Lesenswert?

Danke, gut zu wissen.

von Karl H. (kbuchegg)


Lesenswert?

Peter Zz schrieb:


> void SPI_Send_LL_Word(unsigned long long int Word)

Mach deinem AVR eine Freude und zwinge ihn nicht ...

>     Word >>= 1;

... ständig 64 Bits durch die Gegend schaufeln zu müssen, bzw. ...

>     if (!(Word & 0x01))

... mit 64 Bit hantieren zu müssen, wenns nicht sein muss.



einen unsigned long long kann man in 2 unsigned long aufteilen, die 
wiederum in 2 Stück unsigned int und die in 2 unsigned char.
Prseäntier ihm alles in mungerechten Happen in seiner Lieblingsgröße (8 
Bit), dann läuft der auch zu Hochform auf.

von Georg G. (df2au)


Lesenswert?

Peter Zz schrieb:
> CKDIV8 habe ich ausgeschaltet.

Und was für eine Quarzfrequenz?

von uC W. (ucwriter)


Lesenswert?

- Wenn man das Problem in 8 bits zerlegen kann, würde sich eine 
Hardware-SPI anbieten, falls möglich und vorhanden.

- Alternativ manuelles Loop-unrolling etwas mehr bringen

- Vielleicht auch mal die Code-Optimierung auf max. einstellen.

von kopfkratzer (Gast)


Lesenswert?

uC Writer schrieb:
> Wenn man das Problem in 8 bits zerlegen kann, würde sich eine
> Hardware-SPI anbieten, falls möglich und vorhanden.

Der Tiny84 hat USI in Hardware, da nun nacheinander 4 8bit Werte aus'm 
64bit reinzupacken sollte ja kein Thema sein ;-)

von Peter D. (peda)


Lesenswert?

Peter Zz schrieb:
> mein C Programm ist sehr langsam.

Peter Zz schrieb:
> void SPI_Send_LL_Word(unsigned long long int Word)

Welcher Compiler?

Die 64 Bit Operationen sind beim AVR-GCC nur sehr unwillig 
implementiert, sogar mit double wärst Du schneller.
Ab AVR-GCC 4.7. ist einiges gepimmt worden, aber ein Schnellläufer ist 
64 Bit trotzdem nicht.

Nimm ein Byte-Array und der AVR läuft Dir davon.


Peter

von Klaus (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Präsentier ihm alles in mungerechten Happen in seiner Lieblingsgröße (8
> Bit), dann läuft der auch zu Hochform auf.

Ich möchte wetten, das long long ist vorher extra zusammengebastelt 
worden (z.B. weil Arrays so kompliziert sind).

MfG Klaus

von Peter Z. (Gast)


Lesenswert?

kopfkratzer schrieb:
> Der Tiny84 hat USI in Hardware, da nun nacheinander 4 8bit Werte aus'm
> 64bit reinzupacken sollte ja kein Thema sein ;-)

Hat da jemand ein Beispiel dafür wie man diese UZI anspricht?

von MyName (Gast)


Lesenswert?

Das Internet hat es betimmt ;-)

von Klaus (Gast)


Lesenswert?

Peter Zz schrieb:
> Hat da jemand ein Beispiel dafür wie man diese UZI anspricht?

Bevor du jetzt eine neue Baustelle aufmachst, probiers doch erstmal in 
Software aber Byteweise. Ist ja vielleicht schon schnell genug. Dein 
Code passt ja schon fast. Für die Hardware brauchst du sowieso einzelne 
Bytes.

MfG Klaus

von Spess53 (Gast)


Lesenswert?

Hi

>Hat da jemand ein Beispiel dafür wie man diese UZI anspricht?

Kleiner Tip: Bei ATMEL gibt es AppNotes:

AVR319: Using the USI module for SPI communication on tinyAVR and 
megaAVR devices

MfG Spess

von Klaus (Gast)


Lesenswert?

uC Writer schrieb:
> - Wenn man das Problem in 8 bits zerlegen kann, würde sich eine
> Hardware-SPI anbieten, falls möglich und vorhanden.

Ja.

> - Alternativ manuelles Loop-unrolling etwas mehr bringen

Quatsch.

> - Vielleicht auch mal die Code-Optimierung auf max. einstellen.

Unsinn.

von Peter Z. (Gast)


Lesenswert?

Spess53 schrieb:
> Kleiner Tip: Bei ATMEL gibt es AppNotes:
>
> AVR319: Using the USI module for SPI communication on tinyAVR and
> megaAVR devices

Leider ist dort kein Code-Beispiel, weder in ASM noch in C

von Nik D. (y2kicn)


Lesenswert?

>>Leider ist dort kein Code-Beispiel, weder in ASM noch in C

echt?
http://www.atmel.com/Images/AVR319.zip

Bei Atmel's AppNote Übersicht gibt's jeweils einen PDF- und Zip 
Download.
(http://www.atmel.com/products/microcontrollers/avr/default.aspx?tab=documents)

von Udo S. (urschmitt)


Lesenswert?

Peter Zz schrieb:
> Leider ist dort kein Code-Beispiel, weder in ASM noch in C

Programmieren bedeutet nicht Codebeispiele abzuschreiben oder zu 
kopieren.
Hast du denn mal ausprobiert statt dem unsigned long long ein unsigned 
char array zu benutzen?

von Vlad T. (vlad_tepesch)


Lesenswert?

1
void SPI_Send_LL_Word(uint64_t Word)
2
{
3
  uint8_t* bytes = (uint8_t*)(&Word);
4
  uint8_t i= 6; // 48bits = 6byte
5
  for( ; i!=0; --i, ++bytes)
6
  {
7
    SPI_Send_Byte(*bytes);
8
  }
9
  PORTB |=  (1 << RCK);
10
  PORTB &= ~(1 << RCK);
11
}

wenn man weiß, dass der Zustand von RCK immer 0 ist, kann man das auch 
optimieren:
PINB =  (1 << RCK); // toggle einmal
PINB =  (1 << RCK); // toggle noch einmal

von Klaus (Gast)


Lesenswert?

Vlad Tepesch schrieb:
> wenn man weiß, dass der Zustand von RCK immer 0 ist, kann man das auch
> optimieren:
> PINB =  (1 << RCK); // toggle einmal
> PINB =  (1 << RCK); // toggle noch einmal

Was soll das bringen? In beiden Fällen wird nur ein Assemblerbefehl 
draus! Ebend ein sbi bzw. cbi.

von Joerg W. (joergwolfram)


Lesenswert?

sbi+cbi brauchen zusammen 4 Takte, 2x out aber nur 2 Takte und ist 
deshalb schneller.

Jörg

von uC W. (ucwriter)


Lesenswert?

Klaus schrieb:
> uC Writer schrieb:
>> - Wenn man das Problem in 8 bits zerlegen kann, würde sich eine
>> Hardware-SPI anbieten, falls möglich und vorhanden.
>
> Ja.
>
>> - Alternativ manuelles Loop-unrolling etwas mehr bringen
>
> Quatsch.
>
>> - Vielleicht auch mal die Code-Optimierung auf max. einstellen.
>
> Unsinn.
Selbstverständlich bringt manuelles Loop unrolling etwas, macht aber aus 
einem Käfer kein Ferrari.

Und wenn man nicht manuell "loop unrolled" macht es vielleicht der 
Compiler, wenn Optimierungen einschaltet sind.

von Vlad T. (vlad_tepesch)


Lesenswert?

kopfkratzer schrieb:
> Der Tiny84 hat USI in Hardware,

ehrlich gesagt, die USI habe ich bisher noch nicht so richtig 
verstanden.

Meinem Verständis gibt man der die Daten und muss dann trotzdem selbst 
für jedes Bit, was rausgesendet werden soll einen Befehl ausführen.
Von Parallelität also keine Spur. Der einzige Vorteil ist, dass es ein 
klein wenig schneller ist, als Bitbanging, aber sonst ein ziemlich 
verkrüppeltes Interface. Oder hab ich nur das Datenblatt nicht 
verstanden?

von kopfkratzer (Gast)


Lesenswert?

Vlad Tepesch schrieb:
> Meinem Verständis gibt man der die Daten und muss dann trotzdem selbst
> für jedes Bit, was rausgesendet werden soll einen Befehl ausführen.

Nö,
man stellt ein ob's SPI oder TwoWire ist, definiert ob Master oder Slave 
und dann beschickt man das Register und wartet bis die Hardware den Rest 
erledigt hat, um ein neues Datum einzutragen.
Ist vergleichbar dem ADC im FreeRunningMode :-)

von uC W. (ucwriter)


Lesenswert?

kopfkratzer schrieb:
> Vlad Tepesch schrieb:
>> Meinem Verständis gibt man der die Daten und muss dann trotzdem selbst
>> für jedes Bit, was rausgesendet werden soll einen Befehl ausführen.
>
> Nö,
> man stellt ein ob's SPI oder TwoWire ist, definiert ob Master oder Slave
> und dann beschickt man das Register und wartet bis die Hardware den Rest
> erledigt hat, um ein neues Datum einzutragen.
> Ist vergleichbar dem ADC im FreeRunningMode :-)

Das sieht hier
[Beitrag "SPI mit Attiny84"]
aber anders aus. Hab' aber USI nie benutzt.

von Peter D. (peda)


Lesenswert?

Vlad Tepesch schrieb:
> Meinem Verständis gibt man der die Daten und muss dann trotzdem selbst
> für jedes Bit, was rausgesendet werden soll einen Befehl ausführen.

Pro Bit sind es 2 Befehle und damit kommt man schon auf F_CPU/2 als 
SPI-Takt.
Schneller ist das ATmega-SPI auch nicht. Nur etwas weniger Code (keine 
16 Out-Befehle nötig).

Im Datenblatt steht auch ein Assembler-Beispiel, leicht auf C 
umzuschreiben:
14.3.2 SPI Master Operation Example

Man muß natürlich trotzdem die lahmen "long long" Variablen vermeiden, 
sonst frißt das die gesparte Zeit fast wieder auf.


Peter

von Vlad T. (vlad_tepesch)


Lesenswert?

Peter Dannegger schrieb:
> Pro Bit sind es 2 Befehle und damit kommt man schon auf F_CPU/2 als
> SPI-Takt.
> Schneller ist das ATmega-SPI auch nicht. Nur etwas weniger Code (keine
> 16 Out-Befehle nötig).
die SPI mag genauso langsam sein, aber die macht es nebenbei, während 
mein Prozessor was anderes rechnet (zb die nächsten Daten 
zurechtpopelt).
Spi ist quasi fire-and-forget, während die USI eher sowas wie betreutes 
Wohnen ist.

>
> Im Datenblatt steht auch ein Assembler-Beispiel, leicht auf C
> umzuschreiben:
> 14.3.2 SPI Master Operation Example

genau das kenne ich .

von Dennis H. (t1w2i3s4t5e6r)


Lesenswert?

Vlad Tepesch schrieb:
> Spi ist quasi fire-and-forget, während die USI eher sowas wie betreutes
> Wohnen ist.

Der Spruch ist geil, den muss ich mir merken :)


MfG Dennis

von Peter D. (peda)


Lesenswert?

Vlad Tepesch schrieb:
> die SPI mag genauso langsam sein, aber die macht es nebenbei, während
> mein Prozessor was anderes rechnet (zb die nächsten Daten
> zurechtpopelt).

Diese freien 16 Zyklen bringens natürlich, das ist der absolute Turbo.
Im Ernst, das wirst Du kaum merken.
Und SPI als Interrupt kostet ja schon >20 Zyklen Prolog+Epilog, da wirds 
also sogar langsamer.

Ein merkbarer Unterschied wäre erst, wenn das SPI gepuffert wäre, am 
besten gleich 16 Byte.
Dann könnte man auch SPI-Slave machen, ohne daß der Master immer nach 
jedem Byte lange Gedenkpausen einlegen muß.


Peter

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.