Expose LCD_CAM interrupt bits
Thank you for your contribution!
We appreciate the time and effort you've put into this pull request. To help us review it efficiently, please ensure you've gone through the following checklist:
Submission Checklist 📝
- [ ] I have updated existing examples or added new ones (if applicable).
- [ ] I have used
cargo xtask fmt-packagescommand to ensure that all changed code is formatted correctly. - [ ] My changes were added to the
CHANGELOG.mdin the proper section. - [ ] I have added necessary changes to user code to the Migration Guide.
- [ ] My changes are in accordance to the esp-rs API guidelines
Extra:
- [ ] I have read the CONTRIBUTING.md guide and followed its instructions.
Pull Request Details 📖
Description
The main goal of this PR was to expose a separate object for accessing the interrupt bits of the LCD_CAM.
Other drivers in the hal (like DMA and SPI) expose listen, unlisten, clear, etc. directly on the driver objects themselves, which means you have to put the entire driver in a critical section just because you want to clear some interrupts.
Having a separate object means you can keep your driver wherever and this separate object can go in the critical section.
Having a separate object also gives you the freedom to implement async for both the camera and lcd as necessary, with any locking mechanism of your choosing.
As a consequence of having this separate object, it now needs to be provided to create an async driver. So I've also provided an into_async() and into_blocking() to allow users to switch between the default async implementation and theirs when necessary.
Ideally the whole set_interrupt_handler business should be moved out of the driver file and into a chip specific "interrupt driver" but I'm not about to commit to sort of change in this PR.
Related #2321 .
Testing
(pending)
But it's also not possible to use both drivers in async mode at the same time with this PR, right?
Correct. I meant that in the DIY sense. User can create their own wakers and such.
- Provide a separate peripheral mode, e.g.
BlockingWithInterrupts/Unsplitthat the peripherals start in. From this mode, you can unsplit the interrupt handler and get aBlockingdriver, or convert directly intoAsyncwithout splitting first.
Mmm I can work with this yeah.
pub struct LcdCam<'d, M = BlockingWithInterrupts> { // throw away the Mode trait at this point, not too useful.
pub lcd: Lcd<'d, M>,
pub cam: Cam<'d, M>,
}
impl LcdCam<'d, BlockingWithInterrupts> {
pub fn split_interrupts(self) -> (LcdCam<'d, Blocking>, InterruptControl<'d>) {
let interrupts = unsafe { InterruptControl::steal() };
(
LcdCam { self.... },
interrupts,
)
}
}
I don't think I'll be able to provide a interrupt_controller() -> &mut NamesAreHard for BlockingWithInterrupts mode. At least my Rust isn't quite good enough.
I suppose it won't be particularly useful once users create the individual Camera and I8080 drivers.
I agree Mode can go away - but also peripheral implementations might be simpler with a M: BlockingMode.
I don't think I'll be able to provide a interrupt_controller() -> &mut NamesAreHard for BlockingWithInterrupts mode
Return a reference to a static, with a limited lifetime.
I suppose it won't be particularly useful once users create the individual Camera and I8080 drivers.
Yeah, drivers should only mess with their own bits. As you picked the driver with the worst edge cases, it's a good time to explore our options :)
I intend to come back to this as I think it's an important feature. I'm closing this for now as there's a wave of merge conflicts galore coming in.