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 : 

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#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();
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

init_accelero.h : 

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#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
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

whoami.c : 

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#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();
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

whoami.h : 

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
#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
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

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 : 

Fullscreen
1
2
3
4
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
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

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