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.

TMS320F28335: unintentional interrupt mask

Part Number: TMS320F28335

Hello

I have a trouble with unintentional interrupt mask that happens seldom, may be once in million times, but it disturbs periodic task of XINT1 interrupt.

I find out PIEACK1 is not cleared when it happends even though it gets through the program code such as:

RegsPIECtrl.PIEACK.unWord = ( unsigned int )0x0001;

After that, XINT1 interrupt is not called until SPIRXINTA interrupt is called.

I have no idea why this happends and how I could avoid this.

Anyone can help me?

  • Hi,

    Thanks for your question!

    Is your application using nested interrupts by any chance? If so, this could potentially be related to the known errata (document here) where spurious nested interrupts can occur in a few situations. Please check if anything in the following section applies to your application (then we can debug from there for a workaround):

    "Usage Notes and Known Design Exceptions to Functional Specifications"->"Usage Notes"->"PIE: Spurious Nested Interrupt After Back-to-Back PIEACK Write and Manual CPU Interrupt Mask Clear Usage Note"

    -or-

    "Usage Notes and Known Design Exceptions to Functional Specifications"->"Usage Notes"->"Caution While Using Nested Interrupts"

    Other than this, the other thing to make sure of is that the PIEIER, IER, and INTM for this interrupt are not being modified in other locations (or right before this interrupt). If another piece of code blocks off the PIEIER, IER, or INTM from propagating the interrupt, then that could be the cause.

    Additionally, particularly if using nested interrupts, please ensure that the ISR of an interrupt in one group does not modify the PIEIER of another group. For example, an ISR in group 2 should not modify the PIEIER in group 1. This can cause spurious interrupts to occur.

    Let me know if the errata applies to your application, as other than the items mentioned above, there should be no possibility of a PIEACK call being ignored.

    Regards,

    Vince

  • Thank you for your reply!

    Yes, my application is using nested interrupt.
    I use XINT, TINT0(CPU-Timer0), CPU-Timer2, SPI-Rx, and SPI-Tx for interrupt.
    XINT interrupts every 400 micro seconds and CPU-Timer2 interrupts every 10 micro seconds while XINT is interrupting. CPU-Timer0 interrupts every 100 micro seconds. SPI-Rx and SPI-Tx interrupt when a SPI master starts SPI communication.

    I knew the errata and I had checked my program code. I had found a wrong code sequence where I enable a global interrupt first and then clear a PIEACK in SPI-Rx interrupt function. That's back-to-back and reverse order. So I changed the code as an example of errata 5.1.1 workaround. But the trouble still happends.

    I'm not sure how I can apply the errata 5.1.2, because I do not want any other interrupt during SPI-Rx and SPI-Tx interrupt. So SPI-Rx and SPI-Tx interrupt functions have a global interrupt disable at the begining and have a global interrupt enable at the end. This errata says if I enable interrupts using the EINT instruction in an ISR, then I must disable the interrupts before exiting the ISR. What should I do?

    No interrupt modifies the PIEIER or IER of any other group. As for INTM, since this is a global interrupt mask, it is modified in main loop, XINT, SPI-Rx, and SPI-Tx to make other interrupts disable in a short period and afterwords to make them enable back again.

    Best Regards,

    Toshi

  • Hi Toshi,

    Thanks for taking the time to look into the errata and testing out the workaround!

    So since your testing shows that 5.1.1 was not the cause of this intermittent error, let's instead see if errata 5.1.2. can solve the issue:

    I'm not sure how I can apply the errata 5.1.2, because I do not want any other interrupt during SPI-Rx and SPI-Tx interrupt. So SPI-Rx and SPI-Tx interrupt functions have a global interrupt disable at the begining and have a global interrupt enable at the end. This errata says if I enable interrupts using the EINT instruction in an ISR, then I must disable the interrupts before exiting the ISR. What should I do?

    Basically, the errata 5.1.2. requires that right before the exit from the interrupt, that DINT is called. So the code structure would be something similar to the following (may vary depending on interrupt setup):

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    nested interrupt
    {
    //
    // PSEUDO-CODE INTRO STEPS:
    // * save PIEIER for manual restore at the end of ISR
    // * modify IER
    // * Modify this group's PIEIER if needed
    // * PIEACK
    //
    asm(" NOP"); // <--- This is important,
    // so please make sure NOP is there
    EINT; // since we use EINT, errata 5.1.2 applies
    //
    // Insert ISR Code here.......
    //
    //***************************************************
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    It is okay to DINT at the end of the ISR, because when the ISR does the return call at the very end, INTM is part of the restore. So INTM is cleared again when the ISR function finishes and returns (allowing more interrupts to run).

    See this link (link here) for some more details on the standard interrupt handling, and what is restored automatically during the return.

    So definitely make sure to call the DINT at the end of the nested interrupts, to avoid the issue from errata 5.1.2.

    Let me know if this clears up the issue for you!

    Regards,

    Vince

  • Hi Vince,

    Thanks for your link. I understand about the interrupt handling in detail.
    Sorry but I haven't tried the errata 5.1.2 yet becase of my application design.
    My code configuration of interrupt is like this:

    main(){
      interrupt SPI-Rx enable
      interrupt SPI-Tx enable
      interrupt XINT enable
      EINT
      ...
      while(){...}
    }

    interrupt SPI-Rx(){
      DINT
      ...
      EINT
    }

    interrupt SPI-Tx(){
      DINT
      ...
      EINT
    }

    interrupt XINT(){
      EINT
      ...
    }

    I know I should call DINT right before exit.
    Is that mean I should add DINT right after EINT in SPI-Rx and SPI-Tx?
    Or I didn't need to call EINT?

    Best Regards,

    Toshi

  • Hi Toshi,

    Thanks for the follow up.

    The code you provided is close, but not quite what is required.

    First, to answer your questions. EINT should be called in nested interrupts, but it goes before your normal ISR code. DINT then goes after your normal ISR code.

    The reason to enable EINT before your code is because it is telling the CPU that other interrupts are now allowed to stop the code after it. So you allow all the code between EINT and DINT to be interrupted by other interrupts.

    See the below example for more detail.

    Using the SPI-Rx() specifically for example

    interrupt SPI-Rx(){
      DINT
      ...
      EINT
    }

    Using DINT at the beginning of a nested interrupt should not happen unless you are modifying the PIEIER of a different group. Since you are not doing that, DINT should not be at the beginning of the nested interrupt.

    The way the code should look for the SPI-Rx() for example, should instead be:

    interrupt SPI-Rx()

    {

      // SET UP NESTING

      EINT;

      // NORMAL ISR CODE HERE

      DINT;

      // RESTORE PIEIER

    }

    This would be the same for all the interrupts in which you allow nesting.

    See the following example as a template from the Interrupt Nesting wiki page:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    // // C28x ISR Code // // Enable nested interrupts // // interrupt
    void EPWM1_TZINT_ISR(void)
    {
    uint16_t TempPIEIER;
    TempPIEIER = PieCtrlRegs.PIEIER2.all; // Save PIEIER register for later
    IER |= 0x002; // Set global priority by adjusting IER
    IER &= 0x002;
    PieCtrlRegs.PIEIER2.all &= 0x0002; // Set group priority by adjusting PIEIER2 to allow INT2.2 to interrupt current ISR
    PieCtrlRegs.PIEACK.all = 0xFFFF; // Enable PIE interrupts
    asm(" NOP"); // Wait one cycle
    EINT; // Clear INTM to enable interrupts
    //
    // Insert ISR Code here.......
    // for now just insert a delay
    //
    for(i = 1; i <= 10; i++) {}
    //
    // Restore registers saved:
    //
    DINT;
    PieCtrlRegs.PIEIER2.all = TempPIEIER;
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    Regards,

    Vince

  • Hi Vince,

    I've been testing my application, and there's been no problem anymore. I think the problem is solved by your suggestion.

    Thank you very much.

    Best Regards,

    Toshi