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 | float mflo; |
2 | while (1) |
3 | {
|
4 | /* PD12 to be toggled */
|
5 | GPIO_SetBits(GPIOD, GPIO_Pin_12); |
6 | |
7 | int i, 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'"
Lade doch bitte das ganze Projekt hoch - wenn es geht, bitte mit Makefile.
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
Ups, in dem Anhang "Template" oben ist der Code noch nicht drin! @Moderator: Bitte löschen, das gibt sonst Verwirrung! Mod: erledigt
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...
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.