GCC Cortex-M4 -mfpu=vfpv4 vs. -mfpu=fpv4-sp-d16 - gcc

I'm using a Freescale K22 (Cortex-M4F) with Kinetis Design Studio, which includes a GNU toolchain. I'm trying to use a binary-only library provided by Invensense, and they compiled it with GCC for use on a the Cortex-M4F using the compiler's CPU options "-mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=vfpv4"
The Freescale toolchain defaults to "-mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16". When I try to link my program with the vendor binary-only library, I get link errors like:
c:/freescale/kds_1.1.1/toolchain/bin/../lib/gcc/arm-none-eabi/4.8.0/../../../../arm-none-eabi/bin/ld.exe: error: ./startup/startup.o uses VFP register arguments, 22F_eval_spi_to_invensense_CHECKED_IN.elf does not
c:/freescale/kds_1.1.1/toolchain/bin/../lib/gcc/arm-none-eabi/4.8.0/../../../../arm-none-eabi/bin/ld.exe: failed to merge target specific data of file ./startup/startup.o
I can rebuild the Kinetis platform library for -mfpu=vfpv4, but I still get the link errors, presumably because other Kinetis libraries are compiled with
"-mfpu=fpv4-sp-d16".
Since both are intended for the Cortex-M4 with FPU, is there any actual difference between GCC generated code for vpfv4 and fpv4-sp-d16? Are they actually incompatible, or is the linker just overly pedantic?

Related

Enable VPF libraries (hard) with arm-gcc

I'm trying to build an application that links a library that is built with VFP. I have added the flags -mfpu=fpv4-sp-d16 -mfloat-abi=hard to my arm-gcc command, but it complains about that the standard C library (libm.a and the like) is not built using VFP.
I have noticed that in my arm-gcc toolchain directory, in lib, there is a folder called hard which is supposed to contain the arm standard C libraries built with VFP.
How can I make this library folder the standard one for the arm toolchain?
It seems that I had some missing flags. Below I list all of them:
-mcpu=cortex-m7 -mthumb -mabi=aapcs -mfpu=fpv5-d16 -mfloat-abi=hard

link time warning about VPF registers

I'm trying to port a project from Cortex M0 to Cortex M4 with hardware floating point extension, the new target soc is nRF52832.
The error I am getting from the linker is the following
arm-unknown-eabi/bin/ld: error: x.o uses VFP register arguments, firmware does not
where firmware is the name of the output file fro the linker.
This is an issue with the arm ABI for floating point, I want to use the FPU as it is requested by
the FreeRTOS port I want to use but I don't get how to tweak my linker flags to make it possible.
This is the set of linker flags I'm currently using
-L/path/to/nrfx/mdk
-Wl, --no-undefined
-Wl,--as-needed -march=armv7e-m+fp -mthumb -mfloat-abi=hard -mabi=aapcs
-Wl, --start-group support/libs/libQRCode.a support/libs/libSPIFFS.a
-Wl, --no-undefined
-Wl, --as-needed
-Wl, --gc-sections --specs=nosys.specs -T/path/to/linker_script.ld /toolchain/path/to/lib/libm.a
-Wl, --end-group
The -mfloat-abi flag is a compiler-only flag, so there is no point in passing it to the linker.
In order to be able to build a firmware image that uses the hard-float ABI, all object files passed to the linker must be compiled to use that ABI. You issue is most likely due to the fact that you are passing to the linker one or more object files compiled with the soft-float ABI instead; for example, the /toolchain/path/to/lib/libm.a file path in your linker command line looks suspicious, you should use the hard-float version of libm.a, which you will likely find in the hard/ sub-folder of your toolchain library path.

LLVM / Clang 8 Compilation of OpenMP Code in Windows

I'm using the Windows version of Clang (LLVM) 8 under Windows.
I'm compiling a code which uses OpenMP.
Under the lib folder of Clang there are 2 files which are OpenMP related:
libomp.lib.
libiomp5md.dll.
My questions are:
When I compile the code I use the flags -Xclang -fopenmp for the compiler. In in GCC and ICC using the flags tell the compiler to link the OpenMP library automatically. What about Clang? Does it do it automatically or must I link with libomp.lib manually? Is there a way to trigger automatic linking to the OpenMP library?
Answer: This was answered in Michael Klemm's answer below - Use the clang driver both for compiling and linking and then the -fopenmp will work as in GCC.
When I link with libomp.lib manually (Defining as a library for the linker) the output exe requires libomp.dll while the supplied OpenMP Dynamic Library is libiomp5md.dll. Is that a bug or is it because I link manually?
Answer: The libomp.dll is supplied in the bin folder and not the lib folder.
What's the proper way to utilize OpenMP in Clang under Windows? The clang-cl driver doesn't work with /openmp or -openmp as the MSVC's cl compiler.
Answer: Currently it can be done either with clang -fopenmp ..., clang-cl -Xclang -fopenmp ... or clang-cl /clang:-fopenmp ... (Which is equivalent of -Xclang -fopenmp).
Remark
On Windows I use Windows Driver of Clang using clang-cl.
Adding clarity to what the OpenMP libraries actually are, and how to use them on Windows with clang-cl
libomp.dll and libiomp5md.dll ARE THE SAME FILES!
When compiling for Windows, you link against libomp.lib OR libiomp5md.lib which will link to the same-named DLL at runtime, i.e. libomp.dll OR libiomp5md.dll respectively.
If you load 2 files that use the "different-name DLL," the interpreter will crash and give you a nasty error like: OMP: Error #15: Initializing libiomp5md.dll, but found libomp.dll already initialized.
Why? Because the program has no idea they are the same DLL, they have different names, so it assumes they are different. And it crashes. For this reason only, you can choose to swap which OpenMP DLL you link to in your program.
If your program doesn't crash and give you an error, you can keep using the same link to OpenMP. Otherwise, to silence the error, link to the one that is loaded by another program already.
If using clang-cl.exe which is the "drop-in" Clang replacement for MSVC cl.exe you should pass a compiler argument such as -Xclang -fopenmp which will convert the argument over to "Clang language." Don't forget to still pass to the linker the OpenMP LIB you chose, because on Windows, it won't be automatic.
That's all I've learned as brief as possible about OpenMP linking on Windows.
To compile and link OpenMP code with clang on Windows, you will have to pass -fopenmp to both the compiler and the linker:
clang -fopenmp -o bla.obj -c bla.c
clang -fopenmp -o bla.exe bla.obj

QtWebengine build error with opus and silk codecs

I am trying to build Qt5.9.1 with QtWebengine for an arm platform.
These are some architecture based arguments i am passing to the build.
QMAKE_CFLAGS_RELEASE += -march=armv7-a -mcpu=cortex-a9
QMAKE_CXXFLAGS_RELEASE += -march=armv7-a -mcpu=cortex-a9
By default i can see that the build is going for these values as well.
-mfloat-abi=hard -mtune=generic-armv7-a -mfpu=vfpv3-d16 -mthumb
THIS is the error i am facing.
As far as i know, in cortex-a9 neon is optional and my particular SoC does not support neon.
Also the -print-multi-lib gives this
arm400-linux-g++ -print-multi-lib
armv5te_arm9;#mcpu=arm926ej-s
a9;#mcpu=cortex-a9
a7;#mcpu=cortex-a7
armv5te_arm9_soft;#mcpu=arm926ej-s#mfloat-abi=soft
armv5te_arm9_vfp;#mcpu=arm926ej-s#mfloat-abi=softfp#mfpu=vfp
a9_soft;#mcpu=cortex-a9#mfloat-abi=soft
a9_softfp_vfp;#mcpu=cortex-a9#mfloat-abi=softfp#mfpu=vfp
a9_softfp_vfpv3-d16;#mcpu=cortex-a9#mfloat-abi=softfp#mfpu=vfpv3-d16
a7_soft;#mcpu=cortex-a7#mfloat-abi=soft
a7_softfp_vfpv4;#mcpu=cortex-a7#mfloat-abi=softfp#mfpu=vfpv4
a7_softfp_neon-vfpv4;#mcpu=cortex-a7#mfloat-abi=softfp#mfpu=neon-vfpv4
a7_hard_neon-vfpv4;#mcpu=cortex-a7#mfloat-abi=hard#mfpu=neon-vfpv4
I have tried passing these three possible architecture arguments in the mkspecs.
QMAKE_CFLAGS_RELEASE += -march=armv7-a -mcpu=cortex-a9 -mfloat-abi=soft
QMAKE_CXXFLAGS_RELEASE += -march=armv7-a -mcpu=cortex-a9 -mfloat-abi=soft
For this i got
"arm400-linux-g++: error: -mfloat-abi=soft and -mfloat-abi=hard may not be used together".
I also tried passing these arguments
-mcpu=cortex-a9 -mfloat-abi=softfp -mfpu=vfp
-mcpu=cortex-a9 -mfloat-abi=softfp -mfpu=vfpv3-d16
But it had the same effect.
libxxxx.a(yyyyy.o) uses VFP register arguments, libQt5WebEngineCore.so.5.9.1 does not
I am running out of options here. Why is this issue coming up ?
You have to build all the libs with the same VFP option as your source code.
According to ATPCS(ARM-Thumb procedure call standard), float parameters are passed by VFP registers if available. Otherwise, they are passed by the ARM integer registers.
If lib A is compiled with the soft-float option, you cannot call its functions due to the ABI conflict from lib B or vice versa.
If you don't have certain lib's source code but the binary, your only option is to match the other projects build options to the lib's.
However, chances are good that you will find different versions of the library with various build options.

Cross compiling - Error: selected processor does not support `fmrx r3,fpexc' in ARM mode - Beaglebone

I'm trying to cross-compile a file to flash into the Beaglebone Black.
All works fine, but if I try to enable the FPU with
#define set_en_bit_in_fpexc() do { \
int dummy; \
__asm__ __volatile__ ("fmrx %0,fpexc\n\t" \
"orr %0,%0,#0x40000000\n\t" \
"fmxr fpexc,%0" : "=r" (dummy) : :); \
} while (0)
I get the following error
Error: selected processor does not support `fmrx r3,fpexc' in ARM mode
Error: selected processor does not support `fmxr fpexc,r3' in ARM mode
I also tried with thumb mode, but I get the same errors.
Of course if I remove the part of the code that initialize the FPU it works fine.
Why I get those errors?
Makefile
[...]
CROSSPATH?=/usr/bin
CROSSPFX=$(CROSSPATH)/arm-none-eabi-
CC=$(CROSSPFX)gcc
AS=$(CROSSPFX)as
LD=$(CROSSPFX)ld
NM=$(CROSSPFX)nm
OBJCOPY=$(CROSSPFX)objcopy
OBJDUMP=$(CROSSPFX)objdump
CFLAGS=-Wall -Wextra -O2 -ffreestanding
ARCHFLAGS=-mcpu=cortex-a8 -march=armv7-a -mfpu=neon
CCARCHFLAGS=$(ARCHFLAGS) -marm
[...]
I'm on Arch, kernel 4.8.1
P.S. My professor uses the linaro cross-compiler and it works just fine
Most of the Linaro toolchains are configured for ARMv7 hard-float by default (certainly the Linux ones, I'm less sure about the bare-metal ones). Looking at the configuration of the arm-none-eabi toolchain as packaged by Arch, I surmise it's just using the GCC defaults for things like that, which implies something like ARMv4t, and crucially, soft-float ABI.
Whilst the -mfpu option controls code generation in terms of which floating-point instructions may be used, apparently it's the float ABI which controls whether it'll let you do things which really only make sense on a hardware FPU, rather than under floating-point emulation.
When it's not configured by default, you need to explicitly select a floating-point ABI implying an actual hardware FPU, i.e. -mfloat-abi=hard (or -mfloat-abi=softfp, but there's really no reason to use that unless you need to link against other soft-float code).
-mfpu=vfpv3-d16 -mfloat-abi=hard
Just to give a more direct solution, I had to add -mfpu=vfpv3-d16.
Test code a.S:
fmrx r2, fpscr
Working command:
sudo apt-get install binutils-arm-linux-gnueabihf
arm-linux-gnueabihf-as -mfpu=vfpv3-d16 -mfloat-abi=hard a.S
Note that -mfloat-abi=hard is enabled by default on this particular build of arm-linux-gnueabihf-as, and could be omitted.
The default value of float-abi likely depends on -msoft-float vs -mhard-float controlled at GCC build time with:
./configure --with-float=soft
as documented at: https://gcc.gnu.org/install/configure.html You can get the flags used for your toolchain build with gcc -v as mentioned at: What configure options were used when building gcc / libstdc++? I could not however easily determine its default value if not given.
You may also be interested in -mfloat-abi=softfp which can produce hard floats for the executable, but generate soft function calls: ARM compilation error, VFP registered used by executable, not object file
The possible values of -mfpu= can be found at: https://gcc.gnu.org/onlinedocs/gcc-7.2.0/gcc/ARM-Options.html#ARM-Options
Also note that FMRX is the pre-UAL syntax for VMRS which the newer recommended syntax, see also: Are ARM instructuons SWI and SVC exactly same thing?
Tested on Ubuntu 16.04, arm-linux-gnueabihf-as 2.26.1.

Resources