Forum: Compiler & IDEs Sinusberechnung LPC vs AVR


von Bernd (Gast)


Lesenswert?

Ich habe bis jetzt nur mit AVR gearbeitet.
Da ich für ein kommendes Projekt viel rechnen muss habe ich mir mal das 
Keil ARM Eval Kit runtergeladen.
Dann habe ich einfach mal in das Blinky Beispiel folgende Berechnung 
eingefügt:
Static float x = 3.14;
X = sin(x);

Im Keil Simulator benötigt der LPC im ARM Modus ca. 25.000 Zyklen und 
ca. 400µs für die Berechnung bei 60MHz Takt.
Mein AVR mit 20 MHz Takt mit WINAVR benötigt für dieselbe Berechnung die 
gleiche Zeit.
Ist das normal das der LPC (bzw. die Keil sinus lib) so langsam ist?

Gruß
Bernd

von let (Gast)


Lesenswert?

Ich weiß nicht was die Keil Lib da macht aber die sin()
Funktion rechnet eigentlich mit doppelter Genauigkeit.
Da hilft es auch nicht einen float zu übergeben.
Das das 25000 Takte dauern soll überrascht mich aber schon
etwas.
Der avr-gcc verwendet bei Gleitkomma immer 'float'.

Mit dem Codevision AVR dauert die Rechnung übrigens 130µs. Der
rechnet wie der GCC mit 32bit.


 - Michael

von Bernd (Gast)


Lesenswert?

Ich will es ja auch nicht glauben, dass das so lange dauert - ist aber 
so (auch wenn er mit double rechnet).
Vielleicht kann ich ja cuh nicht die Keil IDE bedienen.

von let (Gast)


Lesenswert?

Ich habe das jetzt mal gemessen:
1
volatile unsigned int value1, value3;
2
volatile float x = 3.14;
3
4
//! test
5
value1 = T0TC;
6
x = sin(x);
7
value3 = T0TC;
8
value3 -= value1;
9
rprintf("Ergebnis: %u\n", value3);
10
// /test
11
12
.lss:
13
    //! test
14
    value1 = T0TC;
15
     598:  e2865901   add  r5, r6, #16384  ; 0x4000
16
     59c:  e5953008   ldr  r3, [r5, #8]
17
     5a0:  e59f60ec   ldr  r6, [pc, #236]  ; 694 <.text+0x694>
18
     5a4:  e5863000   str  r3, [r6]
19
    x = sin(x);
20
     5a8:  e59f40e8   ldr  r4, [pc, #232]  ; 698 <.text+0x698>
21
     5ac:  e5940000   ldr  r0, [r4]
22
     5b0:  eb000fff   bl  45b4 <__aeabi_f2d>
23
     5b4:  eb000748   bl  22dc <sin>
24
     5b8:  eb0011aa   bl  4c68 <__aeabi_d2f>
25
     5bc:  e5840000   str  r0, [r4]
26
    value3 = T0TC;
27
     5c0:  e5953008   ldr  r3, [r5, #8]
28
     5c4:  e59f10d0   ldr  r1, [pc, #208]  ; 69c <.text+0x69c>
29
     5c8:  e5813000   str  r3, [r1]
30
    value3 -= value1;
31
     5cc:  e5913000   ldr  r3, [r1]
32
     5d0:  e5962000   ldr  r2, [r6]
33
     5d4:  e0623003   rsb  r3, r2, r3
34
     5d8:  e5813000   str  r3, [r1]
35
    rprintf("Ergebnis: %u\n", value3);
36
     5dc:  e5911000   ldr  r1, [r1]
37
     5e0:  e59f00b8   ldr  r0, [pc, #184]  ; 6a0 <.text+0x6a0>
38
     5e4:  eb000042   bl  6f4 <rprintf>
39
    // /test

Der Timer0 zählt mit einer Auflösung von 1µs und die Ausgabe
ist: "Ergebnis: 48"
Gerechnet wird mit double. Das ganze läuft auf einem LPC2148
bei 60MHz.
Compiler: arm-elf-gcc (GCC) 4.1.2 (WinARM 4/2007)

 - Michael

von Bernd (Gast)


Angehängte Dateien:

Lesenswert?

Hi,
Danke für deine Mühe.
Ich habe jetzt auch mal den Timer mitlaufen lassen - mit dem gleichen 
Ergebnis.
Mit der Keil GNU IDE bekomme ich nach der sin Berechnung einen Timerwert 
von 459 = 459 µS. Also ca. den Faktor 10 langsamer als bei dir.
Ich habe mal meinen Code mit Startup usw. beigefügt.
Vielleicht kannst du ihn mal bei dir testen?

von Bernd (Gast)


Lesenswert?

Für die Addition von zwei ints brauche ich 15 Takte -
bei doubles schon 660 Takte.

Muss ich vielleicht eine spezielle lib für floating point einbinden?

von let (Gast)


Lesenswert?

Seltsam. Ich prüfe noch mal meine Timer-Konfiguration.
Der Teiler steht auf 60-1 aber vielleicht ist die PClk
langsamer als 60MHz. Am besten lasse ich mal eine LED
im Sekundentakt timergesteuert blinken.
Mal sehe ob ich heute Abend dazu komme weiter zu forschen
bzw. deinen Code laufen zu lassen.

 - Michael

von let (Gast)


Lesenswert?

Sorry, hat etwas gedauert. Ich habe mir mein Programm bzw.
die Konfiguration nochmal angesehen und ich bin mir sicher
das F_CLK = P_CLK = 60MHZ ist.
Toggeln einer LED und rücksetzen von Timer0 wenn T0TC
1.000.000 erreicht hat führt zu einer Blinkfrequenz von
0,5Hz (1s an, 1s aus).

Dein Testprogramm habe ich nicht laufen lassen aber die
startup.s habe ich mir angesehen. Meiner Ansicht nach stimmt
die PLL Initialisierung nicht.
1
.equ    PLLCFG_MSEL,    (0x1F<<0)   /* PLL Multiplier */
2
.equ    PLLCFG_PSEL,    (0x03<<5)   /* PLL Divider */
Das sind die Konstanten M und P. P steht hier auf 8, was
völlig O.k ist aber M ist 32. Laut dem PLL-Tool von
Philips entspricht das (theoretisch) einer F_CLK von 384MHz.
Bei einem 12MHz Quarz müßte M=8 sein.

Was passiert denn wenn du die MSEL Zeile wie folgt abänderst:
1
.equ    PLLCFG_MSEL,    (0x04<<0)   /* PLL Multiplier */
Vielleicht interessiert sich der Simulator aber auch gar nicht
dafür (ich habe den nie benutzt).

Wenn ich das richtig überblicke wird in der timer.c der Timer
durch den Match-Interrupt alle 155µs zurückgesetzt und 'timeval'
um eins hochgezählt. Zumindest dann wenn der Kern mit 60MHz
getaktet wird. Die Peripherie läuft dann mit 30MHz.

 - Michael

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.