Skip to content

Commit

Permalink
WIP: streaming sensor API
Browse files Browse the repository at this point in the history
Signed-off-by: Yuval Peress <peress@google.com>
  • Loading branch information
yperess committed May 16, 2023
1 parent d1ccfc8 commit 066ac53
Show file tree
Hide file tree
Showing 22 changed files with 739 additions and 134 deletions.
4 changes: 4 additions & 0 deletions cmake/linker_script/common/common-rom.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ if(CONFIG_SENSOR_INFO)
zephyr_iterable_section(NAME sensor_info KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4)
endif()

if(CONFIG_SENSOR)
zephyr_iterable_section(NAME sensor_decoder_api KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4)
endif()

if(CONFIG_MCUMGR)
zephyr_iterable_section(NAME mcumgr_handler KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4)
endif()
Expand Down
2 changes: 1 addition & 1 deletion drivers/sensor/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ add_subdirectory_ifdef(CONFIG_NTC_THERMISTOR ntc_thermistor)
add_subdirectory_ifdef(CONFIG_S11059 s11059)

zephyr_library()
zephyr_library_sources(default_rtio_sensor.c)
zephyr_library_sources(sensor_decoders_init.c default_rtio_sensor.c)
zephyr_library_sources_ifdef(CONFIG_USERSPACE sensor_handlers.c)
zephyr_library_sources_ifdef(CONFIG_SENSOR_SHELL sensor_shell.c)
zephyr_library_sources_ifdef(CONFIG_SENSOR_SHELL_BATTERY shell_battery.c)
9 changes: 9 additions & 0 deletions drivers/sensor/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@ config SENSOR_SHELL
help
This shell provides access to basic sensor data.

config SENSOR_SHELL_THREAD_STACK_SIZE
int "Stack size for the sensor shell data processing thread"
depends on SENSOR_SHELL
default 1024
help
The sensor shell uses a dedicated thread to process data coming from the
sensors in either one-shot or streaming mode. Use this config to control
the size of that thread's stack.

