-
Notifications
You must be signed in to change notification settings - Fork 6.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
drivers: sensors: akm09918: make submit function more unblocking
The driver now does not wait for the completion of a measurement in the submit function. Instead it schedule the fetch and the completion of the submission queue entry as delayed work to the system work queue. Signed-off-by: Florian Weber <Florian.Weber@live.de>
- Loading branch information
1 parent
ed31037
commit b7706cb
Showing
3 changed files
with
101 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,54 +1,85 @@ | ||
/* | ||
* Copyright (c) 2023 Google LLC | ||
* Copyright (c) 2024 Croxel Inc. | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <zephyr/logging/log.h> | ||
#include <zephyr/rtio/work.h> | ||
|
||
#include "akm09918c.h" | ||
|
||
LOG_MODULE_DECLARE(AKM09918C, CONFIG_SENSOR_LOG_LEVEL); | ||
|
||
void akm09918c_submit_sync(struct rtio_iodev_sqe *iodev_sqe) | ||
void akm09918_async_fetch(struct k_work *work) | ||
{ | ||
const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data; | ||
struct k_work_delayable *dwork = k_work_delayable_from_work(work); | ||
struct akm09918c_async_fetch_ctx *ctx = | ||
CONTAINER_OF(dwork, struct akm09918c_async_fetch_ctx, async_fetch_work); | ||
const struct sensor_read_config *cfg = ctx->iodev_sqe->sqe.iodev->data; | ||
const struct device *dev = cfg->sensor; | ||
uint32_t min_buf_len = sizeof(struct akm09918c_encoded_data); | ||
int rc; | ||
uint8_t *buf; | ||
uint32_t req_buf_len = sizeof(struct akm09918c_encoded_data); | ||
uint32_t buf_len; | ||
uint8_t *buf; | ||
struct akm09918c_encoded_data *edata; | ||
int rc; | ||
|
||
/* Get the buffer for the frame, it may be allocated dynamically by the rtio context */ | ||
rc = rtio_sqe_rx_buf(iodev_sqe, min_buf_len, min_buf_len, &buf, &buf_len); | ||
rc = rtio_sqe_rx_buf(ctx->iodev_sqe, req_buf_len, req_buf_len, &buf, &buf_len); | ||
if (rc != 0) { | ||
LOG_ERR("Failed to get a read buffer of size %u bytes", min_buf_len); | ||
rtio_iodev_sqe_err(iodev_sqe, rc); | ||
LOG_ERR("Failed to get a read buffer of size %u bytes", req_buf_len); | ||
rtio_iodev_sqe_err(ctx->iodev_sqe, rc); | ||
return; | ||
} | ||
|
||
edata = (struct akm09918c_encoded_data *)buf; | ||
edata->header.timestamp = k_ticks_to_ns_floor64(k_uptime_ticks()); | ||
|
||
rc = akm09918c_sample_fetch_helper(dev, SENSOR_CHAN_MAGN_XYZ, &edata->readings[0], | ||
&edata->readings[1], &edata->readings[2]); | ||
rc = akm09918c_fetch_measurement(dev, &edata->readings[0], &edata->readings[1], | ||
&edata->readings[2]); | ||
if (rc != 0) { | ||
LOG_ERR("Failed to fetch samples"); | ||
rtio_iodev_sqe_err(iodev_sqe, rc); | ||
rtio_iodev_sqe_err(ctx->iodev_sqe, rc); | ||
return; | ||
} | ||
|
||
rtio_iodev_sqe_ok(iodev_sqe, 0); | ||
rtio_iodev_sqe_ok(ctx->iodev_sqe, 0); | ||
} | ||
|
||
void akm09918c_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) | ||
{ | ||
struct rtio_work_req *req = rtio_work_req_alloc(); | ||
int rc; | ||
struct akm09918c_data *data = dev->data; | ||
const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data; | ||
const struct sensor_chan_spec *const channels = cfg->channels; | ||
const size_t num_channels = cfg->count; | ||
|
||
/* Check if the requested channels are supported */ | ||
for (size_t i = 0; i < num_channels; i++) { | ||
switch (channels[i].chan_type) { | ||
case SENSOR_CHAN_MAGN_X: | ||
case SENSOR_CHAN_MAGN_Y: | ||
case SENSOR_CHAN_MAGN_Z: | ||
case SENSOR_CHAN_MAGN_XYZ: | ||
case SENSOR_CHAN_ALL: | ||
break; | ||
default: | ||
LOG_ERR("Unsupported channel type %d", channels[i].chan_type); | ||
rtio_iodev_sqe_err(iodev_sqe, -ENOTSUP); | ||
return; | ||
} | ||
} | ||
|
||
/* start the measurement in the sensor */ | ||
rc = akm09918c_start_measurement(dev, SENSOR_CHAN_MAGN_XYZ); | ||
if (rc != 0) { | ||
LOG_ERR("Failed to fetch samples."); | ||
rtio_iodev_sqe_err(iodev_sqe, rc); | ||
return; | ||
} | ||
|
||
__ASSERT_NO_MSG(req); | ||
/* save information for the work item */ | ||
data->work_ctx.timestamp = k_ticks_to_ns_floor64(k_uptime_ticks()); | ||
data->work_ctx.iodev_sqe = iodev_sqe; | ||
|
||
rtio_work_req_submit(req, iodev_sqe, akm09918c_submit_sync); | ||
rc = k_work_schedule(&data->work_ctx.async_fetch_work, K_USEC(AKM09918C_MEASURE_TIME_US)); | ||
if (rc == 0) { | ||
LOG_ERR("The last fetch has not finished yet. " | ||
"Try again later when the last sensor read operation has finished."); | ||
rtio_iodev_sqe_err(iodev_sqe, -EBUSY); | ||
} | ||
return; | ||
} |