I’m working on an application that is critical for calculation precision.
I’m working with STM32F446XX processor, but I’m wondering if it can compute with double precision, if so, how can I make sure it computes with double precision.
yes, you can declare variables as double and you get computations with double floating point. The Cortex-M4 has a FPU, but only for singlec precision, so the math is done in software and you do not gain benefit of the FPU.
When you need double and speed, then you should use Cortex-M7.
I can see that even if I use double, the compiler chooses to use __aeabi_fmul instead of __aeabi_dmul, is it possible to force the compiler to use double multiplication instead?
that sounds strange, the compiler must choose the right instructions for the variables, and the Cortex-M libs definitely have double support, not like in the AVR 8 bit world.
I had more problems with the reverse case, that double is used because lots of libs don’t care between 42.0 and 42.0f constants, as explained here:
Especially on Cortex-M0 it wil blow your code size when the little ‘f’ is missing on contants or double is explicitly used.
A short piece of code for demonstration of the problem would be helpful, and which compiler and mbed-os version is used.
Hi,
I checked code generation using double variable as test code below.
/* mbed Microcontroller Library
* Copyright (c) 2019 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*/
#include "mbed.h"
double dd = 1.234;
int main()
{
double d;
d = 0.000234;
printf("double = %lf\n", dd*d);
}
Build the test program by Arm compiler:
mbed compile -m NUCLEO_F446RE -t ARM
Generated code by Arm compiler
main
0x00000000: b580 .. PUSH {r7,lr}
0x00000002: f2400000 @... MOVW r0,#:LOWER16: dd
0x00000006: f2c00000 .... MOVT r0,#:UPPER16: dd
0x0000000a: ed900b00 .... VLDR d0,[r0,#0]
0x0000000e: ed9f1b08 .... VLDR d1,[pc,#32] ; [0x30] = 0xb1cc9646
0x00000012: ec510b10 Q... VMOV r0,r1,d0
0x00000016: ec532b11 S..+ VMOV r2,r3,d1
0x0000001a: f7fffffe .... BL __aeabi_dmul
0x0000001e: 4602 .F MOV r2,r0
0x00000020: a005 .. ADR r0,{pc}+0x18 ; 0x38
0x00000022: 460b .F MOV r3,r1
0x00000024: f7fffffe .... BL __2printf
0x00000028: 2000 . MOVS r0,#0
0x0000002a: bd80 .. POP {r7,pc}
0x0000002c: bf00 .. NOP
0x0000002e: bf00 .. NOP
Build the test program by GCC compiler:
mbed compile -m NUCLEO_F446RE -t GCC_ARM
Generated code by GCC
00000000 <main>:
0: 4909 ldr r1, [pc, #36] ; (28 <main+0x28>)
2: b508 push {r3, lr}
4: e9d1 0100 ldrd r0, r1, [r1]
8: a305 add r3, pc, #20 ; (adr r3, 20 <main+0x20>)
a: e9d3 2300 ldrd r2, r3, [r3]
e: f7ff fffe bl 0 <__aeabi_dmul>
12: 4602 mov r2, r0
14: 460b mov r3, r1
16: 4805 ldr r0, [pc, #20] ; (2c <main+0x2c>)
18: f7ff fffe bl 0 <printf>
1c: 2000 movs r0, #0
1e: bd08 pop {r3, pc}
20: b1cc9646 .word 0xb1cc9646
24: 3f2eabbc .word 0x3f2eabbc
Both compiler generated __aeabi_dmul function call, so compiler generated double precision code.
Thanks,
Toyo