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

Transfer object through different .c files

My project starts to grow and I would like to separate different parts of code into modules. Each module will present one .c file together with its .h file. In some .c files, I have to have the instance of the timer_id or  struct which is defined in .h file such as

#define BLE_MASS_DEF(_name) \
static ble_mass_t _name; \
NRF_SDH_BLE_OBSERVER(_name ## _obs, \
BLE_MASS_BLE_OBSERVER_PRIO, \
ble_mass_on_ble_evt, &_name)

The problem is  that these are defined via Macros such as:

APP_TIMER_DEF(m_mass_battery_timer_id);

BLE_MASS_DEF(m_mass);

which means that these instances are only visible in main. c. How can I get these instances from Macros and transfer them to other .c files? I have in mind to define .h file which will have all these variables as external and then I will include them in other .c files. But the problem is that I can not get instances from Macros. I will appreciate for help.

  • Hi,

    As you note the app timer is created using the APP_TIMER_DEF that does a few things, including making a app_timer_id_t instance with the name you provide to APP_TIMER_DEF This is the same regardless of which app timer implementation you use, but I show both here from SDK 17.0.2 for reference:

    #ifdef APP_TIMER_V2
    /**
     * @brief app_timer control block
     */
    typedef struct
    {
        nrf_sortlist_item_t         list_item;     /**< Token used by sortlist. */
        uint64_t                    end_val;       /**< RTC counter value when timer expires. */
        uint32_t                    repeat_period; /**< Repeat period (0 if single shot mode). */
        app_timer_timeout_handler_t handler;       /**< User handler. */
        void *                      p_context;     /**< User context. */
        NRF_LOG_INSTANCE_PTR_DECLARE(p_log)        /**< Pointer to instance of the logger object (Conditionally compiled). */
        volatile bool               active;        /**< Flag indicating that timer is active. */
    } app_timer_t;
    
    /**@brief Timer ID type.
     * Never declare a variable of this type, but use the macro @ref APP_TIMER_DEF instead.*/
    typedef app_timer_t * app_timer_id_t;
    
    #define _APP_TIMER_DEF(timer_id)                                                              \
        NRF_LOG_INSTANCE_REGISTER(APP_TIMER_LOG_NAME, timer_id,                                   \
                                  APP_TIMER_CONFIG_INFO_COLOR,                                    \
                                  APP_TIMER_CONFIG_DEBUG_COLOR,                                   \
                                  APP_TIMER_CONFIG_INITIAL_LOG_LEVEL,                             \
                                  APP_TIMER_CONFIG_LOG_ENABLED ?                                  \
                                             APP_TIMER_CONFIG_LOG_LEVEL : NRF_LOG_SEVERITY_NONE); \
        static app_timer_t CONCAT_2(timer_id,_data) = {                                           \
                .active = false,                                                                  \
                NRF_LOG_INSTANCE_PTR_INIT(p_log, APP_TIMER_LOG_NAME, timer_id)                    \
        };                                                                                        \
        static const app_timer_id_t timer_id = &CONCAT_2(timer_id,_data)
    
    #else //APP_TIMER_V2
    typedef struct app_timer_t { uint32_t data[CEIL_DIV(APP_TIMER_NODE_SIZE, sizeof(uint32_t))]; } app_timer_t;
    
    /**@brief Timer ID type.
     * Never declare a variable of this type, but use the macro @ref APP_TIMER_DEF instead.*/
    typedef app_timer_t * app_timer_id_t;
    
    #define _APP_TIMER_DEF(timer_id)                                      \
        static app_timer_t CONCAT_2(timer_id,_data) = { {0} };           \
        static const app_timer_id_t timer_id = &CONCAT_2(timer_id,_data)
    
    #endif

    So you could declare the app_timer_id_t instance as extern if it was not for the fact that it is static (meaning you have to modify the SDK code if you do it).

    While the above is possible it is perhaps not so clean as it interferes with the SDK code, so a better solution could perhaps be to use the app_timer only in one file, either in your main.c or another file. And if you need to access it, use access functions instead of the app_timer API, so that the actual app_timer API is only called from one file. This would be a mater of preference and how you like to organize your C code more than specific to the nRF5 SDK per se.

Related