ARM

From Gentoo Wiki
Jump to:navigation Jump to:search

This article is not about running Linux on ARM.

It is about compiling code for an ARM processor, taking advantage of its FPU.

Prepare the toolchain

Building with crossdev

If nanolib, hardfloat and C++ support are not important, you may proceed to building.


Building

We use crossdev to create a local ebuild repo with symlinks to your "regular" Gentoo ebuild repository. The ebuilds are thus the same as for your x86_64 system, but are now used for cross-compiling to ARM.

The simplest command to build a toolchain with gcc's the default target configuration:

root #crossdev --target arm-none-eabi

Depending on your CPU, this may not be enough though:

Important
Since there's many differences between the ARM CPU families, your gcc needs to support them.

To see currently available targets:

user $arm-none-eabi-gcc --print-multi-lib

This output is also used by newlib at buildtime to create suitable libc binaries! For example, if you use a Thumb-only Cortex-M CPU and no thumb-only libc (or libc_nano) archives available - you may encounter illegal instructions on your CPU since it tries to execute non-thumb instructions!

You can use with-multilib-list to support more target CPUs.

There are several profiles to enable ARM CPU targets in the gcc source code. This feature is documented in gccsource/INSTALL/configure.html or info gccinstall -n Configuration searching for with-multilib-list:

ARM GCC CPU profiles
profile_name CPU family gcc source file
aprofile Cortex-A CPUs gcc/config/arm/t-aprofile
rmprofile Cortex-R and Cortex-M CPUs gcc/config/arm/t-rmprofile

These can be set (also multiple profiles with comma separation) when installing gcc with --with-multilib-list

root #crossdev --target arm-none-eabi --genv 'EXTRA_ECONF="--with-multilib-list=$profile_name"'

Enable C++ support

Just enable the cxx USE flag in your cross compiler package cross-arm-none-eabi/gcc.

After you set the flag, rebuild the package.


Enable nanolib support

To enable the nano C library, cross-arm-none-eabi/newlib needs the nano USE flag.


Create a ARM gdb

Either build sys-devel/gdb with multitarget USE flag, or emerge the dedicated cross-arm-none-eabi/gdb.


Build for specific CPUs

You probably don't need this when you installed the toolchain with gcc rmprofile (see above). Using it, your toolchain supports all various sub-architectures and flavors with floating point units and without.

To build toolchains for specific CPUs:

Quoting Embedded Artistry[1]:

Note
SOFT

The soft option enables full software floating-point support. The compiler will not generate FPU instructions in soft mode. Instead, the compiler generates library calls to handle floating point operations. The compiler also generates prologue and epilogue functions to pass floating-point arguments (float, double) into integer registers (one for float, two for double).

SOFTFP

The softfp option is a hybrid between hard and soft. The compiler is allowed to generate hardware floating-point instructions, but it still uses the soft-float ABI. Like with soft, the compiler generates functions to pass floating-point arguments to integer registers. Depending on the chosen FPU (-mfpu), the compiler can choose when to use emulated or hardware floating-point instructions.

HARD

The hard option enables full hardware floating-point support. The compiler generates floating-point instructions and uses the floating-point ABI. Floating-point function arguments are passed directly into FPU registers. Since there are no function prologue or epilogue requirements, no pipeline stalls are incurred with floating-point arguments. The hard float option will provide you with the highest performance, but does limit your compiled binary to the selected FPU.

When using the hard option, you must define an FPU using -mfpu.

It's a bit tricky to enable hard floating point targets. One way to enable it, supposing the target processor has an FPU unit, is the following:

root #crossdev --target arm-hardfloat-eabi --env \
           'EXTRA_ECONF="--with-cpu=cortex-m4 
                         --with-float-abi=hard 
                         --with-mode=thumb"'

Analyzing the above command, we replaced -none- with -hardfloat- in the cross-compile target speficier.

As for the EXTRA_ECONF flags, they were copied from a readme.txt file found in the ARM toolchain source's root or the following path for the pre-built version: share/doc/gcc-arm-none-eabi/. Here are the contents of the readme.txt for convenience:

