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

nRF52840 is stuck inside the while (m_xfer_done == false) which writes to the TWI Sensor

I am trying to interface BMI160 Shuttle Board to the nRF52840 Development Kit using TWI interface. I am using IAR Systems IDE and have modified the "twi_sensor" Example code to work with the existing setup. I am able Read and Write to the board and record any movement across all the axis's along with the UP-DOWN motion which counts steps works as intended while being seated. To gauge the accuracy of its internal Step Counting Algorithm and when I start walking with the board in my hand the Board stops communicating over the UART(Putty).

While debugging, I found that the board gets stuck in the "while (m_xfer_done == false)" loop inside the function that writes to the board to read data from the board. Because the code was stuck in the above mentioned loop, I decided to check the SDA line using the oscilloscope to make sure it is busy (low voltage) but the line is having high voltage which means it is free.

Hardware Connection:

1. USB power up of nRF52840 Dev Kit using a Laptop..

2. VDD(3V) Dev Board to Pin 1 (VDD) of the BMI160 Shuttle Board.

3. GND Dev Board to Pin 3 (GND) of the BMI160 Shuttle Board.

4. Pin 1 (VDD) BMI160 Shuttle Board to Pin 2 (VDDIO) of the BMI160 Shuttle Board.

5. Pin 1 (VDD) BMI160 Shuttle Board to Pin 7 (CSB_BMI160) of the BMI160 Shuttle Board to allow I2C interfacing..

6. Pin 0.26 (ARDUINO_SDA_PIN) Dev Kit to Pin 17 (SDA) of the BMI160 Shuttle Board.

7. Pin 0.27 (ARDUINO_SCL_PIN) Dev Kit to Pin 18 (SCL) of the BMI160 Shuttle Board.

Software Code:

#include <stdio.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"

/* TWI instance ID. */
#define TWI_INSTANCE_ID     0

/* Common addresses definition for temperature sensor. */
#define BMI160_ADDR          0x69U

// Registers

#define ACC_X      0x13U // DATA
#define ACC_Y      0x15U // DATA
#define ACC_Z      0x17U // DATA
#define GYR_X      0x0CU // DATA
#define GYR_Y      0x0EU // DATA
#define GYR_Z      0x10U // DATA
#define MAG_X      0x05U // DATA
#define MAG_Y      0x07U // DATA
#define MAG_Z      0x09U // DATA

#define CMD_REG      0x7EU // CMD

#define STEP_CONF_0_REG      0x7AU // STEP CONFIG 0
#define STEP_CONF_1_REG      0x7BU // STEP CONFIG 1

#define STEP_CNT_0_REG           0x78U // STEP COUNT 0
#define STEP_CNT_1_REG           0x79U // STEP COUNT 1

#define INT_MAP_REG_0 0x55U // Interupt Map 0
#define INT_MAP_REG_1 0x56U // Interupt Map 1
#define INT_MAP_REG_2 0x57U // Interupt Map 2

#define INT_STATUS_REG_0 0x1CU // Interupt Status 0
#define INT_STATUS_REG_1 0x1DU // Interupt Status 1
#define INT_STATUS_REG_2 0x1EU // Interupt Status 2
#define INT_STATUS_REG_3 0x1FU // Interupt Status 3

#define IF_CONF_REG   0x6BU // IF_CONF
#define MAG_CONF_REG   0x44U // MAG_CONF

#define IF_CONF_AUTO_MAG   0x20U // CMD
#define MAG_ODR_100 0x08U // on MAG ODR to 100Hz

#define INT_EN_REG_0 0x50U // Interupt Map 0
#define INT_EN_REG_1 0x51U // Interupt Map 1
#define INT_EN_REG_2 0x52U // Interupt Map 2

/* Mode for BMI160. */
#define ACC_NORMAL_MODE 0x11U // on ACC
#define GYR_NORMAL_MODE 0x15U // on GYR
#define MAG_NORMAL_MODE 0x19U // on MAG

#define STEP_CONF_0_NORMAL 0x15U // Normal Mode
#define STEP_CONF_1_NORMAL 0x03U // Normal Mode step cnt enabled 
#define RESET_STEP_CNT 0xB2U // on REST STEP CNT


/* Indicates if operation on TWI has ended. */
static volatile bool m_xfer_done = false;

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

/* Buffer for samples read from temperature sensor. */
static uint8_t m_sample;

void BMI160_set_ACC_mode(void)
{
    ret_code_t err_code;
    /* Writing to CMD_REG to set Accelerometer in NORMAL mode. */
    uint8_t reg[2] = {CMD_REG, ACC_NORMAL_MODE};
    err_code = nrf_drv_twi_tx(&m_twi, BMI160_ADDR, reg, sizeof(reg), false);
    APP_ERROR_CHECK(err_code);
    while (m_xfer_done == false); 
}

void BMI160_set_GYR_mode(void)
{
    ret_code_t err_code;
    /* Writing to CMD_REG to set Gyroscope in NORMAL mode. */
    uint8_t reg[2] = {CMD_REG, GYR_NORMAL_MODE};
    err_code = nrf_drv_twi_tx(&m_twi, BMI160_ADDR, reg, sizeof(reg), false);
    APP_ERROR_CHECK(err_code);
    while (m_xfer_done == false);   
}

void BMI160_set_MAG_mode(void)
{
    ret_code_t err_code;
    /* Writing to CMD_REG to set Magnetometer in NORMAL mode. */
    uint8_t reg[2] = {CMD_REG, MAG_NORMAL_MODE};
    err_code = nrf_drv_twi_tx(&m_twi, BMI160_ADDR, reg, sizeof(reg), false);
    APP_ERROR_CHECK(err_code);
    while (m_xfer_done == false);   
}

void BMI160_reset_step_cnt(void)
{
    ret_code_t err_code;

    /* Writing to CMD_REG reset Step Counter. */
    uint8_t reg[2] = {CMD_REG, RESET_STEP_CNT};
    err_code = nrf_drv_twi_tx(&m_twi, BMI160_ADDR, reg, sizeof(reg), false);
    APP_ERROR_CHECK(err_code);
    while (m_xfer_done == false);
}

void BMI160_STEP_CONF_0(void)
{
    ret_code_t err_code;
	
    uint8_t reg[2] = {STEP_CONF_0_REG, STEP_CONF_0_NORMAL};
    err_code = nrf_drv_twi_tx(&m_twi, BMI160_ADDR, reg, sizeof(reg), false);
    APP_ERROR_CHECK(err_code);
    while (m_xfer_done == false);
}

void BMI160_STEP_CONF_1(void)
{
    ret_code_t err_code;
    
    uint8_t reg[2] = {STEP_CONF_1_REG, STEP_CONF_1_NORMAL};
    err_code = nrf_drv_twi_tx(&m_twi, BMI160_ADDR, reg, sizeof(reg), false);
    APP_ERROR_CHECK(err_code);
    while (m_xfer_done == false);
}

/**
 * @brief Function for reading data from temperature sensor.
 */
static void read_sensor_data()
{
    m_xfer_done = false;

    /* Read 1 byte from the specified address - skip 3 bits dedicated for fractional part of temperature. */
    ret_code_t err_code = nrf_drv_twi_rx(&m_twi, BMI160_ADDR, &m_sample, 1);
    APP_ERROR_CHECK(err_code);
    while (m_xfer_done == false);
}

void write_data_to_read_reg(uint8_t Reg1){
    ret_code_t err_code;
/* Writing to pointer byte. */
    uint8_t reg[2];
    reg[0] = Reg1;
    m_xfer_done = false;
    err_code = nrf_drv_twi_tx(&m_twi, BMI160_ADDR, reg, 1, false);
    APP_ERROR_CHECK(err_code);
    while (m_xfer_done == false);
}

__STATIC_INLINE void data_handler(uint8_t val)
{
    NRF_LOG_INFO("Data Value: %d ", val);
}

/**
 * @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)
            {
                data_handler(m_sample);
            }
            m_xfer_done = true;
            break;
        default:
            break;
    }
}

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

    const nrf_drv_twi_config_t twi_lm75b_config = {
       .scl                = ARDUINO_SCL_PIN,
       .sda                = ARDUINO_SDA_PIN,
       .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_lm75b_config, twi_handler, NULL);
    APP_ERROR_CHECK(err_code);

    nrf_drv_twi_enable(&m_twi);
}

/**
 * @brief Function for main application entry.
 */
int main(void)
{  
    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    NRF_LOG_DEFAULT_BACKENDS_INIT();
    int32_t reading = 0;

    NRF_LOG_INFO("\r\nTWI sensor example started.");
    NRF_LOG_FLUSH();
    twi_init();
    BMI160_reset_step_cnt();
    nrf_delay_ms(100);
    BMI160_set_ACC_mode();
    nrf_delay_ms(100);
    BMI160_set_GYR_mode();
    nrf_delay_ms(100);
    BMI160_set_MAG_mode();
    nrf_delay_ms(100);
    BMI160_STEP_CONF_0();
    nrf_delay_ms(100);
    BMI160_STEP_CONF_1();

    while (true)
    {        
        // Read STEP_CNT 
        nrf_delay_ms(100);
        write_data_to_read_reg(STEP_CNT_0_REG);
        do
        {
            __WFE();
        }while (m_xfer_done == false);
        
        read_sensor_data();
        NRF_LOG_FLUSH();
    }    
}

Function #:  write_data_to_read_reg(uint8_t Reg1)

Loop: while (m_xfer_done == false);

Parents Reply Children
No Data
Related