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.

TMS320F28384S: One question of c28x interrupt nesting

Part Number: TMS320F28384S

Hi champs,

For c28x interrupt nesting, we suggest not to modify PIEIER registers outside of an ISR for that group, otherwise the spurious INTx.1 interrupts can be triggered.

For example, we have INT3.8, INT9.2 and INT9.5 interrupts and want to prioritize INT9.5, if INT9.2 interrupt happens and be latched in IFR.9 before CPU branches to INT3.8 ISR, when we modify PIEIER9 in INT3.8 ISR and then spurious INT9.1 will be triggered, this is the reason we suggest not to modify PIEIER outside of an ISR for that group.

__interrupt void EPWM8_ISR(void)             // INT3.8 ISR
{
    uint16_t TempPIEIER;

    TempPIEIER = PieCtrlRegs.PIEIER9.all;    // Save PIEIER register for later
    IER |= 0x100;                            // Set global priority by adjusting IER
    IER &= 0x100;
    PieCtrlRegs.PIEIER9.all &= 0x0010;      // Set group priority by adjusting PIEIER9 to allow
                                            // INT 9.5 to interrupt current ISR
    
    PieCtrlRegs.PIEACK.all |= 0x0100;       // Enable PIE interrupts
    asm(" NOP");                            // Wait one cycle
    EINT;                                   // Clear INTM to enable interrupts

    // Insert ISR Code here.......

    DINT;
    PieCtrlRegs.PIEIER9.all = TempPIEIER;
}

If we modify above ISR to below function, modify PIEIER9 for INT9.5 and then clear other bits in IFR register before setting IER register, can we modify PIEIER9 in INT3.8 ISR and avoid the spurious INT9.1 interrupt?

If INT9.2 happens before C28x branches to INT3.8 ISR, since INT9.2 is latched in PIEIFR9.2, the INT9.2 interrupt should can be recover when write back the TempPIEIER to PIEIER9 before returning from INT3.8 ISR.

Is it correct please?

__interrupt void EPWM8_ISR(void)             // INT3.8 ISR
{
    uint16_t TempPIEIER;

    TempPIEIER = PieCtrlRegs.PIEIER9.all;    // Save PIEIER register for later
    PieCtrlRegs.PIEIER9.all &= 0x0010;      // Set group priority by adjusting PIEIER9 to allow
                                            // INT 9.5 to interrupt current ISR
    IFR &= 0x100;
    IER |= 0x100;                            // Set global priority by adjusting IER

    IER &= 0x100;
    
    PieCtrlRegs.PIEACK.all |= 0x0100;       // Enable PIE interrupts
    asm(" NOP");                            // Wait one cycle
    EINT;                                   // Clear INTM to enable interrupts

    // Insert ISR Code here.......

    DINT;
    PieCtrlRegs.PIEIER9.all = TempPIEIER;
}

Regards,

-Luke

  • Hi Vince,

    Thanks for your information and sorry for the typo.

    In my example case, if I would like to modify PIEIER9 in INT3.8 ISR, I have to clear IFR.9 and this will prevent INT9.2 from becoming spurious INT9.1 interrupt after PIEIER9 modification, please refer to my new code portion.

    As I know the INTM is set before CPU branching to ISR, so I think we don't have to do DINT again before modifying PIEIER/IER/IFR registers.

    __interrupt void EPWM8_ISR(void)             // INT3.8 ISR
    {
        uint16_t TempPIEIER;

        TempPIEIER = PieCtrlRegs.PIEIER9.all;    // Save PIEIER register for later
        IER |= 0x100;                            // Set global priority by adjusting IER
        IER &= 0x100;
        PieCtrlRegs.PIEIER9.all &= 0x0010;      // Set group priority by adjusting PIEIER9 to allow
                                                // INT 9.5 to interrupt current ISR
        IFR &= ~0x100;                          // Clear IFR.9 to avoid spurious INT9.1 interrupt
        PieCtrlRegs.PIEACK.all |= 0x0100;       // Enable PIE interrupts
        asm(" NOP");                            // Wait one cycle
        EINT;                                   // Clear INTM to enable interrupts

        // Insert ISR Code here.......

        DINT;
        PieCtrlRegs.PIEIER9.all = TempPIEIER;
    }

    With the code above, I think I can modify PIEIER9 in INT3.8 ISR and prioritize INT9.5 interrupt. Do you see any problem please?

    Regards,

    -Luke

  • Hi Luke,

    The DINT is still required before modifying PIEIER/IER/IFR registers, as mentioned in the thread I linked. Please add this as mentioned in that thread and the "Disabling Interrupts" section of the TRM. It should be right before the IER |= line.

    Please also see the code mentioned in that email, 2nd reply, and the corrections I mentioned to it in the 3rd reply:

    5 NOP cycles are required when disabling interrupts as there may be interrupts still propagating.

    In summary, here's the pseudo-code for ISR nesting with modifying PIEIERs from another group:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    __interrupt void EPWM1_TZINT_ISR(void) // EPWM1 Trip Zone
    {
    //
    // make a variable for each PIEIER that gets updated, in this case only 1
    // backup the PIEIERs that will get modified
    //
    uint16_t TempPIEIER;
    TempPIEIER = PieCtrlRegs.PIEIER2.all;
    //
    // DINT -ONLY- needed because we are modifying the PIEIER of another group.
    // This prevents any additional interrupts from propagating to the CPU
    // while we modify the IER and PIEIER
    //
    DINT;
    //
    // SET GLOBAL PRIORITY
    //
    IER |= M_INT2;
    IER &= MINT2;
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • Hi Vince,

    Thanks for your comments.

    I modify my example code as below, then I am able to modify PIEIER9 in INT3.8 ISR and prioritize INT9.5 without problems, correct?

    __interrupt void EPWM8_ISR(void)             // INT3.8 ISR
    {
        uint16_t TempPIEIER;

        TempPIEIER = PieCtrlRegs.PIEIER9.all;    // Save PIEIER register for later
        DINT;                                    // Set INTM to disable interrupts
        IER |= 0x100;                            // Set global priority by adjusting IER

        IER &= 0x100;
        PieCtrlRegs.PIEIER9.all &= 0x0010;      // Set group priority by adjusting PIEIER9 to allow
                                                // INT 9.5 to interrupt current ISR
        asm(" NOP");                            // Wait one cycle
        asm(" NOP");                            // Wait one cycle
        asm(" NOP");                            // Wait one cycle
        asm(" NOP");                            // Wait one cycle
        asm(" NOP");                            // Wait one cycle
        IFR &= ~0x100;                          // Clear IFR.9 to avoid spurious INT9.1 interrupt

        PieCtrlRegs.PIEACK.all |= 0x0100;       // Enable PIE interrupts
        asm(" NOP");                            // Wait one cycle
        EINT;                                   // Clear INTM to enable interrupts

        // Insert ISR Code here.......

        DINT;
        PieCtrlRegs.PIEACK.all = 0xFFFF;       // Enable PIE interrupts
        PieCtrlRegs.PIEIER9.all = TempPIEIER;

    }

    Regards,

    -Luke

  • Hi Luke,

    Correct, this will allow only INT9.5 to nest within this EPWM8_ISR.

    Regards,

    Vince