BMA456 initialization failure

Hello,

I cannot seem to be able to get the initilization  sequence of the BMA456 right. I'm using the bma4_v2.14.12 release of your API in our Zephyr-based project. I have motion_sensor.c for wrapping the hardware access.

At the end of the confugiration, INTERNAL_STATUS.message still is 0x00 (ASIC  not initialized). I2C seems to be working because of the previous operation (reading CHIP_ID) do not fail.

I had to set dev.read_write_len = 2048 because out target's DMA cannot handle the complete config file burst write.

How can I fix this issue? Please find below my motion_sensor.c and the trace our application produced.

[00:00:00.202,789] <inf> bma456: Read from 0x0: 0x16
[00:00:00.203,582] <inf> bma456: Read from 0x7c: 0x2
[00:00:00.204,315] <inf> bma456: Write to 0x7c: 0x2
[00:00:00.204,559] <inf> bma456: Sleeping for 450 us
[00:00:00.205,352] <inf> bma456: Sleeping for 450 us
[00:00:00.206,542] <inf> bma456: Write to 0x59: 0x0
[00:00:00.206,787] <inf> bma456: Sleeping for 450 us
[00:00:00.208,038] <inf> bma456: Write to 0x5b: 0x0
[00:00:00.208,374] <inf> bma456: Sleeping for 450 us
[00:00:00.209,533] <inf> bma456: Write to 0x5c: 0x0
[00:00:00.209,777] <inf> bma456: Sleeping for 450 us
[00:00:00.419,219] <inf> bma456: Write 2048 bytes to 0x5e
[00:00:00.419,464] <inf> bma456: Sleeping for 450 us
[00:00:00.420,806] <inf> bma456: Write to 0x5b: 0x0
[00:00:00.421,020] <inf> bma456: Sleeping for 450 us
[00:00:00.422,180] <inf> bma456: Write to 0x5c: 0x40
[00:00:00.422,424] <inf> bma456: Sleeping for 450 us
[00:00:00.632,049] <inf> bma456: Write 2048 bytes to 0x5e
[00:00:00.633,056] <inf> bma456: Sleeping for 450 us
[00:00:00.635,345] <inf> bma456: Write to 0x5b: 0x0
[00:00:00.636,352] <inf> bma456: Sleeping for 450 us
[00:00:00.638,427] <inf> bma456: Write to 0x5c: 0x80
[00:00:00.639,526] <inf> bma456: Sleeping for 450 us
[00:00:00.850,646] <inf> bma456: Write 2048 bytes to 0x5e
[00:00:00.851,745] <inf> bma456: Sleeping for 450 us
[00:00:00.853,820] <inf> bma456: Write to 0x59: 0x1
[00:00:00.854,797] <inf> bma456: Sleeping for 450 us
[00:00:00.856,353] <inf> bma456: Sleeping for 150000 us
[00:00:01.008,361] <inf> bma456: Read from 0x2a: 0x0
[00:00:01.009,246] <err> bma456: bma456_write_config_file failed: -5
#include "motion_sensor.h"
#include <bma456/bma456.h>
#include <device.h>
#include <logging/log.h>
#include <drivers/i2c.h>
LOG_MODULE_REGISTER(bma456, CONFIG_GPS_CONTROL_LOG_LEVEL);

#define MOTION_SENSOR_I2C_ADDR (0x18)
#define DMA_MAX_TRANSFER_SIZE (2048)

static struct bma4_dev bma456;
static uint8_t i2c_buf[DMA_MAX_TRANSFER_SIZE];

/*!
* @brief Bus communication function pointer which should be mapped to
* the platform specific read functions of the user
*
* @param[in] reg_addr : Register address from which data is read.
* @param[out] read_data : Pointer to data buffer where read data is stored.
* @param[in] len : Number of bytes of data to be read.
* @param[in, out] intf_ptr : Void pointer that can enable the linking of descriptors
* for interface related call backs.
*
* @retval = BMA4_INTF_RET_SUCCESS -> Success
* @retval != BMA4_INTF_RET_SUCCESS -> Failure Info
*
*/
static BMA4_INTF_RET_TYPE motion_sensor_bus_read(uint8_t reg_addr, uint8_t *read_data, uint32_t len, void *intf_ptr) {
int ret;

if (len <= 1) {
ret = i2c_reg_read_byte(intf_ptr, MOTION_SENSOR_I2C_ADDR, reg_addr, read_data);
} else {
ret = i2c_burst_read(intf_ptr, MOTION_SENSOR_I2C_ADDR, reg_addr, i2c_buf, len);
memcpy(read_data, i2c_buf, len);
}

if (ret) {
LOG_ERR("Error reading %lu bytes from 0x%X: %d", len, reg_addr, ret);
} else {
if (len <= 1) {
LOG_INF("Read from 0x%X: 0x%X", reg_addr, *read_data);
} else {
LOG_INF("Read %lu bytes from 0x%X", len, reg_addr);
}
}
return ret;
}

/*!
* @brief Bus communication function pointer which should be mapped to
* the platform specific write functions of the user
*
* @param[in] reg_addr : Register address to which the data is written.
* @param[in] read_data : Pointer to data buffer in which data to be written
* is stored.
* @param[in] len : Number of bytes of data to be written.
* @param[in, out] intf_ptr : Void pointer that can enable the linking of descriptors
* for interface related call backs
*
* @retval = BMA4_INTF_RET_SUCCESS -> Success
* @retval != BMA4_INTF_RET_SUCCESS -> Failure Info
*
*/
static BMA4_INTF_RET_TYPE motion_sensor_bus_write(uint8_t reg_addr, const uint8_t *read_data, uint32_t len,
void *intf_ptr) {
int ret;

if (len <= 1) {
ret = i2c_reg_write_byte(intf_ptr, MOTION_SENSOR_I2C_ADDR, reg_addr, read_data[0]);
} else {
memcpy(i2c_buf, read_data, len);
ret = i2c_burst_write(intf_ptr, MOTION_SENSOR_I2C_ADDR, reg_addr, i2c_buf, len);
}

if (ret) {
LOG_ERR("Error writing %lu bytes to 0x%X: %d", len, reg_addr, ret);
} else {
if (len <= 1) {
LOG_INF("Write to 0x%X: 0x%X", reg_addr, *read_data);
} else {
LOG_INF("Write %lu bytes to 0x%X", len, reg_addr);
}
}

return ret;
}

/*!
* @brief Delay function pointer which should be mapped to
* delay function of the user
*
* @param[in] period : Delay in microseconds.
* @param[in, out] intf_ptr : Void pointer that can enable the linking of descriptors
* for interface related call backs
*
*/
static void motion_sensor_delay(uint32_t period, void *intf_ptr) {
LOG_INF("Sleeping for %lu us", period);
k_sleep(K_USEC(period));
}

int motion_sensor_init(const char *dev_name) {
int8_t ret;
struct device *i2c_dev = device_get_binding(dev_name);

if (NULL == i2c_dev) {
LOG_ERR("Cannot get device binding for %s", log_strdup(dev_name));
return -1;
}

bma456.intf = BMA4_I2C_INTF;
bma456.bus_read = motion_sensor_bus_read;
bma456.bus_write = motion_sensor_bus_write;
bma456.delay_us = motion_sensor_delay;
bma456.intf_ptr = i2c_dev;
bma456.read_write_len = 2048;

if ((ret = bma456_init(&bma456)) != 0) {
LOG_ERR("bma456_init failed: %d", ret);
return ret;
}

if ((ret = bma456_write_config_file(&bma456)) != 0) {
LOG_ERR("bma456_write_config_file failed: %d", ret);
return ret;
}

return ret;
}

 

Best reply by MBEonas

I found the issue while investigating the I2C.

Our I2C driver inserted a start and stopp after writing the first byte (the register address) of the burst transfer. Once we got rid of this behaviour, the BMA456 responds correctly after initialization.

Best Regards

View original
11 replies
Resolved