Skip to content

Commit 1a89d4b

Browse files
FlorianWeber1018MaureenHelm
authored andcommitted
drivers: sensor: 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 <[email protected]>
1 parent 3b6555a commit 1a89d4b

File tree

3 files changed

+109
-35
lines changed

3 files changed

+109
-35
lines changed

drivers/sensor/asahi_kasei/akm09918c/akm09918c.c

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright (c) 2023 Google LLC
3+
* Copyright (c) 2024 Florian Weber <[email protected]>
34
* SPDX-License-Identifier: Apache-2.0
45
*/
56

@@ -21,21 +22,16 @@
2122
LOG_MODULE_REGISTER(AKM09918C, CONFIG_SENSOR_LOG_LEVEL);
2223

2324
/**
24-
* @brief Perform the bus transaction to fetch samples
25+
* @brief Perform the bus transaction to start measurement.
2526
*
2627
* @param dev Sensor device to operate on
27-
* @param chan Channel ID to fetch
28-
* @param x Location to write X channel sample.
29-
* @param y Location to write Y channel sample.
30-
* @param z Location to write Z channel sample.
28+
* @param chan Channel ID for starting the measurement
3129
* @return int 0 if successful or error code
3230
*/
33-
int akm09918c_sample_fetch_helper(const struct device *dev, enum sensor_channel chan, int16_t *x,
34-
int16_t *y, int16_t *z)
31+
int akm09918c_start_measurement(const struct device *dev, enum sensor_channel chan)
3532
{
3633
struct akm09918c_data *data = dev->data;
3734
const struct akm09918c_config *cfg = dev->config;
38-
uint8_t buf[9] = {0};
3935

4036
if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_MAGN_X && chan != SENSOR_CHAN_MAGN_Y &&
4137
chan != SENSOR_CHAN_MAGN_Z && chan != SENSOR_CHAN_MAGN_XYZ) {
@@ -49,11 +45,24 @@ int akm09918c_sample_fetch_helper(const struct device *dev, enum sensor_channel
4945
LOG_ERR("Failed to start measurement.");
5046
return -EIO;
5147
}
52-
53-
/* Wait for sample */
54-
LOG_DBG("Waiting for sample...");
55-
k_usleep(AKM09918C_MEASURE_TIME_US);
5648
}
49+
return 0;
50+
}
51+
52+
/**
53+
* @brief Perform the bus transaction to fetch samples.
54+
*
55+
* @param dev Sensor device to operate on
56+
* @param chan Channel ID to fetch
57+
* @param x Location to write X channel sample.
58+
* @param y Location to write Y channel sample.
59+
* @param z Location to write Z channel sample.
60+
* @return int 0 if successful or error code
61+
*/
62+
int akm09918c_fetch_measurement(const struct device *dev, int16_t *x, int16_t *y, int16_t *z)
63+
{
64+
const struct akm09918c_config *cfg = dev->config;
65+
uint8_t buf[9] = {0};
5766

5867
/* We have to read through the TMPS register or the data_ready bit won't clear */
5968
if (i2c_burst_read_dt(&cfg->i2c, AKM09918C_REG_ST1, buf, ARRAY_SIZE(buf)) != 0) {
@@ -77,8 +86,16 @@ static int akm09918c_sample_fetch(const struct device *dev, enum sensor_channel
7786
{
7887
struct akm09918c_data *data = dev->data;
7988

80-
return akm09918c_sample_fetch_helper(dev, chan, &data->x_sample, &data->y_sample,
81-
&data->z_sample);
89+
int ret = akm09918c_start_measurement(dev, chan);
90+
91+
if (ret) {
92+
return ret;
93+
}
94+
/* Wait for sample */
95+
LOG_DBG("Waiting for sample...");
96+
k_usleep(AKM09918C_MEASURE_TIME_US);
97+
98+
return akm09918c_fetch_measurement(dev, &data->x_sample, &data->y_sample, &data->z_sample);
8299
}
83100

84101
static void akm09918c_convert(struct sensor_value *val, int16_t sample)
@@ -213,7 +230,10 @@ static int akm09918c_init(const struct device *dev)
213230
return rc;
214231
}
215232
data->mode = AKM09918C_CNTL2_PWR_DOWN;
216-
233+
#ifdef CONFIG_SENSOR_ASYNC_API
234+
/* init work for fetching after measurement has completed */
235+
k_work_init_delayable(&data->work_ctx.async_fetch_work, akm09918_async_fetch);
236+
#endif
217237
return 0;
218238
}
219239

drivers/sensor/asahi_kasei/akm09918c/akm09918c.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright (c) 2023 Google LLC
3+
* Copyright (c) 2024 Florian Weber <[email protected]>
34
* SPDX-License-Identifier: Apache-2.0
45
*/
56

@@ -34,6 +35,13 @@ struct akm09918c_data {
3435
int16_t y_sample;
3536
int16_t z_sample;
3637
uint8_t mode;
38+
#ifdef CONFIG_SENSOR_ASYNC_API
39+
struct akm09918c_async_fetch_ctx {
40+
struct rtio_iodev_sqe *iodev_sqe;
41+
uint64_t timestamp;
42+
struct k_work_delayable async_fetch_work;
43+
} work_ctx;
44+
#endif
3745
};
3846

3947
struct akm09918c_config {
@@ -74,22 +82,23 @@ static inline void akm09918c_reg_to_hz(uint8_t reg, struct sensor_value *val)
7482
break;
7583
}
7684
}
85+
int akm09918c_start_measurement(const struct device *dev, enum sensor_channel chan);
7786

87+
int akm09918c_fetch_measurement(const struct device *dev, int16_t *x, int16_t *y, int16_t *z);
7888
/*
7989
* RTIO types
8090
*/
8191

8292
struct akm09918c_decoder_header {
8393
uint64_t timestamp;
84-
} __attribute__((__packed__));
94+
} __packed;
8595

8696
struct akm09918c_encoded_data {
8797
struct akm09918c_decoder_header header;
8898
int16_t readings[3];
8999
};
90100

91-
int akm09918c_sample_fetch_helper(const struct device *dev, enum sensor_channel chan, int16_t *x,
92-
int16_t *y, int16_t *z);
101+
void akm09918_async_fetch(struct k_work *work);
93102

94103
int akm09918c_get_decoder(const struct device *dev, const struct sensor_decoder_api **decoder);
95104

Lines changed: 62 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/*
22
* Copyright (c) 2023 Google LLC
33
* Copyright (c) 2024 Croxel Inc.
4+
* Copyright (c) 2024 Florian Weber <[email protected]>
45
*
56
* SPDX-License-Identifier: Apache-2.0
67
*/
@@ -16,32 +17,46 @@ void akm09918c_submit_sync(struct rtio_iodev_sqe *iodev_sqe)
1617
{
1718
const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data;
1819
const struct device *dev = cfg->sensor;
19-
uint32_t min_buf_len = sizeof(struct akm09918c_encoded_data);
20+
struct akm09918c_data *data = dev->data;
21+
const struct sensor_chan_spec *const channels = cfg->channels;
22+
const size_t num_channels = cfg->count;
2023
int rc;
21-
uint8_t *buf;
22-
uint32_t buf_len;
23-
struct akm09918c_encoded_data *edata;
2424

25-
/* Get the buffer for the frame, it may be allocated dynamically by the rtio context */
26-
rc = rtio_sqe_rx_buf(iodev_sqe, min_buf_len, min_buf_len, &buf, &buf_len);
27-
if (rc != 0) {
28-
LOG_ERR("Failed to get a read buffer of size %u bytes", min_buf_len);
29-
rtio_iodev_sqe_err(iodev_sqe, rc);
30-
return;
25+
/* Check if the requested channels are supported */
26+
for (size_t i = 0; i < num_channels; i++) {
27+
switch (channels[i].chan_type) {
28+
case SENSOR_CHAN_MAGN_X:
29+
case SENSOR_CHAN_MAGN_Y:
30+
case SENSOR_CHAN_MAGN_Z:
31+
case SENSOR_CHAN_MAGN_XYZ:
32+
case SENSOR_CHAN_ALL:
33+
break;
34+
default:
35+
LOG_ERR("Unsupported channel type %d", channels[i].chan_type);
36+
rtio_iodev_sqe_err(iodev_sqe, -ENOTSUP);
37+
return;
38+
}
3139
}
3240

33-
edata = (struct akm09918c_encoded_data *)buf;
34-
edata->header.timestamp = k_ticks_to_ns_floor64(k_uptime_ticks());
35-
36-
rc = akm09918c_sample_fetch_helper(dev, SENSOR_CHAN_MAGN_XYZ, &edata->readings[0],
37-
&edata->readings[1], &edata->readings[2]);
41+
/* start the measurement in the sensor */
42+
rc = akm09918c_start_measurement(dev, SENSOR_CHAN_MAGN_XYZ);
3843
if (rc != 0) {
39-
LOG_ERR("Failed to fetch samples");
44+
LOG_ERR("Failed to fetch samples.");
4045
rtio_iodev_sqe_err(iodev_sqe, rc);
4146
return;
4247
}
4348

44-
rtio_iodev_sqe_ok(iodev_sqe, 0);
49+
/* save information for the work item */
50+
data->work_ctx.timestamp = k_ticks_to_ns_floor64(k_uptime_ticks());
51+
data->work_ctx.iodev_sqe = iodev_sqe;
52+
53+
rc = k_work_schedule(&data->work_ctx.async_fetch_work, K_USEC(AKM09918C_MEASURE_TIME_US));
54+
if (rc == 0) {
55+
LOG_ERR("The last fetch has not finished yet. "
56+
"Try again later when the last sensor read operation has finished.");
57+
rtio_iodev_sqe_err(iodev_sqe, -EBUSY);
58+
}
59+
return;
4560
}
4661

4762
void akm09918c_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe)
@@ -57,3 +72,33 @@ void akm09918c_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe
5772

