How do interrupts behave when they are disabled after firing?

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

I have read a short doc on interrupts and PMIC, but it didn't answer many of my questions. I am programming ATxMega 32e5 and I would like to know how exactly do interrupts behave. Let's say I have two interrupts enabled INT1 and INT2, both have the same priority (eg. medium priority - 0b10). Let's say INT1 fires and I enter ISR for INT1. While in INT1's ISR, INT2 fires and is queued to be executed. However at the end of INT1 I disable INT2 by setting the priority of INT2 to 0. What happens when I leave INT1? Is INT2 executed anyway (is there some kind of caching inside the MCU?) or not? If there is some kind of caching, how can I really disable INT2, or is that not possible?

 

Thanks

This topic has a solution.
Last Edited: Mon. Aug 10, 2020 - 08:13 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Atmel Studio 7 is powerful enough to simulate it.
Did you try it?

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

ISRs execute because the associated INTF is set. So each interrupt source has a "one deep buffer". If one event occurs while another is being serviced then when the CPU gets back from any current ISR it will execute 1 opcode then recheck the set of flags for any that are set. If on is found then it will vector to that handler.

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

I've no experience with the xmega, but there's usually two strategies that are employed:

 

1. at instruction fetch, evaluate the interrupt sources and priorities and decide whether to issue an interrupt

2. the interrupt sources and priorities are evaluated and a pending flag set.

 

I've had recent experience with the Arm Cortex M7 that does #2. It was necessary to specifically clear the required pending flag.

 

hopefully the xmega documentation tells you what strategy it uses. If it uses strategy #2, then there should be a means to clear pending bits, otherwise it is probably strategy #1.

 

There shouldn't be queueing - just flags and priorities. The one with the flag set and the highest priority gets serviced until all flags are cleared.

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

I tested with this code.
A rising edge interrupt is generated by setting the output port to H.

 

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/cpufunc.h>
int main(void){
    // PORT A
    PORTA.OUT = 0;
    PORTA.DIRSET = PIN2_bm | PIN1_bm;
    PORTA.PIN1CTRL = PORT_ISC_RISING_gc;
    PORTA.PIN2CTRL = PORT_ISC_RISING_gc;
    PORTA.INTMASK = PIN2_bm | PIN1_bm;
    PORTA.INTFLAGS = PIN2_bm | PIN1_bm;
    PORTA.INTCTRL = PORT_INTLVL_MED_gc;

    // PMIC
    PMIC.CTRL = PMIC_MEDLVLEX_bm;

    sei();
    while (1);
}
ISR(PORTA_INT_vect){
    _NOP();
    if (PORTA.INTFLAGS & PIN1_bm){
        // PIN1
        PORTA.INTFLAGS = PIN1_bm;
    } 
    else{
        // PIN2
        PORTA.INTFLAGS = PIN2_bm;
    }
}

 

The interrupt does not occur when you start the simulation.
Pause and set PIN1 and PIN2 to H.

It can be confirmed that if you continue this way, a break will occur in the order of _NOP, PIN1, _NOP, PIN2.

 

 

 

Try to set the interrupt priority to 0 when a break occurs at PIN1.

 

 

No interrupt by PIN2 is generated, and it can be confirmed that the interrupt request flag of PIN2 remains set after pausing.

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

I never used Atmel studio before but this looks really good. I use Linux, but I sometimes use Windows VM and wine, so I may give it a try.

Thanks, nice to know there is no such thing that caches interrupts.

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

deli.dado wrote:
but I sometimes use Windows VM and wine,
I think Microsoft made it so VS2015 (and hence AS7) deliberately won't work under wine.

 

If you want to experience Microchip's AVR simulator on Linux you'd be better off looking at the MPLABX alternative to  AS7