-
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
periph/gpio: add gpio_set_cb() function #12082
Conversation
Add a function that allows to change the callback or callback argument of a interrupt enabled GPIO without re-configuring the GPIO.
I like the general idea, but two general things:
I'll take a more in depth look tomorrow, I'm too tired to concentrate now. |
As to 1., I think I should name it The idea here is that the callback function might be static and in another compilation unit, but one still wants to update the callback argument. As to 2., I can do it, but it seems a little overkill as this only provides a setter for two internal variables. |
please keep race conditions in mind.
Guard with irq_disable/restore, or add a note that this should be done externally? |
+1
I strongly disagree. Keep in mind that people like me want to use the API. And this is how people like me are trying to drink water out of glass: With this image in mind: Externally disabling interrupts is certainly to much to ask for ;-) (Also keep in mind that race conditions never trigger during development and testing. They wait until someone depends on it to show up.) |
@kaspar030 good point! |
How about so? |
* @param cb_int where to store the callback | ||
* @param[in] cb the new callback | ||
*/ | ||
static inline void _gpio_update_cb(gpio_t pin, gpio_cb_t *cb_int, gpio_cb_t cb) |
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 can move this to a separate file not to clutter the gpio.h
API.
|
||
if (int_num < 0) { | ||
return -1; | ||
} |
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.
One ATmega specific detail: The ATmegas only have individual interrupt vectors for about 3 pins, but shared interrupt vectors for a group of 8 pins (called pin changed interrupts). On top of the pin changed interrupts a RIOT compatible gpio_init_int()
is implemented, when pseudomodule is used. _int_num()
will however only work for "proper" interrupts, not for pin changed interrupts.
(But I'd say keep it like this for now. I'd even say that it is fine to merge the PR without support for this special case in order to not get lost in the implementation details of a dying platform. This can be easily added later on.)
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.
Atmega is the C64 of the MCU world, I think it will be with us for a bit.
I can just move the code from gpio_init_int()
into a helper function or call the gpio_update_cb()
function from there.
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.
Atmega is the C64 of the MCU world
😆 👍
And there is actually development on that platform. (Not from Microchip, but there is an improved clone of the ATmega328P - seemingly with a proper on chip debug interface (instead of debugWIRE)
I like the new API with separate function calls for the callback function and the argument. Keep in mind that updating the argument will also need to be done in an atomic fashion, e.g. via disabling IRQ temporary. I think that a third function to exchange both atomically would however be needed to update both. Otherwise the interrupt might be triggered right between the calls, so a handler is called with an argument it doesn't expect. (I know, the API is pretty verbose with 3 flavors. But that will be really trivial to use :-)) |
So, summing up the API I would like to see would look somewhat like this: int gpio_update_int(gpio_t pin, gpio_cb_t cb, void *arg);
int gpio_update_cb(gpio_t pin, gpio_cb_t cb);
int gpio_update_arg(gpio_t pin, void *arg); (I changed the naming a bit as I personally prefer But maybe it makes sense (in terms of ROM and/or code size) to have all three of them a |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you want me to ignore this issue, please mark it with the "State: don't stale" label. Thank you for your contributions. |
Just wondering, do we really need to return error here? This is just updating a location in memory, so technically it could never fail. |
If instead an |
But I wonder if we should first focus on the common GPIO API (for both periph and external GPIOs). This PR needs a rebase anyway, so it would be little effort to do it on top of the new GPIO API when it is finally in. |
@benpicco is this PR still on the table? |
Contribution description
It can be desirable to change the function or behavior associated with a GPIO interrupt.
Currently this can only be achieved by calling
gpio_init_int()
again, which not only does lots of unnecessary and possibly time-consuming work, but also forces to expose the GPIO configuration to callers that only want to change the callback argument.Error handling is done (if at all) following the style of the respective GPIO driver. That is, if the rest of the driver did not check if
pin
is valid, I didn't add such checks forgpio_set_cb()
. If it did contain such checks, I copied them.As this function only makes sense to call after
gpio_init_int()
had been called onpin
, it could be argued to drop the checks entirely.Testing procedure
The following program should alternate between the two messages with each press of a button.
(Only tested on samr21-xpro)
Issues/PRs references
none
(this will be used by the at86rf215 driver, a device which contains two basebands but only exposes one GPIO pin. As an optimization, the context points to the netdev that last called
send()
.)