Using Nordic's SDKs with the GNU G++ Compiler

A persistant problem that people using the C++ compiler from the "GNU Tools for ARM Embedded Processors" toolchain has been the way that G++ handles the inline-assembly for the SVC instruction.

Specifically, you get an impossible constraint in 'asm' error when trying to use any softdevice header.

There have been a few questions about this here on the Nordic Developer Zone, here for example, with putative answers on StackOverflow.

However, myself and others have found that the "insert a cast" answer on StackOverflow does not work with the latest (4.9) G++ under the -Os optimization mode. Digging into the issue, it appears that different code generation and optimization options make it hit-and-miss with being able to use the GNU G++ compiler.

Note that often GCC will work even though G++ does not because the rules of type-inference for enumdiffer substantially between C and C++. For the current GNU compilers, even explicitly setting the type via enum : unsigned char { ... } does not work (and might be a compiler bug).

Therefore, I've created a tool on GitHub that automagically translates Nordic's enum header files into Keil-compatible #define constants.

Since I can't release the modified Nordic SDKs, I've opted to release the tool, enum2define.py and just the patch files under the MIT license.

Comments and suggestions (and better yet, patches) are gratefully accepted.

Parents
  • Hi, Carles!

    I'm sorry that I didn't reply earlier, but I did not get mail notification that your comment was here!

    The issue is only with the SVC enumerations due to the way the SVC call is defined in the nrf_svc.h header file. Specifically, it has something to do with the __asm( "svc %0\n" "bx r14" : : "I" (number) : "r0" ); call.

    The "I" (number) constraint requires a compile-time integer constant. In C, enums are just aliases to integers, the compiler has no problem with it. However, C++ does not equate integers with enums; they are a distinct type, even under C++03. You can technically set a typed enum storage class in C++11 via the enum name_t : short { ... syntax, but this does not work for some reason.

    I am not sure if this is a gcc bug or not; I suspect that inline assembly always plays poorly with standards.

    I'm using the official arm-none-eabi-gcc distribution on launchpad, BTW.

    Cheers, -Andrew.

    (BTW, enums that are not used in the SVC calls compile without issue, so the problem is only with enums passed to the inline assembler.)

Comment
  • Hi, Carles!

    I'm sorry that I didn't reply earlier, but I did not get mail notification that your comment was here!

    The issue is only with the SVC enumerations due to the way the SVC call is defined in the nrf_svc.h header file. Specifically, it has something to do with the __asm( "svc %0\n" "bx r14" : : "I" (number) : "r0" ); call.

    The "I" (number) constraint requires a compile-time integer constant. In C, enums are just aliases to integers, the compiler has no problem with it. However, C++ does not equate integers with enums; they are a distinct type, even under C++03. You can technically set a typed enum storage class in C++11 via the enum name_t : short { ... syntax, but this does not work for some reason.

    I am not sure if this is a gcc bug or not; I suspect that inline assembly always plays poorly with standards.

    I'm using the official arm-none-eabi-gcc distribution on launchpad, BTW.

    Cheers, -Andrew.

    (BTW, enums that are not used in the SVC calls compile without issue, so the problem is only with enums passed to the inline assembler.)

Children
No Data