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

Error with nrfx_gpiote.h, offsetof, IAR, and C++

I am trying to use C++ with an nRF5 board, but I'm running into issues with the MDK, IAR (v8.40.2), and C++. When I try to include "nrfx_gpiote.h" in a .cpp file, I get the following errors (this is from the examples\peripherals\gpiote with main.c switched to main.cpp:

Error[Pe028]: expression must have a constant value C:\nRF5_SDK_16.0.0\modules\nrfx\hal\nrf_gpiote.h 84
Error[Pe028]: expression must have a constant value C:\nRF5_SDK_16.0.0\modules\nrfx\hal\nrf_gpiote.h 85
Error[Pe028]: expression must have a constant value C:\nRF5_SDK_16.0.0\modules\nrfx\hal\nrf_gpiote.h 86
Error[Pe028]: expression must have a constant value C:\nRF5_SDK_16.0.0\modules\nrfx\hal\nrf_gpiote.h 88
Error[Pe028]: expression must have a constant value C:\nRF5_SDK_16.0.0\modules\nrfx\hal\nrf_gpiote.h 89
Error[Pe028]: expression must have a constant value C:\nRF5_SDK_16.0.0\modules\nrfx\hal\nrf_gpiote.h 90
Error[Pe028]: expression must have a constant value C:\nRF5_SDK_16.0.0\modules\nrfx\hal\nrf_gpiote.h 91
Error[Pe028]: expression must have a constant value C:\nRF5_SDK_16.0.0\modules\nrfx\hal\nrf_ppi.h 129
Error[Pe028]: expression must have a constant value C:\nRF5_SDK_16.0.0\modules\nrfx\hal\nrf_ppi.h 130
Error[Pe028]: expression must have a constant value C:\nRF5_SDK_16.0.0\modules\nrfx\hal\nrf_ppi.h 131
Error[Pe028]: expression must have a constant value C:\nRF5_SDK_16.0.0\modules\nrfx\hal\nrf_ppi.h 132
Error[Pe028]: expression must have a constant value C:\nRF5_SDK_16.0.0\modules\nrfx\hal\nrf_ppi.h 133
Error[Pe028]: expression must have a constant value C:\nRF5_SDK_16.0.0\modules\nrfx\hal\nrf_ppi.h 134
Error[Pe028]: expression must have a constant value C:\nRF5_SDK_16.0.0\modules\nrfx\hal\nrf_ppi.h 136
Error[Pe028]: expression must have a constant value C:\nRF5_SDK_16.0.0\modules\nrfx\hal\nrf_ppi.h 137
Error[Pe028]: expression must have a constant value C:\nRF5_SDK_16.0.0\modules\nrfx\hal\nrf_ppi.h 138
Error[Pe028]: expression must have a constant value C:\nRF5_SDK_16.0.0\modules\nrfx\hal\nrf_ppi.h 139

Does anyone know why offsetof seems to be failing after the first offsetof in these files only with IAR and C++? I can't get a more minimal reproduction, as IAR will compile (with iccarm.exe -e --c++ test.cpp) even this:

#include <stddef.h>

extern "C"
{
    typedef struct test
    {
        int a;
        int b;
    } test_t;

    typedef enum
    {
        A = offsetof(test_t, a),
        B = offsetof(test_t, b),
    } test_field_t;
}
without issue. It's only when done as part of the larger SDK that it seems to fail. If I include this file from anything with a .c extension there is no issue.
EDIT: Adding IAR version
EDIT2: After speaking with IAR, it seems like this is fixed in IAR 8.50.2. I don't know if this matters for previous versions though. Still trying to find the root cause though.
Parents
  • UPDATE: So, my guess is that it has something to do with how IAR implements the offsetof macro. GCC and Clang use a special built-in function for this, while IAR uses an ARM intrinsic __INTADDR__. I think the issue comes down to the fact that the types that are being offset have volatile qualifiers with IAR, and C is ultimately fine with that being considered constant, but C++ does not allow that. Take for example this C++14 compliant version of offset:

    template <typename T1, typename T2>
    inline size_t constexpr offset_of(T1 T2::*member) {
        constexpr T2 object {};
        return size_t(&(object.*member)) - size_t(&object);
    }

    This fails even on GCC with any of the NRF_<PERIPHERAL>_Type structures because they are not considered literals (my guess is due to the volatile member variables). I don't know why this fails considering the field locations never change, but maybe because IAR doesn't do any special compiler magic it fails. Will update further if I learn more. I've got a support ticket in with IAR to see if this is indeed the issue.

  • FURTHER UPDATE:

    I have found a workaround:
    In nrf_gpiote.h, change the following lines (starts from line 83 in SDK 16.0.0):
        NRF_GPIOTE_TASKS_OUT_0     = offsetof(NRF_GPIOTE_Type, TASKS_OUT[0]), /**< Out task 0. */
        NRF_GPIOTE_TASKS_OUT_1     = offsetof(NRF_GPIOTE_Type, TASKS_OUT[1]), /**< Out task 1. */
        NRF_GPIOTE_TASKS_OUT_2     = offsetof(NRF_GPIOTE_Type, TASKS_OUT[2]), /**< Out task 2. */
        NRF_GPIOTE_TASKS_OUT_3     = offsetof(NRF_GPIOTE_Type, TASKS_OUT[3]), /**< Out task 3. */
    #if (GPIOTE_CH_NUM > 4) || defined(__NRFX_DOXYGEN__)
        NRF_GPIOTE_TASKS_OUT_4     = offsetof(NRF_GPIOTE_Type, TASKS_OUT[4]), /**< Out task 4. */
        NRF_GPIOTE_TASKS_OUT_5     = offsetof(NRF_GPIOTE_Type, TASKS_OUT[5]), /**< Out task 5. */
        NRF_GPIOTE_TASKS_OUT_6     = offsetof(NRF_GPIOTE_Type, TASKS_OUT[6]), /**< Out task 6. */
        NRF_GPIOTE_TASKS_OUT_7     = offsetof(NRF_GPIOTE_Type, TASKS_OUT[7]), /**< Out task 7. */
    to
        NRF_GPIOTE_TASKS_OUT_0     = offsetof(NRF_GPIOTE_Type, TASKS_OUT), /**< Out task 0. */
        NRF_GPIOTE_TASKS_OUT_1     = offsetof(NRF_GPIOTE_Type, TASKS_OUT + 1), /**< Out task 1. */
        NRF_GPIOTE_TASKS_OUT_2     = offsetof(NRF_GPIOTE_Type, TASKS_OUT + 2), /**< Out task 2. */
        NRF_GPIOTE_TASKS_OUT_3     = offsetof(NRF_GPIOTE_Type, TASKS_OUT + 3), /**< Out task 3. */
    #if (GPIOTE_CH_NUM > 4) || defined(__NRFX_DOXYGEN__)
        NRF_GPIOTE_TASKS_OUT_4     = offsetof(NRF_GPIOTE_Type, TASKS_OUT + 4), /**< Out task 4. */
        NRF_GPIOTE_TASKS_OUT_5     = offsetof(NRF_GPIOTE_Type, TASKS_OUT + 5), /**< Out task 5. */
        NRF_GPIOTE_TASKS_OUT_6     = offsetof(NRF_GPIOTE_Type, TASKS_OUT + 6), /**< Out task 6. */
        NRF_GPIOTE_TASKS_OUT_7     = offsetof(NRF_GPIOTE_Type, TASKS_OUT + 7), /**< Out task 7. */
    I honestly have no idea why it's only this one section of the nrf_gpiote.h header file (as others should be included per my SDK and board).
