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

Samr30/gpio: Erasing then write mux can generate spurious IRQ #19993

Open
biboc opened this issue Oct 19, 2023 · 1 comment
Open

Samr30/gpio: Erasing then write mux can generate spurious IRQ #19993

biboc opened this issue Oct 19, 2023 · 1 comment
Assignees
Labels
Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors)

Comments

@biboc
Copy link
Member

biboc commented Oct 19, 2023

Description

Erasing then write mux can generate spurious IRQ from another gpio sharing same extint

Steps to reproduce the issue

Example with PA6 and PB22 which share extint[6]:

void irq(void)
{
    puts("IRQ");
}
int main(void)
{
    gpio_init_int(GPIO_PIN(PA,6), GPIO_IN, GPIO_RISING, (gpio_cb_t)irq, NULL);
    gpio_mux_t mux = GPIO_MUX_D;
    gpio_t pin = GPIO_PIN(PB,22);
    int pin_pos = _pin_pos(pin); // use _pin_pos from gpio.c
    PortGroup* port = _port(pin); // use _port from gpio.c
    while(1) {
        xtimer_usleep(500000);
        port->PMUX[pin_pos >> 1].reg &= ~(0xf << (4 * (pin_pos & 0x1)));
        port->PMUX[pin_pos >> 1].reg |=  (mux << (4 * (pin_pos & 0x1)));
    }
    return 0;
}

This code triggers some time (maybe 2sec, maybe 20sec) an IRQ on PA6!
I can confirm that the line PA6 stays to always 0 so there should not be any IRQ

I suggest to change https:/RIOT-OS/RIOT/blob/2023.10-branch/cpu/sam0_common/periph/gpio.c#L147

void gpio_init_mux(gpio_t pin, gpio_mux_t mux)
{
    PortGroup* port = _port(pin);
    int pin_pos = _pin_pos(pin);

    port->PINCFG[pin_pos].reg |= PORT_PINCFG_PMUXEN;
    port->PMUX[pin_pos >> 1].reg &= ~(0xf << (4 * (pin_pos & 0x1)));
    port->PMUX[pin_pos >> 1].reg |=  (mux << (4 * (pin_pos & 0x1)));
}

by

void gpio_init_mux(gpio_t pin, gpio_mux_t mux)
{
    PortGroup* port = _port(pin);
    int pin_pos = _pin_pos(pin);

    port->PINCFG[pin_pos].reg |= PORT_PINCFG_PMUXEN;
    if (pin_pos & 1) {
        port->PMUX[pin_pos >> 1].bit.PMUXO = mux;
    } else {
        port->PMUX[pin_pos >> 1].bit.PMUXE = mux;
    }
}

Expected results

Set the mux without trigger an interrupt

Actual results

Trigger non desired interrupt

Versions

RIOT 2023-07

@dylad
Copy link
Member

dylad commented Nov 3, 2023

Sorry for the long delay @biboc
Are you using SAMR30-XPRO or a custom board ?
Were you able to reproduce on another SAM0 MCUs ?

I tried to reproduce it on my SAMR21-XPRO and SAML21-XPRO (don't have SAMR30). I kinda reproduce it because my hand touch to EXT1 connector where the PA06 is located triggering unexpected IRQs. Setting a pull-down with the PA06 IRQ seems to fix it.

Otherwise I was not able to reproduce any spurious IRQ after flashing your code snippet (and nothing else) to these boards (and make sure I was far away this time...)

Does it help to disable the mux configuration for your pin before modifying it ? like:

    port->PINCFG[pin_pos].reg &= ~PORT_PINCFG_PMUXEN;
    port->PMUX[pin_pos >> 1].reg &= ~(0xf << (4 * (pin_pos & 0x1)));
    port->PMUX[pin_pos >> 1].reg |=  (mux << (4 * (pin_pos & 0x1)));
    port->PINCFG[pin_pos].reg |= PORT_PINCFG_PMUXEN;

@dylad dylad added the Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors) label Nov 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors)
Projects
None yet
Development

No branches or pull requests

3 participants