Author Topic: Atmel ATSAMC21 interrupt callback flag not cleared  (Read 2018 times)

0 Members and 1 Guest are viewing this topic.

Offline urosgTopic starter

  • Supporter
  • ****
  • Posts: 14
  • Country: si
Atmel ATSAMC21 interrupt callback flag not cleared
« on: May 17, 2021, 11:24:03 am »
Hi,

I am fairly new to the ATSAM Cortex-M family and have started a new project with Atmel Start where I configured all the needed pins etc. and also set four input pins to have interrupts when a low signal is detected.

So far all good, project compiles, starts and the interrupt callback is called when I press the button (signal to low)

BUT the problem is that the last interrupt callback is then constantly called.

I created a global "count" array for that I increment each time the callback is called, and the counter increases for the last interrupt callback that was called.

What am I doing wrong? Reading ASF4 documentation I do not see any reference that a callback should be "closed" with any specific call to function (i.e. clearing interrupt flag manually).

Any help/reference towards possible solution would be greatly appreciated.

 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11248
  • Country: us
    • Personal site
Re: Atmel ATSAMC21 interrupt callback flag not cleared
« Reply #1 on: May 17, 2021, 04:18:51 pm »
Did you configure it for a falling edge detection, or the low level? If later, then callback will be called for the duration of the button press.

You do need to acknowledge all interrupts. I have no idea if ASF does that for you, you will have to check that yourself.
Alex
 

Offline urosgTopic starter

  • Supporter
  • ****
  • Posts: 14
  • Country: si
Re: Atmel ATSAMC21 interrupt callback flag not cleared
« Reply #2 on: May 18, 2021, 07:28:26 am »
I configured as "low level" but the button is a normal SPDT switch (non-latching) and also the bit in EIC.INTFLAG is cleared, but the callback is still firing - since I am also running FreeRTOS it stops processing tasks as the MCU stays in interrupt routine.

I noticed that the INTFLAG is set to 0x81 and the interrupt routine checks only for the first 4 bits - i.e. when cleared INTFLAG remains at 0x80, which shows interrupt at position 7 as active, but looking through code I could not find anything that would enable this interrupt.

 

Offline MadScientist

  • Frequent Contributor
  • **
  • Posts: 439
  • Country: 00
Re: Atmel ATSAMC21 interrupt callback flag not cleared
« Reply #3 on: May 18, 2021, 07:41:01 am »
In the C21 you generally must clear the interrupt flags manually. If you do this too soon you can potentially Re trigger an interrupt when using the EIC
EE's: We use silicon to make things  smaller!
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11248
  • Country: us
    • Personal site
Re: Atmel ATSAMC21 interrupt callback flag not cleared
« Reply #4 on: May 18, 2021, 04:03:39 pm »
INTFLAG value should not be relevant for the interrupt firing. It is also masked by the value of INTENCLR/INTENSET. But looking at the code generated by start, it actually loops waiting for all flags to clear. And it will get confused by the extra bit set.

Can you share your whole project?
Alex
 

Offline urosgTopic starter

  • Supporter
  • ****
  • Posts: 14
  • Country: si
Re: Atmel ATSAMC21 interrupt callback flag not cleared
« Reply #5 on: May 20, 2021, 02:25:53 pm »
Yes, i modified the code a little bit to process only the defined interrupts and to break out of the routine.

Also "detected" PIN for interrupt is not cleared on next loop after a "pin" was found.

Modified routine in "hpl_eic.c":
Code: [Select]
/**
 * \brief Inter EIC interrupt handler
 */
static void _ext_irq_handler(void)
{
volatile uint32_t flags = hri_eic_read_INTFLAG_reg(EIC);
int8_t            pos;
int8_t            intcnt = EXT_IRQ_AMOUNT; /* max. loops - as interrupt map is filled from index 0 to EXT_IRQ_AMOUNT */

hri_eic_clear_INTFLAG_reg(EIC, flags);

ASSERT(callback);

while (flags && intcnt-- > 0) {
pos = ffs(flags) - 1;
while (-1 != pos) {
uint8_t lower = 0, middle, upper = EXT_IRQ_AMOUNT;
uint32_t pin = INVALID_PIN_NUMBER; /* set PIN to INVALID to force detection again */

while (upper >= lower) {
middle = (upper + lower) >> 1;
if (_map[middle].extint == pos) {
pin = _map[middle].pin;
break;
}
if (_map[middle].extint < pos) {
lower = middle + 1;
} else {
upper = middle - 1;
}
}

if (INVALID_PIN_NUMBER != pin) {
callback(pin);
break; /* stop processing this interrupt */
}

flags &= ~(1ul << pos);
pos = ffs(flags) - 1;
}
flags = hri_eic_read_INTFLAG_reg(EIC);
hri_eic_clear_INTFLAG_reg(EIC, flags);
}
}
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11248
  • Country: us
    • Personal site
Re: Atmel ATSAMC21 interrupt callback flag not cleared
« Reply #6 on: May 20, 2021, 06:13:24 pm »
This is not a complete project.

There should be no flags set that correspond to the unconfigured pins. So if some extra flags are set, you must be configuring them. You need to figure out why this happens instead of trying to apply workarounds.
Alex
 

Offline PlainName

  • Super Contributor
  • ***
  • Posts: 6838
  • Country: va
Re: Atmel ATSAMC21 interrupt callback flag not cleared
« Reply #7 on: May 20, 2021, 06:59:30 pm »
Nothing to do with the flag, sorry, but this caught my eye:

Code: [Select]
ASSERT(callback);
...
if (INVALID_PIN_NUMBER != pin) {
callback(pin);
break; /* stop processing this interrupt */
}

ASSERT() is generally there to force a crash on some unexpected situation during development, but you would normally disable them for production. If you do that here and callback is not defined, the ISR will crash. But if you leave the assert enabled, the ISR will crash anyway.

I think that it would be better to check for callback being defined before you call it regardless (i.e. if (callback) callback(pin);), which makes it safe. The assert can then be left in for development to tell you it's screwed, but disabling it won't cause an issue for production.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf