build for ARMv6 with gnueabihf
Asked Answered
S

2

7

I try to build an app for ARMv6 but, fail.

I guess the problem is the Toolchain which supports Hard Float but, ARMv6 does not.

Well, first i set -march=armv6, where compilation fails.

/opt/gcc-linaro-arm-linux-gnueabihf-4.8-2014.03_linux/arm-linux-gnueabihf/libc/usr/include/bits/byteswap.h: In function ‘__bswap_32’: /opt/gcc-linaro-arm-linux-gnueabihf-4.8-2014.03_linux/arm-linux-gnueabihf/libc/usr/include/bits/byteswap.h:45:1: sorry, unimplemented: Thumb-1 hard-float VFP ABI

Additionally, i set -mfloat-abi=soft which make the Linker complain:

/opt/gcc-linaro-arm-linux-gnueabihf-4.8-2014.03_linux/bin/../lib/gcc/arm-linux-gnueabihf/4.8.3/../../../../arm-linux-gnueabihf/bin/ld: error: prog uses VFP register arguments, prog.o does not /opt/gcc-linaro-arm-linux-gnueabihf-4.8-2014.03_linux/bin/../lib/gcc/arm-linux-gnueabihf/4.8.3/../../../../arm-linux-gnueabihf/bin/ld: failed to merge target specific data of file prog.o

Well, how do i actually build for ARMv6? Or is there a bug in the Toolchain?

Synonymize answered 1/2, 2016 at 13:55 Comment(1)
Are you using Linux? Linaro is for a Linux OS/glibc and you will have issue unless you compile with -ffreestanding. I suggest you use a newlib compiler if you are really embedded. The launchpad has several builds for different hosts (including a Linux host development box). Otherwise, you might use the tag 'embedded-linux'.Catchweight
S
8

Your toolchain is configured to emit Thumb code by default. The issue with that is that the only Thumb encodings of floating-point instructions are 32-bit Thumb-2 ones, which to all intents and purposes only exist on ARMv7 or later*, and certainly aren't available on plain ARMv6.

To target pre-v7 architectures, you're best off compiling with -marm to generate ARM code instead of the relatively limited set of 16-bit Thumb instructions.

* I suspect most people will never knowingly encounter an ARM1156.

Seiden answered 1/2, 2016 at 14:11 Comment(3)
Great, thanks. As an addition to your post: i had do kick out -mfloat-abi=soft, beside using -marm.Synonymize
@Synonymize It's a gnueabihf toolchain, so yeah, the bundled libraries are only going to link against hard-float objects. They're probably also Thumb-2, so don't link statically either; really you want to be building against the sysroot of the target device, rather than the minimal one bundled with the toolchain, to avoid nasty surprises and/or subtle incompatibilities.Seiden
The ARM1176JZF-S core found in the BCM2835 SoC (as used on some Raspberry Pi models) is ARMv6z, which includes hard-float support via VFPv2.Pavid
P
11

The ARM1176JZF-S core found in the BCM2835 SoC (as used on some Raspberry Pi models) is ARMv6z architecture, which includes hard-float support via VFPv2, so this is definitely a valid config to target.

The problem is that the maintainers of the Linaro toolchain specify ARMv7A as the minimum supported architecture. It makes cross-compiling for Raspberry Pi using the Debian cross-compiler packages rather hopeless, since various builtins will fail if you correctly configure your build for BCM2835 with -march=armv6z -mtune=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard

This is gcc -v on Raspbian Stretch:

$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/arm-linux-gnueabihf/6/lto-wrapper
Target: arm-linux-gnueabihf
Configured with: ../src/configure -v --with-pkgversion='Raspbian 6.3.0-18+rpi1+deb9u1' --with-bugurl=file:///usr/share/doc/gcc-6/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-6 --program-prefix=arm-linux-gnueabihf- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-libitm --disable-libquadmath --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-6-armhf/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-6-armhf --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-6-armhf --with-arch-directory=arm --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-sjlj-exceptions --with-arch=armv6 --with-fpu=vfp --with-float=hard --enable-checking=release --build=arm-linux-gnueabihf --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf
Thread model: posix
gcc version 6.3.0 20170516 (Raspbian 6.3.0-18+rpi1+deb9u1) 

