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