ATtiny1616 refuses to jump to AC2 vector

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

I'm baffled by this one!

** please note I have simplified the code, kindly don't offer to change the approach it's done this way for a reason not shown here **

I have the RTC PTC with interrupt running (sei() is called), and AC2 also with interrupt running. I can trigger the AC2 change with a hardware wire.

All LED outputs which I'm using for visual checks are tested and working.
 
First I have a few shortcuts for the comparator....
 

#define HW_CMP_STATE(CMP) CMP.STATUS & AC_STATE_bm
#define HW_CMP_INT_RESET(CMP) CMP.STATUS |= AC_CMP_bm
#define HW_CMP_INT_ENABLE(CMP) HW_CMP_INT_RESET(CMP); CMP.INTCTRL |= AC_CMP_bm;
#define HW_CMP_INT_DISABLE(CMP) CMP.INTCTRL &= ~AC_CMP_bm; HW_CMP_INT_RESET(CMP)
#define HW_CMP_INT_STATUS(CMP) CMP.STATUS & AC_CMP_bm

And the interrupt handler which sets a flag then disables the interrupt.
 

ISR(AC2_AC_vect) {

    motionDetected = 1;
    HW_PIN_SET_HIGH(STORAGE_PIN_HIGH_PORT, STORAGE_PIN_HIGH_NUM);
    HW_CMP_INT_DISABLE(AC2);
}

And the while loop. The RTC PTC handler is setting tasker.ops.tasks = 1 and it's being cleared later. For brevity I didn't include that code but wanted to leave it in to state that interrupts are enabled and working for RTC PTC.

HW_CMP_INT_ENABLE(AC2);

while(1) {

    if (tasker.ops.tasks) {
        tasker.ops.tasks = 0;

        if (HW_CMP_INT_STATUS(AC2)) {
            HW_PIN_SET_HIGH(STORAGE_PIN_MEDIUM_PORT, STORAGE_PIN_MEDIUM_NUM);
        }

        if (motionDetected) {
            HW_PIN_SET_HIGH(USB_LED_PIN_PORT, USB_LED_PIN_NUM);
        }
    }
}

So, what happens is it runs and no LED's light up. I then do the hardware level change and STORAGE_PIN_MEDIUM_PORT lights up when the RTC PTC next triggers. This means the AC2 interrupt is working and has set the STATUS flag. 
 

However there's no jump to AC2 (vector 19). The STORAGE_PIN_HIGH_PORT doesn't light up. Neither is motionDetected set, so USB_LED_PIN_PORT doesn't light up either.
 

Bewildering!

Last Edited: Mon. Jul 4, 2022 - 10:56 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I can't see sei() anywhere (global interrupt enable), but it might be hidden behind those macros (or you forgot to post it here)...

Computers don't make errors - What they do they do on purpose.

Last Edited: Mon. Jul 4, 2022 - 11:06 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry I removed all code I considered 'out of focus' but to confirm sei() is called before the first statement, and the RTC PTC interrupt is firing and being handled. 

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

You haven't shown "motionDetected" but if it's set in the ISR and read in the main() line code it MUST be "volatile" for all the usual reasons.

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

Volatile it already is. ;)

Though with it being only a single instruction read in the main() I'm not entirely sure that it's mandatory in this case.

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

Without volatile it might reduce quite literally to a single read prior to the loop, or no read at all if motionDetected is static.

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

snoopy33 wrote:

Volatile it already is. ;)

Though with it being only a single instruction read in the main() I'm not entirely sure that it's mandatory in this case.

it is still necessary. Without volatile it could just make one read outside the loop and keep using that on the basis that it cannot see how the value can change inside the loop. 

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

I suppose you should provide minimal reproducible example that shows that issue. Otherwise we'll keep shooting into the dark

Computers don't make errors - What they do they do on purpose.

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

I knew it had to be something stupid, and it was.

PIT interrupt not clearing (I was clearing RTC). Expected that would lead to a continuous jump to the interrupt but instead it just locked other interrupts up and PIT interrupt continued working fine. Odd! 

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

Odd!

After a reti (isr return) one instruction is executed before any more interrupts are handled. Although slowly, the code outside the pit interrupt is still being run. Your pit interrupt continues to fire after one instruction is executed after its return, and although the ac flag may be set the pit irq has priority (these avr's have options when it comes to interrupt priority).

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

That exactly describes the behaviour. I didn't know it would execute one instruction.

And now on to the next problem!... :)

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

HW_CMP_INT_RESET() should just set the desires interrupt flag bit, not OR-EQUAL it. You clear all pending AC interrupts that way.

 

 

edit:

 

Non-issue in this case since there's only a single interrupt, but something to be aware of with other peripheral.

Last Edited: Mon. Jul 4, 2022 - 05:39 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

snoopy33 wrote:

That exactly describes the behaviour. I didn't know it would execute one instruction.

And now on to the next problem!... :)

Curious, as AVR models since the 1997 databook have had a chapter on "Reset and Interrupt Handling".  I'd think that the information would be carried forward to new series such as the "1-Series".

 

Hmmm--there is a chapter " CPUINT - CPU Interrupt Controller ".  And

13.2 Overview
An interrupt request signals a change of state inside a peripheral and can be used to alter the program execution.
The peripherals can have one or more interrupts. All interrupts are individually enabled and configured. When an
interrupt is enabled and configured, it will generate an interrupt request when the interrupt condition occurs.
The CPU Interrupt Controller (CPUINT) handles and prioritizes the interrupt requests. When an interrupt is enabled
and the interrupt condition occurs, the CPUINT will receive the interrupt request. Based on the interrupt's priority level
and the priority level of any ongoing interrupt, the interrupt request is either acknowledged or kept pending until it has
priority. After returning from the interrupt handler, the program execution continues from where it was before the
interrupt occurred, and any pending interrupts are served after one instruction is executed.

But indeed, 600 pages divided into 40 named chapters is a great burden.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.