Skip to content

[RFC] trait for servicing interrupts #1501

@gendx

Description

@gendx

Observations

While working on chips from the nRF5x family, one thing that came up is that some chips support more interrupts than others. Currently, the code to service pending interrupts is in the nrf52 crate.

fn service_pending_interrupts(&self) {
unsafe {
loop {
if let Some(task) = deferred_call::DeferredCall::next_pending() {
match task {
DeferredCallTask::Nvmc => nvmc::NVMC.handle_interrupt(),
}
} else if let Some(interrupt) = nvic::next_pending() {
match interrupt {
peripheral_interrupts::ECB => nrf5x::aes::AESECB.handle_interrupt(),
peripheral_interrupts::GPIOTE => self.gpio_port.handle_interrupt(),

There is some common code and then a match over the interrupt number, that calls the suitable handle_interrupt function for the suitable driver.

With this architecture, an interrupt only defined on say nrf52840 would have to be added to nrf52, so the driver would also need to be in nrf52 instead of nrf52840. This isn't separating well various chips of the same family.

Alternatively, nrf52840 could redefine the whole chips.rs, which would be a lot of duplicated code for maybe a few unique drivers.

Draft Proposal

To make servicing of interrupts more flexible, an InterruptServiceTrait could be define as follows:

trait InterruptServiceTrait {
    unsafe fn service_interrupt(&self, interrupt: u32) -> bool;
}
  • The function is unsafe, similarly to the match inside the current service_pending_interrupts.
  • It returns a boolean, whether this interrupt number was serviced or not.

This allows composable interrupt services, for example nrf52 defines a set of interrupt handlers, and on top of that nrf52840 only defines its specific interrupts, returning false otherwise to indicate that the parent nrf52 should handle the interrupt.

The chip's constructor, currently here:

impl NRF52 {
pub unsafe fn new(gpio_port: &'static nrf5x::gpio::Port) -> NRF52 {

would be updated to take a interrupt_service: &'static dyn InterruptServiceTrait as parameter to service the interrupt. Then, each "end-user" chip such as nrf52840 or nrf52833 can pass a suitable InterruptServiceTrait to the generic NRF52 chip constructor.

It seems that such a trait wouldn't be specific to Nordic chips but could be useful for all chips, as a trait in the kernel.

Any thoughts?

Misc

Another trait that could be useful to clarify things would be an InterruptHandler trait that defines the handle_interrupt method. For now, drivers have this method by convention, but it isn't formalized as a trait. It could also be useful to put the "enable/disable all interrupts" pattern in this trait.

Metadata

Metadata

Assignees

No one assigned

    Labels

    rfcIssue designed for discussion and to solicit feedback.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions