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.

TMS320F28062: Strange behaviour exiting nested interrupt

Part Number: TMS320F28062


Dear,

I am using nested interrupts in my project with timer 0 (INT1.7) and timer 1 (INT13).

Timer 0 is a 1ms timer to handle my main state machine. In this interrupt I enable the interrupts to make it possible to handle other communication interrupts.

interrupt void CPU_INT_TIMER_T0(void)
{
      // Re-enable this interrupt to receive more timer interrupts
      IER|=PIE_INT1;
      // Acknowledge interrupt group to receive more interrupts for this group
      PieCtrlRegs.PIEACK.all=PIE_INT1;
      asm(" nop");
      // Allow re-entry
      EINT;
      // Framework general timer interrupt
      State_Machine();
      DINT;
} 

Timer 1 is used to add delay before changing a GPIO pin in a RS485 driver. (set hardware direction pin)

interrupt void CPU_INT_INT13(void)
{
     // Call application timer service routine if required
     RS485_InterruptRoutine();
     // Clear any pending interrupt
     IFR&=~PIE_INT13;
} 

Problem I am facing is in some cases (not always) when in interrupt of timer 1 is executed while in interrupt of timer 0 the GPIO is set correctly but when exiting timer 0 interrupt the GPIO is set back to previous state.

1) Entering Timer 0 interrupt

2) Start executing State_Machine() code

3) Entering Timer 1 interrupt

4) Execute RS485_InterruptRoutine()

5) Exiting Timer 1 interrupt with GPIO changed

6) Finishing State_Machine() code

7) Exiting Timer 0 interrupt

8 ) Here the GPIO changes back to previous state

Anyone an idea what can cause this? I guess it depends on when interrupt timer 1 is executing the exiting of interrupt 0 is go wrong?

Thanks on advance.

  • It is not usually necessary to manipulate IER & IFR from within the ISR. Before going further, please try this:

    In the T0 ISR, replace this line...
    IER|=PIE_INT1;
    ...with...
    CpuTimer0Regs.TCR.bit.TIF = 1;


    In the T1 ISR, replace this line...
    IFR&=~PIE_INT13;
    ...with...
    CpuTimer1Regs.TCR.bit.TIF = 1;

    Please let me know if that makes a difference.

    Regards,

    Richard
  • Richard,

    Thanks for the response.

    I made the changes you proposed but this did not makes a difference.

    Regards,

    Bart
  • Bart,

    Thanks for making that change.

    There's nothing in the snippet of code which gives a clue as to why this is happening.  What GPIO pins is RS485_InterruptRoutine() changing and are these being manipulated enywhere else in your code?

    How are you verifying the change happens when you exit T0 ISR?  Are you single stepping through the code?  Is real-time mode enabled?

    Regards,

    Richard

  • Richard,

    The GPIO that is used is GPIO21. This is direction pin of the RS485 driver and is only changed in the driver software with the use of macro.

    #define HAL_RS485A_DIR      0x00200000            // RS485-A direction control
    #define HAL_RS485A_TX       GpioDataRegs.GPACLEAR.all=HAL_RS485A_DIR  // RS485-A direction control TX
    #define HAL_RS485A_RX       GpioDataRegs.GPASET.all=HAL_RS485A_DIR    // RS485-A direction control RX

    We use this concept of nested interrupt and the RS485 driver software on other TMS320F28xx devices for years without any problems. Only the TMS320F28062 has this issue now.

    There is code added to trace the interrupt sequence (at start and end). This information is stored in an array along with the GPIO data.

    A break point is stopping the processor once RS485 communication is going into error. At that point the data of the array is saved and analyzed.

    Out of that information it is clear that within T1 the GPIO is still ok but once back in the T1 routine the GPIO pin is set back to previous state.

    This is an example of the information:

    Timestamp (µs) time between previous state (µs) Description GPIO data
    3160509413 543 CPU Interrupt Timer 0 ENTER 0xF7D2
    3160509346 67 CPU Interrupt Timer 1 ENTER 0xF7D2
    3160509336 10 Changing GPIO21 0xF7F2
    3160509334 2 CPU Interrupt Timer 1 EXIT 0xF7F2
    3160509332 2 CPU Interrupt Timer 0 EXIT 0xF7D2

    Also when an osciloscope is used to monitor the GPIO pin the change of 2µs is also there.

    Regards,

    Bart

  • Bart,

    Thank you for the additional information. The pin should not change unless something in the code is doing it. If you have not already done so, it can be informative to create a minimal project by stripping out as much of the code as you can. That may reveal if something in a background loop, for example, is influencing the result.

    I'd like to run this past some colleagues for their inputs, but before I do that could you clarify a couple of things in your last post please?

    "...but once back in the T1 routine the GPIO pin is set back to previous state."
    You originally said the pin was in the wrong state when exiting T0. Which is correct?

    "...the GPIO pin the change of 2µs is also there."
    What does the 2us mean? Does the pin revert to it's correct state 2us later?

    Thanks.

    Regards,

    Richard
  • Richard,

    The original was wrong, my excuses. It is like the example in the previous post. When exiting timer 1 the GPIO is changed back to the other value.

    The 2µs is the time between setting the GPIO and exiting Timer 1 ISR. So after 2µs the GPIO changes from wanted value to previous value before the ISR of timer 1.

    I will try to simulate the program into a simplified program but because interrupt of timer 1 is triggered by receiving data on RS485 I am not sure that it is possible to simulate the problem. I will give it a shot.

    Thanks.

    Regards,

    Bart
  • Thanks, Bart.

    Could you send me the macros you are using to set and clear the I/O pins please?

    Regards,

    Richard
  • Bart,

    Sorry, you had these macros in an earlier post and I missed them. Are you manipulating these or any other GPIOs in State_Machine() using the GDPAT registers?

    Regards,

    Richard
  • Richard,

    Do you mean GPADAT register? No these are only used to read information and not setting any GPIO.
    For setting and clearing GPIO there is used always GPASET and GPACLEAR register.

    Regards,

    Bart
  • Bart,

    OK, thanks.  I asked about GPDAT because the symptoms feel very much like a non-atomic GPIO instruction being interrupted and then completing when the program returns.

    I think the only way forward is to strip down the code as far as you can until you eliminate the problem and then look for the change.  There has to be something else touching those I/Os.  Keep in mind that the GPIO registers are organised in groups.  On this device, GPIO21 is on port A, and is touched by GPAMUX2 and GPADAT in addition to the atomic SET/CLEAR/TOGGLE registers.

    Please let me know what you find.

    Regards,

    Richard 

  • Richard,

    Problem was found.

    Problem was like you suggested that the interrupt came during manipulation of the GPADAT register.
    In the program GPIO19 was changed by:
    HAL_DO_RESET=HAL.IO.DO.App&0x0001;
    where HAL_DO_RESET is:
    #define HAL_DO_RESET GpioDataRegs.GPADAT.bit.GPIO19

    When we analyzed the assembly code of the compiler it was clear this register was copied to ACC for bit manipulation.
    When the interrupt of Timer1 came during these assembly instructions the GPIO was set back as before after returning the interrupt.

    Thanks for the help!

    Regards,

    Bart
  • Bart,

    Great news.  Thanks for letting us know.

    Regards,

    Richard