10-27-2020 03:26 PM - edited 10-27-2020 03:36 PM
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] [0m<inf> bma456: Read from 0x0: 0x16[0m
[00:00:00.203,582] [0m<inf> bma456: Read from 0x7c: 0x2[0m
[00:00:00.204,315] [0m<inf> bma456: Write to 0x7c: 0x2[0m
[00:00:00.204,559] [0m<inf> bma456: Sleeping for 450 us[0m
[00:00:00.205,352] [0m<inf> bma456: Sleeping for 450 us[0m
[00:00:00.206,542] [0m<inf> bma456: Write to 0x59: 0x0[0m
[00:00:00.206,787] [0m<inf> bma456: Sleeping for 450 us[0m
[00:00:00.208,038] [0m<inf> bma456: Write to 0x5b: 0x0[0m
[00:00:00.208,374] [0m<inf> bma456: Sleeping for 450 us[0m
[00:00:00.209,533] [0m<inf> bma456: Write to 0x5c: 0x0[0m
[00:00:00.209,777] [0m<inf> bma456: Sleeping for 450 us[0m
[00:00:00.419,219] [0m<inf> bma456: Write 2048 bytes to 0x5e[0m
[00:00:00.419,464] [0m<inf> bma456: Sleeping for 450 us[0m
[00:00:00.420,806] [0m<inf> bma456: Write to 0x5b: 0x0[0m
[00:00:00.421,020] [0m<inf> bma456: Sleeping for 450 us[0m
[00:00:00.422,180] [0m<inf> bma456: Write to 0x5c: 0x40[0m
[00:00:00.422,424] [0m<inf> bma456: Sleeping for 450 us[0m
[00:00:00.632,049] [0m<inf> bma456: Write 2048 bytes to 0x5e[0m
[00:00:00.633,056] [0m<inf> bma456: Sleeping for 450 us[0m
[00:00:00.635,345] [0m<inf> bma456: Write to 0x5b: 0x0[0m
[00:00:00.636,352] [0m<inf> bma456: Sleeping for 450 us[0m
[00:00:00.638,427] [0m<inf> bma456: Write to 0x5c: 0x80[0m
[00:00:00.639,526] [0m<inf> bma456: Sleeping for 450 us[0m
[00:00:00.850,646] [0m<inf> bma456: Write 2048 bytes to 0x5e[0m
[00:00:00.851,745] [0m<inf> bma456: Sleeping for 450 us[0m
[00:00:00.853,820] [0m<inf> bma456: Write to 0x59: 0x1[0m
[00:00:00.854,797] [0m<inf> bma456: Sleeping for 450 us[0m
[00:00:00.856,353] [0m<inf> bma456: Sleeping for 150000 us[0m
[00:00:01.008,361] [0m<inf> bma456: Read from 0x2a: 0x0[0m
[00:00:01.009,246] [1;31m<err> bma456: bma456_write_config_file failed: -5[0m
#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;
}
Solved! Go to Solution.
10-27-2020 06:54 PM - edited 10-27-2020 09:05 PM
Hello,
I don't understand what you mean "I had to set dev.read_write_len = 2048 because out target's DMA cannot handle the complete config file burst write."
You mean that your system can't send DMA memory sequencely? ( 0 ~ 15, 16 ~ 31 bytes for 16 bytes each)
Thanks,
10-27-2020 08:34 PM - edited 10-27-2020 09:05 PM
For configuration file uploading, we offer burst write until 110 bytes.
I assumed from the datasheet that we had to write the whole config in one burst of 6kB. When you say "until 110 bytes", do you mean that bursts cannot be larger than 110 bytes or that they must be at least 110 bytes?
However, I don't understand what you mean "I had to set dev.read_write_len = 2048 because out target's DMA cannot handle the complete config file burst write."
You mean that your system can't send DMA memory sequencely? ( 0 ~ 15, 16 ~ 31 bytes for 16 bytes each)
From my understanding of the I2C driver we use, the associated DMA machine only has a 12 bit counter, so we cannot send more than 4095 bytes in one I2C transfer. So by setting
read_write_len = 2048
your API split up the transfer to 3 chunks of 2kB each which our I2C stack can handle.
The error is the same with
read_write_len = 110
I still have the same problem when I use directly consecutive transfers to send all 6kB in one burst.
Is there anything I can check to rule out some common problems? What exactly would you expect the trace to look like on a successful initialization?
Thank you for your quick response.
10-27-2020 09:19 PM
Hello,
I need to correct my answer. The limitation of read wrtie length is only for bma456h, so it's not your case.
You can use it 2048 bytes, 6144 bytes as well.
Let's check step by step. After bma4_write_config_file function calling, did you get any error?
Could you capture your data and upload it?
I'd like to check whether your burst write function can tranfer properly or not.
Reading chip_id is only required signle byte, so you can't check it.
Thanks,
10-27-2020 09:35 PM
Let's check step by step. After bma4_write_config_file function calling, did you get any error?
I did not investigate further if the chip is functional after this function returned an error. I mean, the INTERNAL_STATUS.msg register clearly says that the chips is not configured at this point.
Could you capture your data and upload it?
I'd like to check whether your burst write function can tranfer properly or not.
Reading chip_id is only required signle byte, so you can't check it.
I'll try to get a capture tomorrow but unfortunately, the I2C lines are burried quite good on our electronic.