Ahoi Community,
ich verwende der zeit das TM4C123GXL Launchpad von TI. Der darauf
verbaute Controller ist mit einem Cortex M4 Prozessor ausgestattet.
Zusätzlich verfügt der µC über eine FPU. Ich habe bisher nur mit dem
ATmega8 gearbeitet und die bisherigen Programme für den TM4C123 habe ich
alle mit integer Berechnung durchgeführt.
1) Kann mir jemand verraten ob meine float Berechnungen bei Aktivierung
der FPU automatisch über die FPU mit den integrierten Funktionen (VADD,
VDIV, VSQRT...) berechnet werden oder muss ich diese erst als Funktionen
in Assembler Code anlegen
Beispiel: Wurzelberechnung
CalcSqrt
VSQRT.F32 S0,S0 ; sqrt(input)
BX LR
Beispiel: Multiplikation
CalcMultiply
VMUL.F32 S0,S0,S1 ; multiply(input1, input2)
BX LR
2) Wird die Instruktion VSQRT.F32... bzw. VMUL.F32 automatisch
ausgeführt wenn ich die in math.h enthaltene Funktion sin(float x) bzw.
A * B verwende?
Hier ein Link zum M4 Instruction Set:
http://users.ece.utexas.edu/~valvano/EE345L/Labs/Fall2011/CortexM_InstructionSet.pdf
Du kannst deinem Compiler mitteilen, dass er die Floating Point
berechnungen in Hardware machen soll, der linked dann automatisch die
richtige Library. In GCC (afaik auch im TI Compiler) geht das mittels
1
-mfloat-abi=hard
Eventuell gibt es im Eclipse basierten CCS auch eine Einstellung bei den
Architektur-Optionen.
Eventuell kann es auch notwendig sein
-march armv7e-m -mfpu=fpv4-sp-d16
zu spezifizieren.
Vielen Dank für die schnelle Antwort. Ein paar Fragen habe ich noch.
1) Im Datenblatt des TM4C123 wird ie FPU mittels:
; CPACR is located at address 0xE000ED88
LDR.W R0, =0xE000ED88
; Read CPACR
LDR R1, [R0]
; Set bits 20-23 to enable CP10 and CP11 coprocessors
ORR R1, R1, #(0xF << 20)
; Write back the modified value to the CPACR
STR R1, [R0]; wait for store to complete
DSB
;reset pipeline now the FPU is enabled
ISB
aktiviert. Erzeugt dieser Code das selbe Ergebnis oder wird die FPU
dadurch tatsächlich "nur" aktiviert?
2) Ich verwende als IDE KeilµV. Habe dazu noch eine fred gefunden:
http://www.keil.com/support/docs/3716.htm
Wenn ich das richtig verstehe muss kann ich die Nutzung der FPU über die
IDE einstellen : off, single precision, (double precision -> nicht bei
M4)
3) Ist die tatsächliche Berechnung mittels assembler C=CalcMultiply(A,B)
mit
CalcMultiply
VMUL.F32 S0,S0,S1 ; multiply(input1, input2)
BX LR
schneller als die C Instruktion C=A*B wenn die FPU verwendet wird?
Simsonite schrieb:> Erzeugt dieser Code das selbe Ergebnis oder wird die FPU> dadurch tatsächlich "nur" aktiviert?
Die FPU wird aktiviert. Das ist notwendig, dass sonst beim Aufruf eines
FPU-Befehles die CPU abstürzt.
Aber noch was: Falls du den gcc Compiler benutzt und möchtest, dass z.B.
auch sqrtf Befehle direkt in einen FPU Code übersetzt werden, muss du
folgendes beachten. Nehmen wir mal diesen Code an:
Nach einem Aufruf mit:
arm-none-eabi-gcc floattext.c -mcpu=cortex-m4 -mfpu=fpv4-sp-d16
-mfloat-abi=hard -mthumb -Os -S
bekommst du das folgende Ergebnis:
1
...
2
test:
3
@ args = 0, pretend = 0, frame = 0
4
@ frame_needed = 0, uses_anonymous_args = 0
5
push {r3, lr}
6
fstmfdd sp!, {d8, d9, d10}
7
flds s18, .L2
8
fcpys s20, s0
9
flds s17, .L2+4
10
fadds s18, s0, s18
11
flds s16, .L2+8
12
fdivs s17, s18, s17
13
fmuls s16, s17, s16
14
fabss s19, s16
15
fcpys s0, s19
16
bl sqrtf
17
fcpys s21, s0
18
bl sinf
19
...
Wie du siehst, werden durchweg FPU Befehle benutzt, aber nicht bei
sqrtf. sinf gibts nicht als FPU Befehle beim Cortex-M4. Dass bei sqrtf
die Lib-Funktion aufgerufen wird, liegt daran, dass bei Fehlern nach
IEEE ein Flag gesetzt werden muss. Kann man darauf verzichten, kann man
die Option -ffast-math verwenden. Siehe:
https://answers.launchpad.net/gcc-arm-embedded/+question/246145
Übrigens ist eine Optimierunsstufe notwendig, damit statt der
Lib-Funktion sqrtf der direkte FPU-Befehl benutzt wird!
arm-none-eabi-gcc floattext.c -mcpu=cortex-m4 -mfpu=fpv4-sp-d16
-mfloat-abi=hard -mthumb -ffast-math -Os -S
führt zu:
1
test:
2
...
3
push {r3, lr}
4
fstmfdd sp!, {d8, d9, d10}
5
flds s18, .L2
6
fcpys s21, s0
7
flds s17, .L2+4
8
fadds s18, s0, s18
9
flds s16, .L2+8
10
fmuls s17, s18, s17
11
fmuls s16, s17, s16
12
fabss s20, s16
13
fsqrts s19, s20
14
fcpys s0, s19
15
bl sinf
16
...
Übrigens nicht verwundern, dass die FPU Befehle mit f... beginnen, das
ist eine Eigenart des gcc für ARM. Der Assemblers der GNU-Binutils für
ARM übersetzt das richtig. Nach dem assemblieren und anschließenden
disassemblieren schauen sie so aus:
1
00000000 <test>:
2
0: b508 push {r3, lr}
3
2: ed2d 8b06 vpush {d8-d10}
4
6: ed9f 9a15 vldr s18, [pc, #84] ; 5c <test+0x5c>
5
a: eddf 8a15 vldr s17, [pc, #84] ; 60 <test+0x60>
6
e: ed9f 8a15 vldr s16, [pc, #84] ; 64 <test+0x64>
7
12: ee30 9a09 vadd.f32 s18, s0, s18
8
16: eef0 aa40 vmov.f32 s21, s0
9
1a: ee69 8a28 vmul.f32 s17, s18, s17
10
1e: ee28 8a88 vmul.f32 s16, s17, s16
11
22: eeb0 aac8 vabs.f32 s20, s16
12
26: eef1 9aca vsqrt.f32 s19, s20
13
2a: eeb0 0a69 vmov.f32 s0, s19
14
2e: f7ff fffe bl 0 <sinf>
Der Assembler kann übrigens beide Notierungen:
Aus
Kurzes Update: Die f... Befehle lagen wohl am alten gcc. Die Beispiele
oben waren mit dem 4.9.1 gcc gemacht. Mit dem neuen gcc (gcc version
5.2.1 20151202 (release) [ARM/embedded-5-branch Revision 231848] (GNU
Tools for ARM Embedded Processors)) generiert er jetzt direkt v....f32
Befehle.
Vielen Dank!
Schön langsam kommt Licht ins Dunkel. Kann mir noch jemand sagen ob man
die Einstellungen
arm-none-eabi-gcc floattext.c -mcpu=cortex-m4 -mfpu=fpv4-sp-d16
-mfloat-abi=hard -mthumb -ffast-math -Os -S
direkt in der IDE vornehmen kann, oder muss ich diese in ein bestimmtes
File schreiben?
Simsonite schrieb:> Kann mir noch jemand sagen
Zur Not nochmal einen Thread explizit dafür öffnen, der die benutzte
IDE im Subject benennt. Kann gut sein, dass die, die sich damit
auskennen nicht die sind, die diesen Thread hier lesen.
Simsonite schrieb:> Beispiel: Multiplikation> CalcMultiply> VMUL.F32 S0,S0,S1 ; multiply(input1, input2)> BX LR
Wenn du Float-Operationen in Assembler schreibst, dann wird der
Controller auch die FPU-Einheit benutzen.
ABER:
Wenn du nicht vorher die FPU freigibst, dann kriegst du entwede garnix
oder nen Hardfault. Geht etwa so:
SCB_CPACR = 3<<20;
Ansonsten mußt du die Float-verwendung auch dem Compiler sagen:
--cpu=Cortex-M4.fp.sp
--thumb
-c
Und auch dem Linker:
--cpu=Cortex-M4.fp.sp
...usw.
W.S.