-
Notifications
You must be signed in to change notification settings - Fork 2k
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
sys/cb_mux: Callback multiplexer #8993
Conversation
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.
Two initial questions.
Furthermore, I think the name "cbmplex" is not really clear. I don't have a really good suggestion at the moment, maybe somebody else comes along with a good name.
sys/cbmplex/cbmplex.c
Outdated
return entry; | ||
} | ||
|
||
cbmplex_t *cbmplex_find_flags(cbmplex_t *head, uint8_t flags, uint8_t mask) |
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.
Is there a use case for having different flags and masks? Why not use flags
as a mask?
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.
mask tells the function which bits to search, and flags tells the function what they should be set to. I will put a comment to clarify this.
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.
Of course -_-
sys/include/cbmplex.h
Outdated
typedef struct cbmplex { | ||
struct cbmplex *next; | ||
uint8_t flags; | ||
uint8_t cbid; |
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.
What is the idea behind the callback ID?
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 is whatever the system using the multiplexer uses to identify the callback. In the case of pin interrupts, it would be the pin number.
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.
Not sure I understand what you mean. How does the "system" here know the cbid
? It is not passed as argument in the callback.
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.
See example.
regarding name, "mux" is a more common shorthand for "multiplexer" (in electronics) |
"cb_mux", or "callback_mux" maybe then |
Name changed to cb_mux |
Here is an example usage. Initialization:
Pin change event (on foo's pin):
|
Note: There is an issue with the current definition of cbid. Different systems define gpio_t differently, some use up to a uint32_t. Setting cbid to uint32_t seems really big for small systems, and setting it to gpio_t seems wrong if it is not being used to hold pins. Suggestions? |
Bergzand and I have been discussing potential issues with the API being too specific to pin interrupts. I have tried to make it more generic:
I am thinking of another example use case with timers, e.g. allowing multiple callbacks with RTC/RTT implementations:
|
Have you measured the overhead in response time of this approach against direct callbacks (which costs memory of course)? |
Next on my todo list is to write a test for this code. I can include measuring overhead into that. Finding a callback is O(n), where n is the number of callbacks in the list. I count around 6 instructions per iteration over the list of callbacks. |
Ok, so if we merge this asap you'll be able to provide such a test soon? I want to move forward for interrupt handling on AVR. |
@kYc0o I intend to provide the test in this PR. |
Notice to interested parties, especially @kYc0o and @roberthartung: There are some fundamental problems with using cb_mux for its original intended purpose: getting rid of callback limitations in APIs like periph/gpio.h. This is due to the inability for the implementation to allocate memory for new list entries (i.e. no malloc) in a manner transparent to the code using the API. I suspect that an array will be more appropriate for statically allocated memory. For these reasons I will be scrapping cb_mux unless someone really wants it or has a compelling reason to keep it. Sorry for my oversight in not noticing this, and thanks to @roberthartung for pointing it out. |
@gebart If I am understanding xfa correctly, the memory is still statically allocated at compile time (although in a very neat way). The problem is that something like a periph/gpio.h implementation has no way of knowing how many times pin init functions are going to be called, so I don't see how statically allocated memory would work. Of course the API could be changed to pass memory, but then xfa would not be needed. Or you could redefine the function calls in the API to be macros that hide memory allocation, but that could introduce problems when they are assumed to be function calls. I have been discussing the issue with @kYc0o and the different possible ways around the allocation problem. I think the best compromise so far for use cases like PCINTs is to define an array of structs that contain the callback information. For example, if you had 4 entries, you would be able to use 0-4 PCINTs at a time, but you would get an error if you tried to use 5. You could then allow this number to be changed in periph_conf.h on a board-by-board basis. This would also be much simpler than cb_mux. |
Maybe if we'd introduce a gpio_int_t type, which any user of a gpio interrupt needs to provide? That struct could contain necessary per-platform fields. It would be an API change, but we could move the allocation to wherever the interrupt is used. |
A new type would work. I did interrupts in #9054 by using an array to hold the information, and the max number of entries in the list is defined in board.h. That would be a potential alternative that doesn't require an API change. |
Rebased on trunk and added periph/gpio.h support for cb_mux. No CPU actually supports it yet, but everything should silently ignore the passed gpio_int_t entry. @kaspar030 Is this approximately what you were suggesting? It is going to be a lot of work implementing cb_mux for all of the CPUs. If we are going with this method (rather than using arrays), how should we proceed? |
I have added a comprehensive test routine, and also used it to fix many bugs with the API:
|
Rebased to separate the API changes out into #9159 |
Added a simple benchmark at @kYc0o 's request.
|
I'd ACK in general this PR, however is failing for samr21-xpro. I ran Murdock and HIL tests to know where else is failing. |
Basically it's a printf problem. Just try to use as much as possible portable data types, so their size depend on the architecture. |
printf fixed. Tested again to double check on mega-xplained, and both tests pass. Murdock looks good with the cb_mux tests, but has unrelated failures on ps_schedstatistics and shell board tests. You might notice the double cast: this is because gcc doesn't like to cast from a pointer to an integer of a different size, even if it is guaranteed to be equal or smaller. |
@bergzand Do you think everything here is good to go? |
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.
looks good codewise, but there's an issue with doxygen grouping. See the comment below
sys/include/cb_mux.h
Outdated
*/ | ||
|
||
/** | ||
* @ingroup sys_cb_mux |
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 doxygen group is not defined. you can use a @defgroup
above this line and maybe also add a bit of documentation.
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.
@defgroup
and summary added.
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.
ACK, please squash
fa6490b
to
588b66a
Compare
Unrelated board failures on Murdock again. I am attempting to resubmit the rebased commits to get it to succeed. |
a9cec66
to
4c3edb2
Compare
I gave Murdock several tries but it is still failing here:
|
Created #9220 to try to fix the Murdock issue. |
I removed the |
All green now, merging. Thanks @ZetaR60 ! |
This is a rough sketch of a callback multiplexer, intended primarily for use in CPUs that have multiple pin interrupts tied to a single interrupt vector (but could be useful for other things too). It uses a singly linked list to allow callbacks to be dynamically added and deleted as needed so that all interrupts are usable without wasting memory when few are used.
Posted early in the development process to facilitate discussion in #7610.