When trying to compile code for ARM Cortex devices using the arm-none-eabi-gcc toolchain, you may encounter confusing error messages stating that certain functionality “is not implemented and will always fail”. This typically occurs when the code uses features not supported by the version of GCC being used, or relies on libraries/headers not provided with the toolchain.
There are a few common scenarios that can trigger these errors:
Using C++ code with a C-only compiler
The arm-none-eabi-gcc compiler only supports C code by default. If you try to compile C++ code (.cpp files) you’ll see errors about features like exceptions and RTTI not being implemented. To fix this, you need to use the arm-none-eabi-g++ compiler for C++ files. Simply rename gcc to g++ in your compile commands.
Missing standard C library headers
The arm-none-eabi toolchain only includes a barebones C standard library by default. So if you try to use headers like <cmath>, <thread> etc. that rely on a more fully featured libc implementation, you’ll get “not implemented” errors.
To add full C library support, you need to download and install a compatible newlib distribution for ARM Cortex. Then point your compiler to use the newlib include paths and libs. This will provide the missing headers and library functions.
Using incompatible GCC versions
Sometimes the “not implemented” errors appear randomly even for simple C code. This often indicates a mismatch between the GCC/G++ compilers and the GCC runtime libraries installed on your system.
For example, if you have GCC 8 installed but are using GCC 7’s libraries, you may get these errors due to changes in compiler behavior between versions. Make sure your compiler binaries, include paths, and library paths all point to the same GCC toolchain version.
Undefined reference to compiler built-ins
GCC provides certain built-in functions like __builtin_clz() for counting leading zeros in an integer. If you call these without including the correct compiler options, you’ll see “not implemented” errors as the built-ins are not explicitly defined anywhere.
To fix this, pass -fbuiltin to the compiler to allow use of built-ins. You may also need to enable specific functions with flags like -fno-math-errno and -fno-trapping-math if using floating point built-ins.
Enabling optimized code generation
GCC’s optimizers make assumptions about undefined behavior in your code to generate faster binary code. Sometimes this can cause confusing “not implemented” errors even if your source code is valid.
For example, optimizing based on assumptions about aliasing can produce these errors. Pass -fno-strict-aliasing to disable optimizations based on strict aliasing rules.
Stack protector instrumentation can also trigger such errors. Try -fno-stack-protector to disable the stack protector.
Using soft-float vs hard-float ABI
Some ARM Cortex CPUs like the M-series implement floating point in software, while others like the A-series have hardware FPUs. The compiler defaults to the soft-float ABI which can cause issues if you forget to explicitly specify the ABI target.
Always pass the correct -mfloat-abi option: softfp or hard. Don’t rely on defaults. A mismatch here leads to linking errors about missing floating point implementation.
Including wrong target specific headers
Vendor provided CMSIS headers like stm32fxxx.h contain target specific peripheral addresses and memory map definitions. Including the wrong header for your MCU model will result in invalid access errors.
Double check that the right CMSIS header for your target chip is being included. Also verify if you need to define any macros to choose between device variants if your MCU model has them.
Using non-default compiler optimizations
GCC has many possible code generation options and target specific optimizations. The default settings are tuned for a generic target and good compile time performance.
If you tweak settings like -march, -mcpu, -mthumb, -mfpu etc., it may require additional accompanying options to be specified for correctness. Always double check docs for any newly enabled optimizations.
Bugs in toolchain or libraries
In rare cases, the “not implemented” errors may indicate legitimate bugs or unsupported corner cases in the toolchain itself. Especially if the error persists even in minimal test cases without any complex code.
Updating to the latest patch releases of the compiler and system libraries can help resolve issues caused by known bugs that have since been fixed.
When all else fails – simplify and isolate
Cryptic compiler errors often arise from the interplay of multiple factors that can be tricky to tease apart. If you’re struggling to identify the root cause:
- Try to isolate the error – minimize code until you have a small reproducible example
- Temporarily simplify by disabling optimizations, reducing compiler strictness etc.
- Double check compiler invocations, flags, library search paths and header includes
- Consult compiler docs and resources dedicated to your specific target platform
With some detective work to narrow down the specifics, the not implemented errors usually point squarely at a particular issue that can be addressed in one of the ways discussed above. They may seem mysterious initially, but most cases can be resolved with knowledge of the toolchain’s behavior and limitations.