diff --git a/drivers/sensor/bmi270/Kconfig b/drivers/sensor/bmi270/Kconfig index 25b3dbd223f1e3b..50a2f2f358f4162 100644 --- a/drivers/sensor/bmi270/Kconfig +++ b/drivers/sensor/bmi270/Kconfig @@ -64,8 +64,7 @@ config BMI270_THREAD_STACK_SIZE config BMI270_CRT bool "CRT feature support for bmi270" - default n help - Gyro CRT calibration feature support for bmi270 + BMI270 Gyro Component Re-Trimming(CRT) calibration feature support. endif # BMI270 diff --git a/drivers/sensor/bmi270/bmi270.h b/drivers/sensor/bmi270/bmi270.h index 5bfedb8fa0bfd5f..d2330f5e8154d8c 100644 --- a/drivers/sensor/bmi270/bmi270.h +++ b/drivers/sensor/bmi270/bmi270.h @@ -18,6 +18,7 @@ #include #include #include +#include #define BMI270_REG_CHIP_ID 0x00 #define BMI270_REG_ERROR 0x02 @@ -132,7 +133,6 @@ #define BMI270_GYR_USR_GAIN_MASK 0x7F #define BMI270_GYR_GAIN_EN_MSK BIT(7) #define BMI270_GYR_GAIN_EN_POS 7 -#define BMI270_GYR_GAIN_EN 0x01 #define BMI270_GYR_GAIN_STATUS_SAT_X_POS 0 #define BMI270_GYR_GAIN_STATUS_SAT_X_MASK BIT(0) #define BMI270_GYR_GAIN_STATUS_SAT_Y_POS 1 @@ -146,9 +146,6 @@ #define BMI270_GYR_CRT_CONF_RUNNING_POS 0x02 #define BMI270_GYR_CRT_CONF_RUNNING_EN 0x01 #define BMI270_GYR_CRT_CONF_RUNNING_DIS 0x00 -/* Sensor specific attributes */ -#define BMI270_SENSOR_ATTR_NVM_PROG (SENSOR_ATTR_PRIV_START) -#define BMI270_SENSOR_ATTR_GAIN_COMP (SENSOR_ATTR_PRIV_START + 1) /* Applies to INT1_MAP_FEAT, INT2_MAP_FEAT, INT_STATUS_0 */ #define BMI270_INT_MAP_SIG_MOTION BIT(0) @@ -332,6 +329,11 @@ struct bmi270_data { struct k_work trig_work; #endif #endif /* CONFIG_BMI270_TRIGGER */ +#ifdef CONFIG_BMI270_CRT + /* CRT test results */ + struct bmi2_gyr_user_gain_status crt_result_sts; + struct bmi2_gyro_user_gain_data crt_gain; +#endif /* CONFIG_BMI270_CRT */ }; struct bmi270_feature_reg { diff --git a/drivers/sensor/bmi270/bmi270_crt.c b/drivers/sensor/bmi270/bmi270_crt.c index 8d59804c40fb182..609b7307f3825bc 100644 --- a/drivers/sensor/bmi270/bmi270_crt.c +++ b/drivers/sensor/bmi270/bmi270_crt.c @@ -18,67 +18,6 @@ LOG_MODULE_DECLARE(bmi270, CONFIG_SENSOR_LOG_LEVEL); #define BMI270_NVM_STATUS_CHECK_RETRIES 100 #define BMI270_STATUS_CHECK_POLL_PERIOD_US 10000 -/** @name Enum to define status of gyroscope trigger G_TRIGGER */ -typedef enum { - /*Command is valid*/ - BMI270_CRT_TRIGGER_STAT_SUCCESS = 0x00, - /*Command is aborted due to incomplete pre-conditions*/ - BMI270_CRT_TRIGGER_STAT_PRECON_ERR = 0x01, - /*Command is aborted due to unsuccessful download*/ - BMI270_CRT_TRIGGER_STAT_DL_ERR = 0x02, - /*Command is aborted by host or due to motion detection*/ - BMI270_CRT_TRIGGER_STAT_ABORT_ERR = 0x03 -} GTriggerStatus; - -/** @name Structure to define gyroscope saturation status of user gain - * Describes the saturation status for the gyroscope gain - * update and G_TRIGGER command status - */ -struct bmi2_gyr_user_gain_status { - /* Status in x-axis - * This bit will be 1 if the updated gain - * results to saturated value based on the - * ratio provided for x axis, otherwise it will be 0 - */ - uint8_t sat_x; - - /* Status in y-axis - * This bit will be 1 if the updated gain - * results to saturated value based on the - * ratio provided for y axis, otherwise it will be 0 - */ - uint8_t sat_y; - - /* Status in z-axis - * This bit will be 1 if the updated gain - * results to saturated value based on the - * ratio provided for z axis, otherwise it will be 0 - */ - uint8_t sat_z; - - /* G trigger status - * Status of gyroscope trigger G_TRIGGER command. - * These bits are updated at the end of feature execution . - */ - GTriggerStatus g_trigger_status; -}; - -/** @name Structure to store the compensated user-gain data of gyroscope */ -struct bmi2_gyro_user_gain_data { - /** x-axis */ - int8_t x; - - /** y-axis */ - int8_t y; - - /** z-axis */ - int8_t z; -}; - -/* Global structures to store the CRT test results */ -struct bmi2_gyr_user_gain_status crt_result_sts = {0}; -struct bmi2_gyro_user_gain_data crt_gain = {0}; - /** * @brief This function verifies if advanced power saving mode is enabled * If it enabled, it disables it. @@ -256,7 +195,7 @@ static inline int bmi270_g_trig_1_select_crt(const struct device *dev) } /** @brief Helper method to LOG CRT cmd status */ -static void crt_error_log(GTriggerStatus status) +static void crt_error_log(gtrigger_status status) { switch (status) { case BMI270_CRT_TRIGGER_STAT_SUCCESS: @@ -282,18 +221,16 @@ static void crt_error_log(GTriggerStatus status) * gain update. * * @param[in] dev : Structure instance of bmi270 device - * @param[out] bmi2_gyr_user_gain_status : Structure that stores gyro gain - * CRT test results * * @return Result of select crt enable execution * @retval 0 -> Success * @retval < 0 -> Fail */ -static int bmi270_get_gyro_gain_update_status(const struct device *dev, - struct bmi2_gyr_user_gain_status *result_sts) +static int bmi270_get_gyro_gain_update_status(const struct device *dev) { int ret; const struct bmi270_config *cfg = dev->config; + struct bmi270_data *data = dev->data; const uint8_t result_sts_page = cfg->feature->gyr_gain_status->page; uint16_t status_value; @@ -329,21 +266,26 @@ static int bmi270_get_gyro_gain_update_status(const struct device *dev, LOG_DBG("Read feature reg[0x%02x]@%d = 0x%04x", cfg->feature->gyr_gain_status->addr, result_sts_page, status_value); + /* Get the saturation status for x-axis */ - result_sts->sat_x = (status_value & BMI270_GYR_GAIN_STATUS_SAT_X_MASK) >> + data->crt_result_sts.sat_x = (status_value & BMI270_GYR_GAIN_STATUS_SAT_X_MASK) >> BMI270_GYR_GAIN_STATUS_SAT_X_POS; /* Get the saturation status for y-axis */ - result_sts->sat_y = (status_value & BMI270_GYR_GAIN_STATUS_SAT_Y_MASK) >> + data->crt_result_sts.sat_y = (status_value & BMI270_GYR_GAIN_STATUS_SAT_Y_MASK) >> BMI270_GYR_GAIN_STATUS_SAT_Y_POS; /* Get the saturation status for z-axis */ - result_sts->sat_z = (status_value & BMI270_GYR_GAIN_STATUS_SAT_Z_MASK) >> + data->crt_result_sts.sat_z = (status_value & BMI270_GYR_GAIN_STATUS_SAT_Z_MASK) >> BMI270_GYR_GAIN_STATUS_SAT_Z_POS; /* Get g trigger status */ - result_sts->g_trigger_status = - (GTriggerStatus)((status_value & BMI270_GYR_GAIN_STATUS_G_TRIG_MASK) >> + data->crt_result_sts.g_trigger_status = + (gtrigger_status)((status_value & BMI270_GYR_GAIN_STATUS_G_TRIG_MASK) >> BMI270_GYR_GAIN_STATUS_G_TRIG_POS); - LOG_DBG("Status in x-axis: %d y-axis: %d z-axis %d, gtrigger: %d", result_sts->sat_x, - result_sts->sat_y, result_sts->sat_z, result_sts->g_trigger_status); + + LOG_DBG("Status in x-axis: %d y-axis: %d z-axis %d, gtrigger: %d", + data->crt_result_sts.sat_x, + data->crt_result_sts.sat_y, + data->crt_result_sts.sat_z, + data->crt_result_sts.g_trigger_status); return 0; } @@ -353,19 +295,17 @@ static int bmi270_get_gyro_gain_update_status(const struct device *dev, * gain update. * * @param[in] dev : Structure instance of bmi270 device - * @param[out] bmi2_gyr_user_gain_status : Structure that stores the compensated - * user-gain data of gyroscope * * @return Result of read compensated user-gain data execution * @retval 0 -> Success * @retval < 0 -> Fail */ -static int bmi270_read_gyro_user_gain(const struct device *dev, - struct bmi2_gyro_user_gain_data *gyr_usr_gain) +static int bmi270_read_gyro_user_gain(const struct device *dev) { int ret; /* Variable to define register data */ uint8_t reg_data[3] = {0}; + struct bmi270_data *data = dev->data; /* Get the gyroscope compensated gain values */ ret = bmi270_reg_read(dev, BMI270_GYR_USR_GAIN_0, reg_data, 3); @@ -375,16 +315,16 @@ static int bmi270_read_gyro_user_gain(const struct device *dev, } /* Gyroscope user gain correction X-axis */ - gyr_usr_gain->x = (int8_t)(reg_data[0] & BMI270_GYR_USR_GAIN_MASK); + data->crt_gain.x = (int8_t)(reg_data[0] & BMI270_GYR_USR_GAIN_MASK); /* Gyroscope user gain correction Y-axis */ - gyr_usr_gain->y = (int8_t)(reg_data[1] & BMI270_GYR_USR_GAIN_MASK); + data->crt_gain.y = (int8_t)(reg_data[1] & BMI270_GYR_USR_GAIN_MASK); /* Gyroscope user gain correction z-axis */ - gyr_usr_gain->z = (int8_t)(reg_data[2] & BMI270_GYR_USR_GAIN_MASK); + data->crt_gain.z = (int8_t)(reg_data[2] & BMI270_GYR_USR_GAIN_MASK); - LOG_INF("Gyroscope user gain correction, X: %d Y: %d Z: %d", gyr_usr_gain->x, - gyr_usr_gain->y, gyr_usr_gain->z); + LOG_INF("Gyroscope user gain correction, X: %d Y: %d Z: %d", + data->crt_gain.x, data->crt_gain.y, data->crt_gain.z); return ret; } @@ -408,17 +348,17 @@ static int bmi270_read_gyro_user_gain(const struct device *dev, int bmi270_get_gyro_user_gain(const struct device *dev, struct sensor_value *gain) { int ret; - struct bmi2_gyro_user_gain_data gyr_usr_gain = {0}; + struct bmi270_data *data = dev->data; /* Read user-gain data of gyroscope */ - ret = bmi270_read_gyro_user_gain(dev, &gyr_usr_gain); + ret = bmi270_read_gyro_user_gain(dev); if (ret != 0) { LOG_ERR("Failed in bmi270_read_gyro_user_gain: Error code %d", ret); return ret; } /* Unchanged user-gain data means CRT has not been performed yet */ - if ((gyr_usr_gain.x == 0) && (gyr_usr_gain.y == 0) && (gyr_usr_gain.z == 0)) { + if ((data->crt_gain.x == 0) && (data->crt_gain.y == 0) && (data->crt_gain.z == 0)) { LOG_ERR("CRT has not yet been performed"); return -EAGAIN; } @@ -430,9 +370,9 @@ int bmi270_get_gyro_user_gain(const struct device *dev, struct sensor_value *gai /* Convert compensated user-gain data * into sensor_value type */ - gain->val1 |= gyr_usr_gain.x; - gain->val1 |= (uint32_t)gyr_usr_gain.y << 8; - gain->val1 |= (uint32_t)gyr_usr_gain.z << 16; + gain->val1 |= data->crt_gain.x; + gain->val1 |= (uint32_t)data->crt_gain.y << 8; + gain->val1 |= (uint32_t)data->crt_gain.z << 16; return ret; } @@ -668,14 +608,18 @@ int bmi270_gyro_crt(const struct device *dev) uint8_t tries; const uint8_t g_trigger_cmd = BMI270_CMD_G_TRIGGER; struct bmi2_gyro_user_gain_data before_crt_gain = {0}; + struct bmi270_data *data = dev->data; - /* Initial user gain state */ - ret = bmi270_read_gyro_user_gain(dev, &before_crt_gain); + /* Get initial user gain state */ + ret = bmi270_read_gyro_user_gain(dev); if (ret != 0) { LOG_ERR("Failed in bmi270_read_gyro_user_gain: Error code %d", ret); return ret; } + /* Save initial user gain state */ + memcpy(&before_crt_gain, &(data->crt_gain), sizeof(before_crt_gain)); + /* Disable advanced power save mode */ ret = bmi270_set_aps(BMI270_PWR_CONF_ADV_PWR_SAVE_DIS, dev); if (ret != 0) { @@ -759,28 +703,29 @@ int bmi270_gyro_crt(const struct device *dev) } /* Get CRT results */ - ret = bmi270_get_gyro_gain_update_status(dev, &crt_result_sts); + ret = bmi270_get_gyro_gain_update_status(dev); if (ret != 0) { LOG_ERR("Failed in get_bmi270_crt_results: Error code %d", ret); return ret; } /* Print CRT result status */ - crt_error_log(crt_result_sts.g_trigger_status); + crt_error_log(data->crt_result_sts.g_trigger_status); /* Wait for the gyro gain data to be updated */ k_sleep(K_MSEC(350)); /* Get the gyroscope gain update data */ - ret = bmi270_read_gyro_user_gain(dev, &crt_gain); + ret = bmi270_read_gyro_user_gain(dev); if (ret != 0) { LOG_ERR("Failed in bmi270_read_gyro_user_gain: Error code %d", ret); return ret; } /* Check if new gain values are different */ - if ((before_crt_gain.x == crt_gain.x) && (before_crt_gain.y == crt_gain.y) && - (before_crt_gain.z == crt_gain.z)) { + if ((before_crt_gain.x == data->crt_gain.x) && + (before_crt_gain.y == data->crt_gain.y) && + (before_crt_gain.z == data->crt_gain.z)) { LOG_WRN("CRT new user-gyro gains remained the same"); } diff --git a/include/zephyr/drivers/sensor/bmi270.h b/include/zephyr/drivers/sensor/bmi270.h new file mode 100644 index 000000000000000..bcaf9f014e9f7ef --- /dev/null +++ b/include/zephyr/drivers/sensor/bmi270.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Extended public API for Bosch BMI270 sensor + * + * This exposes an API to the sensor's CRT feature which + * is specific to the application/environment and cannot + * be expressed within the sensor driver abstraction. + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_SENSOR_BMI270_H_ +#define ZEPHYR_INCLUDE_DRIVERS_SENSOR_BMI270_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* Sensor specific attributes */ +enum sensor_attribute_bmi270 { + /* Programs the non volatile memory(nvm) of bmi270 */ + BMI270_SENSOR_ATTR_NVM_PROG = SENSOR_ATTR_PRIV_START, + /* Set BMI270 user gain compensation */ + BMI270_SENSOR_ATTR_GAIN_COMP +}; + +/* Macros for setting gyro gain compensation */ +#define BMI270_GYR_GAIN_EN 0x01 +#define BMI270_GYR_GAIN_DIS 0x00 + +/* Helper Macros for setting gyro gain compensation */ +#define SENSOR_VALUE_WITH_GAIN(var_name, gain_value) \ + struct sensor_value var_name = {.val1 = gain_value, .val2 = 0} + +#define SENSOR_ATTR_SET_GAIN_COMPENSATION(dev, gain_value) \ + do { \ + SENSOR_VALUE_WITH_GAIN(_gain_compensation_var, gain_value); \ + sensor_attr_set(dev, SENSOR_CHAN_GYRO_XYZ, \ + BMI270_SENSOR_ATTR_GAIN_COMP, &_gain_compensation_var); \ + } while (0) + +/** @name Enum to define status of gyroscope trigger G_TRIGGER */ +typedef enum { + /*Command is valid*/ + BMI270_CRT_TRIGGER_STAT_SUCCESS = 0x00, + /*Command is aborted due to incomplete pre-conditions*/ + BMI270_CRT_TRIGGER_STAT_PRECON_ERR = 0x01, + /*Command is aborted due to unsuccessful download*/ + BMI270_CRT_TRIGGER_STAT_DL_ERR = 0x02, + /*Command is aborted by host or due to motion detection*/ + BMI270_CRT_TRIGGER_STAT_ABORT_ERR = 0x03 +} gtrigger_status; + +/** @name Structure to define gyroscope saturation status of user gain + * Describes the saturation status for the gyroscope gain + * update and G_TRIGGER command status + */ +struct bmi2_gyr_user_gain_status { + /* Status in x-axis + * This bit will be 1 if the updated gain + * results to saturated value based on the + * ratio provided for x axis, otherwise it will be 0 + */ + uint8_t sat_x; + + /* Status in y-axis + * This bit will be 1 if the updated gain + * results to saturated value based on the + * ratio provided for y axis, otherwise it will be 0 + */ + uint8_t sat_y; + + /* Status in z-axis + * This bit will be 1 if the updated gain + * results to saturated value based on the + * ratio provided for z axis, otherwise it will be 0 + */ + uint8_t sat_z; + + /* G trigger status + * Status of gyroscope trigger G_TRIGGER command. + * These bits are updated at the end of feature execution . + */ + gtrigger_status g_trigger_status; +}; + +/** @name Structure to store the compensated user-gain data of gyroscope */ +struct bmi2_gyro_user_gain_data { + /** x-axis */ + int8_t x; + + /** y-axis */ + int8_t y; + + /** z-axis */ + int8_t z; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DRIVERS_SENSOR_BMI270_H_ */