Strange behavior on EXTINT ASF Driver for SAM D

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello, 
i've encounterd a realy strange behavior when using the EXTINT ASF Driver for SAM D20. 
Below a short Code example running on a SAMD20 XplainedPro: 

struct usart_module usart;

void extint_handler1(void) { printf("1"); }
void extint_handler2(void) { printf("2"); }

int main (void)
{
	system_init();
	struct usart_config cfg_usart;
	usart_get_config_defaults(&cfg_usart);
	cfg_usart.baudrate = 9600;
	cfg_usart.mux_setting = EDBG_CDC_SERCOM_MUX_SETTING;
	cfg_usart.pinmux_pad0 = EDBG_CDC_SERCOM_PINMUX_PAD0;
	cfg_usart.pinmux_pad1 = EDBG_CDC_SERCOM_PINMUX_PAD1;
	cfg_usart.pinmux_pad2 = EDBG_CDC_SERCOM_PINMUX_PAD2;
	cfg_usart.pinmux_pad3 = EDBG_CDC_SERCOM_PINMUX_PAD3;
	stdio_serial_init(&usart, EDBG_CDC_MODULE, &cfg_usart);
	usart_enable(&usart);
	printf("Ready.");

	struct extint_chan_conf cfg1, cfg2;
	extint_chan_get_config_defaults(&cfg1);
	cfg1.gpio_pin = PIN_PA10;
	cfg1.gpio_pin_mux = PINMUX_PA10A_EIC_EXTINT10;
	extint_chan_set_config(10, &cfg1);
	extint_register_callback(extint_handler1, 10, EXTINT_CALLBACK_TYPE_DETECT);
	extint_chan_enable_callback(10, EXTINT_CALLBACK_TYPE_DETECT);

	// Setup PIN_PA20 but don't enable the Callback yet
	extint_chan_get_config_defaults(&cfg2);
	cfg2.gpio_pin = PIN_PA20;
	cfg2.gpio_pin_mux = PINMUX_PA20A_EIC_EXTINT4;
	extint_chan_set_config(4, &cfg2);
	extint_register_callback(extint_handler2, 4, EXTINT_CALLBACK_TYPE_DETECT);
	extint_chan_disable_callback(4, EXTINT_CALLBACK_TYPE_DETECT); // Explicitly Disable Callback
	while (1)
	{
	}
}	

Test Procedure:

1. Pull down PA10 - a Interrupt occurs and extint_handler1 is invoked (as expected)
2. Pull down PA20 - doesn't no interrupt occurs and the extint_handler2 is NOT invoked (expected also)
3. Pull down PA10 again - a Interrupt occurs, extint_handler1 and extint_handler2 are executed in sequence (NOT EXPECTED!!!)

 

From my understanding the INTFLAG Register of the EIC Module gets updated with detected events as soon as the channel is configured.
The INTENCLR / INTENSET Registers for the EIC controls only the Interrupt generation to the NVIC. 

 

After a look into the AFS Sources for the EXTINT / EIC iv'e seen that there's no check for a specific EIC Channel if the interrupt is enabled or not. 
If the NVIC fires the EIC_Handler, all callbacks for EIC Channels that has a 1 in the INTFLAG register get executed, regardless if the callbacks enabled or not. 

 

Does anybody noticed that before?

 

I can't belive that it should behave like this.

 

 

Olli

 

P.S.: And Yes, I know it's not the best idea to do printf's in an Interrupt handler. Just for Testing wink

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Exactly the same issue.

Did you find a solution?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

oliver.keck wrote:
running on a SAMD20 XplainedPro

So you have a debugger - use it to step through the code and see whether the hypothesis is correct ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have the very same issue and can confirm that this is indeed the case. using EXTINT6, EXTINT8, both level-triggered. Even though EXTINT8 is disabled (also visible in the debugger) the callback for EXTINT8 is called when EXTINT6 caused the interrupt. sure i could unregister each time but that can't be the solution here ..?

 

Notice: EXTINT8 is present but since INT_SET/CLR is disabled I would expect that the callback function is not called. In the ATMEL code INT_SET/CLR is never checked, only the INTFLAG - which in my case is 'Enabled'. The EIC Handler, however, was fired due to EXTINT6 ...

 

Any fixes available?

Last Edited: Sat. May 19, 2018 - 08:38 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi, 

the following Workaround does work for me. I've added some code (orange) to the EIC_Handler from ASF to check if that Particular Interrupt is enabled before firering the Callback-Handler. 

The biggest Pitfall on that solution is, that you must keep that in mind on an update of the ASF and do that change in your Code again or you get the issue back. 

Another issue can be, that it takes slightly more time till the Interrupt handlers fires.

 

As an alternativ, you can check the INTEN flag directly in your Callback-Handler. 

 

 

    File: src/ASF/sam0/drivers/extint/extint_callback.c

void EIC_Handler(void)
{
    /* Find any triggered channels, run associated callback handlers */
    for (_current_channel = 0; _current_channel < EIC_NUMBER_OF_INTERRUPTS ; _current_channel++) {
        if (extint_chan_is_detected(_current_channel)) {
            /* Clear flag */
            extint_chan_clear_detected(_current_channel);
            /* Get EIC */
            Eic *const eic = _extint_get_eic_from_channel(_current_channel);						
            /* Check if Interrupt is enabled for _current_channel */
            if( (eic->INTENSET.reg & (1UL << _current_channel)) != 0 )
            {
                /* Find any associated callback entries in the callback table */			
                if (_extint_dev.callbacks[_current_channel] != NULL) {
                    /* Run the registered callback */
                    _extint_dev.callbacks[_current_channel]();
                }
            }
        }
    }
}

 

NOTE: I did my tests and the Workaround with ASF Version 3.35.1, in newer Versions the EIC_Handler code may be different. 

 

 

Hope that Helps and Regards,

Olli