This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Compile SDK11 with ARM Compiler Version 6

I would like to use the latest ARM Compiler Version 6 (armclang) because I need some features of the C++11 language.

Is it possible to use the latest ARM Compiler Version 6 to compile the SDK 11 ? Which flags should we use to be compatible with all macros currently available for GCC and armcc ?

In future SDK releases, will this compiler be officially supported ?

  • ... a macro which takes the current SVCALL() parameters and spits out that wrapper. That's because in order to do it, you need to know how many arguments you have and possibly have them listed out (I don't remember, it's 2 years since I did this).

    It would mean adding some parameters to SVCCALL() which the other compilers don't use, but clang does, or writing a quick shim for clang. Either works.

  • Hi,

    I was sick and tired not to being able to use a modern toolchain and getting stuck with a deprecated GCC version, because of these (somewhat dodgy) SVC calls.

    Unfortunately, I did not find a way to fix it with a couple of additional macros, because the "signature" parameter of the SVCALL() macro cannot be broken down (at least with the C/C++ preprocessor) into argument types and argument names. It would require the macro arguments to be rewritten with another, less readable syntax.

    Anyway, it is still possible to fix the SDK to build with Clang/LLVM. At least, it now works smoothly with both a BLE 4.0 central and BLE 4.0 peripheral projects, with SDK13, S132 on nRF52 chips, with clang 4.0.1 and -O2 and -O3 optimisation level. YMMV :-)

    The easiest solution I found for now is to modify (to be more precise: add some lines to) a couple of Nordic header files, i.e. the files that contain SVCALL invocations, plus the one that defines this macro (nrf_svc.h).

    As hand-writing the files could be quite error-prone and because this task would have to be repeated on each SDK release, I wrote a small Python3 script to deal with it.

    Building with Clang/LLVM (assuming you have downloaded or built the toolchain with support for ARM Cortex-M4 for use with nRF52) now requires to execute once the following simple steps:

    1. Edit softdevice/s132/include/nrf_svc.h so that SVCALL declare a static inline function when Clang is in used.

      --- a/components/softdevice/s132/headers/nrf_svc.h
      +++ b/components/softdevice/s132/headers/nrf_svc.h
      @@ -50,6 +50,9 @@
       #ifndef SVCALL
       #if defined (__CC_ARM)
       #define SVCALL(number, return_type, signature) return_type __svc(number) signature
      +#elif defined(__clang__)
      +#define SVCALL(number, return_type, signature) \
      +   static inline return_type signature;
       #elif defined (__GNUC__)
       #ifdef __cplusplus
       #define GCC_CAST_CPP (uint16_t)
      
    2. Execute the Python script on your SDK installation. It should print out (to stderr) which are the files to be patched.

      python3.5 nrfsvc.py components/softdevice/s132
      
    3. If everything looks ok, run the same script with the -u option switch, to update the source files. Do not execute this step if you have easy no way to revert back in case something goes wrong, you've been warned... Any SCM tool is your friend here.

      python3.5 nrfsvc.py -u components/softdevice/s132
      
    4. Use your favorite SCM tool to check the changes - svn diff, git diff, ... - and (re)build your project with Clang/LLVM.

    Note that if you run the script on a higher directory level, you'll find a couple of files which contain non-ASCII characters, so the script will discard those files without analysing them, namely:

    • components/ble/common/ble_date_time.h
    • components/ble/common/ble_sensor_location.h
    • components/libraries/crypto/nrf_crypto_keys.h

    It should not hurt as they do not contain SVCALL calls, and I got lazy dealing with those files (and bothering to support Python2.x) - maybe Nordic have fixed them since?

    Basically, what the script does it quite simple:

    1. it searches for all header files from the specified top-level directory
    2. for each script that contains one or more SVCALL invocation, it parses this macro arguments, then emits a static inline function. See below for the details about these functions.
    3. it packages in a new header file the original content of the SDK header file, and appends to this file the new inline function(s), with a couple of macros to generate the proper ARM SVC calls.
    4. if the generation completes successfully, it swaps the original header file with the newly generated one. This last step should prevent from trashing a valid file is something goes wrong, but it should not prevent you from using a SCM tool to revert back at any time.

    The emitted static inline functions are straighgforward:

    Each static inline function declares which ARM registers are actually used by the supervisor call, to let the compiler know which registers are used and spilled, so it does not attempt to optimise them out. This is the root cause of the issue with the incomplete declaration made with the designed-for-GCC, provided macro.

    This is at least r0 - which is used for the return code, and from none up to (r0,) r1, r2, and r3 scratch registers, i.e. for up to 4 32-bit SVC arguments. It would fail with any 64-bit argument (or return code) and would be left undetected, but AFAICT, Nordic does not use them. It also encodes in the SVC opcode which supervisor call is to be made, as with the original macro.

    If you're interested in the script, the latest version it is available from here: github.com/.../nrfsvc.py

Related