Reply
  • FURTHER UPDATE:

    I have found a workaround:
    In nrf_gpiote.h, change the following lines (starts from line 83 in SDK 16.0.0):
        NRF_GPIOTE_TASKS_OUT_0     = offsetof(NRF_GPIOTE_Type, TASKS_OUT[0]), /**< Out task 0. */
        NRF_GPIOTE_TASKS_OUT_1     = offsetof(NRF_GPIOTE_Type, TASKS_OUT[1]), /**< Out task 1. */
        NRF_GPIOTE_TASKS_OUT_2     = offsetof(NRF_GPIOTE_Type, TASKS_OUT[2]), /**< Out task 2. */
        NRF_GPIOTE_TASKS_OUT_3     = offsetof(NRF_GPIOTE_Type, TASKS_OUT[3]), /**< Out task 3. */
    #if (GPIOTE_CH_NUM > 4) || defined(__NRFX_DOXYGEN__)
        NRF_GPIOTE_TASKS_OUT_4     = offsetof(NRF_GPIOTE_Type, TASKS_OUT[4]), /**< Out task 4. */
        NRF_GPIOTE_TASKS_OUT_5     = offsetof(NRF_GPIOTE_Type, TASKS_OUT[5]), /**< Out task 5. */
        NRF_GPIOTE_TASKS_OUT_6     = offsetof(NRF_GPIOTE_Type, TASKS_OUT[6]), /**< Out task 6. */
        NRF_GPIOTE_TASKS_OUT_7     = offsetof(NRF_GPIOTE_Type, TASKS_OUT[7]), /**< Out task 7. */
    to
        NRF_GPIOTE_TASKS_OUT_0     = offsetof(NRF_GPIOTE_Type, TASKS_OUT), /**< Out task 0. */
        NRF_GPIOTE_TASKS_OUT_1     = offsetof(NRF_GPIOTE_Type, TASKS_OUT + 1), /**< Out task 1. */
        NRF_GPIOTE_TASKS_OUT_2     = offsetof(NRF_GPIOTE_Type, TASKS_OUT + 2), /**< Out task 2. */
        NRF_GPIOTE_TASKS_OUT_3     = offsetof(NRF_GPIOTE_Type, TASKS_OUT + 3), /**< Out task 3. */
    #if (GPIOTE_CH_NUM > 4) || defined(__NRFX_DOXYGEN__)
        NRF_GPIOTE_TASKS_OUT_4     = offsetof(NRF_GPIOTE_Type, TASKS_OUT + 4), /**< Out task 4. */
        NRF_GPIOTE_TASKS_OUT_5     = offsetof(NRF_GPIOTE_Type, TASKS_OUT + 5), /**< Out task 5. */
        NRF_GPIOTE_TASKS_OUT_6     = offsetof(NRF_GPIOTE_Type, TASKS_OUT + 6), /**< Out task 6. */
        NRF_GPIOTE_TASKS_OUT_7     = offsetof(NRF_GPIOTE_Type, TASKS_OUT + 7), /**< Out task 7. */
    I honestly have no idea why it's only this one section of the nrf_gpiote.h header file (as others should be included per my SDK and board).
Children
No Data
Related