• AVR Freaks

Helpful ReplyHot!How to disable all interrupts in pic32

Author
hisoka
Starting Member
  • Total Posts : 44
  • Reward points : 0
  • Joined: 2015/11/30 04:49:14
  • Location: 0
  • Status: offline
2016/04/11 02:29:33 (permalink)
0

How to disable all interrupts in pic32

Hello,
Is there a function to disable all interrupts and then re-enable them instead of disable one a time ?
#1
Totem
Super Member
  • Total Posts : 266
  • Reward points : 0
  • Joined: 2014/12/04 02:18:11
  • Location: Mars
  • Status: offline
Re: How to disable all interrupts in pic32 2016/04/11 02:42:17 (permalink)
3.67 (3)
INTDisableInterrupts()
INTEnableInterrupts()
with MLA library installed on xc32.
 
SYS_INT_Disable()
SYS_INT_Enable()
with MPLAB Harmony.
#2
MatthewM
Super Member
  • Total Posts : 204
  • Reward points : 0
  • Joined: 2014/08/08 03:49:49
  • Location: UK
  • Status: offline
Re: How to disable all interrupts in pic32 2016/04/11 02:45:29 (permalink)
4 (1)
DS61108G is the reference manual for PIC32s.
 
They list in an example (8-1, 8-2, 8-3) to disable interrupts:

 
asm volatile(“di”); // Disable all interrupts
asm volatile(“ehb”); // Disable all interrupt
 

 
Alternatively you can 
 

<edit> Removed string.
post edited by MatthewM - 2016/04/11 03:46:37
#3
Mysil
Super Member
  • Total Posts : 3670
  • Reward points : 0
  • Joined: 2012/07/01 04:19:50
  • Location: Norway
  • Status: offline
Re: How to disable all interrupts in pic32 2016/04/11 03:44:15 (permalink)
4.33 (3)
Hi,
The most direct way to disable and enable interrupts are:
    asm volatile ("di");                /* Disable interrupts. */
    asm volatile ("ei");                /* Enable interrupts. */

These are assembler instructions written as inline assembly in C.
They manipulate the general interrupt enable flag in
the system control coprocessor CP0 in the MIPS core.
The register containing this bit is named: 'Status' and may be watched in the debugger as a SFR register.
See PIC32 Family Reference Manual section 2:
http://ww1.microchip.com/downloads/en/DeviceDoc/61113E.pdf
As far as I know, these interrupt disable and enable instructions are the same for MZ.
There are other differences described is another document for PIC32MZ.
 
If you disable and enable interrupts in general code with nested subroutines,
it is recommended to read the current state of the interrupt flag before changing it,
and restore it to what it was before:
    unsigned int status = 0;

    asm volatile("di    %0" : "=r"(status));        /* This will get the current setting, and then disable interrupts */
/* Critical section of code  ... */
    if (status)
        asm volatile("ei    %0" : "=r"(status));    /* Enable interrupts if enabled before. */



There also exists built in functions in XC32 compiler to handle these operations:
    unsigned int saved_state;

/*    Save current Interrupt Enable state and Disable Interrupts. */
    saved_state = __builtin_get_isr_state();
    __builtin_disable_interrupts();


/*  Other code ... */
    __builtin_set_isr_state(saved_state);    /* Set back to what was before. */

See XC32 Compiler User's Guide.
 
Then in libraries like Harmony or Plib, there exists wrappers for these operations.
 
Regards,
   Mysil
#4
hisoka
Starting Member
  • Total Posts : 44
  • Reward points : 0
  • Joined: 2015/11/30 04:49:14
  • Location: 0
  • Status: offline
Re: How to disable all interrupts in pic32 2016/04/11 04:42:56 (permalink)
0
thanks every one.
Another question I have  disabling interrupts does not mean clearing interrupts flags , correct ?
I mean if an interrupt happen after disabling the interrupts, the uC will jump to the ISR after re-enable the interrupts ? correct ?
I hope I was clear.
 
#5
andersm
Super Member
  • Total Posts : 2800
  • Reward points : 0
  • Joined: 2012/10/07 14:57:44
  • Location: 0
  • Status: offline
Re: How to disable all interrupts in pic32 2016/04/11 05:16:14 (permalink)
3 (1)
Mysil
    if (status)
        asm volatile("ei    %0" : "=r"(status));    /* Enable interrupts if enabled before. */ [/code]

This is not correct, because the status value returned by "di" can have other, unrelated bits set. The right way is to restore the previous value of the status register with an mtc0 instruction.
 
