Hallo,
ich programmiere jetzt seit einiger Zeit die STM32 Controller mit dem
Atollic TrueStudio. Ich frage mich jetzt nur ob die FPU der STM32F4
Controller wirklich gestartet wird. Ausgewählt habe ich im
Projekt-Erstellen Dialog vom Atollic TrueStdio "Floating Pointing : Mix
HW/SW implementation". Im Startup-Code steht auch
1
/*FPU settings*/
2
ldrr0,=0xE000ED88/* Enable CP10,CP11 */
3
ldrr1,[r0]
4
orrr1,r1,#(0xF<<20)
5
strr1,[r0]
Hat jemand eine Idee wie ich rausfinden kann ob die FPU läuft?
Moritz
Moritz M. schrieb:> Hat jemand eine Idee wie ich rausfinden kann ob die FPU läuft?
Wieso sollte sie nicht laufen, nachdem Du CP10/11 aktiviert hast? Um das
zu prüfen lässt Du einfach einen FPU Befehl ausführen und schaust, ob er
das gewünschte Ergebnis liefert.
--
Marcus
Hallo,
okay vielen Dank! Wie würde den so ein FPU Befehl aussehen? ich dache
wenn ich mit Gleitkomma rechne würde die FPU das automatisch erledigen?
Moritz
>Wie würde den so ein FPU Befehl aussehen? ich dache
-> Cortex reference manuals.
>wenn ich mit Gleitkomma rechne würde die FPU das automatisch erledigen?
Wenn Du die richtigen Compileroptionen anwendest oder in Assembler
programmierst und den Rat von Marcus oben befolgst, sollte
das auch passieren.
Moritz M. schrieb:> ich dache> wenn ich mit Gleitkomma rechne würde die FPU das automatisch erledigen?
Wenn man dem Compiler mitteilt, dass man das möchte, dann ja:
Gut dass es diesen Thread gibt ;-)
Nicht alle haben bisher die FPU richtig benutzt, bzw. wissen wie es
richtig geht (incl. mich).
Zum ersten, wenn man die Compileroptionen (siehe oben) setzt und man hat
nicht diese 4 Assember Befehle für das Aktivieren der FPU drin und man
nutzt float Zahlen, dann gibt es einen Absturz mit
"Hard-Fault-Exception()" Interrupt.
Somit muss immer beides gemacht werden.
Verwirrender weise zeigt das Listing von GCC den Assembler Befehl
"fmuls" hingegen im Disassembler Fenster beim Debuggen "vmul.f32" an.
Nun zu meinen kleinen Tests:
1
floatf=1.01f;
2
CORE_SysTickEn();
3
vu32it=CORE_GetSysTick();
4
floatf2=f*2.29f;
5
vu32it2=CORE_GetSysTick()-it;
Das Ergebnis ist bei der GCC und der FPU Variante immer gleich. Nur der
Windows Taschenrechner zeit eine andere Zahl.
Die Taktberechnung verbraucht 6 Takte, die habe ich von der
Float-Zählung abgezogen:
GCC: 41
FPU: 5
Dann habe ich die Zeile geändert:
1
floatf2=f/2.29f;
GCC: 155
FPU: 21
Ist doch ein deutlicher Unterschied.
Testboard: STM32F4-Discovery
Compiler: arm-none-eabi-gcc.exe (Sourcery CodeBench Lite 2011.09-69)
4.6.1
Optimierungsstufe: -O0
Defines für den Systic:
1
// Sys-Tick Counter - Messen der Anzahl der Befehle des Prozessors:
Markus Müller schrieb:> Somit muss immer beides gemacht werden.
Ich dachte, das sei nach den beiden ersten Postings klar ;-)
Markus Müller schrieb:> Defines für den Systic:// Sys-Tick Counter - Messen der Anzahl der Befehle des
Prozessors:
> #define CORE_SysTickEn() (*((u32*)0xE0001000)) = 0x40000001> #define CORE_SysTickDis() (*((u32*)0xE0001000)) = 0x40000000> #define CORE_GetSysTick() (*((u32*)0xE0001004))
Ist das der Cortex-SysTick?
Wo hast Du denn diese Adressen/Register gefunden?
Das ist der Befehls-Counter mit dem man exakt messen kann wie viele
Clock-Takte der CPU für die Bearbeitung vergehen.
Die Register stehen im "Cortex-M3 Technical Referenz Manual" unter "Data
Watchpoint and Trace registers" der Firma ARM. Such einfach nach
"E0001000".
Das geht somit auch beim LPC17xx und anderen Prozis mit einem
Cortex-M3/M4 drin.
Dieser Befehl ist wichtig, wenn man Zeitkritische Anwendungen hat und
man kann somit exakt feststellen wie viele µS eine Routine benötigt. Ich
musste mal AD-Interrupts recht komplex berechnen, da war es natürlich
wichtig, dass die Routine weniger Zeit braucht, als wie der Interrupt
erneut aufgerufen wird und die App genügend Reserve hat.
Beim ARM7 musste man dafür noch extra einen Timer
konfigurieren/missbrauchen.
Markus Müller schrieb:> Die Register stehen im "Cortex-M3 Technical Referenz Manual" unter "Data> Watchpoint and Trace registers" der Firma ARM. Such einfach nach> "E0001000".
Aha. Mich hat die Angabe "SysTick" verwirrt. Denn damit assoziiere ich
den Cortex SysTick Timer, dessen Register an einer anderen, aber
ähnlichen Adresse liegen.
Zu "E0001000" findet sich leider auch nix in core_cm4.h
Sehr interessant - wieder etwas gelernt.
Roland H. schrieb:> Zu "E0001000" findet sich leider auch nix in core_cm4.h>> Sehr interessant - wieder etwas gelernt.
Das ist der optimistische Standpunkt :-)
Man könnte auch sagen, die Datenblätter sind zu bescheiden. Die
Stückelinformationen von STM gehen mir machmal auf den Geist!
Vollprofi schrieb:> Die> Stückelinformationen von STM gehen mir machmal auf den Geist!
Das trifft den Falschen.
core_cm4.h wird von ARM bereitgestellt. Das hat mit STM nix zu tun.
Hallo,
wer weiß den wo man die Compiler-Optionen im Atollic TrueStudio einfügen
muss? (Arbeite noch nicht solange mit Atollic TrueStudio)
Ausserdem fügt Atollic TrueStudio auch den Code
1
/*FPU settings*/
2
ldrr0,=0xE000ED88/* Enable CP10,CP11 */
3
ldrr1,[r0]
4
orrr1,r1,#(0xF<<20)
5
strr1,[r0]
ein, wenn man "Floating Pointing: Software implementation" auswählt.
Moritz
Benutzt du denn die Vollversion von Atollic TrueStudio.
Die frühen Demoversionen konnten kein Hardware Fließkomma und die
aktuellen können zwar Fließkomma aber haben eine Größenbeschränkung.
Soviel ich weiß kann die code sourcery lite von 2011 die du verwendest
noch keine native FPU Unterstützung des Cortex M4. Dagegen soll die von
ARM (https://launchpad.net/gcc-arm-embedded/4.6) herausgegebene
Toolchain dies können (habe ich nicht verifiziert). Ich habe diese
anstatt der code sourcery lite installiert und die geht stattdessen
einwandfrei.
Grüße
Zitat aus lauchpad.net:
Features:
* All GCC 4.6 features, plus latest mainline features
* Cortex-M0/M1/M3 support
* Cortex-M4 with hard float multilib support
Markus Müller schrieb:> Ich nutze Codesourcery Lite und wie man oben sieht (Taktmessung) klappt> das auch mit den FPU Befehlen.
Das kann ich auch bestätigen, solange keine Funktionen aus der Mathlib
verwendet werden.
Bei der Version von Launchpad ist eine Multilib dabei, da klappt es auch
mit mathematischen Funktionen und der FPU. Das hab ich getestet.
Hallo,
okay ich hab jetzt die CooCox CoIDE. Wo fügt ihr die FPU Init Befehle
ein?
(startup_stm32f4xx.c ?)
Ich finde es übrigens super dass das gleich in das STM32-Tutorial
eingefügt wurde! :)
Moritz
Aktivierung ist in den STMicro Beispielen für STM32F4 aus der
StdPeriphLib (das ist nicht das Codepacket zum STM32F4 Discovery-Board)
in system_STM32F4.c/SystemInit() untergebracht. Sieht so aus:
SCB->CPACR|=((3UL<<10*2)|(3UL<<11*2));/* set CP10 and CP11 Full Access */
6
#endif
7
...
__FPU_PRESENT und __FPU_USED werden in STM32F4xx.h bzw. core_cm4.h
definiert, in letzterer durch Auswertung von vordefinierten Macros in
Abhängigkeit von den Compileroptionen.
Man kann relativ leicht die StdPeriphLib aktualisieren, muss dann nur
auf die HSE-Frequenz und die PLL Einstellung in SystemInit achten.
Hallo!
Wenn ich das Beispiel von Markus Müller auf meinem STM32F4Discovery
probiere komme ich auch auf die 21 Takte bei der Division, nur bei der
Multiplikation auf 12 Takte anstatt wie bei ihm 5 Takte.
Was könnt der Grund hierfür sein?
In CP10 steht 0b11 und in CP11 auch 0b11!
Der Disassembly Code für die Multiplikation:
float f2 = f * 2.29f;
ED977A03 vldr s14, [r7, #12]
EDDF7A0B vldr s15, 0x080003F0 <__text_start__+0x5C>
EE677A27 vmul.f32 s15, s14, s15
EDC77A02 vstr s15, [r7, #8]
Danke für eure Hilfe!!
Hi, hab ne Zwischenfrage zu "__FPU_PRESENT und __FPU_USED werden in
STM32F4xx.h bzw. core_cm4.h definiert"
In der STM32F4xx.h steht
#define __FPU_PRESENT 1 /*!< FPU present
Dennoch erhalte ich beim bauen folgende Fehlermeldung:
Libraries\CMSIS\Include/core_cm4.h:131:8: warning: #warning "Compiler
generates FPU instructions for a device without an FPU (check
__FPU_PRESENT)"
Ich habe als Flag -D"ARM_MATH_CM4" eingetragen, damit der Kompiler die
Mathe-Funktionen lädt. Hab ich etwas vergessen?
Ich hatte ein ähnliches Problem und habe in diesem Thread einige
Antworten auf meine Fragen gefunden. Ich möchte hier noch ergänzen, was
zu tun ist, damit auch die Quadratwurzel von der FPU berechnet wird. Als
Entwicklungsumgebung verwende ich eclipse unter Linux (siehe
http://www.mikrocontroller.net/articles/STM32F4-Discovery).
*) Die von Roland H. oben genannten Compiler-Optionen lassen sich in
eclipse bequem unter "Project->Properties->C/C++ Build->Settings->Tool
Settings->Target Processor" einstellen.
*) Im release-Modus wird standardmäßig mit der Option "-Os" kompiliert,
die für minimale Größe des generierten Codes sorgt. Dabei wird offenbar
der Aufruf einer Bibliotheksfunktion bevorzugt. Um das zu ändern, muss
die Laufzeit optimiert werden, z.B. mit der Option "-O3". Das geht im
gleichen Dialog-Fenster unter "...->Tool Settings->ARM Linux GCC C
Compiler->Optimization->Optimization level".
*) Die C-Funktion sqrt() berechnet die Quadratwurzel in "double
precision", wandelt also das Argument in double um, berechnet die
Wurzel, und wandelt das Ergebnis zurück in float um (alles auf der CPU).
Um die Berechnung auf der FPU zu erzwingen, ist die Funktion sqrtf() zu
verwenden. Im Disassembler kann man dann verifizieren, dass tatsächlich
der Befehl "vsqrt.f32" ausgeführt wird.
Schöne Grüße,
Markus
Erstmal vielen Dank, das ist schon sehr sehr hilfreich, was hier
gepostet ist!
Aber eine Ergänzung hat mir noch gefehlt.
Bei mir gab es mit dem Flag beim Linken
Hallo,
ich belebe den fred nochmal, weil ich ein ähnliches Problem habe:
Ich betreibe ein Olimex board mit einem STM32F405 unter C mit gcc und
Eclipse, ich lade das Programm über JTAG.
Geht alles wunderbar, solange ich kein float benutze.
Falls ich das tue, übersetzt und linkt er problemlos, der 'launcher'
meckert aber mir unverständliches.
In stm32f4xx.h finde ich:
#if !defined (__FPU_PRESENT)
#define __FPU_PRESENT 1 /*!< FPU present
*/
#endif /* __FPU_PRESENT */
scheint ok.
Wenn ich sowas in die main.c einbaue meckert der Compiler, beide Werte
sind also 1
#if (__FPU_PRESENT == 1)&& (__FPU_USED == 1)
hhhhhhh
#endif
Im Makefile steht:
CFLAGS += -mfloat-abi=hard
CFLAGS += -mfpu=fpv4-sp-d16
Im Makefile nur angegeben:
CFLAGS += -mfloat-abi=hard
geht auch nicht.
CFLAGS += -mfloat-abi=softfp
geht auch nicht
Irgendwo ist noch ein Schalterchen, das ich nicht kenne. Könnt Ihr mir
den verraten?
Bin ARM Anfänger, weiß ich.
THX
Cheers
Detlef
Noch was: Wieso kennt er 'cos' nicht wenn ich math.h include?
Noch noch was: Wie kann ich das Listingfile des Assemblers behalten,
meine Konfiguration schmeist das weg?
Die FPU units sind eingeschaltet, das wird bei SystemInit gemacht, die
Defines sind beide 1:
/* FPU settings
------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11
Full Access */
#endif
Was kanns denn sonst noch sein?
Cheers
Detlef
Ich habe nochmal tiefer gegraben, meine Konfiguration machte laut
Assemblerlisting Soft-floatingpoint.
Wenn ich das -mfpu=fpv4-sp-d16 Flag rausgenommen habe, also so
#CFLAGS += -mfpu=fpv4-sp-d16
hat er Hard-floatingpoint kompiliert aber ist trotzdem irgendwo
abgeschmiert, wenn ich floating-point benutzt habe.
Ich kann kein float aufm CortexM4, wieso könnt Ihr das?
Cheers
Detlef
SuseLunix schrieb:> Du nimmst schon "float", kein "double" oder?
Das war es!
Ich habe mir für die Tests das Ergebnis von 0.7*(n++) ausgeben lassen.
Das in 0.7f*(n++) geändert beendet alle Probleme (naja, erstmal).
Danke!!!
Cheers
Detlef
gut. Hab die FPU selbst noch nicht benutzt, will das aber in den
nächsten Tagen tun und hab mich gestern Abend etwas eingelesen. Und da
bin ich über ein Dokument/Webseite gestolpert wo stand, dass es bei
double eine Hardware exception gäbe.
Die FPU ist halt für float (32Bit) gemacht. Double sollte eigentlich
über Bibliotheksfunktionen laufen.
Aber wie gesagt, ich stehe auch gerade am Anfang bzw. bald vor den
gleichen Problemen.
Hallo,
nochwas zum CortexM4:
sinf ist laut math.h die float Variante vom Sinus.
Der Linker findet aber die lib wohl nicht: undefined reference.
Was für ne lib muss ich denn dazu noch einbinden?
gute Nacht
Detlef
Hallo,
Du kopierst die libm.a in den Projektordner wo sich auch schon die
libgcc.a befindet. libm.a gibts gibts in mindestens drei
Geschmacksrichtungen: hard/soft float, thumb. Die richtige nehmen. Dann
libm.a in die Linker commandline, wo auch schon libgcc.a vorhanden ist.
Cheers
Detlef