• AVR Freaks

Helpful ReplyHot!Interrupt Controller

Author
ericmar
Super Member
  • Total Posts : 200
  • Reward points : 0
  • Joined: 2006/07/25 00:38:01
  • Location: Malaysia
  • Status: offline
2008/04/07 20:42:38 (permalink)
0

Interrupt Controller

Hi,

I am a little bit confuse about the Interrupt Controller in PIC24. I am now working on the PIC24HJ256GP210.

I had done some works on the PIC18F8722 before and back then, there are only high and low priority if not wrong. But now the PIC24 has so many priority levels.

I took a look on the code example of CE211 - External interrupt pins but still not very understand. I would appreciate if anyone can point me to a reference whereby I can refer to for a more comprehensive way of implementing the Interrupt control. A working example other than the external interrupt would be the best reference for me. Maybe implementing a hardware timer interrupt which generates interrupt every few milliseconds.

May I know how does the Interrupt Nesting Disable (NSTDIS) bit work? What does an Interrupt Nesting mean?

Thanks for any help in advance.

Regards,
Eric
#1
jtemples
عُضْوٌ جَدِيد
  • Total Posts : 11284
  • Reward points : 0
  • Joined: 2004/02/13 12:31:19
  • Location: Southern California
  • Status: offline
RE: Interrupt Controller 2008/04/07 21:15:59 (permalink)
0
Just as with the PIC18, you don't even need to worry about interrupt priorities and nesting unless you have a specific need. Just leave them all at their default settings. The major difference you need to be aware of is that each interrupt on the PIC24 has its own vector, and thus you don't need to test interrupt flags in the handler.
#2
zardoz1
Super Member
  • Total Posts : 1852
  • Reward points : 0
  • Joined: 2005/07/09 08:03:28
  • Location: 's-Hertogenbosch, The Netherlands
  • Status: offline
RE: Interrupt Controller 2008/04/07 23:08:30 (permalink) ☄ Helpfulby ReverseEMF 2019/09/08 11:22:21
5 (2)
Just as with the PIC18, you don't even need to worry about interrupt priorities and nesting unless you have a specific need. Just leave them all at their default settings.


Leaving the interrupt priorities at their default level will not work since the default value (after startup) is 0.
Some info.  I was wrong here, default value after startup is 4!!

First the interrupt mechanism of PIC24 and dsPIC30/33 is great. It is structured and very effective.

For every interrupt source there are three important settings:

First there is a three bit value specifying the interrupt priority (xxIP, where xx is the name of the interrupt source). This can contain a value from 0 to 7 where 0 is the lowest priority and 7 is the highest priority. An interrupt with a higher priority can preempt an active interrupt handler with a lower priority. Value 0 actually means the interrupt is disabled since the main program will run at value 0. The interrupt priority must be higher than the current value to be handled and 0 is not higher than 0. So the value for this three bit field (xxIP) should be 1..7.

Second there is an xxIE bit for every interrupt source. This is the interrupt enable flag. When 0, the interrupt effectivelly is disabled, when 1, the interrupt is enabled. Using this bit is the preferred way to enable/disable interrupts since the bit can be changed in an atomic instruction while the three bit xxIP field can not.

Third there is the xxIF flag. When the interrupt occurs, this bit is set by the hardware. It is essential to reset the bit in the interrupt routine otherwise when leaving the interrupt handler, the interrupt is still active and the interrupt handler will be entered again.. and again.. and again. Forgetting to reset this bit in the interrupt handler is one of the most frequent sources of errors. This bit can also be set from software, errectivelly resulting in a software interrupt.

Related to the priority there is a three bit field in the status register (IPL). The value of this field determines what interrupts can occur. When the software starts, the value of this field is 0 meaning priority 1..7 are enabled. When an interrupt occurs, the interrupt priority of that interrupt is set in this field in the status register (by the hardware), which effectivelly causes lower and equal priority interrupts to be blocked. Returning from the interrupt routine RETFIE will restore the status register and thus the interrupt priority existing before the interrupt routine was activated.
post edited by zardoz1 - 2008/04/07 23:42:52


