Forum: Compiler & IDEs STM32F4xx: Fragen zum startup


von Fabian (Gast)


Lesenswert?

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

von Der Weise (Gast)


Lesenswert?

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...

von Tester (Gast)


Lesenswert?

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.

von Roland H. (batchman)


Lesenswert?

> 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.

von Fabian (Gast)


Lesenswert?

>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

von Roland H. (batchman)


Lesenswert?

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 :-)

von Fabian (Gast)


Lesenswert?

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

von Roland H. (batchman)


Lesenswert?

> 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 :-)

von Fabian (Gast)


Lesenswert?

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'"

von Roland H. (batchman)


Lesenswert?

Lade doch bitte das ganze Projekt hoch - wenn es geht, bitte mit 
Makefile.

von Fabian (Gast)


Lesenswert?

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

von Fabian (Gast)


Lesenswert?

Ups, in dem Anhang "Template" oben ist der Code noch nicht drin!
@Moderator: Bitte löschen, das gibt sonst Verwirrung!

Mod: erledigt

von Roland H. (batchman)


Lesenswert?

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.

von Max P. (eizo)


Lesenswert?

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.

von Fabian (Gast)


Lesenswert?

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