hisokaAnother question I have  disabling interrupts does not mean clearing interrupts flags , correct ?
I mean if an interrupt happen after disabling the interrupts, the uC will jump to the ISR after re-enable the interrupts ? correct ?

Yes, that is right.
#6
Mysil
Super Member
  • Total Posts : 3670
  • Reward points : 0
  • Joined: 2012/07/01 04:19:50
  • Location: Norway
  • Status: offline
Re: How to disable all interrupts in pic32 2016/04/11 08:11:35 (permalink) ☄ Helpfulby Maddy_me 2018/10/22 15:38:03
4 (3)
andersm is right,
"di" instruction return the entire contents of Status register,
so test will need mask to test value of IE bit.
Bit and field definitions for coprocessor 0 is available in <cp0defs.h>
#include <cp0defs.h>
   unsigned int status = 0;

    asm volatile("di    %0" : "=r"(status));        /* This will get the current setting, and then disable interrupts */
    asm volatile("ehb");                            /* Execution Hazard Barrier instruction, to make sure previous instruction take effect before proceeding. */
/* Critical section of code  ... */
    if (status & _CP0_STATUS_IE_MASK)               /* Test if Interrupt Enable was set. */
        asm volatile("ei    %0" : "=r"(status));    /* Enable interrupts if enabled before. */

Also "ehb" instruction inserted, inspiration from MatthewM in message #3.
 
   Mysil
#7
gaiuscosades
New Member
  • Total Posts : 14
  • Reward points : 0
  • Joined: 2019/02/06 02:42:05
  • Location: Austria
  • Status: offline
Re: How to disable all interrupts in pic32 2019/04/21 09:45:43 (permalink)
0
Mysil
andersm is right,
"di" instruction return the entire contents of Status register,
so test will need mask to test value of IE bit.
Bit and field definitions for coprocessor 0 is available in <cp0defs.h>
#include <cp0defs.h>
 
   unsigned int status = 0;

    asm volatile("di    %0" : "=r"(status));        /* This will get the current setting, and then disable interrupts */
 
    asm volatile("ehb");                            /* Execution Hazard Barrier instruction, to make sure previous instruction take effect before proceeding. */
/* Critical section of code  ... */
 
    if (status & _CP0_STATUS_IE_MASK)               /* Test if Interrupt Enable was set. */
 
        asm volatile("ei    %0" : "=r"(status));    /* Enable interrupts if enabled before. */

Also "ehb" instruction inserted, inspiration from MatthewM in message #3.
 
   Mysil




Thanks for this post!
 
But isn't the status load in the line after the if statement useless? As I see it the ei instruction also loads the status register and sets the Interrupt Enable afterwards, but with the status register unused afterwards this seems kind of redundant, or am I misunderstanding something?
#8
andersm
Super Member
  • Total Posts : 2800
  • Reward points : 0
  • Joined: 2012/10/07 14:57:44
  • Location: 0
  • Status: offline
Re: How to disable all interrupts in pic32 2019/04/21 10:32:25 (permalink)
0
gaiuscosadesAs I see it the ei instruction also loads the status register and sets the Interrupt Enable afterwards, but with the status register unused afterwards this seems kind of redundant, or am I misunderstanding something?

I think you mean the status variable? If you're not interested in the previous value of the status register, then yes, you can omit the register argument of the ei instruction (which is the same as specifying $r0 as the argument).
#9
gaiuscosades
New Member
  • Total Posts : 14
  • Reward points : 0
  • Joined: 2019/02/06 02:42:05
  • Location: Austria
  • Status: offline
Re: How to disable all interrupts in pic32 2019/04/21 10:40:49 (permalink)
0
andersm
gaiuscosadesAs I see it the ei instruction also loads the status register and sets the Interrupt Enable afterwards, but with the status register unused afterwards this seems kind of redundant, or am I misunderstanding something?

I think you mean the status variable? If you're not interested in the previous value of the status register, then yes, you can omit the register argument of the ei instruction (which is the same as specifying $r0 as the argument).



Ok. but in what case should I care for the status variable after the if? The status should not be modified in the critical section anyway...
I am just trying to understand in which case, getting the status inside the if clause could be usefull, for the further program?
Thanks.
#10
andersm
Super Member
  • Total Posts : 2800
  • Reward points : 0
  • Joined: 2012/10/07 14:57:44
  • Location: 0
  • Status: offline
Re: How to disable all interrupts in pic32 2019/04/22 07:27:59 (permalink)
0
You can try locating the instruction set designers, and ask them what use cases they had in mind. I half suspect it's just to provide symmetry with the di instruction.
#11
gaiuscosades
New Member
  • Total Posts : 14
  • Reward points : 0
  • Joined: 2019/02/06 02:42:05
  • Location: Austria
  • Status: offline