Compare to arm-linux-gnueabi-gcc-6 -v on Ubuntu 18.04:

$ arm-linux-gnueabihf-gcc-6 -v
Using built-in specs.
COLLECT_GCC=arm-linux-gnueabihf-gcc-6
COLLECT_LTO_WRAPPER=/usr/lib/gcc-cross/arm-linux-gnueabihf/6/lto-wrapper
Target: arm-linux-gnueabihf
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 6.4.0-17ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-6/README.Bugs --enable-languages=c,ada,c++,go,d,fortran,objc,obj-c++ --prefix=/usr --with-as=/usr/bin/arm-linux-gnueabihf-as --with-ld=/usr/bin/arm-linux-gnueabihf-ld --program-suffix=-6 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-libitm --disable-libquadmath --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib --enable-multiarch --enable-multilib --disable-sjlj-exceptions --with-arch=armv7-a --with-fpu=vfpv3-d16 --with-float=hard --with-mode=thumb --disable-werror --enable-multilib --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=arm-linux-gnueabihf --program-prefix=arm-linux-gnueabihf- --includedir=/usr/arm-linux-gnueabihf/include
Thread model: posix
gcc version 6.4.0 20180424 (Ubuntu/Linaro 6.4.0-17ubuntu1)

and note that the former has --with-arch=armv6 --with-fpu=vfp --with-float=hard whereas the latter has --with-arch=armv7-a --with-fpu=vfpv3-d16 --with-float=hard This blog post provides one solution (basically using Clang and self-building the binutils):

Pavid answered 6/7, 2018 at 0:57 Comment(4)
I wonder how it's possible to compile raspberry pi linux kernel with arm-linux-gnueabihf for Pi Zero as described here: raspberrypi.org/documentation/linux/kernel/building.md, has something changed since?Sarpedon
@Sarpedon I'm wrapping my head around this too. On my Pi Zero I can't run binaries that were cross compiled with crossbuild-essential-armhf, but for some unknown reasons I can happily run a kernel built using the same cross toolchain.Tiepolo
@itachi, the reason is the kernel doesn't have any external dependencies and with your regular user-space app compilation you at least have glibc and the loader. The issue is that when you compile it uses an armv7 glibc and this forces your app to be re-targeted to armv7. The trick it to make sure all the dependencies that you compile against have the correct target architecture.Sarpedon
@Sarpedon Yeah, I was sitting 'till late hours yesterday and finally sorted this out. The "problem" is during the linking stage. When I cross compile my binary without linking, using all flags like -march, -mcpu etc., and then run readelf against this binary, the architecture section looks exactly the same as for the same code compiled on RPi. BUT, after linking, everything looks like for armv7. I assume the only solution is to compile ARM GCC toolchain by myself, targeted to armv6 (at least for older Pies and Zero).Tiepolo
S
8

Your toolchain is configured to emit Thumb code by default. The issue with that is that the only Thumb encodings of floating-point instructions are 32-bit Thumb-2 ones, which to all intents and purposes only exist on ARMv7 or later*, and certainly aren't available on plain ARMv6.

To target pre-v7 architectures, you're best off compiling with -marm to generate ARM code instead of the relatively limited set of 16-bit Thumb instructions.

* I suspect most people will never knowingly encounter an ARM1156.

Seiden answered 1/2, 2016 at 14:11 Comment(3)
Great, thanks. As an addition to your post: i had do kick out -mfloat-abi=soft, beside using -marm.Synonymize
@Synonymize It's a gnueabihf toolchain, so yeah, the bundled libraries are only going to link against hard-float objects. They're probably also Thumb-2, so don't link statically either; really you want to be building against the sysroot of the target device, rather than the minimal one bundled with the toolchain, to avoid nasty surprises and/or subtle incompatibilities.Seiden
The ARM1176JZF-S core found in the BCM2835 SoC (as used on some Raspberry Pi models) is ARMv6z, which includes hard-float support via VFPv2.Pavid

© 2022 - 2024 — McMap. All rights reserved.