-
Notifications
You must be signed in to change notification settings - Fork 8.3k
i2c: Asynchronous Transfers #45251
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
i2c: Asynchronous Transfers #45251
Conversation
924d001 to
74889b6
Compare
2963fb9 to
da528fb
Compare
f3318d8 to
beb2168
Compare
3f28ffb to
a4d75df
Compare
85658cf to
d2f24bb
Compare
|
In place of a common set of callback helpers, provide a direct k_poll_signal wrapper alongside the callback version of i2c_transfer, so adds i2c_transfer_cb (callback) and i2c_transfer_signal (k_poll_signal, wraps the callback API). This matches my discussions @henrikbrixandersen on discord |
6d1fba2 to
3050731
Compare
i2c_transfer_async is the asynchronous version of i2c_transfer where the completion of the transfer is notified to the caller using a callback. This can be used in conjuction with the common callbacks and datatypes in async.h for directly doing an async transfer with an IPC object to notify a thread. Signed-off-by: Tom Burdick <thomas.burdick@intel.com>
Implements i2c_transfer_cb for the mcux driver Signed-off-by: Tom Burdick <thomas.burdick@intel.com>
Adds a simple test case against the FXOS8700 sensor and its built in FIFO using i2c. Pulls data from the sensor using both synchronous and asynchronous transfers. Signed-off-by: Tom Burdick <thomas.burdick@intel.com>
|
I did spend some time trying to make the k_poll_signal i2c_transfer_signal a user space friendly syscall with some success. The downsides came to needing to alloc/free things when user space was being used to keep the life of a copy of the i2c_msg array around long enough. It's certainly something that can be addressed in a future PR. |
| struct i2c_target_config *cfg); | ||
| #ifdef CONFIG_I2C_CALLBACK | ||
| typedef int (*i2c_api_transfer_cb_t)(const struct device *dev, | ||
| struct i2c_msg *msgs, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i still think that it would be better to put all this into a struct. Struct can be later on extended without breaking api (e.g adding list node field if we go into direction of queued transfers).
Current version is suitable only for bus with one device since with more we might hit collision and handling collision is painful. At the end, it should be really fire and forget. Using struct gives path towards that without need of breaking the API in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be done by providing an asynchronous lock/unlock pair of functions
i2c_lock_async(dev, cb0, data);
i2c_transfer_cb(dev, i2c_msgs, cb1, data);
i2c_transfer_cb(dev, more_i2c_msgs, cb2, data);
i2c_unlock_async(dev, cb3, data);
Obviously not in a row like that but in a callback chain. Callback chaining like this is what RTIO makes look more like a queue of requests and pollable responses.
That's how I was planning on dealing with this issue rather than trying to embed a request queue directly in the device driver. In effect there's an application allocated request queue over all devices rather than each device having its own. This way you can do request chaining or parallelism with most of the I/O task concurrency that something like a promise pipeline might give you.
It also shares all the code and logic then in something common to all device driver classes.
The blocking api can look like a semaphore given at the end of a fixed callback chain like above.
I could be wrong though, and I thought you tried to embed the queue in the device before but ran into issues.
Provides i2c_transfer_cb as an optional API along with a wrapper that provides i2c_transfer_signal (async with a k_poll_signal notifier).
Notably i2c_transfer_cb should not block so it can be initiated from an ISR if so desired as done in the frdm_k64f example. If it would block, returning -EWOULDBLOCK is expected.