config SENSOR_SHELL_BATTERY
bool "Sensor shell 'battery' command"
depends on SHELL
Expand Down
10 changes: 5 additions & 5 deletions drivers/sensor/default_rtio_sensor.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ static void sensor_submit_fallback(const struct device *dev, struct rtio_iodev_s

static void sensor_iodev_submit(struct rtio_iodev_sqe *iodev_sqe)
{
const struct sensor_read_config *cfg = iodev_sqe->sqe->iodev->data;
const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data;
const struct device *dev = cfg->sensor;
const struct sensor_driver_api *api = dev->api;

if (api->submit != NULL) {
api->submit(dev, iodev_sqe);
} else {
} else if (!cfg->is_streaming) {
sensor_submit_fallback(dev, iodev_sqe);
}
}
Expand Down Expand Up @@ -69,9 +69,9 @@ static inline uint32_t compute_min_buf_len(size_t num_channels, int num_output_s
*/
static void sensor_submit_fallback(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe)
{
const struct sensor_read_config *cfg = iodev_sqe->sqe->iodev->data;
const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data;
const enum sensor_channel *const channels = cfg->channels;
const size_t num_channels = cfg->num_channels;
const size_t num_channels = cfg->count;
int num_output_samples = compute_num_samples(channels, num_channels);
uint32_t min_buf_len = compute_min_buf_len(num_channels, num_output_samples);
uint64_t timestamp_ns = k_ticks_to_ns_floor64(k_uptime_ticks());
Expand Down Expand Up @@ -167,7 +167,7 @@ void z_sensor_processing_loop(struct rtio *ctx, sensor_processing_callback_t cb)
rtio_cqe_get_mempool_buffer(ctx, cqe, &buf, &buf_len);

/* Release the CQE */
rtio_cqe_release(ctx);
rtio_cqe_release(ctx, cqe);

/* Call the callback */
cb(rc, buf, buf_len, userdata);
Expand Down
2 changes: 1 addition & 1 deletion drivers/sensor/icm42688/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ zephyr_library_sources(
icm42688.c
icm42688_common.c
icm42688_decoder.c
icm42688_rtio.c
icm42688_spi.c
)

zephyr_library_sources_ifdef(CONFIG_ICM42688_STREAM icm42688_rtio.c)
zephyr_library_sources_ifdef(CONFIG_ICM42688_TRIGGER icm42688_trigger.c)
zephyr_library_sources_ifdef(CONFIG_EMUL_ICM42688 icm42688_emul.c)
zephyr_include_directories_ifdef(CONFIG_EMUL_ICM42688 .)
15 changes: 15 additions & 0 deletions drivers/sensor/icm42688/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ config EMUL_ICM42688
Enable the hardware emulator for the ICM42688. Doing so allows exercising
sensor APIs for this IMU in native_posix and qemu.

config ICM42688_DECODER
bool "ICM42688 decoder logic"
default y if ICM42688
help
Compile the ICM42688 decoder API which allows decoding raw data returned
from the sensor.

if ICM42688

choice
Expand All @@ -42,6 +49,14 @@ config ICM42688_TRIGGER_OWN_THREAD

endchoice

config ICM42688_STREAM
bool "Use hardware FIFO to stream data"
select ICM42688_TRIGGER
default y
depends on SPI_RTIO
help
Use this config option to enable streaming sensor data via RTIO subsystem.

config ICM42688_TRIGGER
bool

Expand Down
42 changes: 25 additions & 17 deletions drivers/sensor/icm42688/icm42688.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ int icm42688_channel_get(const struct device *dev, enum sensor_channel chan,
{
struct icm42688_sensor_data *data = dev->data;

return icm42688_channel_parse_readings(chan, data->readings, &data->dev_data.cfg, val);
return icm42688_channel_parse_readings(chan, data->readings, &data->cfg, val);
}

int icm42688_sample_fetch(const struct device *dev, enum sensor_channel chan)
Expand Down Expand Up @@ -165,7 +165,7 @@ static int icm42688_attr_set(const struct device *dev, enum sensor_channel chan,
enum sensor_attribute attr, const struct sensor_value *val)
{
const struct icm42688_sensor_data *data = dev->data;
struct icm42688_cfg new_config = data->dev_data.cfg;
struct icm42688_cfg new_config = data->cfg;
int res = 0;

__ASSERT_NO_MSG(val != NULL);
Expand Down Expand Up @@ -213,7 +213,7 @@ static int icm42688_attr_get(const struct device *dev, enum sensor_channel chan,
enum sensor_attribute attr, struct sensor_value *val)
{
const struct icm42688_sensor_data *data = dev->data;
const struct icm42688_cfg *cfg = &data->dev_data.cfg;
const struct icm42688_cfg *cfg = &data->cfg;
int res = 0;

__ASSERT_NO_MSG(val != NULL);
Expand Down Expand Up @@ -288,22 +288,17 @@ int icm42688_init(const struct device *dev)
LOG_ERR("Failed to initialize triggers");
return res;
}

res = icm42688_trigger_enable_interrupt(dev);
if (res != 0) {
LOG_ERR("Failed to enable triggers");
return res;
}
#endif

data->dev_data.cfg.accel_mode = ICM42688_ACCEL_LN;
data->dev_data.cfg.gyro_mode = ICM42688_GYRO_LN;
data->dev_data.cfg.accel_fs = ICM42688_ACCEL_FS_2G;
data->dev_data.cfg.gyro_fs = ICM42688_GYRO_FS_125;
data->dev_data.cfg.accel_odr = ICM42688_ACCEL_ODR_1000;
data->dev_data.cfg.gyro_odr = ICM42688_GYRO_ODR_1000;
data->cfg.accel_mode = ICM42688_ACCEL_LN;
data->cfg.gyro_mode = ICM42688_GYRO_LN;
data->cfg.accel_fs = ICM42688_ACCEL_FS_2G;
data->cfg.gyro_fs = ICM42688_GYRO_FS_125;
data->cfg.accel_odr = ICM42688_ACCEL_ODR_1000;
data->cfg.gyro_odr = ICM42688_GYRO_ODR_1000;
data->cfg.fifo_en = IS_ENABLED(CONFIG_ICM42688_STREAM);

res = icm42688_configure(dev, &data->dev_data.cfg);
res = icm42688_configure(dev, &data->cfg);
if (res != 0) {
LOG_ERR("Failed to configure");
return res;
Expand All @@ -327,8 +322,21 @@ void icm42688_unlock(const struct device *dev)
#define ICM42688_SPI_CFG \
SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA | SPI_WORD_SET(8) | SPI_TRANSFER_MSB

#define ICM42688_RTIO_DEFINE(inst) \
SPI_DT_IODEV_DEFINE(icm42688_spi_iodev_##inst, DT_DRV_INST(inst), ICM42688_SPI_CFG, 0U); \
RTIO_DEFINE(icm42688_rtio_##inst, 8, 4);

#define ICM42688_DEFINE_DATA(inst) \
IF_ENABLED(CONFIG_ICM42688_STREAM, (ICM42688_RTIO_DEFINE(inst))); \
static struct icm42688_sensor_data icm42688_driver_##inst = { \
IF_ENABLED(CONFIG_ICM42688_STREAM, ( \
.r = &icm42688_rtio_##inst, \
.spi_iodev = &icm42688_spi_iodev_##inst, \
)) \
};

#define ICM42688_INIT(inst) \
static struct icm42688_sensor_data icm42688_driver_##inst = {0}; \
ICM42688_DEFINE_DATA(inst); \
\
static const struct icm42688_sensor_config icm42688_cfg_##inst = { \
.dev_cfg = \
Expand Down
20 changes: 12 additions & 8 deletions drivers/sensor/icm42688/icm42688.h
Original file line number Diff line number Diff line change
Expand Up @@ -385,17 +385,17 @@ struct icm42688_cfg {
/* TODO additional FIFO options */

/* TODO interrupt options */
bool interrupt1_drdy;
bool interrupt1_fifo_ths;
bool interrupt1_fifo_full;
};

struct icm42688_trigger_entry {
struct sensor_trigger trigger;
sensor_trigger_handler_t handler;
};

/**
* @brief Device data (struct device)
*/
struct icm42688_dev_data {
struct icm42688_sensor_data {
struct icm42688_cfg cfg;
#ifdef CONFIG_ICM42688_TRIGGER
#if defined(CONFIG_ICM42688_TRIGGER_OWN_THREAD)
Expand All @@ -405,16 +405,20 @@ struct icm42688_dev_data {
#elif defined(CONFIG_ICM42688_TRIGGER_GLOBAL_THREAD)
struct k_work work;
#endif
#ifdef CONFIG_ICM42688_STREAM
struct rtio_iodev_sqe *streaming_sqe;
struct rtio *r;
struct rtio_iodev *spi_iodev;
uint8_t int_status;
uint16_t fifo_count;
atomic_t reading_fifo;
#endif /* CONFIG_ICM42688_STREAM */
const struct device *dev;
struct gpio_callback gpio_cb;
sensor_trigger_handler_t data_ready_handler;
const struct sensor_trigger *data_ready_trigger;
struct k_mutex mutex;
#endif /* CONFIG_ICM42688_TRIGGER */
};

struct icm42688_sensor_data {
struct icm42688_dev_data dev_data;

int16_t readings[7];
};
Expand Down
13 changes: 9 additions & 4 deletions drivers/sensor/icm42688/icm42688_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "icm42688.h"
#include "icm42688_reg.h"
#include "icm42688_spi.h"
#include "icm42688_trigger.h"

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(ICM42688_LL, CONFIG_SENSOR_LOG_LEVEL);
Expand Down Expand Up @@ -71,7 +72,7 @@ int icm42688_reset(const struct device *dev)

int icm42688_configure(const struct device *dev, struct icm42688_cfg *cfg)
{
struct icm42688_dev_data *dev_data = dev->data;
struct icm42688_sensor_data *dev_data = dev->data;
const struct icm42688_dev_cfg *dev_cfg = dev->config;
int res;

Expand Down Expand Up @@ -173,8 +174,12 @@ int icm42688_configure(const struct device *dev, struct icm42688_cfg *cfg)
}

/* Pulse mode with async reset (resets interrupt line on int status read) */
res = icm42688_spi_single_write(&dev_cfg->spi, REG_INT_CONFIG,
BIT_INT1_DRIVE_CIRCUIT | BIT_INT1_POLARITY);
if (IS_ENABLED(CONFIG_ICM42688_TRIGGER)) {
res = icm42688_trigger_enable_interrupt(dev, cfg);
} else {
res = icm42688_spi_single_write(&dev_cfg->spi, REG_INT_CONFIG,
BIT_INT1_DRIVE_CIRCUIT | BIT_INT1_POLARITY);
}
if (res) {
LOG_ERR("Error writing to INT_CONFIG");
return res;
Expand Down Expand Up @@ -263,7 +268,7 @@ int icm42688_configure(const struct device *dev, struct icm42688_cfg *cfg)

int icm42688_safely_configure(const struct device *dev, struct icm42688_cfg *cfg)
{
struct icm42688_dev_data *drv_data = dev->data;
struct icm42688_sensor_data *drv_data = dev->data;
int ret = icm42688_configure(dev, cfg);

if (ret == 0) {
Expand Down
Loading

0 comments on commit 066ac53

Please sign in to comment.