Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

twi_scanner hangs in nRF52832

I'm using a custom board designed around this nRF52832 module. Testing the twi_scanner from examples of `nRF5_SDK_17.0.2_d674dde`. Built and flashed the firmware successfully (with Black Magic Probe debugger). 

Problem is, the firmware doesn't log the address of the I2C device (BNO055) or *any* I2C device. Even when the slot is not populated, it does not show that "no I2C device has been found". 

Here is main.c:

/** @file
 * @defgroup tw_scanner main.c
 * @{
 * @ingroup nrf_twi_example
 * @brief TWI Sensor Example main file.
 *
 * This file contains the source code for a sample application using TWI.
 *
 */

#include <stdio.h>

#include "app_error.h"
#include "app_util_platform.h"
#include "boards.h"
#include "nrf_drv_twi.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"

/* TWI instance ID. */
#if TWI0_ENABLED
#define TWI_INSTANCE_ID 0
#elif TWI1_ENABLED
#define TWI_INSTANCE_ID 1
#endif

/* Number of possible TWI addresses. */
#define TWI_ADDRESSES 127

#define BOARD_CUSTOM 1

/* TWI instance. */
static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(TWI_INSTANCE_ID);

/**
 * @brief TWI initialization.
 */
void twi_init(void) {
    ret_code_t err_code;

    const nrf_drv_twi_config_t twi_config = {
        .scl = 11,
        .sda = 10,
        .frequency = NRF_DRV_TWI_FREQ_100K,
        .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
        .clear_bus_init = false};

    err_code = nrf_drv_twi_init(&m_twi, &twi_config, NULL, NULL);
    APP_ERROR_CHECK(err_code);

    nrf_drv_twi_enable(&m_twi);
}

/**
 * @brief Function for main application entry.
 */
int main(void) {
    ret_code_t err_code;
    uint8_t address;
    uint8_t sample_data;
    bool detected_device = false;

    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    NRF_LOG_DEFAULT_BACKENDS_INIT();

    NRF_LOG_INFO("TWI scanner started.");
    NRF_LOG_FLUSH();
    twi_init();

    for (address = 1; address <= TWI_ADDRESSES; address++) {
        NRF_LOG_INFO("%d\n", (uint32_t) address);
        err_code =
            nrf_drv_twi_rx(&m_twi, address, &sample_data, sizeof(sample_data));
        if (err_code == NRF_SUCCESS) {
            detected_device = true;
            NRF_LOG_INFO("TWI device detected at address 0x%x.", address);
        }
        NRF_LOG_FLUSH();
    }

    if (!detected_device) {
        NRF_LOG_INFO("No device was found.");
        NRF_LOG_FLUSH();
    }

    while (true) {
        /* Empty loop. */
    }
}

/** @} */

I've disabled deferred (`#define NRF_LOG_DEFERRED 0`) in config.

The code hangs specifically at this function :

err_code = nrf_drv_twi_rx(&m_twi, address, &sample_data, sizeof(sample_data));

Or more specifically, it never exits this block: 

else
    {
        bool transmission_finished = false;
        do {
            if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_SUSPENDED))
            {
                NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_SUSPENDED));
                transmission_finished = true;
            }

            if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_STOPPED))
            {
                nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_STOPPED);
                NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_STOPPED));
                transmission_finished = true;
            }

            if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_ERROR))
            {
                nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_ERROR);
                NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_ERROR));

                bool lasttx_triggered = nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_LASTTX);
                uint32_t shorts_mask = nrf_twim_shorts_get(p_twim);

                if (!(lasttx_triggered && (shorts_mask & NRF_TWIM_SHORT_LASTTX_STOP_MASK)))
                {
                    // Unless LASTTX event arrived and LASTTX_STOP shortcut is active,
                    // triggering of STOP task in case of error has to be done manually.
                    nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
                    nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STOP);

                    // Mark transmission as not finished yet,
                    // as STOPPED event is expected to arrive.
                    // If LASTTX_SUSPENDED shortcut is active,
                    // NACK has been received on last byte sent
                    // and SUSPENDED event happened to be checked before ERROR,
                    // transmission will be marked as finished.
                    // In such case this flag has to be overwritten.
                    transmission_finished = false;
                }

                if (lasttx_triggered && (shorts_mask & NRF_TWIM_SHORT_LASTTX_SUSPEND_MASK))
                {
                    // When STOP task was triggered just before SUSPEND task has taken effect,
                    // SUSPENDED event may not arrive.
                    // However if SUSPENDED arrives it always arrives after ERROR.
                    // Therefore SUSPENDED has to be cleared
                    // so it does not cause premature termination of busy loop
                    // waiting for STOPPED event to arrive.
                    nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_SUSPENDED);

                    // Mark transmission as not finished yet,
                    // for same reasons as above.
                    transmission_finished = false;
                }
            }
        } while (!transmission_finished);

There are 4k7 pull-up resistors on the i2c device. I've checked with a logic analyzer. Both SDA/SCL are always high no matter what. The i2c_scanner of arduino nano detects the address.

Related