Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs

Linker error when merging twi-examples into ble_app_uart

Hello,

as I see, many in DevZone have had a problem like this: we tried to merge twi-functionality into the basic ble_app_uart example. We set proper defines in sdk_config.h, we add missing .c files, and we add include paths, but the linker just complains that it cant see some of the functions like `nrfx_twim_init' or "nrfx_twim_enable". 

In my case, I did the following

  • copied the main.c code from twi_sensor into my main.c
  • added nrf_drv_twi.c, nrfx_twi.c and nrfx_twi_twim.c into the  /nRF_Drivers section of my codebase
  • add the following include paths in the "common" project settings:
    • ../../../../../../integration/nrfx
    • ../../../../../../integration/nrfx/legacy
    • ../../../../../../modules/nrfx
    • ../../../../../../modules/nrfx/drivers/include

    • ../../../../../../modules/nrfx/hal

    • ../../../../../../modules/nrfx/mdk

  • Configured my sdk_config.h so that it matches the one from the twi_scanner and twi_sensor examples (please see the attachment):

and I ended up with the linker errors:

Building ‘MERS_s132’ from solution ‘MERS_s132’ in configuration ‘Debug’

Linking MERS_s132.elf
Output/Debug/Obj/MERS_s132/nrf_drv_twi.o: in function `nrf_drv_twi_init':
undefined reference to `nrfx_twim_init'
Output/Debug/Obj/MERS_s132/MERS_LIS3DH.o: in function `nrf_drv_twi_enable':
undefined reference to `nrfx_twim_enable'
Build failed

I scratched my head a long time about this one. Everything seemed like in those two examples, and like the people in DevZone have suggested.

Finally, after the suggestion of one member here, I deleted all TWI-related defines from TWI_ENABLED on, and the error is gone. But when I flashed my nRF52-DK, something was wrong -  the scanner application returned true for every address probed (but obviously there should be no devices present).

So what sense does it make? What should be used in the end? Why do twi-examples work with legacy defines just fine?

I'm using SDK  v17.1.0 on nRF52-DK, 

Best regards, 

P.

Parents
  • Hi,

    If it builds fine without any errors, then I think we can assume that everything is included for it to work. The culprit might be related to something else.

    the scanner application returned true for every address probed (but obviously there should be no devices present).
    copied the main.c code from twi_sensor into my main.c

    Is your code based on twi_sensor or tw_scanner? 

    What pin are you using for the SDA line and is it connected to something externally? Do you get the same result if you connect the pin to VDD?

    regards
    Jared 

  • Hi Jared, thanks for the reply. 

    I am using nRF52-DK, unmodified, so everything shoud be as shipped.

    Is your code based on twi_sensor or tw_scanner? 

    I have tried both. For the clarity, the last time I was testing the setup, i used twi_scanner (which retourned positive for every address it has scanned).

    Best,

    P

    EDIT: hello, the issue seems to have been solved when the handler is excluded from the twi_init function, that is if the init is called like this:

    err_code = nrf_drv_twi_init(&m_twi, &twi_lm75b_config, NULL, NULL);

    now the scanner works and no twi device is detected, as it should be. Originally, I had the handler address sent to init function (leftover from twi_sensor example).

    Why is that so? Why the scanner example makes trouble if the handler address is passed through?

  • Hmm, I can't see how that would make any difference. Not providing a handler to the initialize function means the driver will be configured in blocking mode

Reply Children
  • Hi, I have added a dummy handler function like this:

    /**
     * @brief TWI events handler.
     */
    void twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
    {
        switch (p_event->type)
        {
            case NRF_DRV_TWI_EVT_DONE:
                if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_RX)
                {
                   NRF_LOG_INFO("\n\rTWI Data handler");
                   NRF_LOG_FLUSH();
                }
                //m_xfer_done = true;
                break;
            default:
                break;
        }
    }
    

    Then if I make my init function like this:

    nrf_drv_twi_init(&m_twi, &twi_config, &twi_handler, NULL);

    the twi_scanner example finds a device at every address.But if I exlude the handler pointer, like this:

    nrf_drv_twi_init(&m_twi, &twi_config, NULL, NULL);

    it works fine again. 

    Why is that so?

  • Hi,

    The TWI scanner example in the SDK is built to be run in blocking mode. The function will return a NRF_SUCCESS only if it finds a slave on the bus and the transfer is successful.

    However, if the driver is used in non blocking mode, then the function will return immediately, before the transfer has finished with a NRF_SUCCESS. It will then eventually generate a nrf_drv_twi_evt_type_t event that indicates if the transfer was successful or not. 

    Because the function returns immediately with NRF_SUCCESS in non-blocking mode, the example code will interpret this as a device has been found on the address. 

    regards

    Jared 

Related