Skip to content
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

EIC accepts any pin, even if it's not the correct EXTINT pad #781

Open
supersimple33 opened this issue Nov 11, 2024 · 5 comments
Open

EIC accepts any pin, even if it's not the correct EXTINT pad #781

supersimple33 opened this issue Nov 11, 2024 · 5 comments
Labels
bug Something isn't working

Comments

@supersimple33
Copy link
Contributor

I have been trying to implement a external interrupt controller on the grand_central_m4. I believe the following code is correct based on what I saw in a few examples on here however the led does not turn on when pressing the connected switch.

//! Uses an external interrupt to blink an LED.
//!
//! You need to connect a button between D46 and ground. Each time the button
//! is pressed, the LED will count the total number of button presses so far.
#![no_std]
#![no_main]

use cortex_m::interrupt::free;
use cortex_m::interrupt::Mutex;
use grand_central_m4::hal::eic;
use grand_central_m4::hal::eic::pin::ExternalInterrupt;
use grand_central_m4::pin_alias;
#[cfg(not(feature = "use_semihosting"))]
use panic_halt as _;
#[cfg(feature = "use_semihosting")]
use panic_semihosting as _;

use bsp::hal;
use bsp::pac;
use grand_central_m4 as bsp;

use bsp::entry;
use hal::clock::GenericClockController;
use hal::delay::Delay;
use hal::eic::pin::{ExtInt3, Sense};
use hal::gpio::{Pin, PullUpInterrupt};
use hal::prelude::*;
use pac::{interrupt, CorePeripherals, Peripherals};

use core::cell::RefCell;
use core::sync::atomic::{AtomicUsize, Ordering};

use cortex_m::peripheral::NVIC;

static RED_LED: Mutex<RefCell<Option<bsp::RedLed>>> = Mutex::new(RefCell::new(None));

fn toggle_led() {
    free(|cs| {
        RED_LED.borrow(cs).borrow_mut().as_mut().map(|l| l.toggle());
    });
}

#[entry]
fn main() -> ! {
    let mut peripherals = Peripherals::take().unwrap();
    let mut core = CorePeripherals::take().unwrap();
    let mut clocks = GenericClockController::with_internal_32kosc(
        peripherals.GCLK,
        &mut peripherals.MCLK,
        &mut peripherals.OSC32KCTRL,
        &mut peripherals.OSCCTRL,
        &mut peripherals.NVMCTRL,
    );
    let pins = bsp::Pins::new(peripherals.PORT);
    free(|cs| {
        RED_LED
            .borrow(cs)
            .replace(Some(pin_alias!(pins.red_led).into()))
    });

    let mut delay = Delay::new(core.SYST, &mut clocks);

    let gclk1 = clocks.gclk1();
    let eic_clock = clocks.eic(&gclk1).unwrap();
    let mut eic = eic::init_with_ulp32k(&mut peripherals.MCLK, eic_clock, peripherals.EIC);
    let button: Pin<_, PullUpInterrupt> = pins.d46.into();
    eic.button_debounce_pins(&[button.id()]);
    let mut extint_button = ExtInt3::new(button);
    extint_button.sense(&mut eic, Sense::BOTH);
    extint_button.enable_interrupt(&mut eic);
    let config_eic = eic.finalize();

    // Enable EIC interrupt in the NVIC

    free(|_| unsafe {
        core.NVIC.set_priority(interrupt::EIC_EXTINT_3, 1);
        NVIC::unmask(interrupt::EIC_EXTINT_3);
    });

    // Blink the LED once to show that we have started up.

    toggle_led();
    delay.delay_ms(200u8);
    toggle_led();
    delay.delay_ms(200u8);

    loop {
        delay.delay_ms(200u8);
        // toggle_led();
        for _ in 0..0xffff {
            cortex_m::asm::nop();
        }
    }
}

#[interrupt]
fn EIC_EXTINT_3() {
    // Increase the counter and clear the interrupt.
    toggle_led();
    unsafe {
        // Accessing registers from interrupts context is safe
        let eic = &*pac::EIC::ptr();
        let set_flags = eic.intflag.read().extint().bits();
        eic.intflag
            .modify(|_, w| w.extint().bits(0b1111111111110111 & set_flags));
    }
}

@sajattack
Copy link
Member

GCLK1 is the 32KHz osciallator. You probably want gclk0.

@supersimple33
Copy link
Contributor Author

@sajattack Ohh yeah I forgot that. But after switching to GCLK0 the code still does not work.

@jbeaurivage
Copy link
Contributor

@supersimple33, according to the datasheet, looks like you should be using the EXTINT[6] line for the PC06 (d46) pin.
Can you try modifying your code to see if that works?

From a quick glance at the eic module, it looks like an ExtInt* will accept any pin without emitting a compile error, not just the pins that belong to its interrupt line. This is clearly a bug with the HAL and I think it should be addressed.

@supersimple33
Copy link
Contributor Author

@jbeaurivage Yeah that was totally it I forgot to double check the interrupts lines. You relieved so much pain, thank you!

@jbeaurivage
Copy link
Contributor

No problem! I'll keep this open, because the eic module needs some work to avoid this kind of mistake happening in the future.

@jbeaurivage jbeaurivage reopened this Nov 14, 2024
@jbeaurivage jbeaurivage changed the title EIC Not Working on grand_central_m4 EIC accepts any pin, even if it's not the correct EXTINT pad Nov 14, 2024
@jbeaurivage jbeaurivage added the bug Something isn't working label Nov 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants