This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28379D: USER1 Interrupt nesting

Other Parts Discussed in Thread: TMS320F28379D, C2000WARE
  1. Part Number: TMS320F28379D

Dear TI,

I have a question about the nesting interrupts. I am learning this using the C2000 example because directly from my project I couldn't run my theory. The goal of this question is to confirm if a USER1 interrupt could be interrupted by another interrupt.

The USER1 interrupt is a non-maskable interrupt, which means whatever happens the CPU will reach it if a __asm(" TRAP #Number) is executed, is this interrupt could be interrupted by a higher interrupt form the other peripherals?

To make this experiment I added some small modifications to the swprioritized_interrupts_cpu01 project from c2000ware. you could do the same thing from your side if you want, for this reason I am using this example.

First, I added some code to the User1 ISR in this file SWPrioritizedDefaultIsr.c:

//
// Connected to USER1 of CPU (non-maskable):
//
__interrupt void USER1_ISR(void)     // User Defined trap 1
{
    EINT;

    //
    // Insert ISR Code here.......
    //
    for(i = 1; i <= 100; i++) {}


    // Next two lines for debug only to halt the processor here
    // Remove after inserting ISR Code
//   __asm ("      ESTOP0");
//    for(;;);
    //
    //  Add ISR to Trace
    //
    ISRTrace[ISRTraceIndex] = 0xCA01;
    ISRTraceIndex++;
}

The for loop is 10 times longer than the for loops in other interrupt service routines. My goal is to see if this interrupt service routine will be nested with the highest priority interrupt.

Second, I am runing the __asm("    TRAP #20") instruction after and before the PieCtrlRegs.PIEIFR1.all = ISRS_GROUP1:

//
// CASE 1:
//
#if (CASE==1)
       //
       // Force all group 1 interrupts at once by writing to the PIEIFR1
       // register
       //

       //
       // Prepare for the test:
	   // Disable interrupts
	   // Clear the trace buffer, PIE Control Register, CPU IER and IFR
       // registers
       //
	   DINT;
	   for(i = 0; i < 50; i++)
       {
           ISRTrace[i] = 0;
       }

	   ISRTraceIndex = 0;
       InitPieCtrl();

       IER = 0;
       IFR &= 0;

       //
       // Enable the PIE block
       //
       PieCtrlRegs.PIECTRL.bit.ENPIE = 1;

       //
       // Enable PIE group 1 interrupt 1-8
       //
       PieCtrlRegs.PIEIER1.all = 0x00FF;

       //
       // Make sure PIEACK for group 1 is clear (default after reset)
       //
       PieCtrlRegs.PIEACK.all = M_INT1;

       //
       // Enable CPU INT1
       //
       IER |= M_INT1;

       //
       // Force all valid interrupts for Group 1
       //
       __asm("    TRAP #20");
       PieCtrlRegs.PIEIFR1.all = ISRS_GROUP1;


       //
       // Enable global Interrupts CPU level:
       //
	   EINT;   // Enable Global interrupt INTM

       //
	   // Wait for all Group 1 interrupts to be serviced
       //
	   while(PieCtrlRegs.PIEIFR1.all != 0x0000 ){}

       //
       // Stop here and check the ISRTrace to determine which order the
       // ISR Routines completed.  The order is dependant on the priority
       // assigned in the F2837xD_SWPrioritizedIsrLevels.h file
       //
       // The ISRTrace will contain a list of values corresponding to the
       // interrupts serviced in the order they were serviced.
	   // For example if the ISRTrace looks like this
	   //        0x0014     ISR Group 1 interrupt 4
	   //        0x0017     ISR Group 1 interrupt 7
	   //        0x0016     ISR Group 1 interrupt 6
	   //        0x0015     ISR Group 1 interrupt 5
	   //        0x0018     ISR Group 1 interrupt 8
	   //        0x0012     ISR Group 1 interrupt 2
	   //        0x0011     ISR Group 1 interrupt 1
	   //        0x0000     end of trace
       //
	  __asm("        ESTOP0");

I am executing the first case of the example.

I am using the same  F2837xD_SWPrioritizedIsrLevels.h from TI:

#define	INT1PL      2        // Group1 Interrupts (PIEIER1)
#define	INT2PL      1        // Group2 Interrupts (PIEIER2)
#define	INT3PL      4        // Group3 Interrupts (PIEIER3)
#define	INT4PL      2        // Group4 Interrupts (PIEIER4)
#define	INT5PL      2        // Group5 Interrupts (PIEIER5)
#define	INT6PL      3        // Group6 Interrupts (PIEIER6)
#define	INT7PL      5        // Group7 Interrupts (PIEIER6)
#define	INT8PL      5        // Group8 Interrupts (PIEIER6)
#define	INT9PL      3        // Group9 Interrupts (PIEIER9)
#define	INT10PL     6        // Group10 Interrupts (PIEIER6)
#define	INT11PL     6        // Group11 Interrupts (PIEIER6)
#define	INT12PL     8        // Group12 Interrupts (PIEIER6)
#define	INT13PL     4        // XINT13
#define	INT14PL     4        // INT14 (TINT2)
#define	INT15PL     4        // DATALOG
#define	INT16PL     4        // RTOSINT



...
#define G1_1PL		5		// ADCA1_INT
#define G1_2PL		3		// ADCB1_INT
#define G1_3PL		1		// ADCC1_INT
#define G1_4PL		4		// XINT1_INT
#define G1_5PL		4		// XINT2_INT
#define G1_6PL		1		// ADCD1_INT
#define G1_7PL		12		// TIMER0_INT
#define G1_8PL		5		// WAKE_INT
#define G1_9PL		0   	// Reserved
#define G1_10PL		0   	// Reserved
#define G1_11PL		0   	// Reserved
#define G1_12PL		0   	// Reserved
#define G1_13PL		8		// IPC1_INT
#define G1_14PL		13		// IPC2_INT
#define G1_15PL		15		// IPC3_INT
#define G1_16PL		9		// IPC4_INT

Results:

In this picture, we could see that the USER1 interrupt gets the first interrupt executed even if #define G1_3PL 1 // ADCC1_INT is the highest priority?

Does the USER interrupt is interrupted when the ADCC1_INT it has arrived? I am not sure that the USER1 interrupt is nested with th high priority, I think that even if we define the highest priority interrupts, when USER interrupt start execution it doesn't stop till the end and other highest priority are in the pending state.

Could you please clarify this point?

Thank you in advance,

Regards,

S.Tarik

  • Hi S.Tarik,

    User interrupts are non-maskable, it will be serviced immediately after the TRAP instruction. 

    Using the SW prioritization logic, you can only control the priorities of the PIE interrupts and C28x interrupts INT1-16.

    Regards,

    Veena

  • They are non maskable, but don't you enable ALL other interrupts within USER1_ISR by the EINT instruction?

  • Hi,

    EINT/DINT instruction only controls the maskable interrupts. So, in your code where you force the interrupts : 

    __asm(" TRAP #20");
    PieCtrlRegs.PIEIFR1.all = ISRS_GROUP1;

    The user interrupt ISR is hit immediately after the TRAP instruction, even though INTM is disabled. Hence the Group1 interrupt flag may not be even set inside the USER ISR. Can you try reversing the order?

    PieCtrlRegs.PIEIFR1.all = ISRS_GROUP1;
    __asm(" TRAP #20");


    This way, you make sure the Group1 interrupt is set before USER ISR  hits. Inside the ISR, after you enable EINT, hardware will see the Group1 interrupt flag and will branch to the corresponding ISR

    Regards,

    Veena

  • Hello StephanS and Veena,

    I reverse the order as you mentioned.

    and here is the results,

    The USER interrupt is the last one executed like it has the lowest priority!

    I made some changes to the order priority in the header file:

    I agree with you, the TRAP instruction is not maskable, but what I am trying to experiment is the ability to execute and interrupt inside the USER interrupt.

    I am trying to make the Timer interrupt trig inside the User interrupt.

  • Hi,

    As Stephen mentioned, EINT instruction will enable all the interrupts. Ideally, you should be selecting enabling only those interrupts for which you need higher priority. That is what is done in the SW prioritized interrupts logic. If you look at the interrupt_ex3_sw_prioritization example, you can find that the ISR updates the IER and PIE registers before EINT. The macros M_INT1 and MG1_7 are configured in such a way that it only enables the interrupts which has higher priority than the Timer interrupt. You can use a similar logic to extend these for USER interrupts. 

    Regards,

    Veena

  • Great,

    I am debugging this example to practice this and understand the nesting deeply.

    To do so, I am using the first group with the Timer0 highest interrupt. In the example first case, I am firing the 8 interrupts and I am adding a breakpoint to each interrupt like in the picture below.

    When I click F8, the PC runs to the ADCA1 interrupt, it's not the software's highest priority but, it goes in this interrupt first.

    It's normal for the first time because hardware takes place and the software prioritization will start from the ADCA1_ISR.

    My questions are:

    1. In the second F8 the program counter hit the Timer0 interrupt but before reaching the Timer0 interrupt the PIEIER1.all = 0x00FE.

    It supports having  PIEIER1.all = 0x0040? I couldn't understand, Does the MG1_7 shifting takes more cycles and in this stage, the PIEIER1.all is still not affected?

    2. The 10 cycles for the loop is it mandatory in the interrupts? Do I have to keep this for loop for nesting or is it just for demonstration of CPU load?

    Thank you in advance,

    S.T

  • Can you share the priorities you have configured for each of those interrupts? Are you checking the IER register values just before the EINT statement?

    2. The 10 cycles for the loop is it mandatory in the interrupts? Do I have to keep this for loop for nesting or is it just for demonstration of CPU load?

    That is just for the demo. You can remove that and insert the actual ISR code there

    Regards,

    Veena

  • Hi,

    In this case, the ISR 1.1 will enable all the other Group1 interrupts (since they have higher priority than INT1.1), hence you see 0xFE. Next it should hit ISR1.2 due to hardware priority and in ISR1.2, only those interrupts with higher priority than itself is enabled, and so on...

    Hope that is clear.

    Regards,

    Veena

  • Hi Veena,

    I want to make the same thing for the user interrupt is it possible,

    Could share an example for USER1 code please Thank you in advance