AVIX
the PIC32 & dsPIC/PIC24 RTOS with:
- Zero Latency Interrupts
- The best performance!
- Integrated Power Management
Download here: http://www.avix-rt.com/
#3
houta69
Super Member
  • Total Posts : 275
  • Reward points : 0
  • Joined: 2007/08/04 09:33:43
  • Location: Georgia, USA
  • Status: offline
RE: Interrupt Controller 2008/04/07 23:28:26 (permalink)
5 (1)
Everything you say is true. You probably understand the architecture better than anyone else with the possible exception of the people who designed it.

Once an interrupt is enabled though, doesn't it default to priority level 4 (except for the CPU and trap interrupts)?  Could be wrong but I think this is what jtemples was getting at. Thanks
 
[EDIT] I just checked my manual and found the following in 8.1.5
 
Note: At a device Reset, the IPCn registers are initialized such that all user interrupt
sources are assigned to priority level 4.
post edited by houta69 - 2008/04/07 23:32:25

-Adam
#4
zardoz1
Super Member
  • Total Posts : 1852
  • Reward points : 0
  • Joined: 2005/07/09 08:03:28
  • Location: 's-Hertogenbosch, The Netherlands
  • Status: offline
RE: Interrupt Controller 2008/04/07 23:40:29 (permalink)
0
You are right about this, never noticed it (never to old to learn)
 
At POR, all interrupts are disabled because the IE bits reset to 0. Like in all examples, I always use the sequence of setting the IP value and next enabling the interrupt. Don't like default values but that's a different story.


AVIX
the PIC32 & dsPIC/PIC24 RTOS with:
- Zero Latency Interrupts
- The best performance!
- Integrated Power Management
Download here: http://www.avix-rt.com/
#5
ericmar
Super Member
  • Total Posts : 200
  • Reward points : 0
  • Joined: 2006/07/25 00:38:01
  • Location: Malaysia
  • Status: offline
RE: Interrupt Controller 2008/04/08 00:02:25 (permalink)
0
ORIGINAL: zardoz1

Just as with the PIC18, you don't even need to worry about interrupt priorities and nesting unless you have a specific need. Just leave them all at their default settings.


Leaving the interrupt priorities at their default level will not work since the default value (after startup) is 0.
Some info.  I was wrong here, default value after startup is 4!!

First the interrupt mechanism of PIC24 and dsPIC30/33 is great. It is structured and very effective.

For every interrupt source there are three important settings:

First there is a three bit value specifying the interrupt priority (xxIP, where xx is the name of the interrupt source). This can contain a value from 0 to 7 where 0 is the lowest priority and 7 is the highest priority. An interrupt with a higher priority can preempt an active interrupt handler with a lower priority. Value 0 actually means the interrupt is disabled since the main program will run at value 0. The interrupt priority must be higher than the current value to be handled and 0 is not higher than 0. So the value for this three bit field (xxIP) should be 1..7.

Second there is an xxIE bit for every interrupt source. This is the interrupt enable flag. When 0, the interrupt effectivelly is disabled, when 1, the interrupt is enabled. Using this bit is the preferred way to enable/disable interrupts since the bit can be changed in an atomic instruction while the three bit xxIP field can not.

Third there is the xxIF flag. When the interrupt occurs, this bit is set by the hardware. It is essential to reset the bit in the interrupt routine otherwise when leaving the interrupt handler, the interrupt is still active and the interrupt handler will be entered again.. and again.. and again. Forgetting to reset this bit in the interrupt handler is one of the most frequent sources of errors. This bit can also be set from software, errectivelly resulting in a software interrupt.

Related to the priority there is a three bit field in the status register (IPL). The value of this field determines what interrupts can occur. When the software starts, the value of this field is 0 meaning priority 1..7 are enabled. When an interrupt occurs, the interrupt priority of that interrupt is set in this field in the status register (by the hardware), which effectivelly causes lower and equal priority interrupts to be blocked. Returning from the interrupt routine RETFIE will restore the status register and thus the interrupt priority existing before the interrupt routine was activated.

Thanks for your explanation. Your info is not too lengthy but great for understanding.