Re: How to disable all interrupts in pic32 2019/04/22 07:58:01 (permalink)
0
With that I am pretty sure you are right, because so they can reuse the same opcode decoding logic for both and just insert the one bit that is different for the "ei" and "di" instruction opcodes into the new value of the status register.
 
But my question was only if you had a specific reason to write *asm volatile("ei    %0" : "=r"(status));* instead of *asm volatile("ei");* and that I did understand something wrong about the code put forward. But, so it seems, it was just convinience and symmetry also, which is of course also perfectly fine!
Thanks for the clarification.
#12
boatbodger
Junior Member
  • Total Posts : 108
  • Reward points : 0
  • Joined: 2011/03/27 15:39:07
  • Location: 0
  • Status: offline
Re: How to disable all interrupts in pic32 2020/02/07 06:05:50 (permalink)
0
If I use status = __builtin_disable_interrupts(); the documentation implies that  calling __builtin_set_isr_state(status) should restore the situation to how it was before the first call.
However, in my experience, interrupts do not get re-enabled if this sequence is used.
Even if I follow ...set_isr_status(status) with ...enable_interrupts(), the interrupt controller appears to end up stuffed.
By contrast, if I simply use __builtin_disable_interrupts(), do my thing, then __builtin_enable_interrupts() normal operation appears to continue.
Unfortunately, the XC32 Compiler User Guide is pretty hazy on the subject.
 
Can anyone else throw further light on how they are supposed to be used?
 
With thanks,
Chris
#13
boatbodger
Junior Member
  • Total Posts : 108
  • Reward points : 0
  • Joined: 2011/03/27 15:39:07
  • Location: 0
  • Status: offline
Re: How to disable all interrupts in pic32 2020/02/07 06:21:07 (permalink)
0
By the way, I have just discovered that Harmony provides two functions
bool SYS_INT_Disable(void);
void SYS_INT_Restore(bool);
Which do in fact appear to work.
The only flag which seems to be needed to carry through the critical bit is whether or not global interrupts were disabled.
This leaves me very unclear about what get_isr_status and set_isr_status are useful for.
#14
andersm
Super Member
  • Total Posts : 2800
  • Reward points : 0
  • Joined: 2012/10/07 14:57:44
  • Location: 0
  • Status: offline
Re: How to disable all interrupts in pic32 2020/02/07 09:25:18 (permalink) ☄ Helpfulby boatbodger 2020/02/07 10:06:31
0
__builtin_set_isr_state() is used to restore the value returned by __builtin_get_isr_state(). There is no direct counterpart to the __builtin_disable_interrupts() function, but you can use the _mtc0() to restore the returned value to the Status register:
unsigned long status = __builtin_disable_interrupts();
_mtc0(12, 0, status);

The __builtin_disable_interrupts() function is just an intrinsic for the "di" assembler instruction, but the corresponding "ei" instruction unconditionally enables interrupts, which is why you must use an "mtc0" instruction to restore the old value.
 
As explained in the documentation, __builtin_get_isr_state() returns both the current priority level and enable bit, while the others just return the enable bit.
#15
boatbodger
Junior Member
  • Total Posts : 108
  • Reward points : 0
  • Joined: 2011/03/27 15:39:07
  • Location: 0
  • Status: offline
Re: How to disable all interrupts in pic32 2020/02/07 10:15:00 (permalink)
0
That's helpful - thank you.
Which documentation should I be looking at? I did not manage to find the detail you described in the XC32 compiler user guide (v2.30).  Where did you find this information?.
Thanks in advance.
#16
andersm
Super Member
  • Total Posts : 2800
  • Reward points : 0
  • Joined: 2012/10/07 14:57:44
  • Location: 0
  • Status: offline
Re: How to disable all interrupts in pic32 2020/02/07 10:27:21 (permalink)
0
Appendix D, "Built-In Functions".
#17
boatbodger
Junior Member
  • Total Posts : 108
  • Reward points : 0
  • Joined: 2011/03/27 15:39:07
  • Location: 0
  • Status: offline
Re: How to disable all interrupts in pic32 2020/02/07 10:35:26 (permalink)
0
Hmmmm  That's what I've been reading, but i now realise that the document is a bit odd, in that whilst there is a description in that appendix for get_isr_state and set_isr_state, no such descriptions are provided for disable_interrupts and enable_interrupts.  Anyway, thanks so much for making it clear.  Much appreciated.
#18
Jump to:
© 2020 APG vNext Commercial Version 4.5