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