mciantyre / teensy4-rs

Rust support for the Teensy 4
Apache License 2.0
271 stars 31 forks source link

Provide a GPIO interrupt example #101

Closed algesten closed 2 years ago

algesten commented 3 years ago

Is your feature request related to a problem? Please describe.

As a new user of Rust embedded, I found the teensy4-rs related crates very good and straightforward. Thanks!

I'm trying to figure out how to configure a GPIO pin as an interrupt. The examples dir has plenty of interrupt examples, but I believe not one doing it with GPIO.

Searching around for cortex-m-rt related examples configuring GPIO, I find examples doing it with stm32, however it doesn't seem quite to apply to teensy4.

I think my problem is that I don't understand how to associate a pin with a specific interrupt. This is what I got.

    #[cortex_m_rt::interrupt]
    fn GPIO1_INT0() {
        info!("interrupt!");
    }

    cortex_m::interrupt::free(|_cs| {
        unsafe { cortex_m::peripheral::NVIC::unmask(bsp::interrupt::GPIO1_INT0) };
    });

and also:

    let mut p = bsp::Peripherals::take().unwrap();
    let pins = bsp::t40::into_pins(p.iomuxc);
    let input1 = GPIO::new(pins.p12);

What I believe I need is some way to relate interrupt GPIO1_INT0 to pins.p12, but can't for my life figure out how.

In the stm32 world they seem to have some SYSCFG peripheral that is used to do this association (step 3 here). Is the problem maybe that some peripheral is missing in imxrt?

Describe the solution you'd like

If there is a way forward in existing teensy4-rs, I'd love to understand it. I'm also happy to provide a PR for the GPIO example, if I can figure out how it works.

Describe alternatives you've considered

My fallback will be polling, seems inelegant though.

algesten commented 3 years ago

Been digging a bit more, and I'm leaning towards that this isn't currently possible. From the code comment in usb.c and digging through the bindings from rust to the USB c code, I find this:

    //_VectorsRam[IRQ_USB1+16] = &isr;
    // NOTE(mciantyre): disabling interrupt registration and enabling.
    // Rust code will be responsible for enabling the interrupt. We have
    // no dynamic ISR registration, so the USB_OTG1 interrupt is known
    // statically. We'll call isr() inside of that interrupt.
    // attachInterruptVector(IRQ_USB1, &isr);
    // NVIC_ENABLE_IRQ(IRQ_USB1);

Rust code will be responsible for enabling the interrupt.

I think this is the stuff cortex_m::peripheral::NVIC::unmask does together with the proc macro for cortex_m_rt::interrupt (I assume the proc macro overwrites the empty handler).

We have no dynamic ISR registration, so the USB_OTG1 interrupt is known statically. We'll call isr() inside of that interrupt.

This confuses me a bit, the proc macro seems to be doing some kind of dynamic registration. I also think isr is called poll in the binding, but unsure.


The above aside, this thread I believe tells me how to set up an GPIO interrupt in C https://forum.pjrc.com/threads/58432-Nanosecond-Resolution-Interrupts-on-Teensy-4-0

I think it boils down to:

#define IRQ_PIN 0

void setup() {
    pinMode(IRQ_PIN, INPUT);
    CCM_CCGR1 |= CCM_CCGR1_GPIO1(CCM_CCGR_ON);
    attachInterruptVector(IRQ_GPIO1_0_15, &pin_isr);
    NVIC_ENABLE_IRQ(IRQ_GPIO1_0_15);
    GPIO1_ICR1 = 0x00; // set to 0
    GPIO1_GDIR &= ~0x08;  // Make sure set as input in GPIO1
    GPIO1_EDGE_SEL = 0x08; // set to 0
    GPIO1_ISR = 0xffff;
    GPIO1_IMR = 0x08;
}

void pin_isr(void) {
}

Next up is to investigate how much of the above code is covered by cortex-m, cortex-m-rt, imxrt-ral.

mciantyre commented 3 years ago

Welcome! And sorry for the trouble. One issue I see is that the imxrt-hal doesn't have an easy way to enable interrupts on GPIO inputs. Let's track that feature in imxrt-rs/imxrt-hal#109. Once that's implemented, I can add an example here.

Knowing which interrupt to register for a specific GPIO input requires some knowledge of the processor. Generally, there's one ISR for every 16 GPIOs (on 1060 MCUs). The interrupt names resemble something like GPIO4_Combined_16_31. We'll cover the GPIO input to vector dispatch within imxrt-hal documentation.

If you'd like to take the lead on imxrt-rs/imxrt-hal#109, I'm happy to mentor. Otherwise, I can probably get to it within the next few weeks.