-
Notifications
You must be signed in to change notification settings - Fork 249
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
embedded_hal_async::digital::Wait implementation for Pin #903
base: main
Are you sure you want to change the base?
Conversation
{ | ||
fn on_interrupt() { | ||
let pin_id = I::ID; | ||
let mut pin = unsafe { new_pin(pin_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.
Please add a comment why this is safe.
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 on_interrupt()
implementation has changed and this is not needed anymore
if pin.interrupt_status(Interrupt::LevelLow) | ||
|| pin.interrupt_status(Interrupt::LevelHigh) | ||
|| pin.interrupt_status(Interrupt::EdgeLow) | ||
|| pin.interrupt_status(Interrupt::EdgeHigh) |
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.
interrupt_status
reads PROCx_INTS and then returns the bit selected by the parameter. As the read is volatile, the compiler can't aggregate the 4 reads to a single one. Therefore, this is quite inefficient.
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.
Changed implementation to read register using proc_ints
pin.clear_interrupt(Interrupt::LevelLow); | ||
pin.clear_interrupt(Interrupt::LevelHigh); |
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 level interrupts can't be cleared. From the datasheet (section 2.19.3):
The level interrupts are not latched. This means that if the pin is a logical 1 and the level high interrupt is active, it will become inactive as soon as the pin changes to a logical 0. The edge interrupts are stored in the INTR register and can be cleared by writing to the INTR register.
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.
Thanks for pointing this out, changed the implementation
|
||
let _ = CPFn::new( | ||
self, | ||
Self::poll_is_high, |
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 don't think "wait for rising edge" can use poll_is_high as its poll function. A high level does not imply that an edge has occurred.
Better read the INTR register. (This may require that you don't clear the INTR bit in on_interrupt, but only do it in the poll function. I don't remember the details of the waker interactions.)
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.
Initialy before this call there was a code to ensure pin is low.
I updated the implementation to not clear interrupt inside on_interrupt and use a poll function specific to the relevant edge interrupt
Thanks for taking a look, I'll work on addressing the comments |
Currently this implementation is only for rp2040.
I plan to implement also the rp235x version, but firstly I would like to fix any issues in the rp2040 implementation to not waste review time if there are soundness issues or other changes needed.