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

'NRFX_TWI0_INST_IDX' undeclared - possible solution and bug found

A while back I was working on I2C and came across the compiler error " 'NRFX_TWI0_INST_IDX' undeclared ", which seemed to be related to NRF drivers vs NRFX drivers confusion. I recall researching here and not finding anything. I am sorry I don't recall every little detail, but still wanted to share:

I wonder whether there is a bug in apply_old_config.h line 1116 in SDK16.0.0

It reads "#if defined(TWI_ENABLED)", and in this case #undef's a number of NRFX related defines.

Since in the sdk_config.h file (at least in many examples), TWI_ENABLED is almost always #defined (just sometimes a 0), the above statement is almost always true.

I believe the line should read something along the lines of 

#if defined(TWI_ENABLED) && (TWI_ENABLED==1)

I also recall, that apply_old_config.h is unconditionally included through many levels, starting with #include "nrfx_twi.h" in my main.c and cascading into nrfx_glue.h . Ie, you can't avoid the line above in apply_old_config.h .

An alternate solution for me was, to change the sdk_config.h line 

// <e> TWI_ENABLED - nrf_drv_twi - TWI/TWIM peripheral driver - legacy layer
//==========================================================
#ifndef TWI_ENABLED
#define TWI_ENABLED 0
#endif

to

//#define TWI_ENABLED 0

Hope this is of help to someone. And maybe Nordic can review the #define in apply_old_config.h

Parents
  • I think the intention is that the legacy definitions should be the dominant ones, meaning that if both TWI_ENABLED and NRFX_TWI_ENABLED are defined, it should always choose TWI_ENABLED. No matter if TWI_ENABLED is set to 0 or 1.

    That is the reason #if defined(TWI_ENABLED) is used. It will check if it is defined, and change the NRFX_TWI_ENABLED accordingly.

    Best regards,

    Simon

  • So if I read the links you provided below, and in particular the definition of "legacy", is the Nordic suggested way then to

    * use nrf_drv_twi.h, the "legacy" driver, and to

    * include nrfx_twi.c in the project

    Ie, to NOT use nrfx_twi.h directly ?

    (and similarly use nrf_drv_spi.h together with nrfx_spi.c) ? Or am I confused now ?

