-
Notifications
You must be signed in to change notification settings - Fork 8.3k
[DNM] [RFC] drivers: i2c: Add i2c_async for asynchronous transfers #23371
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
Conversation
This comment has been minimized.
This comment has been minimized.
tbursztyka
left a comment
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.
The example is maybe not the best one (at least the init process: it looses the error check on chip id afaik)
And I did not realize this meant that much change in user code to switch to async, and it will - at this stage - make it painful for maintainers to support both modes (do not forget that some users may not need such advanced feature). I think the most important part to improve is this then.
include/drivers/i2c.h
Outdated
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 would avoid this. Primarily because it's going to be called in interrupt context (I know, gpio does it, but we agreed about that when it was designed to do so). In SPI we use struct k_poll_signal instead for notifying when a call is done (the only difference being that the call does not return -EBUSY but waits until it gets its turn but that's another story). Using such kernel object is I think better since it provides more flexibility and robustness as well as avoiding to run a cb in interrupt context.
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.
If this is supposed to be an asynchronous API, I'd really like to see it use async_notify rather than assume a callback is the user's desired interface for results.
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.
async_notify would mean such async function would be usable only within the async library. It may not be what all users want. They might want to use a simpler system, thus why using k_poll_signal might be more relevant.
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.
async_notify (from #23229) is simply an abstraction that describes how the caller wants to be notified that an operation completes. It allows callback, poll (signal), or spin-wait notifications, so can be used from a variety of contexts with or without POLL support.
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.
Sure, however result and flags attribute seem useless (signal owns already a result attribute, and for the cb it could just take a result as parameter). Would be worth having an intermediate structure just for signal or cb then.
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.
async_notify holds 2 useless attributes (result and flags), it can be another one.
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.
They are not useless. See #23229 (comment). Please provide feedback there if you are unconvinced so we don't have to track discussions in two places.
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.
flags are needed to distinguish between callback or signal. and i advocate for moving result into union (it's needed for spinwait mode): #23229 (comment)
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.
oh yes, missed that entirely. Well, do you really need a interrupt context cb then? :)
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.
yes, i do. I don't want dedicated thread to talk to i2c. If i have signal then i need thread context to wait for the completion and i want to be able to do that from any context (interrupts).
include/drivers/i2c.h
Outdated
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 see why you are doing this: it's easier then to manage async object memory space, as each and every driver would own it directly. But on the other hand, it is an object the driver will never use by itself.
I think this needs to be reconsidered, finding a way to manager async objects directly into the async manager.
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 agree. currently i had to do something to get this object. I already made a proposal of different approach: #22409
include/drivers/i2c.h
Outdated
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.
Could you have a separate patch for all the above? (Am I wrong if I say it could be used on i2c_transfer()? thus why I think it deserves its own patch.)
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.
yes, except for delay parameter which was added to the flags. but you are right, i will extract it to separate patch.
drivers/sensor/hts221/hts221.h
Outdated
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.
remove 'data'
I'm not a fan of packing up many features into a single API that would have be be independently supported in multiple drivers. Why should a single-transaction API include a start delay? Better to have a multi-operation description that steps through a sequence of operations, one of which could be a generic "delay" (for time, or for event) that is interpreted by an service-agnostic multi-operation sequencing engine, while service-specific operations are passed off to a common driver function like |
yes, it might be that chip id would need to be taken out, alternatively it can be checked after whole sequence. Another option that sequence manager is supporting is pausing. sequence can be configured so that after chip id read there is a pause callback. User checks chip id and aborts sequence if it is wrong or resumes. This is not yet implemented in i2c_async (supported by async_seq) |
I will look into that. |
Note that legacy API will keep work and hts221 change was done only to showcase new api. I expect that asynchronous API will go in without any changes in sensors. It will serve for those who wants to use i2c asynchronously (custom driver). It's hard to tell if other vendors switch to that api. Since legacy and async can be mixed, sensor can have most parts common and for example two versions of read out call. However, this is too far into the future as that would require sensor API to be asynchronous. |
Full asynchronous support for APIs such as bus transactions generally require managing operations from unrelated clients. This API provides a data structure and functions to manage those operations generically, leaving the service to provide only the service-specific operation description and implementation. Signed-off-by: Peter Bigot <peter.bigot@nordicsemi.no>
Manager is handlng execution of sequence of operations and notifies once sequence is completed. Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
|
API 2020-07-07: Moved from triage to in-progress pending further activity per #23371 (comment) |
PR content:
Proposed extension to i2c API:
i2c_single_transfer(dev, msg, add, callback, user_data).Extendingi2c_msgflags to contain milliseconds delay field which can be used within sequence to delay message execution.Added helper macros for initializing set of message, e.g.I2C_MSG_TXRX()i2c_asyncinstance associated with given device:i2c_get_async(dev)Added new module
drivers/i2c/i2c_asyncwhich wrapsqueue_operation_managerandasync_seq_managerto provide safe and managed, asynchronous access to i2c.i2c_single_transfer()to execute item within the sequence.i2c_async_msgitems and may be constant, e.g. whole sensor initialization procedure can be stored in flash.struct i2c_msgi2c_async_resume().i2c_asyncis a generic part and vendor specific driver implements only single transfer functionality (along with configure and getting async instance). This way specific driver is only focused on it's core functionality, all access management, semaphores, etc. is removed from the driver. It is in opposition to current state where each driver is implementing own mechanisms for access control.i2c_asyncimplementsz_i2c_async_sync_transferwhich is used to provide backward compatibility (it is called byi2c_transfer).Modified
i2c_nrfx_twimdriver to implementi2c_single_transferModified
hts221sensor driver to show how to use i2c_async. This is temporary of course, just to show new way.How to control I2C using
i2c_async?Asynchronous access to i2c does not happen through i2c API because there can be multiple context accessing same i2c device. Access must be managed.
queued operation manageris created to handle that generic task (see #23333) thus user is actually talking toqueued operation managerAPI using handle to the manager associated with given i2c device. The manager works withqueued operationsobject so i2c operation must contain queued operation structure. i2c operation consists of one or morei2c_msg. Messages build a sequence which is executed by the queue operation manager. Completion of the i2c operation is notified usingasync notifyobject (see #23229) which is part of the i2c operation.async notifystandardizes methods of notification of completion of asynchronous operation.Scheduling of asynchronous i2c is performed in following steps:
struct i2c_async_opini2c_async.h). Helper macros can be used to create it. Operation contains queued operation object and pointer to the sequence (pointer because sequence can be in flash and operation must be in rw memory).i2c_asyncobject to use. Usei2c_get_async(dev).async_notify. Usei2c_async_get_notify(op)to get async notify from the operation.queue_operation_submit(mngr, op, PRI)Example code:
Benefits
SENSOR_BUS_MSG_TXRX(),SENSOR_BUS_OP_DEFINE)misc
PR is based on unmerged work:
async_notifyrefactor onoff to separate async notification, standardize terminology, and add functionality #23229queued_operationadd queued operation manager #23333async_seqAsynchronous sequence manager #23075hts221 sensor changes commit will be removed from final PR