user $cat readme.txt
--------------------------------------------------------------------------
| Arm core   | Command Line Options                       | multilib     |
|------------|--------------------------------------------|--------------|
| Cortex-M0+ | -mthumb -mcpu=cortex-m0plus                | thumb        |
| Cortex-M0  | -mthumb -mcpu=cortex-m0                    | /v6-m        |
| Cortex-M1  | -mthumb -mcpu=cortex-m1                    |              |
|------------|--------------------------------------------|--------------|
| Cortex-M3  | -mthumb -mcpu=cortex-m3                    | thumb        |
|            |                                            | /v7-m        |
|------------|--------------------------------------------|--------------|
| Cortex-M4  | -mthumb -mcpu=cortex-m4                    | thumb        |
| (No FP)    |                                            | /v7e-m       |
|------------|--------------------------------------------|--------------|
| Cortex-M4  | -mthumb -mcpu=cortex-m4 -mfloat-abi=softfp | thumb        |
| (Soft FP)  |                                            | /v7e-m+fp    |
|            |                                            | /softfp      |
|------------|--------------------------------------------|--------------|
| Cortex-M4  | -mthumb -mcpu=cortex-m4 -mfloat-abi=hard   | thumb        |
| (Hard FP)  |                                            | /v7e-m+fp    |
|            |                                            | /hard        |
|------------|--------------------------------------------|--------------|
| Cortex-M7  | -mthumb -mcpu=cortex-m7                    | thumb        |
| (No FP)    |                                            | /v7e-m       |
|            |                                            | /nofp        |
|------------|--------------------------------------------|--------------|
| Cortex-M7  | -mthumb -mcpu=cortex-m7 -mfloat-abi=softfp | thumb        |
| (Soft FP)  |                                            | /v7e-m+dp    |
|            |                                            | /softfp      |
|------------|--------------------------------------------|--------------|
| Cortex-M7  | -mthumb -mcpu=cortex-m7 -mfloat-abi=hard   | thumb        |
| (Hard FP)  | -mfpu=fpv5-sp-d16                          | /v7e-m+dp    |
|            |                                            | /hard        |
|------------|--------------------------------------------|--------------|
| Cortex-M23 | -mthumb -mcpu=cortex-m23                   | thumb        |
|            |                                            | /v8-m.base   |
|------------|--------------------------------------------|--------------|
| Cortex-M33 | -mthumb -mcpu=cortex-m33                   | thumb        |
|  (No FP)   |                                            | /v8-m.main   |
|            |                                            | /nofp        |
|------------|--------------------------------------------|--------------|
| Cortex-M33 | -mthumb -mcpu-cortex-m33                   | thumb        |
| (Soft FP)  | -mfloat-abi=softfp                         | /v8-m.main+fp|
|            |                                            | /softfp      |
|------------|--------------------------------------------|--------------|
| Cortex-M33 | -mthumb -mcpu=cortex-m33                   | thumb        |
| (Hard FP)  | -mfloat-abi=hard                           | /v8-m.main+fp|
|            |                                            | /hard        |
|------------|--------------------------------------------|--------------|
| Cortex-R4  | [-mthumb] -mcpu=cortex-r?                  | thumb        |
| Cortex-R5  |                                            | /v7          |
| Cortex-R7  |                                            | /nofp        |
| Cortex-R8  |                                            |              |
| (No FP)    |                                            |              |
|------------|--------------------------------------------|--------------|
| Cortex-R5  | [-mthumb] -mcpu=cortex-r?                  | thumb        |
| Cortex-R7  | -mfloat-abi=softfp                         | /v7+fp       |
| Cortex-R8  |                                            | /softfp      |
| (Soft FP)  |                                            |              |
|------------|--------------------------------------------|--------------|
| Cortex-R5  | [-mthumb] -mcpu=cortex-r?                  | thumb        |
| Cortex-R7  | -mfloat-abi=hard                           | /v7+fp       |
| Cortex-R8  |                                            | /hard        |
| (Hard FP)  |                                            |              |
|------------|--------------------------------------------|--------------|
| Cortex-R52 | [-mthumb] -mcpu=cortex-r52                 | thumb        |
| (No FP)    |                                            | /v7          |
|            |                                            | /nofp        |
|------------|--------------------------------------------|--------------|
| Cortex-R52 | [-mthumb] -mcpu=cortex-r52                 | thumb        |
| (Soft FP)  | -mfloat-abi=softfp                         | /v7+fp       |
|            |                                            | /softfp      |
|------------|--------------------------------------------|--------------|
| Cortex-R52 | [-mthumb] -mcpu=cortex-r52                 | thumb        |
| (Soft FP)  | -mfloat-abi=hard                           | /v7+fp       |
|            |                                            | /hard        |
|------------|--------------------------------------------|--------------|
| Cortex-A*  | [-mthumb] -mcpu=cortex-a*                  | thumb        |
| (No FP)    |                                            | /v7          |
|            |                                            | /nofp        |
|------------|--------------------------------------------|--------------|
| Cortex-A*  | [-mthumb] -mcpu=cortex-a*                  | thumb        |
| (Soft FP)  | -mfloat-abi=softfp                         | /v7+fp       |
|            |                                            | /softfp      |
|------------|--------------------------------------------|--------------|
| Cortex-A*  | [-mthumb] -mcpu=cortex-a*                  | thumb        |
| (Hard FP)  | -mfloat-abi=hard                           | /v7+fp       |
|            |                                            | /hard        |
--------------------------------------------------------------------------


Using the pre-built toolchain

A pre-built toolchain is the GNU Arm Embedded Toolchain. Remember to update your PATH by prepending the location of the toolchain's bin folder:

user $export PATH="/path/to/toolchain/bin:$PATH"

Writing code

Error message: .... uses VFP register arguments ... does not

This probably means that some of the libraries being linked, were compiled with hardfloat (-mfloat=hardfloat) while others with floatfp or float. This can also happen when the compiler was compiled in an opposite to the code manner.

Error message: undefined reference to `__stack_chk_guard'

The __stack_chk* symbols are defined by libc.a and are used for stack smashing protection.

In the case of compilation errors like undefined reference to `__stack_chk_guard', you can disable stack smashing guards by disabling the ssp USE for cross-arm*/gcc.


Using Mbed

Mbed is an online platform for writing and compiling code for various boards. It has an export function that enables retrieving the said code including a Makefile and the imported libraries.

Note
If arm-hardfloat-eabi or -mfloat=hard is used, the Makefile must be adapted since it uses arm-none-eabi and -march=floatfp.
Important
If instead of the mbed-os library, the mbed one is included, being precompiled, it might not link against hardfloatly compiled code.

Missing mbed_config.h

If compilation fails with a missing mbed_config.h file, Makefile needs to be adapted with a point to the root folder's mbed_config.h file.

Using STM32CubeMX

STM32CubeMX can be used to initialize code. In provides a graphical user interface to choose pin modes and clocks.

Using pre-built toolchain's samples

The pre-built GNU Arm Embedded Toolchain, comes with code samples and Makefiles.

See also

External resources

  1. Embedded Artistry explains the difference between hard, softfp and soft (the three ARM floating point compiler options).
  2. Discussion on the problems enabling hardfloat.
  3. Another similar discussion in the Gentoo forums.

Referencies

  1. Phillip Johnston. "Demystifying ARM Floating Point Compiler Options", October 11, 2017. Retrieved on 2019-09-30