Reply Children
  • Yes, you have understood it correctly, don't use the NRFX layer directly. The NRFX source files should be included in the project since they are used by the legacy functions.

    You can see that the NRFX layer is used similarly in the nRF Connect SDK (one of our newest projects), where Zephyr functions are used as the top layer.

    Best regards,

    Simon

  • Thanks for the clarification, Simon. But is it asked too much to put a one-liner into your online documentation where the nrfx twi (and spi) drivers are explained ?

    See Software Development Kit -> SDK16 -> Hardware Drivers -> nRF52832 Drivers -> TWI

    Modules
    Software controlled TWI Master driver
    Software controlled TWI Master driver (deprecated).

    TWI driver - legacy layer
    Layer providing compatibility with the former API. <--- "legacy layer" and "former API" don't suggest this is the preferred method.

    TWI driver
    Two Wire Interface master (TWI) peripheral driver. <--- this should instead hint that direct use of the nrfx layer is discouraged.

    TWI HAL
    Hardware access layer for managing the TWI peripheral.

    And then secondly, I changed my code to use the nrf_drv_twi instead, and included the nrfx_twi.c as part of my project to link against. My original findings still seem to hold true: in sdk_config.h

    // <e> TWI_ENABLED - nrf_drv_twi - TWI/TWIM peripheral driver - legacy layer
    //==========================================================
    #ifndef TWI_ENABLED
    //#define TWI_ENABLED 0
    #endif

    I had to comment out the TWI_ENABLED line (unless I am doing something wrong elsewhere). For one, we just learned that the "legacy layer" is the preferred layer, so who would guess that you actually have to remove this line from the config file ? (Referring to the title of this entry)

    Lastly, you seem to hint (citing the linked references) that it maybe ok to uncomment/remove defines from the sdk_config file. But that is not even possible with the CMSIS config wizard, so maybe it shouldn't be promoted as the config tool, then.

    Simon, I am not trying to be difficult. Just painting the picture from the perspective of a new-comer to Nordic. It can be really confusing. Reminds me of the "no pain no gain" motto that some people cherish. I truly appreciate your help.

  • Actually, Simon, I have to correct something. If I don't use the nrfx driver directly, but instead the nrf_drv_twi, and also properly define the TWI with TWI_ENABLED and also enabling the instance TWI0_ENABLED, then it is not necessary to uncomment the line. And consequently the configuration could be properly made using CMSIS. So the trick was to use the nrf_drv_twi instead of the nrfx driver directly. I'll write a summary so we can have a single answer to the thread.

  • I am sorry for not addressing your question right away, I'll try to do that now (go to the bottom to get right to the solution).

    Let's go in reverse order:

    • The macro NRFX_TWI0_INST_IDX is defined in nRF5SDK16\modules\nrfx\drivers\include\nrfx_twi.h:

    #ifndef __NRFX_DOXYGEN__
    enum {
    #if NRFX_CHECK(NRFX_TWI0_ENABLED)
        NRFX_TWI0_INST_IDX,
    #endif
    #if NRFX_CHECK(NRFX_TWI1_ENABLED)
        NRFX_TWI1_INST_IDX,
    #endif
        NRFX_TWI_ENABLED_COUNT
    };
    #endif

    • The header file nrfx_twi.h is included from nRF5SDK16\modules\nrfx\drivers\src\nrfx_twi.c:

    #if NRFX_CHECK(NRFX_TWI_ENABLED)
    
    #if !(NRFX_CHECK(NRFX_TWI0_ENABLED) || NRFX_CHECK(NRFX_TWI1_ENABLED))
    #error "No enabled TWI instances. Check <nrfx_config.h>."
    #endif
    
    #include <nrfx_twi.h>
    #include <hal/nrf_gpio.h>
    #include "prs/nrfx_prs.h"
    .
    .

    • For nrfx_twi.h to be included you have to define NRFX_TWI_ENABLED and at least one TWI instance (NRFX_TWI0_ENABLED or NRFX_TWI1_ENABLED)
      • Take a look at apply_old_config.h to see how NRFX_TWI_ENABLED is defined:

    #if defined(TWI_ENABLED)
    
    #undef NRFX_TWI_ENABLED
    #define NRFX_TWI_ENABLED   (TWI_ENABLED && (NRFX_TWI0_ENABLED  || NRFX_TWI1_ENABLED))
    #undef NRFX_TWIM_ENABLED
    #define NRFX_TWIM_ENABLED  (TWI_ENABLED && (NRFX_TWIM0_ENABLED || NRFX_TWIM1_ENABLED))
    <

    • TWI_ENABLED has to be defined (=1)
    • NRFX_TWI0_ENABLED  || NRFX_TWI1_ENABLED has to be defined:
      • Take a look at apply_old_config.h to see how these are defined:

    #if defined(TWI_PRESENT) && !defined(TWIM_PRESENT)
    
    #undef NRFX_TWI0_ENABLED
    #define NRFX_TWI0_ENABLED   TWI0_ENABLED
    #undef NRFX_TWIM0_ENABLED
    #define NRFX_TWIM0_ENABLED  0
    
    #undef NRFX_TWI1_ENABLED
    #define NRFX_TWI1_ENABLED   TWI1_ENABLED
    #undef NRFX_TWIM1_ENABLED
    #define NRFX_TWIM1_ENABLED  0


    Solution:

    Okay, I see now that this takes too long time too explain in-depth, but I think you can fix the error by setting the following defines accordingly:

    • TWI_ENABLED 1
    • TWI0_ENABLED 1
    • TWI0_USE_EASY_DMA 0
      • This will make the TWI drivers use NRFX_TWI0_INST_IDX instead of NRFX_TWIM0_INST_IDX

    So when you get any complaints about NRFX twi instance 0 (not twim), then simply enable the legacy instance 0 (TWI0_ENABLED 1 ) and disable dma for that instance (TWI0_USE_EASY_DMA 0)

    I hope this solves your issues.

    Best regards,

    Simon

Related