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

nrf_svci.h does not compile with gcc, SDK 12.1.0

I'm getting the following compilation error when trying to build the DFU bootloader example, using gcc 4.9.3 (4_9-2015q3) on Mac.

In file included from /Users/Eliot/dev/nRF5_SDK_12.1.0_0d23e2a/components/libraries/crypto/nrf_crypto.h:17:0,
                 from dfu_req_handling.c:35:
/Users/Eliot/dev/nRF5_SDK_12.1.0_0d23e2a/components/libraries/svc/nrf_svci.h:69:93: error: expected declaration specifiers or '...' before ')' token
                                                                                  __VA_ARGS__)           \

Here's the context from nrf_svci.h:

#elif defined (__GNUC__)

        #ifdef __cplusplus
                #define GCC_CAST_CPP (uint8_t)
        #else
                #define GCC_CAST_CPP
        #endif

        #define SVCI_DECL(svci_num, return_type, function_name, ...)   \
                _Pragma("GCC diagnostic push")                          \
                _Pragma("GCC diagnostic ignored \"-Wreturn-type\"")     \
                __attribute__((naked, unused))                          \
                static return_type function_name(uint32_t svci_num,  \
                                                                                 __VA_ARGS__)           \
                {                                                       \
                        __asm __volatile (                                  \
                                "mov r12, %1\n\t"                               \
                                "svc %0\n\t"                                    \
                                "bx r14\n\t"                                    \
                                : /* no output */                               \
                                : "I" (GCC_CAST_CPP NRF_SVCI_SVC_NUM), "r" (svci_num)  \
                                : "r12" /* do we need to clobber? */            \
                        );                                                  \
                }                                                       \
                _Pragma("GCC diagnostic pop")

I guess this has something to do with the use of var args within a macro, but I don't know what exactly.

  • Don't use CFLAGS += -std=gnu99 if you want this to compile (thanks: Nguyen Hoan Hoang).

  • Note that this bug is still present in SDK 12.1.

    The root of this problem appears to be that the __VA_ARGS__ expansion has changed for C99 and C11. In the old non-standard GCC days when __VA_ARGS__ expanded to empty, the preprocessor removed the preceding comma. Not so any more with C99 and C11. See stackoverflow.com/.../standard-alternative-to-gccs-va-args-trick

    With GCC, you can get rid of the syntax error is as simple as replacing __VA_ARGS__ with ##__VA_ARGS__. However, that leads to a parameter type conflict with the expanded function declaration and definition. Basically, the declaration lists uint32_t svci_num as the first argument to the function, while the definition on the next lines does not.

    For example, the first definition of nrf_crypto_init gets expanded from SVCI_DECL [sic] to the following:

    __attribute__((naked, unused)) static uint32_t nrf_crypto_init(uint32_t NRF_CRYPTO_SVCI_INIT) ...
    

    However, the following second definition expands to

    static inline uint32_t nrf_crypto_init(void) ...
    

    Apparently the mistake is that the first definition should actually define svci_nrf_crypto_init instead of defining nrf_crypto_init with a different signature.

    Here is a potential, mostly untested fix:

    --- a/Product_Configurations/SampoDFU/include/nrf_svci.h
    +++ b/Product_Configurations/SampoDFU/include/nrf_svci.h
    @@ -66,7 +66,7 @@ extern "C" {
                     _Pragma("GCC diagnostic ignored \"-Wreturn-type\"")     \
                     __attribute__((naked, unused))                          \
                     static return_type function_name(uint32_t svci_num,  \
    -                                                                                 __VA_ARGS__)           \
    +                                                 ##__VA_ARGS__)           \
                     {                                                       \
                             __asm __volatile (                                  \
                                     "mov r12, %1\n\t"                               \
    @@ -122,23 +122,23 @@ extern "C" {
     #else
     
     #define SVCI_0(svci_num, return_type, function_name) \
    -        SVCI_DECL(svci_num, return_type, function_name) \
    +        SVCI_DECL(svci_num, return_type, svci_##function_name) \
             static __INLINE return_type function_name(void) {return svci_##function_name(svci_num);}
     
     #define SVCI_1(svci_num, return_type, function_name, p0t, p0n) \
    -        SVCI_DECL(svci_num, return_type, function_name, p0t p0n) \
    +        SVCI_DECL(svci_num, return_type, svci_##function_name, p0t p0n) \
             static __INLINE return_type function_name(p0t p0n) {return svci_##function_name(svci_num, p0n);}
     
     #define SVCI_2(svci_num, return_type, function_name, p0t, p0n, p1t, p1n) \
    -        SVCI_DECL(svci_num, return_type, function_name, p0t p0n, p1t p1n) \
    +        SVCI_DECL(svci_num, return_type, svci_##function_name, p0t p0n, p1t p1n) \
             static __INLINE return_type function_name(p0t p0n, p1t p1n) {return svci_##function_name(svci_num, p0n, p1n);}
     
     #define SVCI_3(svci_num, return_type, function_name, p0t, p0n, p1t, p1n, p2t, p2n) \
    -        SVCI_DECL(svci_num, return_type, function_name, p0t p0n, p1t p1n, p2t p2n) \
    +        SVCI_DECL(svci_num, return_type, svci_##function_name, p0t p0n, p1t p1n, p2t p2n) \
             static __INLINE return_type function_name(p0t p0n, p1t p1n, p2t p2n) {return svci_##function_name(svci_num, p0n, 
    p1n, p2n);}
     
     #define SVCI_4(svci_num, return_type, function_name, p0t, p0n, p1t, p1n, p2t, p2n, p3t, p3n) \
    -        SVCI_DECL(svci_num, return_type, function_name, p0t p0n, p1t p1n, p2t p2n, p3t p3n) \
    +        SVCI_DECL(svci_num, return_type, svci_##function_name, p0t p0n, p1t p1n, p2t p2n, p3t p3n) \
             static __INLINE return_type function_name(p0t p0n, p1t p1n, p2t p2n, p3t p3n) {return svci_##function_name(svci_n
    um, p0n, p1n, p2n, p3n);}
     
     #endif  // SVCALL_AS_NORMAL_FUNCTION
    

    Here is another tentative patch, to the other bug briefly discussed below. It may or may not work.

    --- a/components/libraries/svc/nrf_svc_function.h 
    +++ b/components/libraries/svc/nrf_svc_function.h
    @@ -50,7 +50,7 @@ STATIC_ASSERT(sizeof(nrf_svc_func_reg_t) % 4 == 0);
      * @details     This macro places the variable in a section named "svc_data" that
                 the SVC handler uses during regular operation.
      */
    -#define SVC_REGISTER_FUNCTION(svc_var) NRF_SECTION_VARS_ADD(svc_data, svc_var)
    +#define SVC_REGISTER_FUNCTION(svc_var) NRF_SECTION_VARS_REGISTER_VAR(svc_data, svc_var)
     
     
     #ifdef __cplusplus
    
  • This solution does not work for me in Segger embedded studio. I can change the C standards (90, 99, 11), but can't figure out how to compel the ide to remove those flags. In short: I did not have much luck with your patch.

Related