Anyway, is it possible to post an example of setting up a simple interrupt with an interrupt service routine? I just need a template to start with.

Thanks.

Regards,
Eric
#6
ericmar
Super Member
  • Total Posts : 200
  • Reward points : 0
  • Joined: 2006/07/25 00:38:01
  • Location: Malaysia
  • Status: offline
RE: Interrupt Controller 2008/04/08 00:25:34 (permalink)
0
I just wrote some codes and it is working quite fine. Can anyone help me to take a look on my codes?

May I know if you guys usually put all the ISRs in one file, say ISR.c, or put each ISR separately (for e.g. ISR_UART in Uart.c, etc.).

Thanks.

Regards,
Eric


#include <P24HJ256GP210.h>

#define FCY      10000000
#define BAUDRATE 9600               
#define BRGVAL   ((FCY/BAUDRATE)/4)-1

// UART Configuration
void InitUart1(void)
{
    U1MODEbits.STSEL    = 0;    // 1-stop bit
    U1MODEbits.PDSEL     = 0;    // 8-bit data, no parity
    U1MODEbits.BRGH      = 1;    // High-Speed
    U1MODEbits.URXINV     = 0;    // UxRX Idle state is ‘1’
    U1MODEbits.ABAUD     = 0;    // Autobaud Disabled
    U1MODEbits.LPBACK     = 0;    // Loopback mode is disabled
    U1MODEbits.WAKE         = 0;    // No wake-up enabled
    U1MODEbits.UEN          = 0;    // UxTX & UxRX pins are enabled and used;
                                // UxCTS & UxRTS/BCLK pins controlled by port latches
    U1MODEbits.RTSMD     = 1;    // UxRTS pin in Simplex mode
    U1MODEbits.IREN         = 0;    // IrDA encoder and decoder disabled
    U1MODEbits.USIDL    = 0;    // Continue module operation in Idle mode

    U1BRG = BRGVAL;                // BAUD Rate Setting for 9600

    U1STAbits.UTXISEL0 = 0;        // Interrupt after one Tx character is transmitted
    U1STAbits.UTXISEL1 = 0;                                       
    U1STAbits.URXISEL  = 0;        // Interrupt after one RX character is received
   
    //********************************************************************************
    //  Enable UART Rx and Tx
    //********************************************************************************/
    U1MODEbits.UARTEN   = 1;    // Enable UART1
    U1STAbits.UTXEN     = 1;    // Enable UART1 Tx

    IEC4bits.U1EIE         = 0;    // UART1 Error Interrupt disabled
   
    IEC0bits.U1TXIE     = 1;    // Enable UART1 Tx Interrupt
    IEC0bits.U1RXIE     = 1;    // Enable UART1 Rx Interrupt
}

void __attribute__((interrupt, no_auto_psv)) _U1RXInterrupt(void)
{
    unsigned char ch;
    ch = U1RXREG;
   
    IFS0bits.U1RXIF = 0;        // Clear the U1RX Interrupt Flag;

    while(!U1STAbits.TRMT);        // Echo Back Received Character
    U1TXREG = ch;
}

void __attribute__ ((interrupt, no_auto_psv)) _U1TXInterrupt(void)
{
    IFS0bits.U1TXIF = 0;         // Clear the U1TX Interrupt Flag
}

void __attribute__ ((interrupt, no_auto_psv)) _U1ErrInterrupt(void)
{
    IFS4bits.U1EIF = 0; // Clear the UART1 Error Interrupt Flag
}



post edited by ericmar - 2008/04/08 00:27:49
#7
zardoz1
Super Member
  • Total Posts : 1852
  • Reward points : 0
  • Joined: 2005/07/09 08:03:28
  • Location: 's-Hertogenbosch, The Netherlands
  • Status: offline
RE: Interrupt Controller 2008/04/08 00:28:15 (permalink)
0
Unfortunatelly currently I have no access to code so I can not provide you with an example. I think however the C30 user manual contains a number of examples.
 
And believe me, this interrupt architecture is one of the most advanced you can find, I really love it. Also very glad Microchip decided to port the same interrupt architecture to PIC32 even improving it with a single disable/enable interrupt instruction.
 
