Author Topic: Momentarily disable interrupt routine  (Read 2646 times)

Offline Raffaele

  • Jr. Member
  • **
  • Posts: 65
    • View Profile
Momentarily disable interrupt routine
« on: May 17, 2020, 04:23:02 PM »
Hi,
is it possible to momentarily disable an interrupt? Or its handler?

I mean, I configure the interrupt

Code: [Select]
INTERRUPT_SETUP interrupt_setup;
interrupt_setup.int_type       = PORT_INTERRUPT;                    // identifier to configure port interrupt
interrupt_setup.int_handler    = fn_my_interrupt_handler;           // handling function
interrupt_setup.int_priority   = PRIORITY_PORT_B_INT;              // interrupt priority level
interrupt_setup.int_port       = PORTB;                  // the port that the interrupt input is on
interrupt_setup.int_port_bits  = INTERRUPT_PIN;           // the IRQ input connected
interrupt_setup.int_port_sense = (IRQ_RISING_EDGE | PULLUP_ON);  // interrupt is to be falling edge sensitive
fnConfigureInterrupt((void *)&interrupt_setup);

Then at some point I want to suspend handling the interrupt and then activate it again. Something like this:


Code: [Select]
suspend_interrupt();
function();
reactivate_interrupt();

Is it possible?

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: Momentarily disable interrupt routine
« Reply #1 on: May 17, 2020, 04:45:29 PM »
Hi

There are three ways to momentarily disable/re-enable interrupts.

1. Globally by using
uDisable_Interrupt();
..
uEnable_Interrupt();


2. By disabling only the port interrupt source:
fnMaskInterrupt(irq_PORTB_ID);
...
fnUnmaskInterrupt(irq_PORTB_ID);


3. By disabling only a single port interrupt source:
    _DIS_ARM_PORT_INTERRUPT(B, INTERRUPT_PIN);                                      // example of disabling the interrupt
...
    _RE_ARM_PORT_INTERRUPT(B, INTERRUPT_PIN, PORT_IRQC_RISING);                     // example of re-enabling or changing its sensitivity



It is possible that some of these are missing in the open source version at the moment so these are the sources/macros in case something is missing.

    // Macros for disabling port interrupt and re-arming (or changing sensitivity)
    //
    #define _DIS_ARM_PORT_INTERRUPT(port, bit)       PORT##port##_PCR##bit &= ~(PORT_IRQC_INT_MASK)
    #define _RE_ARM_PORT_INTERRUPT(port, bit, sense) PORT##port##_PCR##bit = ((PORT##port##_PCR##bit & ~(PORT_IRQC_INT_MASK)) | (sense))



extern void fnMaskInterrupt(int iInterruptID)
{
#if defined _WINDOWS                                                     // back up the present enabled interrupt registers
    IRQ0_31_CER = IRQ32_63_CER = IRQ64_95_CER = 0;                       // reset registers
#endif
    volatile unsigned long *ptrIntMask = IRQ0_31_CER_ADD;
    ptrIntMask += (iInterruptID/32);                                     // move to the clear enable register in which this interrupt is controlled
    *ptrIntMask = (0x01 << (iInterruptID % 32));                         // disable the interrupt
#if defined _WINDOWS
    IRQ0_31_SER  &= ~IRQ0_31_CER;                                        // synchronise the interrupt masks
    IRQ32_63_SER &= ~IRQ32_63_CER;
    IRQ64_95_SER &= ~IRQ64_95_CER;
    IRQ0_31_CER   = IRQ0_31_SER;
    IRQ32_63_CER  = IRQ32_63_SER;
    IRQ64_95_CER  = IRQ64_95_SER;
#endif
}

extern void fnUnmaskInterrupt(int iInterruptID)
{
#if defined _WINDOWS                                                     // back up the present enabled interrupt registers
    unsigned long ulState0 = IRQ0_31_SER;
    unsigned long ulState1 = IRQ32_63_SER;
    unsigned long ulState2 = IRQ64_95_SER;
    IRQ0_31_SER = IRQ32_63_SER = IRQ64_95_SER = IRQ0_31_CER = IRQ32_63_CER = IRQ64_95_CER = 0; // reset registers
#endif
    volatile unsigned long *ptrIntSet = IRQ0_31_SER_ADD;
    ptrIntSet += (iInterruptID / 32);                                    // move to the clear enable register in which this interrupt is controlled
    *ptrIntSet = (0x01 << (iInterruptID % 32));                          // enable the interrupt
#if defined _WINDOWS
    IRQ0_31_SER |= ulState0;                                             // synchronise the interrupt masks
    IRQ32_63_SER |= ulState1;
    IRQ64_95_SER |= ulState2;
    IRQ0_31_CER = IRQ0_31_SER;
    IRQ32_63_CER = IRQ32_63_SER;
    IRQ64_95_CER = IRQ64_95_SER;
#endif
}


Regards

Mark

Offline Raffaele

  • Jr. Member
  • **
  • Posts: 65
    • View Profile
Re: Momentarily disable interrupt routine
« Reply #2 on: May 29, 2020, 08:41:58 PM »
I had notifications off for this post.

Always very helpful Mark