5873
rtio_work_req_submit(req, iodev_sqe, akm09918c_submit_sync);
5974
}
75+
76+
void akm09918_async_fetch(struct k_work *work)
77+
{
78+
struct k_work_delayable *dwork = k_work_delayable_from_work(work);
79+
struct akm09918c_async_fetch_ctx *ctx =
80+
CONTAINER_OF(dwork, struct akm09918c_async_fetch_ctx, async_fetch_work);
81+
const struct sensor_read_config *cfg = ctx->iodev_sqe->sqe.iodev->data;
82+
const struct device *dev = cfg->sensor;
83+
uint32_t req_buf_len = sizeof(struct akm09918c_encoded_data);
84+
uint32_t buf_len;
85+
uint8_t *buf;
86+
struct akm09918c_encoded_data *edata;
87+
int rc;
88+
89+
/* Get the buffer for the frame, it may be allocated dynamically by the rtio context */
90+
rc = rtio_sqe_rx_buf(ctx->iodev_sqe, req_buf_len, req_buf_len, &buf, &buf_len);
91+
if (rc != 0) {
92+
LOG_ERR("Failed to get a read buffer of size %u bytes", req_buf_len);
93+
rtio_iodev_sqe_err(ctx->iodev_sqe, rc);
94+
return;
95+
}
96+
edata = (struct akm09918c_encoded_data *)buf;
97+
rc = akm09918c_fetch_measurement(dev, &edata->readings[0], &edata->readings[1],
98+
&edata->readings[2]);
99+
if (rc != 0) {
100+
rtio_iodev_sqe_err(ctx->iodev_sqe, rc);
101+
return;
102+
}
103+
rtio_iodev_sqe_ok(ctx->iodev_sqe, 0);
104+
}

0 commit comments

Comments
 (0)