-
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
gpio.h/cb_mux API change and interim compatibilty #9159
Conversation
c7ef2ca
to
dfe8bac
Compare
The dependency, #8993, has now been merged. This PR is required for @roberthartung and @TorbenPetersen to continue their work on a rewrite of #7610 |
Hi @ZetaR60 I have implemented a first version of #7610 however I receive an error:
Additionally why is this PR not based on the code you used in #8951? |
dfe8bac
to
fdd8e80
Compare
Rebased on trunk, and removed use of volatile (it's probably not necessary). I also made the definitions of INT_ENTRY agnostic to the presence of cb_mux. @TorbenPetersen I did not base the code on #8951 because this PR is not dependent on the refactor, and I anticipated that I would need to resolve conflicts anyway (there was 1 other conflict). |
Can we get this merged? Once this is merged, we can create a replacement PR for #7610 that implements pin change interrupts with cb_mux. |
@TorbenPetersen Can you post some test results here using the new API with your PCINT code? The interrupt commands in tests/periph_gpio would work well for this. |
@ZetaR60 requested that I post some test results of my PCINT code.
As you can see, the Interrupt is working. Is this enough @ZetaR60? |
@TorbenPetersen Thank you, that is excellent. I didn't have a way of testing this and I didn't want another bug like the issue you had with volatile sneaking into the master branch. |
Hi, when can we expect his to be merged? We need this Branch for the implementation of PCINT. As far as I know, there is no other way to handle the callbacks for the PCINTs. |
fdd8e80
to
9010c17
Compare
Rebased on trunk and resolved conflicts. |
Unfortunately it needs another rebase... We should try to get this in so it doesn't rebase every time a file is touched. |
8917dd7
to
8541fed
Compare
@kaspar030 I find this conversation a bit frustrating, because we discussed different possibilities in #8993. I had initially discarded the idea of an API change in favor of arrays, except that you suggested that an API change would be preferable:
What exactly were you suggesting, if not what was in this PR? I tried to stick closely your suggestion to ensure that this PR would be approved. |
@kaspar030 Just to point out a couple of counterpoints to your objections:
Platforms that do not use this feature just pass a null pointer, not actual memory.
I wrote a benchmark test in #8993 to address this specific issue. It was found that the traversal time of the singly linked list in cb_mux is approximately 4us per entry on an ATmega1284P at 8MHz (mega-xplained). This CPU is actually one of the worst cases for this as well: it is 8 bit, so it must use multiple operations to do >8bit comparisons; it is also one of the slowest clocks of the various boards that RIOT supports, with many systems >5x the clock rate, and a few at 10x or more; it is also an old architecture, which may use its clock cycles less efficiently than newer ones. A typical system using only a few interrupts would use a couple microseconds or less to retrieve the information it needs. I don't think it is typical to require an interrupt response of less than a couple microseconds. I have also been considering a simpler way of allocating the memory. A simple macro would be capable of both allocating the memory and returning a pointer to it, so it could just be put into the place of the entry pointer argument in
|
Yes, and I'm sorry. It seemed like a good idea at the time. Is there an issue describing the actual issue we're trying to solve? I think we need to come up with a more solid idea of what we're trying to solve and what are the implications of possible solutions. I'm still not unconvinced that passing memory for callbacks could not be a viable solution. But as is, that memory is wasted on platforms which do not use it (for portable code), and that is a no-go. |
One problem is that the induced delay (of using a linked list) is also indeterministic. That might be acceptable in many applications, but should not be forced by the generic interface. |
There is no memory allocated on systems that do not use it. In order for memory to be allocated, a macro
The problem is to design a method of allocating memory for interrupt information that has the following qualities:
Some possible solutions:
An indeterministic delay, when sufficiently small, is in practice equivalent to a deterministic delay of zero. There are various delays of this sort already. Also, a change in various conditions during compilation could introduce a variance in the deterministic delay (e.g. compiler changes, or just fixes to the code). In order for code to be stable it must handle this variance to the deterministic delay, which would also lead to resilience against small indeterministic delays.
Is this the primary issue with the PR after the clarification on the memory issue? Less than a couple microseconds is insufficiently small? We could benchmark some other systems using tests/cb_mux_bench, if you prefer. |
@kaspar030 Could you elaborate on the justification for your objections? I am assuming that your point about always passing memory has been resolved by my earlier clarification, which leaves the point about interrupt delays and indeterminism. Is this the sole remaining objection? Do you have a particular example or use-case that requires pin interrupt delays to be less than a couple microseconds, or requires said delays to vary less than a couple microseconds? I apologize if I seem to be argumentative or pushy on this issue, especially since I know that you are pretty busy and this takes you away from other work. I would not be objecting so strongly if there was not already a significant amount of labor associated with this PR, and that several problems that have simple solutions with this PR will become awkward and difficult again. |
ping @kaspar030 I was hoping to finish our discussion in time for the deadline on the 16th. |
Sorry for the delay.
In RIOT, we try hard to avoid macros for many reasons. You will not find many throughout the codebase. Sometimes there are exceptions, but those are usually well argued for and hidden deep in implementations. The extra parameter would require every user of the API to use a macro (in order to avoid wasting memory in implementations that don't need it).
Random google hit on microsecond interrupt latency: The gist of it is that in real time control applications, microseconds do matter. Please also consider the concept behind periph/gpio (and all the other periph interfaces). They try to be as slim as possible. In this case that means, if the hardware can do an interrupt latency (from pin event to execution of ISR code) of N cycles, periph/gpio tries hard to add only a minimal amount to that. In theory, with shared EXTI lines, that should not be more than a "find first set" operation on a register, a memory read for getting callback and arg and the function call overhead. Having to traverse a linked list would multiply that latency. Also, even if the actual gpio application might not need a very low delay, something else in the system might need the cycles. Remember, the MCU is blocked during that time. It would be OK for e.g., the AVR implementation to use linked lists because the platform has tighter memory constraints and therefore the tradeoffs might be chosen differently. But periph/gpio is supposed to be a generic interface, thus we don't want to introduce the overhead at this level, if we don't have to. |
Hi, |
@TorbenPetersen I have been considering how best to proceed. I think there are some unsolved problems with using arrays with an adjustable array size. Right now, a parameter like this would be set in the board files. This may be reasonable for many uses (specifically handling interrupts generated on the board), but some applications may require additional interrupts coming from off-board. I don't think there is currently any good way of setting a default in the board files and then overriding it in the application files. Also, even with a solution, it is much more desirable to configure it automatically. A possible alternative to arrays is to implement Another possibility is to implement tiers of interrupts, where there is an arbitrary number of low-speed interrupts using cb_mux with passed memory, and a few high-speed interrupts using directly accessed callback information (like the current interrupt implementations). This would allow for mitigation of the latency issue we have been discussing. Having two systems in parallel would add complexity though. Sorry if this isn't a great answer for picking a specific path forward. I know there desire for an implementation soon, but I have been having trouble coming up with a good solution that is both widely practical and fulfills the stringent requirements that we have been discussing. |
The be completely honest: your opinion on this would be really much appreciated @kaspar030 . It would be rather painfully to go through all of this again (find another solution, write code, scrap it at the end).
It may be desirable to configure it automatically. But I don't think this needs to be there from the start. Cant we just find a way to implement this first, so we can have a working way for PCINTs in RIOT? Such features like automatic configuration can be added later.
I agree. This approach seems memory consuming too. I was not able to come up with any other solution either. FYI: if we want to implement the PCINTs using arrays, we could use this PR: #7610 |
ping @ALL ? |
@kaspar030 Would a |
Whats the advantage of a one-way malloc over the LL? |
@TorbenPetersen Oneway-malloc is for allocating memory for the linked list. With typical application programming, you would just use |
I see, but using a LL still has some overhead in performance which is what initially caused this to not be merged? |
@roberthartung See @kaspar030 's comment above:
The issue was changing the API to support the memory allocation for the linked lists, not its use on AVR. |
@kaspar030 Could you give us some feedback on the |
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. |
This PR adds support for cb_mux in periph/gpio.h to be used for managing interrupts.
Specific changes:
(void)entry;
MODULE_CB_MUX
is enabled and gpio_init_int is called, that file will also declare a global cb_mux entry and pass it to gpio_init_int.MODULE_CB_MUX
is disabled and gpio_init_int is called, a NULL pointer is passed to it.This set up permits CPUs to set up cb_mux on a case by case basis, and not have any changes to the behavior of anything that does not implement it.
Depends on: #8993