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

Trouble: TWI(I2C) stops at the function of i2c_reg_read_byte On nRF9160 DK. Why?

I'm trying to have nRF9160 DK communicate with an external accelerometer. 

nRF9160 stop working at the function of i2c_reg_read_byte in the code below.

Does anybody give any advice?

<main.c>

#include <nrf9160.h>
#include <zephyr.h>
#include <misc/printk.h>
#include <i2c.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>

#define I2C_ACCEL_WRITE_ADDR 0x32
#define I2C_ACCEL_READ_ADDR 0x33

struct device *i2c_accel;
uint8_t WhoAmI = 0u;

uint8_t init_accelerometer(){
    i2c_accel = device_get_binding("I2C_2");
    if (!i2c_accel) {
		printk("error\r\n");
        return -1;
	} else  {
        i2c_configure(i2c_accel, I2C_SPEED_SET(I2C_SPEED_STANDARD));
        return 0;
    }
}

void main(void)
{
    printk("Hello, World!\r\n");
    init_accelerometer();

	while (1) {
        printk("loop head\r\n");

        if (i2c_reg_read_byte(i2c_accel, I2C_ACCEL_READ_ADDR, 0x0F, WhoAmI) != 0) { // stop wroking at this line
                printk("Error on i2c_read()\n");
        } else {
                printk("no error\r\n");
        }

        printk("WhoAmI = %u\r\n", WhoAmI);
        printk("enter sleep\r\n");
        k_sleep(1000);
	}
}

<prj.conf>

CONFIG_TRUSTED_EXECUTION_SECURE=y
# needed to get the NRF_UARTE2 define
CONFIG_UART_2_NRF_UARTE=y

CONFIG_TRUSTED_EXECUTION_NONSECURE=y
CONFIG_SERIAL=y
CONFIG_UART_INTERRUPT_DRIVEN=y

CONFIG_I2C=y
CONFIG_I2C_NRFX=y
CONFIG_I2C_2=y
CONFIG_I2C_INIT_PRIORITY=60

<overlay file>

/* needed to get the NRF_UARTE2 defined */
&uart2 {
	current-speed = <1000000>;
	status = "ok";
	tx-pin = <18>;
	rx-pin = <17>;
	rts-pin = <19>;
	cts-pin = <21>;
};

&i2c2 {
	status = "ok";
	sda-pin = <10>;
	scl-pin = <11>;
	clock-frequency = <100000>; 
};

UPDATE:

<printk>
***** Booting Zephyr OS v1.13.99-ncs2 *****
Hello, World!
loop head
// stack here

  • Do you have the source code for i2c_reg_read_byte() ?

    If yes, you should be able to see the line(s) of code where it is stuck inside of i2c_reg_read_byte()

    That would help us to help you further.   

    Thanks, Martin

  • Hi, mtsunstrum!. Thank you for your comment.

    I took i2c_reg_read_byte from zephyr driver.

    docs.zephyrproject.org/.../io_interfaces.html

    the definition is below. 

    /**
     * @brief Read internal register of an I2C device.
     *
     * This routine reads the value of an 8-bit internal register of an I2C
     * device synchronously.
     *
     * @param dev Pointer to the device structure for the driver instance.
     * @param dev_addr Address of the I2C device for reading.
     * @param reg_addr Address of the internal register being read.
     * @param value Memory pool that stores the retrieved register value.
     *
     * @retval 0 If successful.
     * @retval -EIO General input / output error.
     */
    static inline int i2c_reg_read_byte(struct device *dev, u16_t dev_addr,
    				    u8_t reg_addr, u8_t *value)
    {
    	return i2c_burst_read(dev, dev_addr, reg_addr, value, 1);
    }
  • You are just showing us code only.

    That does not help us help you.

    With your JTAG debugger, you should be able to show the exact line of code that is giving you some problem.

    Maybe to restate your question: nRF9160 stop working at the function of i2c_reg_read_byte in the code below.

    For others to help you, you have to say exactly what is not working. "stop working" is not sufficient to help you.

  • <i2c.h>
    
    static inline int _impl_i2c_transfer(struct device *dev,
    				     struct i2c_msg *msgs, u8_t num_msgs,
    				     u16_t addr)
    {
    	const struct i2c_driver_api *api =
    		(const struct i2c_driver_api *)dev->driver_api;
    
    	return api->transfer(dev, msgs, num_msgs, addr);
    }

    After the debugger reaches "return api->transfer", I2C seems to be stacked.

    When I step into "return api->transfer",  debugging stops at a line of "if (res != NRFX_SUCCESS)"

    <i2c_nrfx_twim.c>
    
    static int i2c_nrfx_twim_transfer(struct device *dev, struct i2c_msg *msgs,
    				  u8_t num_msgs, u16_t addr)
    {
    	for (size_t i = 0; i < num_msgs; i++) {
    		if (I2C_MSG_ADDR_10_BITS & msgs[i].flags) {
    			return -ENOTSUP;
    		}
    
    		nrfx_twim_xfer_desc_t cur_xfer = {
    			.p_primary_buf  = msgs[i].buf,
    			.primary_length = msgs[i].len,
    			.address	= addr,
    			.type		= (msgs[i].flags & I2C_MSG_READ) ?
    					  NRFX_TWIM_XFER_RX : NRFX_TWIM_XFER_TX
    		};
    
    		nrfx_err_t res = nrfx_twim_xfer(&get_dev_config(dev)->twim,
    					       &cur_xfer,
    					       (msgs[i].flags & I2C_MSG_STOP) ?
    					       0 : NRFX_TWIM_FLAG_TX_NO_STOP);
    		if (res != NRFX_SUCCESS) { // STOP HERE
    			if (res == NRFX_ERROR_BUSY) {
    				return -EBUSY;
    			} else {
    				return -EIO;
    			}
    		}
    
    		k_sem_take(&(get_dev_data(dev)->sync), K_FOREVER);
    		res = get_dev_data(dev)->res;
    		if (res != NRFX_SUCCESS) {
    			LOG_ERR("Error %d occurred for message %d", res, i);
    			return -EIO;
    		}
    	}
    
    	return 0;
    }

  • Keep going .... 

    'res' tells you the result status. What is the value of 'res' ?

    And when you look in the nRF52 documentation what does that value of 'res' indicate as a possible reason for the failure ?

Related