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

Compilation error : redefinition of nrf_twi_mngr_queue and nrf_twi_sensor_pool on SDK 16.

Hello everyone,

I'm working with a nrf52840 devboard on which I put a LIS2DH12 accelerometer. I had a perfectly working example program featuring multiple functions. My program is very similar to this one, featured in another topic, that helped me a lot : https://devzone.nordicsemi.com/f/nordic-q-a/36089/using-the-lis2dh12-driver-of-the-sdk-v15-0-0-to-configure-the-lis2dh12-sensor/139406#139406.

Once it was working, I decided to sort my functions in different files to make it easier and clearer to find. This is where the trouble begins : I can't figure a way to compile my program now that the functions are separated in different files.

To take the most simple example, let's say I have 2 .c and 2 .h associated files :  init_accelero.c / .h which contains the initialization functions, and whoami.c / .h which holds a simple function that prints the value of the Who Am I registry. Here's the code for the 4 of them :

init_accelero.c : 

#include "init_accelero.h"

int acc_init()
{


	nrf_drv_twi_config_t const config = {
	   .scl                = 27,
	   .sda                = 26,
	   .frequency          = NRF_DRV_TWI_FREQ_100K,
	   .interrupt_priority = APP_IRQ_PRIORITY_LOWEST,
	   .clear_bus_init     = false
	};
	bsp_board_init(BSP_INIT_LEDS);

	APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
	NRF_LOG_DEFAULT_BACKENDS_INIT();

	NRF_LOG_INFO("TWI sensor example started.");
	NRF_LOG_FLUSH();


	err = nrf_twi_mngr_init(&m_nrf_twi_mngr, &config);
	APP_ERROR_CHECK(err);

	err = nrf_twi_sensor_init(&m_nrf_twi_sensor);
	APP_ERROR_CHECK(err);

	err = lis2dh12_init(&m_lis2dh12);
	APP_ERROR_CHECK(err);

	LIS2DH12_DATA_CFG(m_lis2dh12, LIS2DH12_ODR_10HZ, true, true, true, true, LIS2DH12_SCALE_8G, 0);
	err = lis2dh12_cfg_commit(&m_lis2dh12);
	APP_ERROR_CHECK(err);
	
	return err;
}

init_accelero.h : 

#ifndef INIT_ACCELERO_H
#define INIT_ACCELERO_H

#include <stdio.h>
#include <math.h>
#include <stdbool.h>

#include "boards.h"
#include "app_util_platform.h"
#include "app_error.h"
#include "nrf_drv_twi.h"
#include "nrf_delay.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#include "lis2dh12.h"
#include "nrf_drv_gpiote.h"

#define TWI_INSTANCE_ID             0

#define MAX_PENDING_TRANSACTIONS    33

#define LIS2DH12_MIN_QUEUE_SIZE     32

uint32_t err;

NRF_TWI_MNGR_DEF(m_nrf_twi_mngr, MAX_PENDING_TRANSACTIONS, TWI_INSTANCE_ID);

NRF_TWI_SENSOR_DEF(m_nrf_twi_sensor, &m_nrf_twi_mngr, LIS2DH12_MIN_QUEUE_SIZE);

LIS2DH12_INSTANCE_DEF(m_lis2dh12, &m_nrf_twi_sensor, LIS2DH12_BASE_ADDRESS_HIGH);

int acc_init();

#endif

whoami.c : 

#include "whoami.h"

void print_identity(ret_code_t r, void *p_register_data)
{
    NRF_LOG_INFO("Identity: %d", *((uint8_t *)p_register_data));
}

int get_whoami()
{
	err = lis2dh12_who_am_i_read(&m_lis2dh12, print_identity, &m_data);
	nrf_delay_ms(100);
	APP_ERROR_CHECK(err);
	return err;
}

int main(void)
{
	acc_init();

	while (true){
		get_whoami();
	}
}

whoami.h : 

#ifndef WHOAMI_H
#define WHOAMI_H

#include "init_accelero.h"

static uint8_t m_data;

int get_whoami();
void print_identity(ret_code_t, void *);

#endif

The error comes from those 3 lines of code in init_accelero.h, when I call NRF_TWI_MNGR_DEF, NRF_TWI_SENSOR_DEF and LIS2DH12_INSTANCE_DEF.  Here's the output of my Make command : 

c:/program files (x86)/gnu tools arm embedded/9 2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/bin/ld.exe: _build/nrf52840_xxaa/whoami.c.o:C:\Users\Hugo\eclipse\eclipse-workspace\LIS2DH12_Unity/./inc/init_accelero.h:29: multiple definition of `m_nrf_twi_sensor_pool'; _build/nrf52840_xxaa/init_accelero.c.o:C:\Users\Hugo\eclipse\eclipse-workspace\LIS2DH12_Unity/./inc/init_accelero.h:29: first defined here
c:/program files (x86)/gnu tools arm embedded/9 2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/bin/ld.exe: _build/nrf52840_xxaa/whoami.c.o:C:\Users\Hugo\eclipse\eclipse-workspace\LIS2DH12_Unity/./inc/init_accelero.h:27: multiple definition of `m_nrf_twi_mngr_queue'; _build/nrf52840_xxaa/init_accelero.c.o:C:\Users\Hugo\eclipse\eclipse-workspace\LIS2DH12_Unity/./inc/init_accelero.h:27: first defined here
collect2.exe: error: ld returned 1 exit status
make: *** [../../../Documents/nRF5_SDK_16.0.0_98a08e2/components/toolchain/gcc/Makefile.common:294: _build/nrf52840_xxaa.out] Error 1

