1. Temperature Interface According to BMI08x datasheet, temperature reading requires both MSB and LSB bytes to be read and processed correctly. Temp data processing should follow the formula: Temp in °C = (temp_msb * 8) + (temp_lsb / 32) This patch implements the correct reading sequence and calculation method as specified in the datasheet. 2. Trigger Setting Previously we set handler and then trigger struct. However under some situation, as long as we set the handler, we get into ISR immediately and never set trigger struct. I simply changed the sequence. Testing: - Verified temperature readings match datasheet - Tested on stm32f407igh board with BMI08x sensor Fixes: #82375 Signed-off-by: Wenxi Xu <xuwenxi0517@gmail.com>
135 lines
3.4 KiB
C
135 lines
3.4 KiB
C
/* Bosch BMI08X inertial measurement unit driver, trigger implementation
|
|
*
|
|
* Copyright (c) 2022 Meta Platforms, Inc. and its affiliates
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <zephyr/drivers/gpio.h>
|
|
#include <zephyr/drivers/sensor.h>
|
|
#include <zephyr/pm/device.h>
|
|
#include <zephyr/kernel.h>
|
|
|
|
#define DT_DRV_COMPAT bosch_bmi08x_gyro
|
|
#include "bmi08x.h"
|
|
|
|
#include <zephyr/logging/log.h>
|
|
LOG_MODULE_DECLARE(BMI08X_GYRO, CONFIG_SENSOR_LOG_LEVEL);
|
|
|
|
static void bmi08x_handle_drdy_gyr(const struct device *dev)
|
|
{
|
|
struct bmi08x_gyro_data *data = dev->data;
|
|
|
|
#ifdef CONFIG_PM_DEVICE
|
|
enum pm_device_state state;
|
|
|
|
(void)pm_device_state_get(dev, &state);
|
|
if (state != PM_DEVICE_STATE_ACTIVE) {
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if (data->handler_drdy_gyr) {
|
|
data->handler_drdy_gyr(dev, data->drdy_trig_gyr);
|
|
}
|
|
}
|
|
|
|
static void bmi08x_handle_interrupts_gyr(void *arg)
|
|
{
|
|
const struct device *dev = (const struct device *)arg;
|
|
|
|
bmi08x_handle_drdy_gyr(dev);
|
|
}
|
|
|
|
#ifdef CONFIG_BMI08X_GYRO_TRIGGER_OWN_THREAD
|
|
static void bmi08x_gyr_thread_main(void *arg1, void *unused1, void *unused2)
|
|
{
|
|
k_thread_name_set(NULL, "bmi08x_gyr_trig");
|
|
|
|
ARG_UNUSED(unused1);
|
|
ARG_UNUSED(unused2);
|
|
|
|
const struct device *dev = (const struct device *)arg1;
|
|
struct bmi08x_gyro_data *data = dev->data;
|
|
|
|
while (1) {
|
|
k_sem_take(&data->sem, K_FOREVER);
|
|
bmi08x_handle_interrupts_gyr((void *)dev);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_BMI08X_GYRO_TRIGGER_GLOBAL_THREAD
|
|
static void bmi08x_gyr_work_handler(struct k_work *work)
|
|
{
|
|
struct bmi08x_gyro_data *data = CONTAINER_OF(work, struct bmi08x_gyro_data, work);
|
|
|
|
bmi08x_handle_interrupts_gyr((void *)data->dev);
|
|
}
|
|
#endif
|
|
|
|
static void bmi08x_gyr_gpio_callback(const struct device *port, struct gpio_callback *cb,
|
|
uint32_t pin)
|
|
{
|
|
struct bmi08x_gyro_data *data = CONTAINER_OF(cb, struct bmi08x_gyro_data, gpio_cb);
|
|
|
|
ARG_UNUSED(port);
|
|
ARG_UNUSED(pin);
|
|
|
|
#if defined(CONFIG_BMI08X_GYRO_TRIGGER_OWN_THREAD)
|
|
k_sem_give(&data->sem);
|
|
#elif defined(CONFIG_BMI08X_GYRO_TRIGGER_GLOBAL_THREAD)
|
|
k_work_submit(&data->work);
|
|
#endif
|
|
}
|
|
|
|
int bmi08x_trigger_set_gyr(const struct device *dev, const struct sensor_trigger *trig,
|
|
sensor_trigger_handler_t handler)
|
|
{
|
|
struct bmi08x_gyro_data *data = dev->data;
|
|
|
|
if ((trig->chan == SENSOR_CHAN_GYRO_XYZ) && (trig->type == SENSOR_TRIG_DATA_READY)) {
|
|
data->drdy_trig_gyr = trig;
|
|
data->handler_drdy_gyr = handler;
|
|
return 0;
|
|
}
|
|
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
int bmi08x_gyr_trigger_mode_init(const struct device *dev)
|
|
{
|
|
struct bmi08x_gyro_data *data = dev->data;
|
|
const struct bmi08x_gyro_config *cfg = dev->config;
|
|
int ret;
|
|
|
|
if (!gpio_is_ready_dt(&cfg->int_gpio)) {
|
|
LOG_ERR("GPIO device not ready");
|
|
return -ENODEV;
|
|
}
|
|
|
|
#if defined(CONFIG_BMI08X_GYRO_TRIGGER_OWN_THREAD)
|
|
k_sem_init(&data->sem, 0, K_SEM_MAX_LIMIT);
|
|
|
|
k_thread_create(&data->thread, data->thread_stack,
|
|
CONFIG_BMI08X_GYRO_THREAD_STACK_SIZE, bmi08x_gyr_thread_main, (void *)dev,
|
|
NULL, NULL, K_PRIO_COOP(CONFIG_BMI08X_GYRO_THREAD_PRIORITY), 0, K_NO_WAIT);
|
|
#elif defined(CONFIG_BMI08X_GYRO_TRIGGER_GLOBAL_THREAD)
|
|
data->work.handler = bmi08x_gyr_work_handler;
|
|
data->dev = dev;
|
|
#endif
|
|
|
|
gpio_pin_configure_dt(&cfg->int_gpio, GPIO_INPUT);
|
|
|
|
gpio_init_callback(&data->gpio_cb, bmi08x_gyr_gpio_callback, BIT(cfg->int_gpio.pin));
|
|
|
|
ret = gpio_add_callback(cfg->int_gpio.port, &data->gpio_cb);
|
|
|
|
if (ret < 0) {
|
|
LOG_ERR("Failed to set gpio callback.");
|
|
return ret;
|
|
}
|
|
gpio_pin_interrupt_configure_dt(&cfg->int_gpio, GPIO_INT_EDGE_TO_ACTIVE);
|
|
|
|
return ret;
|
|
}
|