Hallo ich habe mir ein STM32F4-Discovery-Board zugelegt und gerade den
Eclipse-Codesourcery-Toolchain aufgesetzt.
Als erstes hab ich mich durch die Beispielprojekte geklickt und bin am
Startup-Code (startup_stm32f4xx.S) hängen geblieben.
Dort fand ich zwei wundersame Einträge:
...
.cpu cortex-m3
.fpu softvfp
...
Die erste Zeile kann ich mir halbwegs erklären: Die Cortex-M4 sind
codekompatibel zu den Cortex -M3(?).
Warum wird aber eine Emulation statt der Hardware FPU gewählt?
Oder spielt das einfach keine Rolle, weil die FPU im startup sowieso
nicht gebraucht wird? Auf den Rest des Programms hat das keine
Auswirkungen, oder?
Fabian
Fabian schrieb:> Auf den Rest des Programms hat das keine> Auswirkungen, oder?
Wenn man den Compiler auf Hard-FPU stellt (kann man zB beim Atollic
Studio beim Projekt erstellen) wird die eben auch verwendet, der
Compiler interessiert sich ja nicht für diese Assembler-Datei. Warum das
da im Startupcode drinsteht weiß ich jetzt aber auch nicht...
Mann muss unterscheiden zwischen Cortex M4 und Cortex M4F, nur letzterer
hat eine FPU. Wenn man einen M4F ohne FPU betreibt ist es letzlich ein
M4 und ein M4 verhält sich erstmal genauso wie ein Cortex M3.
> Die erste Zeile kann ich mir halbwegs erklären: Die Cortex-M4 sind> codekompatibel zu den Cortex -M3(?).
Ich hatte das mal - im Zuge der Aktivierung der FPU - auf cortex-m4
geändert. M. W. macht das aber keinen Unterschied, M3 und M4 basieren
beide auf ARMv7-M.
> Warum wird aber eine Emulation statt der Hardware FPU gewählt?> Oder spielt das einfach keine Rolle, weil die FPU im startup sowieso> nicht gebraucht wird?
Spielt keine Rolle. FPU wird im startup eher selten benötigt :-)
> Auf den Rest des Programms hat das keine> Auswirkungen, oder?
Nein. Bezieht sich nur auf den startup. Für C/C++ spielt die
-mcpu-Einstellung eine Rolle, ggf. ergänzt um -mfloat-abi und -mfpu.
>Ich hatte das mal - im Zuge der Aktivierung der FPU - auf cortex-m4>geändert.>Nein. Bezieht sich nur auf den startup. Für C/C++ spielt die>-mcpu-Einstellung eine Rolle, ggf. ergänzt um -mfloat-abi und -mfpu
Wie geht das genau vor sich?
Wenn ich unter Properties->C/C++ Build->Settings->Tool Settings den
cortex-m4 auswähle, erstellt der GCC Code, der die FPU nutzt?
Den Cortex-M4F hab ich nicht in der Liste.
Reicht das, oder muss ich da noch mehr machen?
Fabian
Fabian schrieb:> Wenn ich unter Properties->C/C++ Build->Settings->Tool Settings den> cortex-m4 auswähle
Komisch. Finde ich bei mir im Emacs gar nicht ;-)
> den cortex-m4 auswähle, erstellt der GCC Code, der die FPU nutzt?
M. W. nach nicht, sonder nur bei cortex-m4f.
Ich setze deshalb explizit:
1
-mcpu=cortex-m4
2
-mfloat-abi=hard
3
-mfpu=fpv4-sp-d16
beim stm32f407.
Und danach war im Assembler-Listing etwas, was nach FPU aussieht (z. B.
vmul.f32 anstelle von Funktionsaufrufen).
Prüf's mal nach, am besten mit einer kleinen Performance-Messung :-)
Danke! Werde ich morgen tun! Ein Unterschied ist schon sichtbar: mit
-mfloat-abi=hard ist der Code ein paar hundert Byte kleiner als mit
-mfloat-abi=soft.
Das Flag ist wohl ziemlich geheim...
"-mfloat-abi" ist der erste Suchbegriff, den ich kenne, bei dem Google
Null Treffer hat! ;-)
Fabian
> Ein Unterschied ist schon sichtbar: mit> -mfloat-abi=hard ist der Code ein paar hundert Byte kleiner als mit> -mfloat-abi=soft.
Ein gutes Zeichen.
> Das Flag ist wohl ziemlich geheim...> "-mfloat-abi" ist der erste Suchbegriff, den ich kenne, bei dem Google> Null Treffer hat! ;-)
Wenn Du mit Anführungszeichen suchst, also "-mfloat-abi", dann wird Dir
geholfen :-)
So, dann mal das Ergebnis:
Ich habe es leider nicht geschafft, den Controller mit einer der
FPU-Einstellungen
-mfloat-abi=hard
-mfloat-abi=soft
-mfloat-abi=softfp
ans laufen zu kriegen. Compilieren war kein Problem, aber bei der ersten
Rechenoperation ist er in die Exception-Routine "HardwareFault"
gesprungen.
Ich habe auch verschieden weitere Einstellungen probiert, leider alles
ohne Erfolg.
Eine Performancemesung hab ich trotzdem gemacht (alle Flags bzgl. fpu
wieder rausgenommen):
1
floatmflo;
2
while(1)
3
{
4
/* PD12 to be toggled */
5
GPIO_SetBits(GPIOD,GPIO_Pin_12);
6
7
inti,k;
8
9
10
mflo=0;
11
12
for(i=0;i<50000;i++)
13
{
14
mflo=mflo+3.0f;
15
16
};
17
18
19
GPIO_ResetBits(GPIOD,GPIO_Pin_12);
20
21
22
k=0;
23
24
for(i=0;i<50000;i++)
25
{
26
k=k+3;
27
28
};
29
}
Ergebnis ist folgendes: Highzeit: 22,62ms, Lowzeit 5,645ms
High/Low = 4,00... . Die Integer-Rechnung ist nur um den Faktor vier
schneller! So ganz ohne FPU lauft das anscheinend nicht ab; eine reine
Emulation hätte sicher zu einem Faktor >10 geführt.
Ich kann daraus bis jetzt keine Taktzyklenzahl berechnen. Auf dem Board
ist wohl ein 8MHz-Oszillator drauf, was die interne PLL aber mit den
Standardeinstellungen (ich hab da nix verstellt) daraus macht, weiß ich
noch nicht.
Der Compiler wird mit folgenden Flags aufgerufen:
"-I"F:/workspace/Template" -O0 -Wall -Wa,-adhlns="main.o.lst" -c
-fmessage-length=0 -MMD -MP -MF"main.d" -MT"main.d" -mcpu=cortex-m3
-mthumb -g3 -gdwarf-2 -o "main.o" "../main.c"
'Finished building: ../main.c'"
Ich habe mal .lst unter die Lupe genommen (mit Flags):
...
mflo = mflo + 3.0f;
8000210: ed97 7a03 vldr s14, [r7, #12]
8000214: eef0 7a08 vmov.f32 s15, #8
8000218: ee77 7a27 vadd.f32 s15, s14, s15
800021c: edc7 7a03 vstr s15, [r7, #12]
...
Das sieht sehr nach einem float-Befehl aus, der Controller blieb aber
trotzdem hängen, auch ohne Debugger!
Die Einstellungen
.cpu cortex-m4
.fpu vfp
im startup hatten jedenfalls keinen Effekt.
Durch ein zufälliges Suchergebnis bin ich auf diesen Link gestoßen:
http://forums.leaflabs.com/topic.php?id=1056&page=4
Zitat:
>Some infos to get the F4 FPU running:>- the CodeSourcery arm-none-eabi-gcc-4.5.2 works fine>- to be able to use the fpu use the compiler options -mfpu=fpv4-sp-d16 >-mfloat-abi=softfp>- make sure you do NOT use -fpack-struct, as the fpu load and save>instructions need word aligned addresses. Otherwise the code throws an>exception using unaligned addresses.>- the fpu needs to be enabled in the startup code somewhere. Currently I >use>ldr r0, =0xe000ed88 //; enable cp10,cp11> ldr r1,[r0]> ldr r2, =0xf00000> orr r1,r1,r2> str r1,[r0]>in start.S, but it might be better to add>SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full >Access
*/
>somewhere.
Zitat Ende.
Seit dem ich den Assembler Code ins startup eingefügt habe arbeitet die
FPU!
Na dann ... let's rock!
Fabian
Fabian schrieb:> Seit dem ich den Assembler Code ins startup eingefügt habe arbeitet die> FPU!
Aha. Komisch, bei mir war das dabei (discovery) - ich hatte damals die
startups von CM3 und CM4 verglichen, dabei sind mir die vier Zeilen
aufgefallen. Die Version in meinen Dateien sind sogar älter !?
Schön dass es jetzt geht.
> Ups, in dem Anhang "Template" oben ist der Code noch nicht drin!> @Moderator: Bitte löschen, das gibt sonst Verwirrung!
Einfach nochmals posten.
Ich habe es nicht getestet, er sollte mit 168 MHz rennen.
Ganz nett wäre es, noch eine UART-Ausgabe für UART2 zu machen, und mit
einem Timer die Zeit messen für x Durchläufe.
Bitte daran denken, dass der GCC je nach Optimierung evtl. Deinen Code
auf nix zusammenstutzt, da alle Variablen nicht wirklich verwendet
werden. Deshalb alles irgendwie zusammenzählen, und dann am Ende z. B.
via UART ausgeben. volatile ist nicht hilfreich, da es den GCC von
Optimierungen abhält.
Bitte noch von "Template" nach "fpu-demo" oder so umbenennen.
Ich würde es dann so zusammenbauen, dass "Auspacken", "make" zum Bauen
für Linux genügt - es gibt hier immer Bedarf für eine kleine STM32 App
mit etwas SystemInit, GPIO, UART, Timer. Mit FPU umso besser.
Die oben erwähnten Hinweise beziehen sich ja auf die Codesourcery
Toolchain. Hat schon jemand die FPU mit der Yagarto Toolchain
erfolgreich in Betrieb nehmen können? Bei -mfloat-abi=hard kommt es dort
zu Fehlern.
Max Power schrieb:> Bei -mfloat-abi=hard kommt es dort> zu Fehlern.
Geht es etwas genauer? Am besten lädst du mal den Code und die Ausgabe
auf der Console hoch...
Roland H. schrieb:> Ganz nett wäre es, noch eine UART-Ausgabe für UART2 zu machen, und mit> einem Timer die Zeit messen für x Durchläufe.
Dafür fehlt mir im Moment noch die Erfahrung mit den Libs, das wird
etwas dauern...