(although I have no use for disabling interrupts myself since AVIX doesn't need to wink)


AVIX
the PIC32 & dsPIC/PIC24 RTOS with:
- Zero Latency Interrupts
- The best performance!
- Integrated Power Management
Download here: http://www.avix-rt.com/
#8
zardoz1
Super Member
  • Total Posts : 1852
  • Reward points : 0
  • Joined: 2005/07/09 08:03:28
  • Location: 's-Hertogenbosch, The Netherlands
  • Status: offline
RE: Interrupt Controller 2008/04/08 00:35:15 (permalink)
0
May I know if you guys usually put all the ISRs in one file, say ISR.c, or put each ISR separately (for e.g. ISR_UART in Uart.c, etc.).

 
There is no reason to put all ISR's in a single file. Normally you have some kind of a file structure based on functionality like a file for serial IO. You can just place the related ISR's in that file.
 
One thing I do is define the different interrupt priority levels in a global header file since when tuning your system you might want to play with this and see the relations. This is easier if all priorities are written in one location and this file is included by the code dealing with the actual IP register settings.


AVIX
the PIC32 & dsPIC/PIC24 RTOS with:
- Zero Latency Interrupts
- The best performance!
- Integrated Power Management
Download here: http://www.avix-rt.com/
#9
ericmar
Super Member
  • Total Posts : 200
  • Reward points : 0
  • Joined: 2006/07/25 00:38:01
  • Location: Malaysia
  • Status: offline
RE: Interrupt Controller 2008/04/08 00:42:40 (permalink)
0
ORIGINAL: zardoz1

May I know if you guys usually put all the ISRs in one file, say ISR.c, or put each ISR separately (for e.g. ISR_UART in Uart.c, etc.).


There is no reason to put all ISR's in a single file. Normally you have some kind of a file structure based on functionality like a file for serial IO. You can just place the related ISR's in that file.

One thing I do is define the different interrupt priority levels in a global header file since when tuning your system you might want to play with this and see the relations. This is easier if all priorities are written in one location and this file is included by the code dealing with the actual IP register settings.

hi zardoz1,

Thanks for your reply again! May I find out more information about your so called "file structure based on functionality" practice? I just want to learn from experienced programmers in the way they think it is efficient and organized in terms of structuring their source codes. Everyone may have their own conventions or standard when it comes to programming but it is always good to share experience so that fresh programmers can learn and write their programs in a more better way. It can be taken as some sort of programming culture I believe.

By the way, may I know what the "no_auto_psv" is in the an ISR? Thanks.

Regards,
Eric
post edited by ericmar - 2008/04/08 00:44:34
#10
zardoz1
Super Member
  • Total Posts : 1852
  • Reward points : 0
  • Joined: 2005/07/09 08:03:28
  • Location: 's-Hertogenbosch, The Netherlands
  • Status: offline
RE: Interrupt Controller 2008/04/08 01:55:59 (permalink)
5 (1)
What I meant with the file structure is just a basic separation of the different parts of your code in multiple source files.

Often a program contains multiple functional units like UART, ADC, LCD etc.

Often the code of each functional part is placed in a .c file and a related .h file.

The .c file contains the implementation and the .h file contains the definitions needed by other modules (interface). This is just a very basic structure where most people start with. Based on the scale of the project, version control system used etc. more complicated structures may exist.



no_auto_psv deals with the PSV register. PSV register is the Program Space Visibility register used to directly access Flash memory content. The part of flash which is visible is a page (I think it is 32K but I am not sure). Suppose you want to access more than 32K of flash, the PSV register needs to get a different value. Would this be done from an ISR, the PSV register must be saved upon entry of the ISR, which is accomplished by auto_psv. When using no_auto_psv, the PSV register is not saved.
post edited by zardoz1 - 2008/04/08 01:57:26


AVIX
the PIC32 & dsPIC/PIC24 RTOS with:
- Zero Latency Interrupts
- The best performance!
- Integrated Power Management
Download here: http://www.avix-rt.com/
#11
Jonathan_m84
Starting Member
  • Total Posts : 37
  • Reward points : 0
  • Joined: 2008/02/19 04:25:13
  • Location: Den Helder, NL
  • Status: offline
RE: Interrupt Controller 2008/04/11 05:18:41 (permalink)
0
Hi eric, here some sample code where i play with the timers and the uart and the different priorities... im not an expert but this should help you out a little...


 
#include "p24hj12gp202.h"
#define  FCY    40000000
#define  BAUDRATE   19200
#define  BRGVAL    ((FCY/BAUDRATE)/16)-1
#define  _NOPSV    __attribute__((no_auto_psv)) // saves you a little typing :p
 
char output[20];
 
/* UART interrupts */
void _ISR _NOPSV _U1TXInterrupt(void){
 IFS0bits.U1TXIF = 0;


void _ISR _NOPSV _U1RXInterrupt(void){
 dat=U1RXREG;
 if (dat=='}'){
  U1TXREG='}';
  Nop();
  U1TXREG='\r';
  Nop();
  U1TXREG='\n';
 } else U1TXREG=dat; //ping pong
 IFS0bits.U1RXIF=0;
}
/* Timer 0, 1 en 2 interrupts */
void _ISR _NOPSV _T1Interrupt(void){
 time1++;
 IFS0bits.T1IF=0;
}  
void _ISR _NOPSV _T2Interrupt(void){
 time2++;
 IFS0bits.T2IF=0;
}
void _ISR _NOPSV _T3Interrupt(void){
 time3++;
 IFS0bits.T3IF=0;


void initUART(){
 U1MODEbits.STSEL = 0;
 U1MODEbits.PDSEL = 0;
 U1MODEbits.ABAUD = 0;
  
 U1BRG = BRGVAL;
 
 U1STAbits.UTXISEL0 = 0;
 U1STAbits.UTXISEL1 = 0;
 U1STAbits.URXISEL = 0;
 
 RPINR18bits.U1RXR = 9;  // Receive is RP9
    RPOR4bits.RP8R=3;  // Transmit is RP8
 
 U1MODEbits.UARTEN = 1;
 U1STA=0x0440;
 IEC0bits.U1RXIE=1;
 IEC0bits.U1TXIE=1;
 
 IFS0bits.U1RXIF=0;
 IFS0bits.U1TXIF=0;
 IPC2bits.U1RXIP=0x03; // uart has priority 3
 IPC3bits.U1TXIP=0x03; //
 for (i=0;i<10;i++){
  Nop();
 }
}

void initTMR1(){ //Timer1
 T1CONbits.TCS=0;
 T1CONbits.TGATE=0;
 T1CONbits.TCKPS=0b00;
 TMR1=0x0000;
 
 PR1=0x27;//(FCY/1000000)-1; //  interval is 1 us
 
 IPC0bits.T1IP=0b111; // timer has higher priority (7)
 IFS0bits.T1IF=0; // clear flag
 IEC0bits.T1IE=1;// enable interrupt
 
 T1CONbits.TON=0; // timer off
}
void initTMR2(){ //Timer2

 T2CONbits.TCS=0;
 T2CONbits.TGATE=0;
 T2CONbits.TCKPS=0b00;
 TMR2=0x0000;
 PR2=0x27;  // 40-1 = 0x27 = 1us
 IPC1bits.T2IP=0x01; // low priority
 IFS0bits.T2IF=0; // flag low
 IEC0bits.T2IE=1; // enable interrupt
 
 T2CONbits.TON=0; // timer off
}
void initTMR3(){ //Timer3

 T3CONbits.TCS=0;
 T3CONbits.TGATE=0;
 T3CONbits.TCKPS=0b00;
 TMR3=0x0000;
 PR3=0x27; // 1 us
 IPC2bits.T3IP=0x01; // low priority
 IFS0bits.T3IF=0; // clear flag
 IEC0bits.T3IE=1; // enable interrupt
 
 T1CONbits.TON=0; // timer off
}

void initUC(){
 // PLL
  PLLFBD=0x1E; // see manual for this...
 CLKDIVbits.PLLPRE=0b00010;
 CLKDIVbits.PLLPOST=0;
  while(!OSCCONbits.LOCK){
  Nop();
 }
 OSCCONbits.IOLOCK=0;
 CORCONbits.IPL3=0;
 SRbits.IPL=0x00; // CPU priority
}

void writeString(char *data){
 while(*data!='\0'){
         while(!U1STAbits.TRMT);
         U1TXREG=*data;
         *data++;
 }
}

void delay_us(uns16 us){
 time1=0;
 TMR1 = 0;
  T1CONbits.TON=1;
  while(us>=time1){
   Nop();
   }
 T1CONbits.TON=0;


int main(){
 initUC();
 initTMR1();
 initTMR2();
 initTMR3();
 AD1PCFGL=0x3FF; // all digital
 
 initPorts(); 
 TRISA = 0x0000;  // all outputs
 TRISB = 0xC280;  // RB15/14/9/7=input, rest is output..
 
 LATB = 0x00;
 LATA = 0x00;
 initUART();
 
   writeString("\r\nPIC 24HJ12GP202 test");
    writeString("\r\n");
   
 while(1){
   delay_ms(100);
   PORTAbits.RA0^=1;
   delay_ms(100);  
   PORTAbits.RA0^=1;
 }
 
 return 0;
}

#12
CraigHB
Super Member
  • Total Posts : 244
  • Reward points : 0
  • Joined: 2007/04/18 22:01:21
  • Location: Reno, Nevada
  • Status: offline
RE: Interrupt Controller 2008/05/13 12:28:43 (permalink)
0
I just have a comment if that's okay.  I'm a hobbyist and have recently started using the 24F parts after spending quite a bit of time with the 18F.  I have to agree that big fat interrupt table is wonderful.  So many things are just a piece of cake with the 24F.   The feature set of this product is amazing.
#13
hoarder
New Member
  • Total Posts : 11
  • Reward points : 0
  • Joined: 2008/09/10 18:57:57
  • Location: Melbourne
  • Status: offline
RE: Interrupt Controller 2008/09/24 17:00:32 (permalink)
0
Hi, i was just wondering if someone could tell me what the closing brace means in the above code?

if (dat=='}'){
 U1TXREG='}';
cheers

#14
hexreader
Super Member
  • Total Posts : 1030
  • Reward points : 0
  • Joined: 2008/05/04 03:06:55
  • Location: England
  • Status: online
RE: Interrupt Controller 2008/09/24 17:29:37 (permalink)
0
The first and third '}' in your post are just an ascii character, not to be confused with the second { which is part of the C code and matches up with a closing } further down in the original code.
 
Here is an alternative formatting style, that might be clearer:
 

    dat=U1RXREG;         //received character to dat

    if ( dat == '}' )        // if character '}' received then add carriage return and new line
    {
        U1TXREG = '}';       //echo the '}' character
        Nop();               // allow time for 4 byte FIFO to fill
        U1TXREG = '\r';      // add in a carriage return
        Nop();               // allow time for 4 byte FIFO to fill
        U1TXREG = '\n';      // add in a new-line character
    }
    else U1TXREG = dat;   //ping pong  - if not a '}' character, then just echo the received character
I have guessed at suitable comments for what I think the author intended.
 
I notice that U1TXREG is being filled without first checking that TX buffer is free. This would normally cause bad things to happen, but presumably the author is confident that the four byte FIFO will be empty at this point.
#15
angbit
New Member
  • Total Posts : 5
  • Reward points : 0
  • Joined: 2008/01/22 06:53:38
  • Location: 0
  • Status: offline
Re: RE: Interrupt Controller 2011/05/23 08:14:33 (permalink)
0
Hi,

I'm using a PIC24FJ64GA102.
My question is: are the interupt events sampled by the main clock rate (Fosc) or the instruction clock rate (Fosc/2)? Which clock switch the interrupt flag bits?
#16
Aussie Susan
Super Member
  • Total Posts : 3612
  • Reward points : 0
  • Joined: 2008/08/18 22:20:40
  • Location: Melbourne, Australia
  • Status: offline
Re: RE: Interrupt Controller 2011/05/23 20:02:09 (permalink)
0
Please don't hijack other threads - there is no reason not to start your own thread.

Also, I'm not sure that "sampled" is really the right term here. Whenever an interrupt source requests service (which could be asynchronous to the rest of the MCU's operation), the current instruction will complete before the hardware will start the interrupt process (assuming priority levels permit etc)

Susan
#17
ReverseEMF
New Member
  • Total Posts : 30
  • Reward points : 0
  • Joined: 2012/03/14 17:30:40
  • Location: 0
  • Status: offline
Re: RE: Interrupt Controller 2019/09/08 11:16:18 (permalink)
0
I know this thread is old, but I hit on this from a search, and have, subsequently gained further understanding of Nested Interrupts, and to supplement the splendid explanation of Interrupt Priority, offered by zardoz-1 here's my newly acquired understanding of 24F Interrupt Nesting [since that was also part of the original question]:
 
First a set of foundational bullet points:
  • Following a POR, NSTDIS is reset.  Thus, Interrupt Nesting is the default functionality.
  • When NSTDIS is set, Interrupt Nesting is disabled, and the IPL<2:0> bits become Read Only [IPL3 is always Read Only].
  • The quintessential difference between NSTDIS == 0 [Nesting] and NSTDIS == 1 [NO Nesting] is this: When Nesting is in effect, an Interrupt Request [IRQ] CAN interrupt an Interrupt Service Routine [ISR].  When nesting is disabled, NO user-settable IRQ can interrupt an ISR.
    When nesting is disabled, if an IRQ occurs during an ISR, the ISR will finish before the new interrupt is handled.  While this IRQ has it's flag set, but is not being serviced, it has a "pending" status. 
    In fact, this is why the IPL bits become read-only when nesting is disabled.  When the NSTDIS bit is set, the CPU priority level, for all interrupts, is set to level 7 [i.e. the IPL<2:0> bits are all assigned a value of 1 -- IPL3 excluded -- which is only set by a TRAP exception]. 
    Thus, because all user settable interrupts are intrinsically set to level 7, they all exclude each other, by the very rule that an IRQ can only interrupt an ISR, if it has a priority level greater than the interrupt being serviced.
    So, fun fact: Technically, Nesting is always in effect, but is forced to not happen, when nesting is disabled, by the system's manipulation of the IPL<2:0> bits -- namely, by insuring all user settable interrupts have the same priority, by setting all of the IPL<2:0> bits for every interrupt.
  • The documentation only seems to imply this, but when nesting is disabled, the conclusion of an interrupt service routine [i.e. following the RETFIE instruction call], any interrupt flag that is set [a pending interrupt], will call the ISR associated with the flag, and so on, one after another -- should there be more than one.  So, in other words, if in IRQ happens during an ISR, the xxxIF interrupt flag, for that IRQ, will be set, but the service routine, for that new interrupt, won't be called until the current routine finishes.  When an interrupt flag is set, during an ISR, the flag indicates a "pending" interrupt, which means, all interrupts, eventually, get services.  And NSTDIS merely determines whether that happens via nesting, or one after another.
So, bottom line, Nesting is merely the ability of a subsequent interrupt request, to interrupt an interrupt being serviced -- but ONLY if that subsequent interrupt has a higher priority level than the interrupt being serviced.
The documentation doesn't seem to mention this, but I'm sure this nesting has an impact on the number of available CALLs/Nestings, and can lead to a stack overflow, if the stack pointer reaches the end of RAM.

PLEASE CORRECT ME IF ANY OF THIS IS WRONG!!
post edited by ReverseEMF - 2019/09/08 11:21:21

The Electrons Flow Round and Round...
#18
Gort2015
Klaatu Barada Nikto
  • Total Posts : 3233
  • Reward points : 0
  • Joined: 2015/04/30 10:49:57
  • Location: 0
  • Status: offline
Re: RE: Interrupt Controller 2019/09/08 12:53:14 (permalink)
0
11 Years later.

MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
https://www.youtube.com/watch?v=Iu1qa8N2ID0
+ ST:Continues, "What Ships are Made for", Q's back.
#19
Jump to:
© 2019 APG vNext Commercial Version 4.5