I know I'm supposed to call those macros once, and that's why I didn't have any trouble when everything was in one single file. However now both of my C files are using m_lis2dh12, which means I have no choice but include "init_accelero.h" in both C files. The problem is that it seems like variables used inside those macros like nrf_twi_mngr_queue and nrf_twi_sensor_pool are redefined ? I don't quite understand why it would be redefined here, honestly, and I don't know how I could solve this compilation issue. There must be another way than just putting all functions in a single file, right ?

I've been trying different things to avoid this error but other errors occured instead. For example, when I tried putting those macros in a function and then calling this function from acc_init(), I had : "section attribute cannot be specified for local variables", even if I declared m_nrf_twi_mngr, m_nrf_twi_sensor, m_lis2dh12 in init_accelero.h . I tried just putting those macros at the beggining of init_accelero.c, which didn't give me any compilation error but obviously prevented get_whoami() from working since it doesn't have access to the initialization of m_lis2dh12.

I hope I was clear enough, if you need more info, don't hesitate to ask. This is probably an easy thing to solve but I can't figure out how. I'm not programming for nrf since very long so I don't not understand how everything works yet, and I may have missed an obvious fix to this.

Thanks in advance !

Hugo

Parents
  • Hi,

    It is correct that your approach will lead to redefinitions. I would recommend you to use the following approach:

    1. Declare extern pointers in init_accelero.h to the objects you are interested in:
      extern nrf_twi_mngr_t * p_nrf_twi_mngr;
      extern nrf_twi_sensor_t * p_nrf_twi_sensor;
      extern lis2dh12_instance_t * p_lis2dh12;


    2. Move the DEF macros inside init_accelero.c and implement the pointers that were declared as extern in the header:
      NRF_TWI_MNGR_DEF(m_nrf_twi_mngr, MAX_PENDING_TRANSACTIONS, TWI_INSTANCE_ID);
      NRF_TWI_SENSOR_DEF(m_nrf_twi_sensor, &m_nrf_twi_mngr, LIS2DH12_MIN_QUEUE_SIZE);
      LIS2DH12_INSTANCE_DEF(m_lis2dh12, &m_nrf_twi_sensor, LIS2DH12_BASE_ADDRESS_HIGH);
      
      const nrf_twi_mngr_t * p_nrf_twi_mngr;
      nrf_twi_sensor_t * p_nrf_twi_sensor;
      lis2dh12_instance_t * p_lis2dh12;
      


    3. During init, assign the address of the actual objects to the pointers:
      void twi_pointes_init(void)
      {
          p_nrf_twi_mngr = &m_nrf_twi_mngr;
          p_nrf_twi_sensor = &m_nrf_twi_sensor;
          p_lis2dh12 = &m_lis2dh12;
      }

    Best regards,
    Jørgen

Reply
  • Hi,

    It is correct that your approach will lead to redefinitions. I would recommend you to use the following approach:

    1. Declare extern pointers in init_accelero.h to the objects you are interested in:
      extern nrf_twi_mngr_t * p_nrf_twi_mngr;
      extern nrf_twi_sensor_t * p_nrf_twi_sensor;
      extern lis2dh12_instance_t * p_lis2dh12;


    2. Move the DEF macros inside init_accelero.c and implement the pointers that were declared as extern in the header:
      NRF_TWI_MNGR_DEF(m_nrf_twi_mngr, MAX_PENDING_TRANSACTIONS, TWI_INSTANCE_ID);
      NRF_TWI_SENSOR_DEF(m_nrf_twi_sensor, &m_nrf_twi_mngr, LIS2DH12_MIN_QUEUE_SIZE);
      LIS2DH12_INSTANCE_DEF(m_lis2dh12, &m_nrf_twi_sensor, LIS2DH12_BASE_ADDRESS_HIGH);
      
      const nrf_twi_mngr_t * p_nrf_twi_mngr;
      nrf_twi_sensor_t * p_nrf_twi_sensor;
      lis2dh12_instance_t * p_lis2dh12;
      


    3. During init, assign the address of the actual objects to the pointers:
      void twi_pointes_init(void)
      {
          p_nrf_twi_mngr = &m_nrf_twi_mngr;
          p_nrf_twi_sensor = &m_nrf_twi_sensor;
          p_lis2dh12 = &m_lis2dh12;
      }

    Best regards,
    Jørgen

Children
Related